CUBRID Engine  latest
db_query.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * db_query.c - QUERY INTERFACE MODULE (Client Side)
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "db_query.h"
32 
33 #include "error_manager.h"
34 #include "storage_common.h"
35 #include "object_representation.h"
36 #include "object_primitive.h"
37 #include "db.h"
38 #include "schema_manager.h"
39 #include "server_interface.h"
40 #include "system_parameter.h"
41 #include "xasl_generation.h"
42 #include "network_interface_cl.h"
43 #include "transaction_cl.h"
44 #include "dbtype.h"
45 
46 #define DB_OID_INCLUDED(r) ((r)->oid_included == true)
47 #define DB_INVALID_INDEX(i,cnt) ((i) < 0 || (i) >= (cnt))
48 #define DB_INVALID_RESTYPE(t) \
49  ((t) != T_SELECT && \
50  (t) != T_CALL && \
51  (t) != T_OBJFETCH && \
52  (t) != T_GET)
53 
54 #define PLAN_BUF_INITIAL_LENGTH (1024)
55 
56 /* A resource mechanism used to effectively handle memory allocation for the
57  query result structures. */
59 {
60  int free_qres_cnt; /* number of free query_result structures */
61  int max_qres_cnt; /* maximum number of free structures to keep */
62  DB_QUERY_RESULT *free_qres_list; /* list of free query entry structures */
63 };
64 
65 static struct
66 { /* global query table variable */
67  int qres_cnt; /* number of active query entries */
68  int qres_closed_cnt; /* number of closed query entries */
69  int entry_cnt; /* # of result list entries */
70  DB_QUERY_RESULT **qres_list; /* list of query result entries */
71  struct alloc_resource alloc_res; /* allocation structure resource */
72 } Qres_table =
73 {
74  0, 0, 0, (DB_QUERY_RESULT **) NULL,
75  {
76  0, 0, (DB_QUERY_RESULT *) NULL}
77 }; /* query result table */
78 
79 static const int QP_QRES_LIST_INIT_CNT = 10;
80  /* query result list initial cnt */
81 static const float QP_QRES_LIST_INC_RATE = 1.25f;
82  /* query result list increment ratio */
83 
84 static char *db_Execution_plan = NULL;
85 static int db_Execution_plan_length = -1;
86 
88 static void free_query_result (DB_QUERY_RESULT * q_res);
90 static int or_packed_query_format_size (const DB_QUERY_TYPE * q, int *count);
91 static char *or_pack_query_format (char *buf, const DB_QUERY_TYPE * q, const int count);
92 static char *or_unpack_query_format (char *buf, DB_QUERY_TYPE ** q);
93 
94 /*
95  * allocate_query_result() - This function allocates a query_result structure
96  * from the free list of query_result structures if any, or by malloc to
97  * allocate a new structure.
98  * return : DB_QUERY_RESULT pointer or NULL
99  */
100 static DB_QUERY_RESULT *
102 {
103  DB_QUERY_RESULT *q_res;
104 
105  q_res = Qres_table.alloc_res.free_qres_list;
106  if (q_res != NULL)
107  {
108  Qres_table.alloc_res.free_qres_list = q_res->next;
109  Qres_table.alloc_res.free_qres_cnt--;
110  }
111  else
112  {
113  q_res = (DB_QUERY_RESULT *) malloc (DB_SIZEOF (DB_QUERY_RESULT));
114  if (q_res == NULL)
115  {
117  }
118  }
119 
120  return q_res;
121 }
122 
123 /*
124  * free_query_result() - This function frees the query_result structure by
125  * putting it to the free query_result structure list if there are not
126  * many in the list, or by calling db_free.
127  * return : void
128  * q_res(in): Query result structure to be freed.
129  */
130 static void
132 {
133  if (Qres_table.alloc_res.free_qres_cnt < Qres_table.alloc_res.max_qres_cnt)
134  {
135  q_res->next = Qres_table.alloc_res.free_qres_list;
136  Qres_table.alloc_res.free_qres_list = q_res;
137  Qres_table.alloc_res.free_qres_cnt++;
138  }
139  else
140  {
141  free_and_init (q_res);
142  }
143 }
144 
145 /*
146  * db_free_query_format() - This function frees the query type area.
147  * return : void
148  * q(in): Pointer to the query type list
149  *
150  * note : p->domain is a pointer to a cached domain structure,
151  * and should no longer be freed.
152  */
153 void
155 {
156  DB_QUERY_TYPE *p, *n;
157 
158  n = q;
159  while (n != NULL)
160  {
161  p = n;
162  n = n->next;
163  if (p->name != NULL)
164  {
165  free_and_init (p->name);
166  }
167  if (p->attr_name != NULL)
168  {
170  }
171  if (p->spec_name != NULL)
172  {
174  }
175  if (p->original_name != NULL)
176  {
178  }
179  if (p->src_domain != NULL)
180  {
182  }
183  free_and_init (p);
184  }
185 }
186 
187 /*
188  * or_packed_query_format_size - calculate the size of the packed query format
189  * return: size
190  * columns(in): query format information
191  * count (out): will hold the count of columns when the function returns
192  */
193 static int
195 {
196  int size = 0;
197  int len = 0;
198  int columns_cnt = 0;
199  const DB_QUERY_TYPE *column = NULL;
200  /* number of columns in the list */
201  size = OR_INT_SIZE;
202  if (columns == NULL)
203  {
204  /* only an integer containing the size (0) */
205  return size;
206  }
207 
208  for (column = columns; column != NULL; column = column->next)
209  {
210  /* column type */
211  size += OR_INT_SIZE;
212  /* column name */
213  size += or_packed_string_length (column->name, &len);
214  /* attribute name */
215  size += or_packed_string_length (column->attr_name, &len);
216  /* spec name */
217  size += or_packed_string_length (column->spec_name, &len);
218  /* user specified column name */
219  size += or_packed_string_length (column->original_name, &len);
220  /* column data type */
221  size += OR_INT_SIZE;
222  /* column data size */
223  size += OR_INT_SIZE;
224  /* column domain information */
225  size += or_packed_domain_size (column->domain, true);
226  /* column source domain information */
227  size += or_packed_domain_size (column->src_domain, true);
228  /* column user visible */
229  size += OR_INT_SIZE;
230  columns_cnt++;
231  }
232  *count = columns_cnt;
233  return size;
234 }
235 
236 /*
237  * or_pack_query_format - pack a query format list
238  * return : advanced pointer
239  * buf (in) : buffer pointer
240  * columns (in): the query format list
241  * count (in) : the count of query format contained in the list
242  */
243 static char *
244 or_pack_query_format (char *buf, const DB_QUERY_TYPE * columns, const int count)
245 {
246  char *ptr = NULL;
247  int len = 0;
248  const DB_QUERY_TYPE *column;
249 
250  if (count != 0)
251  {
252  /* sanity check */
253  assert (columns != NULL);
254  }
255  /* pack the number of columns */
256  ptr = or_pack_int (buf, count);
257  if (count == 0)
258  {
259  return ptr;
260  }
261 
262  for (column = columns; column != NULL; column = column->next)
263  {
264  /* column type */
265  ptr = or_pack_int (ptr, (int) column->col_type);
266  /* column name */
267  len = (column->name == NULL) ? 0 : (int) strlen (column->name);
268  ptr = or_pack_string_with_length (ptr, column->name, len);
269 
270  /* attribute name */
271  len = (column->attr_name == NULL) ? 0 : (int) strlen (column->attr_name);
272  ptr = or_pack_string_with_length (ptr, column->attr_name, len);
273 
274  /* spec name */
275  len = (column->spec_name == NULL) ? 0 : (int) strlen (column->spec_name);
276  ptr = or_pack_string_with_length (ptr, column->spec_name, len);
277 
278  /* user specified column name */
279  len = (column->original_name == NULL) ? 0 : (int) strlen (column->original_name);
280  ptr = or_pack_string_with_length (ptr, column->original_name, len);
281  /* column data type */
282  ptr = or_pack_int (ptr, column->db_type);
283  /* column data size */
284  ptr = or_pack_int (ptr, column->size);
285  /* column domain information */
286  ptr = or_pack_domain (ptr, column->domain, 1, 1);
287  /* column source domain information */
288  ptr = or_pack_domain (ptr, column->src_domain, 1, 1);
289  /* column user visible */
290  ptr = or_pack_int (ptr, column->visible_type);
291  }
292 
293  return ptr;
294 }
295 
296 /*
297  * or_unpack_query_format - unpack a query format list
298  * return : advanced pointer
299  * buf (in) : buffer pointer
300  * columns (in/out): the columns list
301  * count (in/out) : the count of columns contained in the list
302  *
303  * Note: This function allocates memory for all members of the query format
304  * object. This memory is not allocated in the private heap of the current
305  * thread and needs to be released using free_and_init.
306  */
307 static char *
308 or_unpack_query_format (char *buf, DB_QUERY_TYPE ** columns)
309 {
310  char *ptr = NULL;
311  int size = 0, i = 0;
312  DB_QUERY_TYPE *head = NULL, *current = NULL;
313  TP_DOMAIN *tp_dom = NULL;
314  ptr = or_unpack_int (buf, &size);
315  for (i = 0; i < size; i++)
316  {
317  int tmp = 0;
318  DB_QUERY_TYPE *column = (DB_QUERY_TYPE *) malloc (sizeof (DB_QUERY_TYPE));
319 
320  if (column == NULL)
321  {
323  goto error_cleanup;
324  }
325  /* column type */
326  ptr = or_unpack_int (ptr, &tmp);
327  column->col_type = (DB_COL_TYPE) tmp;
328  /* column name */
329  ptr = or_unpack_string_alloc (ptr, &(column->name));
330  /* attribute name */
331  ptr = or_unpack_string_alloc (ptr, &(column->attr_name));
332  /* spec name */
333  ptr = or_unpack_string_alloc (ptr, &(column->spec_name));
334  /* user specified column name */
335  ptr = or_unpack_string_alloc (ptr, &(column->original_name));
336  /* column data type */
337  ptr = or_unpack_int (ptr, &tmp);
338  column->db_type = (DB_TYPE) tmp;
339  /* column data size */
340  ptr = or_unpack_int (ptr, &(column->size));
341  /* column domain information */
342  ptr = or_unpack_domain (ptr, &tp_dom, NULL);
343  if (tp_dom != NULL)
344  {
345  column->domain = tp_domain_cache (tp_dom);
346  }
347  else
348  {
349  column->domain = NULL;
350  }
351  tp_domain_free (tp_dom);
352  tp_dom = NULL;
353  /* column source domain */
354  ptr = or_unpack_domain (ptr, &tp_dom, NULL);
355  if (tp_dom != NULL)
356  {
357  column->src_domain = sm_domain_copy (tp_dom);
358  }
359  else
360  {
361  column->src_domain = NULL;
362  }
363  tp_domain_free (tp_dom);
364  /* column user visible */
365  ptr = or_unpack_int (ptr, &tmp);
366  column->visible_type = (COL_VISIBLE_TYPE) tmp;
367 
368  column->next = NULL;
369 
370  if (head == NULL)
371  {
372  head = column;
373  current = head;
374  }
375  else
376  {
377  current->next = column;
378  current = current->next;
379  }
380  }
381 
382  *columns = head;
383  return ptr;
384 
385 error_cleanup:
386  while (head != NULL)
387  {
388  current = head;
389  head = head->next;
390 
391  /* free name */
392  free_and_init (current->name);
393  /* free attribute name */
394  free_and_init (current->attr_name);
395  /* free spec name */
396  free_and_init (current->spec_name);
397  /* free user specified column name */
398  free_and_init (current->original_name);
399  free_and_init (current);
400  }
401  return ptr;
402 }
403 
404 
405 /*
406  * db_init_prepare_info () - initialize a prepare info object
407  * return : void
408  * info (in/out): prepare info
409  */
410 void
412 {
413  assert (info != NULL);
414  info->statement = NULL;
415  info->columns = NULL;
416  info->host_variables.size = 0;
417  info->host_variables.vals = NULL;
419  info->auto_param_count = 0;
420  info->recompile = 0;
421  info->oids_included = 0;
422  info->into_list = NULL;
423  info->into_count = 0;
424 }
425 
426 /*
427  * db_pack_prepare_info () - pack a prepare info object
428  * return : packed size or error
429  * info (in) : prepared info
430  * buffer (out) : buffer to pack to
431  */
432 int
433 db_pack_prepare_info (const DB_PREPARE_INFO * info, char **buffer)
434 {
435  char *ptr = NULL;
436  int packed_size = 0, i = 0;
437  int query_len = 0, columns_cnt = 0;
438 
439  assert (*buffer == NULL);
440  assert (info != NULL);
441 
442  /* calculate packed size */
443  /* parameters */
444  packed_size += OR_INT_SIZE;
445  if (info->host_variables.size != 0)
446  {
447  int size = 0, i = 0;
448  for (i = 0; i < info->host_variables.size; i++)
449  {
450  size += OR_VALUE_ALIGNED_SIZE (&(info->host_variables.vals[i]));
451  }
452  packed_size += size;
453 
454  size = 0;
455  for (i = 0; i < info->host_variables.size - info->auto_param_count; i++)
456  {
458  }
459  packed_size += size;
460  }
461  /* calculate size for columns */
462  packed_size += or_packed_query_format_size (info->columns, &columns_cnt);
463  /* packed size for query */
464  packed_size += or_packed_string_length (info->statement, &query_len);
465  /* statement type */
466  packed_size += OR_INT_SIZE;
467  /* auto parameters count */
468  packed_size += OR_INT_SIZE;
469  /* recompile */
470  packed_size += OR_INT_SIZE;
471  /* oids included */
472  packed_size += OR_INT_SIZE;
473  /* into list length */
474  packed_size += OR_INT_SIZE;
475  /* into list names */
476  for (i = 0; i < info->into_count; i++)
477  {
478  packed_size += or_packed_string_length (info->into_list[i], NULL);
479  }
480 
481  ptr = (char *) malloc (packed_size);
482  if (ptr == NULL)
483  {
484  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) packed_size);
485  return ER_FAILED;
486  }
487  *buffer = ptr;
488 
489  /* begin packing */
490  /* columns */
491  ptr = or_pack_query_format (ptr, info->columns, columns_cnt);
492  /* query */
493  ptr = or_pack_string_with_length (ptr, info->statement, query_len);
494  /* statement type */
495  ptr = or_pack_int (ptr, info->stmt_type);
496  /* auto parameters count */
497  ptr = or_pack_int (ptr, info->auto_param_count);
498  /* recompile */
499  ptr = or_pack_int (ptr, info->recompile);
500  /* oids included */
501  ptr = or_pack_int (ptr, info->oids_included);
502  /* into list length */
503  ptr = or_pack_int (ptr, info->into_count);
504  for (i = 0; i < info->into_count; i++)
505  {
506  ptr = or_pack_string (ptr, info->into_list[i]);
507  }
508  /* parameters */
509  if (info->host_variables.size == 0)
510  {
511  ptr = or_pack_int (ptr, 0);
512  }
513  else
514  {
515  int i = 0;
516  ptr = or_pack_int (ptr, info->host_variables.size);
517  for (i = 0; i < info->host_variables.size; i++)
518  {
519  ptr = or_pack_db_value (ptr, &(info->host_variables.vals[i]));
520  }
521  for (i = 0; i < info->host_variables.size - info->auto_param_count; i++)
522  {
523  ptr = or_pack_domain (ptr, info->host_var_expected_domains[i], 0, 0);
524  }
525  }
526 
527  return packed_size;
528 }
529 
530 /*
531  * db_unpack_prepare_info () - unpack a DB_PREPARE_INFO object
532  * return : error code or NO_ERROR
533  * info (out) : DB_PREPARE_INFO object
534  * buffer (in): serialized form of the DB_PREPARE_INFO object
535  */
536 int
538 {
539  int i = 0;
540  char *ptr = NULL;
541 
542  assert (info != NULL);
543  assert (buffer != NULL);
544 
545  /* unpack column info */
546  ptr = or_unpack_query_format (buffer, &info->columns);
547  /* unpack query */
548  ptr = or_unpack_string_alloc (ptr, &info->statement);
549  /* unpack statement type */
550  ptr = or_unpack_int (ptr, (int *) &info->stmt_type);
551  /* unpack auto parameters count */
552  ptr = or_unpack_int (ptr, &info->auto_param_count);
553  /* unpack recompile */
554  ptr = or_unpack_int (ptr, &info->recompile);
555  /* oids included */
556  ptr = or_unpack_int (ptr, &info->oids_included);
557  /* unpack into list length */
558  ptr = or_unpack_int (ptr, &info->into_count);
559  if (info->into_count > 0)
560  {
561  info->into_list = (char **) malloc (info->into_count * sizeof (char *));
562  if (info->into_list == NULL)
563  {
565  goto error;
566  }
567  for (i = 0; i < info->into_count; i++)
568  {
569  ptr = or_unpack_string_alloc (ptr, &info->into_list[i]);
570  }
571  }
572  /* unpack parameters */
573  ptr = or_unpack_int (ptr, &(info->host_variables.size));
574  if (info->host_variables.size > 0)
575  {
576  unsigned int i = 0, var_count;
577 
578  var_count = info->host_variables.size;
579  info->host_variables.vals = (DB_VALUE *) malloc (var_count * sizeof (DB_VALUE));
580  if (info->host_variables.vals == NULL)
581  {
583  info->host_variables.size * sizeof (DB_VALUE));
584  goto error;
585  }
586  for (i = 0; i < var_count; i++)
587  {
588  ptr = or_unpack_db_value (ptr, &(info->host_variables.vals[i]));
589  }
590 
591  var_count = info->host_variables.size - info->auto_param_count;
592  info->host_var_expected_domains = (TP_DOMAIN **) malloc (var_count * sizeof (TP_DOMAIN *));
593  if (info->host_var_expected_domains == NULL)
594  {
596  goto error;
597  }
598  for (i = 0; i < var_count; i++)
599  {
600  ptr = or_unpack_domain (ptr, &info->host_var_expected_domains[i], NULL);
601  }
602  }
603  return NO_ERROR;
604 
605 error:
606  if (info->statement != NULL)
607  {
608  free_and_init (info->statement);
609  }
610  if (info->columns != NULL)
611  {
612  DB_QUERY_TYPE *col = info->columns;
613  DB_QUERY_TYPE *next_p = NULL;
614  while (col != NULL)
615  {
616  next_p = col->next;
617  if (col->name != NULL)
618  {
619  free_and_init (col->name);
620  }
621  if (col->attr_name != NULL)
622  {
623  free_and_init (col->attr_name);
624  }
625  if (col->spec_name != NULL)
626  {
627  free_and_init (col->spec_name);
628  }
629  if (col->original_name != NULL)
630  {
632  }
633  tp_domain_free (col->domain);
634  tp_domain_free (col->src_domain);
635 
636  free_and_init (col);
637  col = next_p;
638  }
639  }
640  if (info->host_variables.vals != NULL)
641  {
644  }
645  if (info->host_var_expected_domains)
646  {
648  }
649  if (info->into_list != NULL)
650  {
651  for (i = 0; i < info->into_count; i++)
652  {
653  if (info->into_list[i] != NULL)
654  {
655  free_and_init (info->into_list[i]);
656  }
657  }
658  free_and_init (info->into_list);
659  }
660  return ER_FAILED;
661 }
662 
663 #if defined(WINDOWS) || defined (ENABLE_UNUSED_FUNCTION)
664 /*
665  * db_free_colname_list() - This function frees the column name list.
666  * return : void
667  * colname_list(in): list of column names
668  * cnt(in): number of names
669  */
670 void
671 db_free_colname_list (char **colname_list, int cnt)
672 {
673  int i;
674 
675  if (colname_list == NULL)
676  {
677  return;
678  }
679 
680  for (i = 0; i < cnt; i++)
681  {
682  if (colname_list[i] != NULL)
683  {
684  free_and_init (colname_list[i]);
685  }
686  }
687 
688  free_and_init (colname_list);
689 }
690 
691 /*
692  * db_free_domain_list() - This function frees the domain list.
693  * return : void
694  * domain_list(in): List of domain pointers
695  * cnt(in): Number of domain pointers
696  */
697 void
698 db_free_domain_list (SM_DOMAIN ** domain_list, int cnt)
699 {
700  int i;
701 
702  if (domain_list == NULL)
703  {
704  return;
705  }
706 
707  for (i = 0; i < cnt; i++)
708  {
709  if (domain_list[i] != NULL)
710  {
711  sm_domain_free (domain_list[i]);
712  }
713  }
714 
715  free_and_init (domain_list);
716 }
717 #endif
718 
719 /*
720  * db_free_query_result() - This function frees the areas allocated for the
721  * query result structure and also the supplied query result structure
722  * pointer r.
723  * return : void
724  * r(in): Query Result Structure pointer
725  */
726 void
728 {
729  DB_VALUE **valp;
730  int k;
731 #if defined (ENABLE_UNUSED_FUNCTION)
732  DB_VALUE *val;
733 #endif
734 
735  if (r == NULL)
736  {
737  return;
738  }
739 
740  /* disconnect query result from the query table */
741 #if defined(QP_DEBUG)
742  if (Qres_table.qres_list[r->qtable_ind] != r)
743  {
744  (void) fprintf (stdout, "*WARNING*: Misconnection between the query" "result structure and query table.\n");
745  return;
746  }
747 #endif
748 
749  Qres_table.qres_list[r->qtable_ind] = (DB_QUERY_RESULT *) NULL;
750  Qres_table.qres_cnt--;
751  if (r->status == T_CLOSED && Qres_table.qres_closed_cnt > 0)
752  {
753  Qres_table.qres_closed_cnt--;
754  }
755 
756  /* free type list */
758  r->query_type = NULL;
759 
760  switch (r->type)
761  {
762  case T_SELECT:
763  break;
764 
765  case T_CALL:
766  db_value_free (r->res.c.val_ptr);
767  break;
768 
769  case T_OBJFETCH:
770  {
771  for (k = 0, valp = r->res.o.valptr_list; k < r->col_cnt; k++, valp++)
772  {
773  db_value_free (*valp);
774  }
776  }
777  break;
778 
779 #if defined (ENABLE_UNUSED_FUNCTION)
780  case T_GET:
781  {
782  for (k = 0, val = r->res.g.tpl_list; k < (r->res.g.n_tuple * r->col_cnt); k++, val++)
783  {
784  db_value_clear (val);
785  }
787  }
788  break;
789 #endif
790  default:
791  break;
792  }
793 
794  r->status = T_CLOSED;
795 
796  free_query_result (r);
797 }
798 
799 /*
800  * db_alloc_query_format() - This function allocates specified number of type
801  * list nodes. And query type pointer set to the beginning of allocated list
802  * is returned.
803  * return : query type pointer or NULL on failure
804  * cnt(in): number of nodes in the type list
805  */
808 {
809  DB_QUERY_TYPE *p, *q;
810  int k;
811 
812  if (cnt == 0)
813  {
814  return NULL;
815  }
816 
817  q = (DB_QUERY_TYPE *) malloc (DB_SIZEOF (DB_QUERY_TYPE));
818  if (q == NULL)
819  {
821  return NULL;
822  }
823  /* initialize */
824  q->db_type = DB_TYPE_NULL;
825  q->size = 0;
826  q->name = (char *) NULL;
827  q->attr_name = (char *) NULL;
828  q->spec_name = (char *) NULL;
829  q->original_name = (char *) NULL;
830  q->domain = (SM_DOMAIN *) NULL;
831  q->src_domain = (SM_DOMAIN *) NULL;
833  q->col_type = DB_COL_OTHER;
834 
835  for (k = 0, p = q, p->next = NULL; k < cnt - 1; k++, p = p->next, p->next = NULL)
836  {
837  p->next = (DB_QUERY_TYPE *) malloc (DB_SIZEOF (DB_QUERY_TYPE));
838  if (p->next == NULL)
839  {
842  return NULL;
843  }
844  /* initialize */
845  p->next->db_type = DB_TYPE_NULL;
846  p->next->size = 0;
847  p->next->name = (char *) NULL;
848  p->next->attr_name = (char *) NULL;
849  p->next->spec_name = (char *) NULL;
850  p->next->original_name = (char *) NULL;
851  p->next->domain = (SM_DOMAIN *) NULL;
852  p->next->src_domain = (SM_DOMAIN *) NULL;
854  p->next->col_type = DB_COL_OTHER;
855  }
856 
857  return q;
858 }
859 
860 /*
861  * db_alloc_query_result() - This function allocates a query result structure
862  * for the indicated type and column count.
863  * return : query result pointer or NULL on failure.
864  * r_type(in): query Result Structure type
865  * col_cnt(in): column count
866  */
869 {
870  DB_QUERY_RESULT *r, **qres_ptr;
871  int ind, k;
872  int new_cnt;
873 
874 #if defined(QP_DEBUG)
875  if (DB_INVALID_RESTYPE (r_type))
876  {
878  return (DB_QUERY_RESULT *) NULL;
879  }
880 #endif
881 
882  /* first search query table result list to see if there is place */
883  for (ind = 0, qres_ptr = Qres_table.qres_list; ind < Qres_table.entry_cnt && *qres_ptr != NULL; ind++, qres_ptr++)
884  {
885  ; /* NULL */
886  }
887 
888  if (ind == Qres_table.entry_cnt)
889  {
890  /* query table is full, so enlarge the table */
891  if (Qres_table.entry_cnt == 0)
892  { /* first time allocation */
894  if (Qres_table.qres_list == NULL)
895  {
898  return (DB_QUERY_RESULT *) NULL;
899  }
900  Qres_table.entry_cnt = QP_QRES_LIST_INIT_CNT;
901 
902  /* initialize query_result allocation resource */
903  Qres_table.alloc_res.free_qres_cnt = 0;
904  Qres_table.alloc_res.max_qres_cnt = Qres_table.entry_cnt;
905  Qres_table.alloc_res.free_qres_list = (DB_QUERY_RESULT *) NULL;
906  }
907  else
908  {
909  /* expand the existing table */
910  new_cnt = (int) ((Qres_table.entry_cnt * QP_QRES_LIST_INC_RATE) + 1);
911  Qres_table.qres_list =
912  (DB_QUERY_RESULT **) realloc (Qres_table.qres_list, new_cnt * DB_SIZEOF (DB_QUERY_RESULT *));
913  if (Qres_table.qres_list == NULL)
914  {
915  return (DB_QUERY_RESULT *) NULL;
916  }
917  Qres_table.entry_cnt = new_cnt;
918 
919  /* expand query result allocation resource */
920  Qres_table.alloc_res.max_qres_cnt = Qres_table.entry_cnt;
921  }
922 
923  /* initialize newly allocated entries */
924  for (k = ind, qres_ptr = (DB_QUERY_RESULT **) Qres_table.qres_list + ind; k < Qres_table.entry_cnt;
925  k++, qres_ptr++)
926  {
927  *qres_ptr = (DB_QUERY_RESULT *) NULL;
928  }
929  }
930  qres_ptr = (DB_QUERY_RESULT **) Qres_table.qres_list + ind;
931 
932  *qres_ptr = allocate_query_result ();
933  if (*qres_ptr == NULL)
934  {
935  return (DB_QUERY_RESULT *) NULL;
936  }
937 
938  /* connect query result structure to the query table */
939  r = *qres_ptr;
940  r->qtable_ind = ind;
941  Qres_table.qres_cnt++;
942 
943  /* allocation of query type list is done later */
944  r->query_type = (DB_QUERY_TYPE *) NULL;
945  r->type_cnt = 0;
946 
947  switch (r_type)
948  {
949  case T_SELECT:
950  break;
951 
952  case T_CALL:
953  r->res.c.val_ptr = (DB_VALUE *) NULL;
954  break;
955 
956  case T_OBJFETCH:
957  {
958  r->res.o.valptr_list = (DB_VALUE **) malloc (col_cnt * DB_SIZEOF (DB_VALUE *));
959  if (r->res.o.valptr_list == NULL)
960  {
963  return NULL;
964  }
965  /*
966  * Initialize the vector so that db_free_query_result() doesn't go
967  * haywire if this QUERY_RESULT gets freed before being completely
968  * populated.
969  */
970  for (k = 0; k < col_cnt; k++)
971  r->res.o.valptr_list[k] = NULL;
972  }
973  break;
974 #if defined (ENABLE_UNUSED_FUNCTION)
975  case T_GET:
976  if (col_cnt <= 0)
977  {
978  r->res.g.tpl_list = NULL;
979  }
980  else
981  {
982  r->res.g.tpl_list = (DB_VALUE *) malloc (col_cnt * DB_SIZEOF (DB_VALUE));
983  if (r->res.g.tpl_list == NULL)
984  {
987  return NULL;
988  }
989  for (k = 0; k < col_cnt; k++)
990  {
991  db_make_null (&r->res.g.tpl_list[k]);
992  }
993  }
994  break;
995 #endif
996  default:
997  break;
998  }
999 
1000  return r;
1001 }
1002 
1003 /*
1004  * db_init_query_result() - This function initializes the query result
1005  * structure according to the type.
1006  * return : void
1007  * r(out): query Result Structure
1008  * r_type(in): query Result Structure Type
1009  */
1010 void
1012 {
1013  if (r == NULL)
1014  {
1015  return;
1016  }
1017 
1018  r->type = r_type;
1019  r->status = T_OPEN;
1020  r->col_cnt = 0;
1021  r->oid_included = false;
1022 
1023  switch (r->type)
1024  {
1025  case T_SELECT:
1026  {
1027  r->res.s.query_id = -1;
1028  r->res.s.stmt_id = -1;
1029  r->res.s.stmt_type = (CUBRID_STMT_TYPE) 0;
1031  }
1032  break;
1033 
1034  case T_CALL:
1035  r->res.c.crs_pos = C_BEFORE;
1036  break;
1037 
1038  case T_OBJFETCH:
1039  r->res.o.crs_pos = C_BEFORE;
1040  break;
1041 
1042 #if defined (ENABLE_UNUSED_FUNCTION)
1043  case T_GET:
1044  {
1045  r->res.g.crs_pos = C_BEFORE;
1046  r->res.g.tpl_idx = 0;
1047  }
1048  break;
1049 #endif
1050  default:
1051  break;
1052  }
1053  r->next = (DB_QUERY_RESULT *) NULL;
1054 }
1055 
1056 #if defined(WINDOWS) || defined (CUBRID_DEBUG)
1057 /*
1058  * db_dump_query_result() - this function dumps the content of the query result
1059  * structure to standard output.
1060  * return : void
1061  * r: Query Result Structure
1062  */
1063 void
1064 db_dump_query_result (DB_QUERY_RESULT * r)
1065 {
1066  if (r == NULL)
1067  {
1068  return;
1069  }
1070 
1071 #if defined(QP_DEBUG)
1072  if (DB_INVALID_RESTYPE (r->type))
1073  {
1075  return;
1076  }
1077 #endif
1078 
1079  fprintf (stdout, "\nQuery Result Structure: \n");
1080  fprintf (stdout, "Type: %s \n",
1081  (r->type == T_SELECT) ? "T_SELECT" : (r->type == T_CALL) ? "T_CALL"
1082  : (r->type == T_OBJFETCH) ? "T_OBJFETCH" : (r->type == T_GET) ? "T_GET" : "T_UNKNOWN");
1083  fprintf (stdout, "Status: %s \n",
1084  (r->status == T_OPEN) ? "T_OPEN" : (r->status == T_CLOSED) ? "T_CLOSED" : "T_UNKNOWN");
1085  fprintf (stdout, "Column Count: %d \n", r->col_cnt);
1086  fprintf (stdout, "Oid_Included: %s \n", (r->oid_included) ? "Yes" : "No");
1087  fprintf (stdout, "\n");
1088  if (r->type == T_SELECT)
1089  {
1090  fprintf (stdout, "Query_id: %lld \n", (long long) r->res.s.query_id);
1091  fprintf (stdout, "Stmt_id: %d \n", r->res.s.stmt_id);
1092  fprintf (stdout, "Tuple Cnt: %d \n", r->res.s.cursor_id.list_id.tuple_cnt);
1093  fprintf (stdout, "Stmt_type: %d \n", r->res.s.stmt_type);
1094  } /* if */
1095  else if (r->type == T_GET)
1096  {
1097  fprintf (stdout, "Tuple Cnt: %d \n", r->res.g.n_tuple);
1098  }
1099  fprintf (stdout, "\n");
1100 }
1101 #endif
1102 
1103 #if defined(WINDOWS) || defined (ENABLE_UNUSED_FUNCTION)
1104 /*
1105  * db_cp_colname_list() - This function forms a new column name list from the
1106  * given one.
1107  * return : column name list. NULL on error
1108  * colname_list(in): List of column names
1109  * cnt(in): Number of columns
1110  *
1111  * note : The returned column name list must be freed with db_free_colname_list
1112  */
1113 char **
1114 db_cp_colname_list (char **colname_list, int cnt)
1115 {
1116  char **newname_list;
1117  int i;
1118  size_t size;
1119 
1120  if (colname_list == NULL)
1121  {
1122  return NULL;
1123  }
1124 
1125  newname_list = (char **) malloc (cnt * DB_SIZEOF (char *));
1126  if (newname_list == NULL)
1127  {
1129  return NULL;
1130  }
1131 
1132  for (i = 0; i < cnt; i++)
1133  {
1134  newname_list[i] = NULL;
1135  }
1136 
1137  for (i = 0; i < cnt; i++)
1138  {
1139  size = strlen (colname_list[i]) + 1;
1140  newname_list[i] = (char *) malloc (size);
1141  if (newname_list[i] == NULL)
1142  {
1144  db_free_colname_list (newname_list, cnt);
1145  return NULL;
1146  }
1147  memcpy (newname_list[i], colname_list[i], size);
1148  }
1149 
1150  return newname_list;
1151 }
1152 
1153 /*
1154  * db_cp_domain_list() - This function forms a new domain list pointer.
1155  * return : new domain list. NULL on error.
1156  * domain_list(in): List of domain pointers
1157  * cnt(in): Number of domain pointers
1158  *
1159  * note: The content of each domain pointer is NOT copied to a new area, only
1160  * pointers are set to the contents. There the actual domain pointers
1161  * must NOT be freed until qp_free_domain_ptr() is explicitly called.
1162  */
1163 SM_DOMAIN **
1164 db_cp_domain_list (SM_DOMAIN ** domain_list, int cnt)
1165 {
1166  SM_DOMAIN **newdomain_list;
1167  int i;
1168 
1169  if (domain_list == NULL)
1170  {
1171  return NULL;
1172  }
1173 
1174  newdomain_list = (SM_DOMAIN **) malloc (cnt * DB_SIZEOF (SM_DOMAIN *));
1175  if (newdomain_list == NULL)
1176  {
1178  return NULL;
1179  }
1180 
1181  for (i = 0; i < cnt; i++)
1182  {
1183  newdomain_list[i] = NULL;
1184  }
1185 
1186  for (i = 0; i < cnt; i++)
1187  {
1188  newdomain_list[i] = sm_domain_copy (domain_list[i]);
1189  if (newdomain_list[i] == NULL)
1190  {
1191  db_free_domain_list (newdomain_list, cnt);
1192  return NULL;
1193  }
1194  }
1195 
1196  return newdomain_list;
1197 }
1198 #endif
1199 
1200 /*
1201  * db_clear_client_query_result() - This function is called when a transaction
1202  * commits/aborts on the client or when the server goes down, in order to
1203  * close the existing the query result structures.
1204  * return : void
1205  * notify_server(in) :
1206  */
1207 void
1208 db_clear_client_query_result (int notify_server, bool end_holdable)
1209 {
1210  DB_QUERY_RESULT **qres_ptr;
1211  int k;
1212 
1213  /* search query table result list and mark existing entries as closed */
1214  for (k = 0, qres_ptr = Qres_table.qres_list; k < Qres_table.entry_cnt; k++, qres_ptr++)
1215  {
1216  if (*qres_ptr == NULL)
1217  {
1218  continue;
1219  }
1220  if (((*qres_ptr)->type == T_SELECT && !(*qres_ptr)->res.s.holdable) || end_holdable)
1221  {
1222  /* if end_holdable is false, only end queries that are not holdable */
1223  db_query_end_internal (*qres_ptr, notify_server);
1224  }
1225  }
1226 }
1227 
1228 /*
1229  * db_cp_query_type_helper() - Copies the given type to a newly allocated type
1230  * return : dest or NULL on error.
1231  * src(in): query type to be copied
1232  * dest(in): query type newly allocated
1233  *
1234  * note : It is no longer necessary to use regu_cp_domain() to copy the
1235  * domain field, since it is now a pointer to a cached domain structure.
1236  */
1237 static DB_QUERY_TYPE *
1239 {
1240  size_t size;
1241 
1243  {
1244  /* special collation domain behave like VARIABLE in query output */
1246  dest->db_type = DB_TYPE_VARIABLE;
1247  dest->size = 0;
1249  }
1250  else
1251  {
1252  dest->db_type = src->db_type;
1253  dest->size = src->size;
1254  dest->domain = src->domain;
1255  }
1256 
1257  dest->name = NULL;
1258  dest->attr_name = NULL;
1259  dest->spec_name = NULL;
1260  dest->original_name = NULL;
1261  dest->src_domain = NULL;
1262  dest->visible_type = src->visible_type;
1263  dest->col_type = src->col_type;
1264 
1265  if (src->name != NULL)
1266  {
1267  size = strlen (src->name) + 1;
1268  dest->name = (char *) malloc (size);
1269  if (dest->name == NULL)
1270  {
1272  return NULL;
1273  }
1274  memcpy ((char *) dest->name, src->name, size);
1275  }
1276 
1277  if (src->attr_name != NULL)
1278  {
1279  size = strlen (src->attr_name) + 1;
1280  dest->attr_name = (char *) malloc (size);
1281  if (dest->attr_name == NULL)
1282  {
1284  return NULL;
1285  }
1286  memcpy ((char *) dest->attr_name, src->attr_name, size);
1287  }
1288 
1289  if (src->spec_name != NULL)
1290  {
1291  size = strlen (src->spec_name) + 1;
1292  dest->spec_name = (char *) malloc (size);
1293  if (dest->spec_name == NULL)
1294  {
1296  return NULL;
1297  }
1298  memcpy ((char *) dest->spec_name, src->spec_name, size);
1299  }
1300 
1301  if (src->original_name != NULL)
1302  {
1303  size = strlen (src->original_name) + 1;
1304  dest->original_name = (char *) malloc (size);
1305  if (dest->original_name == NULL)
1306  {
1308  return NULL;
1309  }
1310  memcpy ((char *) dest->original_name, src->original_name, size);
1311  }
1312 
1313  if (src->src_domain != NULL)
1314  {
1315  dest->src_domain = sm_domain_copy (src->src_domain);
1316  }
1317 
1318  return dest;
1319 }
1320 
1321 /*
1322  * db_cp_query_type() - This function copies the given type list into a newly
1323  * allocated type list.
1324  * return : new type list or NULL on error.
1325  * query_type(in): query type list to be copied
1326  * copy_only_user(in):
1327  */
1328 DB_QUERY_TYPE *
1329 db_cp_query_type (DB_QUERY_TYPE * query_type, int copy_only_user)
1330 {
1331  DB_QUERY_TYPE *q;
1332  DB_QUERY_TYPE *ptr1, *ptr2;
1333  int cnt;
1334 
1335  /* find count of nodes to copy */
1336  for (cnt = 0, ptr1 = query_type; ptr1; ptr1 = ptr1->next)
1337  {
1338  if ((ptr1->visible_type != SYSTEM_ADDED_COLUMN) && (!copy_only_user || ptr1->visible_type == USER_COLUMN))
1339  {
1340  cnt++;
1341  }
1342  }
1343 
1344  q = db_alloc_query_format (cnt);
1345  if (q == NULL)
1346  {
1347  return NULL;
1348  }
1349 
1350  for (ptr1 = query_type, ptr2 = q; ptr1; ptr1 = ptr1->next)
1351  {
1352  if ((ptr1->visible_type != SYSTEM_ADDED_COLUMN) && (!copy_only_user || ptr1->visible_type == USER_COLUMN))
1353  {
1354  ptr2 = db_cp_query_type_helper (ptr1, ptr2);
1355  if (ptr2 == NULL)
1356  {
1358  return NULL;
1359  }
1360 
1361  ptr2 = ptr2->next;
1362  }
1363  }
1364 
1365  return q;
1366 }
1367 
1368 #if defined(WINDOWS) || defined (ENABLE_UNUSED_FUNCTION)
1369 /*
1370  * db_get_query_type() - This function forms a query type list structure from
1371  * the given parmeters. The cnt field refers to number of nodes in the
1372  * provided lists which is actual column count of the query result list file.
1373  * If oid_included is set to true, the first node of the lists which
1374  * correspond to the first hidden oid column is eliminated from the formed
1375  * type list.
1376  * return : DB_QUERY_TYPE pointer or NULL.
1377  * type_list(in): data type list
1378  * size_list(in): size list
1379  * colname_list(in): column name list(can be NULL)
1380  * attrname_list(in): attribute name list(can be NULL)
1381  * domain_list(in): domain list(can be NULL)
1382  * src_domain_list(in): source Domain list(can be NULL)
1383  * cnt(in): number of columns
1384  * oid_included(in): hidden first oid column included
1385  */
1386 DB_QUERY_TYPE *
1387 db_get_query_type (DB_TYPE * type_list, int *size_list, char **colname_list, char **attrname_list,
1388  SM_DOMAIN ** domain_list, SM_DOMAIN ** src_domain_list, int cnt, bool oid_included)
1389 {
1390  DB_QUERY_TYPE *q, *type_ptr;
1391  DB_TYPE *typep;
1392  char **colnamep;
1393  char **attrnamep;
1394  SM_DOMAIN **domainp;
1395  SM_DOMAIN **src_domainp;
1396  int *sizep;
1397  int k;
1398  int type_cnt;
1399  size_t size;
1400 
1401  CHECK_CONNECT_NULL ();
1402 
1403  if (type_list == NULL || size_list == NULL || cnt <= 0)
1404  {
1405  return NULL;
1406  }
1407 
1408  type_cnt = (oid_included) ? (cnt - 1) : cnt;
1409 
1410  q = db_alloc_query_format (type_cnt);
1411  if (q == NULL)
1412  {
1413  return NULL;
1414  }
1415 
1416  typep = type_list;
1417  sizep = size_list;
1418  colnamep = colname_list;
1419  attrnamep = attrname_list;
1420  domainp = domain_list;
1421  src_domainp = src_domain_list;
1422  type_ptr = q;
1423  for (k = 0; k < cnt; k++)
1424  {
1425 
1426  if (!(oid_included && k == 0))
1427  {
1428  type_ptr->db_type = *typep;
1429  type_ptr->size = *sizep;
1430  type_ptr->name = (char *) NULL;
1431  type_ptr->attr_name = (char *) NULL;
1432  type_ptr->spec_name = (char *) NULL;
1433  type_ptr->original_name = (char *) NULL;
1434  type_ptr->domain = (SM_DOMAIN *) NULL;
1435  type_ptr->src_domain = (SM_DOMAIN *) NULL;
1436  type_ptr->visible_type = USER_COLUMN;
1437  if (colname_list)
1438  {
1439  /* column names can NOT be NULL */
1440  size = strlen (*colnamep) + 1;
1441  type_ptr->name = (char *) malloc (size);
1442  if (type_ptr->name == NULL)
1443  {
1446  return NULL;
1447  }
1448  memcpy ((char *) type_ptr->name, *colnamep, size);
1449  }
1450  if (attrname_list)
1451  {
1452  if (*attrnamep) /* attribute names can be NULL */
1453  {
1454  size = strlen (*attrnamep) + 1;
1455  type_ptr->attr_name = (char *) malloc (size);
1456  if (type_ptr->attr_name == NULL)
1457  {
1460  return NULL;
1461  }
1462  memcpy ((char *) type_ptr->attr_name, *attrnamep, size);
1463  }
1464  }
1465  if (domain_list)
1466  {
1467  type_ptr->domain = sm_domain_copy (*domainp);
1468  }
1469  if (src_domain_list)
1470  {
1471  type_ptr->src_domain = sm_domain_copy (*src_domainp);
1472  }
1473 
1474  type_ptr = type_ptr->next;
1475  }
1476  typep++;
1477  sizep++;
1478  if (colname_list)
1479  {
1480  colnamep++;
1481  }
1482  if (attrname_list)
1483  {
1484  attrnamep++;
1485  }
1486  if (domain_list)
1487  {
1488  domainp++;
1489  }
1490  if (src_domain_list)
1491  {
1492  src_domainp++;
1493  }
1494  }
1495 
1496  return q;
1497 }
1498 #endif
1499 
1500 /*
1501  * db_execute_with_values() - This function executes a dynamic sql select query
1502  * with input values
1503  * return : error code
1504  * CSQL_query (IN) : query string to be executed
1505  * result (OUT): pointer to the query result structure
1506  * query_error (OUT): set to the error information, if any.
1507  * arg_count (IN) : number of input values
1508  * vals (IN) : input values
1509  */
1510 int
1511 db_execute_with_values (const char *CSQL_query, DB_QUERY_RESULT ** result, DB_QUERY_ERROR * query_error, int arg_count,
1512  DB_VALUE * vals)
1513 {
1514  int error;
1515  int stmt_no;
1516  DB_SESSION *session = NULL;
1517 
1518  error = db_open_buffer_and_compile_first_statement (CSQL_query, query_error, DB_NO_OIDS, &session, &stmt_no);
1519  if (session == NULL)
1520  {
1521  return error;
1522  }
1523 
1524  if (arg_count > 0)
1525  {
1526  db_push_values (session, arg_count, vals);
1527  }
1528 
1529  if (stmt_no > 0)
1530  {
1531  error = db_execute_statement_local (session, stmt_no, result);
1532  }
1533 
1534  db_close_session_local (session);
1535 
1536  return (error);
1537 }
1538 
1539 /*
1540  * QUERY PRE-PROCESSING ROUTINES
1541  */
1542 
1543 /*
1544  * db_get_query_format() - This function is used to perform syntax and semantic
1545  * checking on a query statement without actually causing query results to
1546  * be generated. The returned type list contains information about each
1547  * column in the resulting query tuples, including the name, data type, and
1548  * size of the values in the column.
1549  * return : error code
1550  * CSQL_query(in): query string
1551  * type_list(out): Set to the query format list
1552  * query_error(out): Set to the error information, if any.
1553  *
1554  * note : The user should call the db_query_format_free() function when
1555  * finished with the format list.
1556  */
1557 int
1558 db_get_query_format (const char *CSQL_query, DB_QUERY_TYPE ** result, DB_QUERY_ERROR * query_error)
1559 {
1560  int error;
1561 
1562  error = db_compile_and_execute_queries_internal (CSQL_query, result, query_error, DB_NO_OIDS, 0, true);
1563 
1564  return (error < 0 ? error : NO_ERROR);
1565 } /* db_get_query_format */
1566 
1567 /*
1568  * db_query_format_next() - This function is used to scan the elements of the
1569  * query type list returned by the db_get_query_format() function.
1570  * return : Pointer to the next type list node, or NULL
1571  * query_type(in): Pointer to the current type list node
1572  *
1573  * note : Do not pass the result of this function to the
1574  * db_query_format_free()function.
1575  */
1576 DB_QUERY_TYPE *
1578 {
1579  CHECK_1ARG_NULL (query_type);
1580  return query_type->next;
1581 }
1582 
1583 /*
1584  * db_query_format_col_type() - This function returns the column type of the
1585  * current query type
1586  * return : column type of the current type list node
1587  * query_type(in): Pointer to the current type list node
1588  */
1591 {
1592  CHECK_1ARG_RETURN_EXPR (query_type, DB_COL_OTHER);
1593  return query_type->col_type;
1594 }
1595 
1596 
1597 /*
1598  * db_query_format_name() - This function is used to get the name of a column
1599  * in a query format descriptor list.
1600  * return : Column name of the current type list node
1601  * query_type(in): Pointer to the current type list node
1602  *
1603  * note : Do not free this string. it is freed with the descriptor in the
1604  * db_query_format_free() function. If the column was derived from a
1605  * constant expression, the column name is similarly derived.
1606  * for example, x + 10.
1607  */
1608 char *
1610 {
1611  CHECK_1ARG_NULL (query_type);
1612  return ((char *) query_type->name);
1613 }
1614 
1615 /*
1616  * db_query_format_attr_name() - This function returns attribute name of the
1617  * current query type list node.
1618  * return : attribute name of the current type list node
1619  * query_type(in): pointer to the current type list node
1620  */
1621 char *
1623 {
1624  CHECK_1ARG_NULL (query_type);
1625  return ((char *) query_type->attr_name);
1626 }
1627 
1628 /*
1629  * db_query_format_spec_name() - This function returns the spec name of the
1630  * current query type list node.
1631  * return : spec name of the current type list node
1632  * query_type(in): Pointer to the current type list node
1633  */
1634 char *
1636 {
1637  CHECK_1ARG_NULL (query_type);
1638  return ((char *) query_type->spec_name);
1639 }
1640 
1641 /*
1642  * db_query_format_original_name() - This function returns user-specfified text
1643  * of the query type list node.
1644  * return : user-specified text of the current type list node
1645  * query_type: Pointer to the current type list node
1646  */
1647 char *
1649 {
1650  CHECK_1ARG_NULL (query_type);
1651  return ((char *) query_type->original_name);
1652 }
1653 
1654 /*
1655  * db_query_format_domain() - This function returns domain information of
1656  * current query type list node.
1657  * return : domain information of the current type list node
1658  * query_type(in): pointer to the current type list node
1659  */
1660 SM_DOMAIN *
1662 {
1663  CHECK_1ARG_NULL (query_type);
1664  return query_type->domain;
1665 }
1666 
1667 /*
1668  * db_query_format_src_domain() - Returns source domain information of current
1669  * query type list node.
1670  * return : source domain information of the current type node
1671  * query_type(in): Pointer to the current type list node
1672  *
1673  */
1674 SM_DOMAIN *
1676 {
1677  CHECK_1ARG_NULL (query_type);
1678  return query_type->src_domain;
1679 }
1680 
1681 /*
1682  * db_query_format_type() - This function is used to get the basic type
1683  * identifier of a column in a query format descriptor list.
1684  * return : basic type id of a column
1685  * query_type(in): Pointer to the current type list node
1686  *
1687  * note : Use the db_query_format_domain() function for non-primitive types.
1688  */
1689 DB_TYPE
1691 {
1692  CHECK_1ARG_RETURN_EXPR (query_type, DB_TYPE_NULL);
1693  return query_type->db_type;
1694 }
1695 
1696 /*
1697  * db_query_format_size() - This function is used to get the data size of a
1698  * column in a query format descriptor list node for fixed types,
1699  * and 0 for variable types.
1700  * return : data size of the current type list node
1701  * query_type(in): Pointer to the current type list node
1702  */
1703 int
1705 {
1706  CHECK_1ARG_MINUSONE (query_type);
1707  return query_type->size;
1708 }
1709 
1710 /*
1711  * db_query_format_free() - This function frees a query format list. You should
1712  * call this function when you are finished with the query format returned
1713  * by the db_get_query_format(), db_get_query_result_format() and
1714  * db_object_describe() functions.
1715  * return : void
1716  * query_type(in): pointer to the beginning of the query type list
1717  *
1718  * note : Make sure to pass the head of the list and not an element in the
1719  * middle of the list. You must use the exact return value. Do not use the
1720  * return value of the db_query_format_next() function.
1721  */
1722 void
1724 {
1725  if (query_type == NULL)
1726  {
1727  return;
1728  }
1729 
1730  db_free_query_format (query_type);
1731 }
1732 
1733 /*
1734  * db_query_format_class_name() - This function returns the name of the class
1735  * which the current type list node belongs to.
1736  * return : name of the class which the current type list node belongs to.
1737  * query_type(in): Pointer to the current type list node
1738  */
1739 const char *
1741 {
1742  SM_DOMAIN *src_domain = NULL;
1743 
1744  CHECK_1ARG_NULL (query_type);
1745 
1746  src_domain = db_query_format_src_domain (query_type);
1747  if (src_domain == NULL)
1748  {
1749  return (const char *) NULL;
1750  }
1751  if (src_domain->class_mop == NULL)
1752  {
1753  return NULL;
1754  }
1755 
1756  return db_get_class_name (src_domain->class_mop);
1757 }
1758 
1759 /*
1760  * db_query_format_is_non_null() - This function returns the nullability of
1761  * current type list node.
1762  * return : nullability of current type list node
1763  * query_type(in): Pointer to the current type list node
1764  */
1765 int
1767 {
1768  SM_DOMAIN *src_domain = NULL;
1769  DB_ATTRIBUTE *attr = NULL;
1770 
1772 
1773  src_domain = db_query_format_src_domain (query_type);
1774  if (src_domain && src_domain->class_mop && query_type->attr_name)
1775  {
1776  attr = db_get_attribute (src_domain->class_mop, query_type->attr_name);
1777  if (attr)
1778  {
1779  return db_attribute_is_non_null (attr);
1780  }
1781  }
1782 
1783  /*
1784  * query_type is not an attribute.
1785  * It may be an expression and will be treated as nullable.
1786  */
1787  return 0;
1788 }
1789 
1790 /*
1791  * QUERY PROCESSING ROUTINES
1792  */
1793 
1794 /*
1795  * db_query_execute() - This function executes the given query and set query
1796  * result. The query result structure contains a LIST FILE identifier which
1797  * identifies the file on the server side that contains the query result as
1798  * a set of tuples, and also a cursor identifier which is used to scan
1799  * through this set of tuples in the query result.
1800  * return : error code.
1801  * CSQL_query(in): CSQL query string to be executed
1802  * result(out): Pointer to the query result structure
1803  * query_error(out): Set to the error information, if any.
1804  *
1805  * note : result must be deallocated with db_query_end() function.
1806  */
1807 int
1808 db_query_execute (const char *CSQL_query, DB_QUERY_RESULT ** result, DB_QUERY_ERROR * query_error)
1809 {
1810  int error;
1811 
1812  error = db_compile_and_execute_queries_internal (CSQL_query, result, query_error, DB_NO_OIDS, 1, true);
1813 
1814  return (error < 0 ? error : NO_ERROR);
1815 }
1816 
1817 /*
1818  * db_execute() - This function is used to evaluate the CSQL_query statement(s)
1819  * given in the string. The result descriptor is used with the cursor
1820  * functions to access the individual tuple values. The return value is the
1821  * row count (the number of rows) returned from the last statement executed.
1822  * return : integer, negative implies error.
1823  * Positive is the count of qualified rows
1824  * CSQL_query(in): query string to be executed
1825  * result(out): Pointer to the query result structure
1826  * query_error(out): Set to the error information, if any.
1827  *
1828  * note : The DB_QUERY_RESULT structure obtained from db_execute(is invalidated
1829  * at transaction boundaries (i.e., whenever db_commit_transaction()or
1830  * db_abort_transaction() is executed).
1831  * These structures should be closed with db_query_end()before committing or
1832  * aborting the transaction. Any attempt to use such a structure after the
1833  * end of the transaction in which it was created will result in an error.
1834  */
1835 int
1836 db_execute (const char *CSQL_query, DB_QUERY_RESULT ** result, DB_QUERY_ERROR * query_error)
1837 {
1838  int retval;
1839 
1840  retval = db_compile_and_execute_queries_internal (CSQL_query, result, query_error, DB_NO_OIDS, 1, true);
1841  return (retval);
1842 }
1843 
1844 /*
1845  * db_execute_oid() -
1846  * return :
1847  * CSQL_query(in):
1848  * result(out):
1849  * query_error(out):
1850  */
1851 int
1852 db_execute_oid (const char *CSQL_query, DB_QUERY_RESULT ** result, DB_QUERY_ERROR * query_error)
1853 {
1854  int retval;
1855 
1856  retval = db_compile_and_execute_queries_internal (CSQL_query, result, query_error, DB_ROW_OIDS, 1, true);
1857 
1858  return (retval);
1859 }
1860 
1861 #if defined(WINDOWS) || defined (ENABLE_UNUSED_FUNCTION)
1862 /*
1863  * db_query_execute_immediate() -
1864  * return :
1865  * CSQL_query(in):
1866  * result(out):
1867  * query_error(out):
1868  */
1869 int
1870 db_query_execute_immediate (const char *CSQL_query, DB_QUERY_RESULT ** result, DB_QUERY_ERROR * query_error)
1871 {
1872  int r;
1873 
1874 #if defined(CUBRID_DEBUG)
1875  fprintf (stdout, "db_query_execute_immediate is a deprecated function.\n");
1876  fprintf (stdout, "use the equivalent function db_execute.\n");
1877 #endif
1878 
1879  r = db_compile_and_execute_queries_internal (CSQL_query, result, query_error, DB_NO_OIDS, 1, true);
1880 
1881  return r;
1882 }
1883 
1884 /*
1885  * db_get_objfetch_query_result() - This function forms an query result
1886  * structure from the given list of values, list of column sizes and
1887  * column names. The query result structure for an object_fetch, is
1888  * treated exactly as a list file of one tuple.
1889  * return : DB_QUERY_RESULT*
1890  * val_list(in): List of values
1891  * val_cnt(in): Number of values
1892  * size_list(out): List of column sizes
1893  * colname_list(out): List of column names
1894  * attrname_list(out): List of attribute names
1895  */
1897 db_get_objfetch_query_result (DB_VALUE * val_list, int val_cnt, int *size_list, char **colname_list,
1898  char **attrname_list)
1899 {
1900  DB_QUERY_RESULT *r;
1901  DB_QUERY_TYPE *typep;
1902  DB_VALUE *valp, **ovalp;
1903  int k;
1904  int *sizep;
1905  char **namep;
1906  char **attr_namep;
1907  size_t str_size;
1908 
1909  CHECK_CONNECT_NULL ();
1910  CHECK_1ARG_NULL (val_list);
1911 
1912  r = db_alloc_query_result (T_OBJFETCH, val_cnt);
1913  if (r == NULL)
1914  {
1915  return NULL;
1916  }
1918  r->type = T_OBJFETCH;
1919  r->col_cnt = val_cnt;
1920  r->oid_included = false;
1921 
1922  /* allocate and initialize type list */
1923  r->type_cnt = val_cnt;
1924  r->query_type = db_alloc_query_format (val_cnt);
1925  if (r->query_type == NULL)
1926  {
1928  return NULL;
1929  }
1930  if (val_cnt > 0)
1931  {
1932  for (k = 0, typep = r->query_type, valp = val_list, sizep = size_list, namep = colname_list, attr_namep =
1933  attrname_list; k < val_cnt; k++, typep = typep->next, valp++, sizep++)
1934  {
1935  typep->db_type = DB_VALUE_TYPE (valp);
1936  typep->size = *sizep;
1937  typep->name = (char *) NULL;
1938  typep->attr_name = (char *) NULL;
1939  typep->spec_name = (char *) NULL;
1940  typep->original_name = (char *) NULL;
1941  typep->domain = (SM_DOMAIN *) NULL;
1942  typep->src_domain = (SM_DOMAIN *) NULL;
1943  if (colname_list != NULL)
1944  {
1945  /* column names can NOT be NULL */
1946  str_size = strlen (*namep) + 1;
1947  typep->name = (char *) malloc (str_size);
1948  if (typep->name == NULL)
1949  {
1952  return NULL;
1953  }
1954  memcpy ((char *) typep->name, *namep, str_size);
1955  namep++;
1956  }
1957  if (attrname_list != NULL)
1958  {
1959  /* attribute names can be NULL */
1960  if (*attr_namep)
1961  {
1962  str_size = strlen (*attr_namep) + 1;
1963  typep->attr_name = (char *) malloc (str_size);
1964  if (typep->attr_name == NULL)
1965  {
1968  return NULL;
1969  }
1970  memcpy ((char *) typep->attr_name, *attr_namep, str_size);
1971  }
1972  attr_namep++;
1973  }
1974  }
1975  }
1976  r->res.o.crs_pos = C_BEFORE;
1977  for (k = 0, ovalp = r->res.o.valptr_list, valp = val_list; k < r->col_cnt; k++, ovalp++, valp++)
1978  {
1979  *ovalp = db_value_copy (valp);
1980  if ((*ovalp) == NULL)
1981  {
1983  return NULL;
1984  }
1985  }
1986  return r;
1987 }
1988 #endif
1989 
1990 /*
1991  * db_get_db_value_query_result() - This function forms a query result
1992  * structure from the given db_value. The query result structure for the
1993  * db_value is treated exactly like a list file of one_tuple, one_column.
1994  * return : DB_QUERY_RESULT*
1995  * val(in): Single Value
1996  */
1999 {
2000  DB_QUERY_RESULT *r;
2001 
2002  CHECK_CONNECT_NULL ();
2003  CHECK_1ARG_NULL (val);
2004 
2005  r = db_alloc_query_result (T_CALL, 1);
2006  if (r == NULL)
2007  {
2008  return NULL;
2009  }
2010 
2012  r->type = T_CALL;
2013  r->col_cnt = 1;
2014  r->oid_included = false;
2015 
2016  /* allocate and initialize type list */
2017  r->type_cnt = 1;
2019  if (r->query_type == NULL)
2020  {
2022  return NULL;
2023  } /* if */
2024  r->query_type->db_type = DB_VALUE_TYPE (val);
2025  r->query_type->name = (char *) NULL;
2026  r->query_type->attr_name = (char *) NULL;
2027  r->query_type->spec_name = (char *) NULL;
2028  r->query_type->original_name = (char *) NULL;
2029  r->query_type->domain = (SM_DOMAIN *) NULL;
2030  r->query_type->src_domain = (SM_DOMAIN *) NULL;
2031  r->query_type->size = 0;
2032 
2033  r->res.c.crs_pos = C_BEFORE;
2034  r->res.c.val_ptr = db_value_copy (val);
2035  if (r->res.c.val_ptr == NULL)
2036  {
2038  return NULL;
2039  }
2040 
2041  return r;
2042 }
2043 
2044 /*
2045  * db_get_query_result_format() - The query format list of the given query
2046  * result is returned.
2047  * return : error code
2048  * result(in): Pointer to the query result structure
2049  * type_list(out): Set to the query format list
2050  *
2051  * note : The caller should call db_query_format_free routine to
2052  * deallocate the allocated type list region.
2053  */
2054 int
2056 {
2057  int retval;
2058 
2060  *type_list = NULL;
2061 
2062  CHECK_1ARG_ERROR (result);
2063  if (result->status == T_CLOSED)
2064  {
2067  }
2068 
2069  *type_list = db_cp_query_type (result->query_type, true);
2070  if (*type_list == NULL)
2071  {
2072  assert (er_errid () != NO_ERROR);
2073  retval = er_errid ();
2074  return (retval);
2075  }
2076 
2077  return NO_ERROR;
2078 }
2079 
2080 /*
2081  * db_query_next_tuple() - This function makes the next tuple in the LIST FILE
2082  * referred by the query result structure the current active tuple of the
2083  * query result cursor and returns DB_CURSOR_SUCCESS.
2084  * return : error code or cursor
2085  * result(in/out): Pointer to the query result structure
2086  */
2087 int
2089 {
2090  int retval;
2091  CURSOR_POSITION *c_pos;
2092 
2094  CHECK_1ARG_ERROR (result);
2095 
2096  if (result->status == T_CLOSED)
2097  {
2100  }
2101 
2102  switch (result->type)
2103  {
2104  case T_SELECT:
2105  retval = cursor_next_tuple (&result->res.s.cursor_id);
2106  break;
2107 
2108  case T_CALL:
2109  case T_OBJFETCH:
2110  {
2111  c_pos = ((result->type == T_CALL)
2112  ? (CURSOR_POSITION *) (&result->res.c.crs_pos) : (CURSOR_POSITION *) (&result->res.o.crs_pos));
2113  switch (*c_pos)
2114  {
2115  case C_BEFORE:
2116  *c_pos = C_ON;
2117  retval = DB_CURSOR_SUCCESS;
2118  break;
2119  case C_ON:
2120  case C_AFTER:
2121  *c_pos = C_AFTER;
2122  retval = DB_CURSOR_END;
2123  break;
2124  default:
2125  retval = ER_QPROC_UNKNOWN_CRSPOS;
2127  break;
2128  }
2129  }
2130  break;
2131 
2132 #if defined (ENABLE_UNUSED_FUNCTION)
2133  case T_GET:
2134  {
2135  c_pos = &result->res.g.crs_pos;
2136 
2137  if (result->res.g.n_tuple == 0)
2138  {
2139  *c_pos = C_AFTER;
2140  retval = DB_CURSOR_END;
2141  }
2142  else
2143  {
2144  switch (*c_pos)
2145  {
2146  case C_BEFORE:
2147  {
2148  result->res.g.tpl_idx = 0;
2149  *c_pos = C_ON;
2150  retval = DB_CURSOR_SUCCESS;
2151  }
2152  break;
2153  case C_ON:
2154  {
2155  result->res.g.tpl_idx += result->col_cnt;
2156  if (result->res.g.tpl_idx >= (result->res.g.n_tuple * result->col_cnt))
2157  {
2158  *c_pos = C_AFTER;
2159  retval = DB_CURSOR_END;
2160  break;
2161  }
2162  retval = DB_CURSOR_SUCCESS;
2163  }
2164  break;
2165  case C_AFTER:
2166  retval = DB_CURSOR_END;
2167  break;
2168  default:
2169  retval = ER_QPROC_UNKNOWN_CRSPOS;
2171  break;
2172  }
2173  }
2174  }
2175  break;
2176 #endif
2177  default:
2178  {
2179  retval = ER_QPROC_INVALID_RESTYPE;
2181  }
2182  break;
2183  }
2184 
2185  return (retval);
2186 }
2187 
2188 /*
2189  * db_query_prev_tuple() - This function makes the previous tuple in the LIST
2190  * FILE referred by query result structure the current active tuple of the
2191  * query result cursor and returns DB_CURSOR_SUCCESS.
2192  * return : error code or cursor
2193  * result(in/out): Pointer to the query result structure
2194  */
2195 int
2197 {
2198  int retval;
2199  CURSOR_POSITION *c_pos;
2200 
2202 
2203  CHECK_1ARG_ERROR (result);
2204 
2205  if (result->status == T_CLOSED)
2206  {
2209  }
2210 
2211  switch (result->type)
2212  {
2213  case T_SELECT:
2214  retval = cursor_prev_tuple (&result->res.s.cursor_id);
2215  break;
2216 
2217  case T_CALL:
2218  case T_OBJFETCH:
2219  {
2220  c_pos = ((result->type == T_CALL)
2221  ? (CURSOR_POSITION *) (&result->res.c.crs_pos) : (CURSOR_POSITION *) (&result->res.o.crs_pos));
2222  switch (*c_pos)
2223  {
2224  case C_BEFORE:
2225  case C_ON:
2226  {
2227  *c_pos = C_BEFORE;
2228  retval = DB_CURSOR_END;
2229  }
2230  break;
2231 
2232  case C_AFTER:
2233  {
2234  *c_pos = C_ON;
2235  retval = DB_CURSOR_SUCCESS;
2236  }
2237  break;
2238 
2239  default:
2240  retval = ER_QPROC_UNKNOWN_CRSPOS;
2242  break;
2243  }
2244  }
2245  break;
2246 
2247 #if defined (ENABLE_UNUSED_FUNCTION)
2248  case T_GET:
2249  {
2250  c_pos = &result->res.g.crs_pos;
2251  if (result->res.g.n_tuple == 0)
2252  {
2253  *c_pos = C_BEFORE;
2254  retval = DB_CURSOR_END;
2255  break;
2256  }
2257  else
2258  {
2259  switch (*c_pos)
2260  {
2261  case C_BEFORE:
2262  retval = DB_CURSOR_SUCCESS;
2263  break;
2264  case C_ON:
2265  {
2266  result->res.g.tpl_idx -= result->col_cnt;
2267  if (result->res.g.tpl_idx < 0)
2268  {
2269  *c_pos = C_BEFORE;
2270  retval = DB_CURSOR_END;
2271  break;
2272  }
2273  retval = DB_CURSOR_SUCCESS;
2274  }
2275  break;
2276  case C_AFTER:
2277  {
2278  result->res.g.tpl_idx = (result->res.g.n_tuple - 1) * result->col_cnt;
2279  *c_pos = C_ON;
2280  retval = DB_CURSOR_SUCCESS;
2281  }
2282  break;
2283  default:
2284  retval = ER_QPROC_UNKNOWN_CRSPOS;
2286  break;
2287  }
2288  }
2289  }
2290  break;
2291 #endif
2292  default:
2293  retval = ER_QPROC_INVALID_RESTYPE;
2295  break;
2296  }
2297 
2298  return (retval);
2299 }
2300 
2301 /*
2302  * db_query_first_tuple() - This function makes the first tuple in the LIST
2303  * FILE referred by the query result structure the current active tuple
2304  * of the query result cursor and DB_CURSOR_SUCCESS.
2305  * return : error code or cursor
2306  * result(in/out): Pointer to the query result structure
2307  */
2308 int
2310 {
2311  int retval;
2313 
2314  CHECK_1ARG_ERROR (result);
2315 
2316  if (result->status == T_CLOSED)
2317  {
2320  }
2321 
2322  switch (result->type)
2323  {
2324  case T_SELECT:
2325  retval = cursor_first_tuple (&result->res.s.cursor_id);
2326  break;
2327 
2328  case T_CALL:
2329  {
2330  result->res.c.crs_pos = C_ON;
2331  retval = DB_CURSOR_SUCCESS;
2332  }
2333  break;
2334 
2335  case T_OBJFETCH:
2336  {
2337  result->res.o.crs_pos = C_ON;
2338  retval = DB_CURSOR_SUCCESS;
2339  }
2340  break;
2341 
2342 #if defined (ENABLE_UNUSED_FUNCTION)
2343  case T_GET:
2344  if (result->res.g.n_tuple == 0)
2345  {
2346  retval = DB_CURSOR_END;
2347  }
2348  else
2349  {
2350  result->res.g.tpl_idx = 0;
2351  result->res.g.crs_pos = C_ON;
2352  retval = DB_CURSOR_SUCCESS;
2353  }
2354  break;
2355 #endif
2356  default:
2357  {
2358  retval = ER_QPROC_INVALID_RESTYPE;
2360  }
2361  break;
2362  }
2363 
2364  return (retval);
2365 }
2366 
2367 /*
2368  * db_query_last_tuple() - This function is used to position the cursor
2369  * directly to the last tuple within the query result.
2370  * return : error code or cursor
2371  * result(in/out): Pointer to the query result structure
2372  */
2373 int
2375 {
2376  int retval;
2378 
2379  CHECK_1ARG_ERROR (result);
2380 
2381  if (result->status == T_CLOSED)
2382  {
2385  }
2386 
2387  switch (result->type)
2388  {
2389  case T_SELECT:
2390  retval = cursor_last_tuple (&result->res.s.cursor_id);
2391  break;
2392 
2393  case T_CALL:
2394  {
2395  result->res.c.crs_pos = C_ON;
2396  retval = DB_CURSOR_SUCCESS;
2397  }
2398  break;
2399 
2400  case T_OBJFETCH:
2401  {
2402  result->res.o.crs_pos = C_ON;
2403  retval = DB_CURSOR_SUCCESS;
2404  }
2405  break;
2406 
2407 #if defined (ENABLE_UNUSED_FUNCTION)
2408  case T_GET:
2409  if (result->res.g.n_tuple == 0)
2410  {
2411  retval = DB_CURSOR_END;
2412  }
2413  else
2414  {
2415  result->res.g.crs_pos = C_ON;
2416  result->res.g.tpl_idx = (result->res.g.n_tuple - 1) * result->col_cnt;
2417  retval = DB_CURSOR_SUCCESS;
2418  }
2419  break;
2420 #endif
2421  default:
2422  retval = ER_QPROC_INVALID_RESTYPE;
2424  break;
2425  }
2426 
2427  return (retval);
2428 }
2429 
2430 /*
2431  * db_query_seek_tuple() - This function set the cursor to a specific tuple
2432  * according to value of the offset and seek_mode. Seek mode can only take
2433  * DB_CURSOR_SEEK_SET, DB_CURSOR_SEEK_CUR, DB_CURSOR_SEEK_END values.
2434  * If offset value is n and seek_mode value is:
2435  * DB_CURSOR_SEEK_SET: The cursor is set to the nth tuple from
2436  * the beginning. (absolute access)
2437  * DB_CORSOR_SEEK_CUR: The cursor is set to its current position
2438  * _plus_ n. (relative access)
2439  * DB_CURSOR_SEEK_END: The cursor is set to the last tuple
2440  * position _plus_ n. (relative access)
2441  *
2442  * return : On success, the function returns DB_CURSOR_SUCCESS.
2443  *
2444  * On end_of_scan, the cursor position is changed, the function
2445  * returns DB_CURSOR_END.
2446  *
2447  * On failure, the cursor position remains unchanged the function
2448  * returns corresponding error code.
2449  *
2450  * result(in/out): Query result structure
2451  * offset(in): Offset tuple count
2452  * seek_mode(in): Tuple seek mode
2453  */
2454 int
2455 db_query_seek_tuple (DB_QUERY_RESULT * result, int offset, int seek_mode)
2456 {
2457  int scan;
2458  int rel1, rel2, rel3, rel_n;
2459  int curr_tplno, tpl_cnt;
2460  DB_QUERY_TPLPOS *tplpos;
2461  CURSOR_POSITION *c_pos;
2462 
2464  CHECK_1ARG_ERROR (result);
2465 
2466  if (result->status == T_CLOSED)
2467  {
2470  }
2471 
2472  switch (result->type)
2473  {
2474  case T_SELECT:
2475  {
2476  tplpos = db_query_get_tplpos (result);
2477  if (tplpos == NULL)
2478  {
2479  assert (er_errid () != NO_ERROR);
2480  return er_errid ();
2481  }
2482 
2483  /* find the optimal relative position for the scan: relative to the beginning, current tuple position or end. */
2484  curr_tplno = result->res.s.cursor_id.tuple_no;
2485  tpl_cnt = result->res.s.cursor_id.list_id.tuple_cnt;
2486  switch (seek_mode)
2487  {
2488  case DB_CURSOR_SEEK_SET:
2489  {
2490  rel1 = offset; /* relative to beginning */
2491  rel2 = offset - curr_tplno; /* relative to current tuple */
2492  rel3 = offset - (tpl_cnt - 1); /* relative to end */
2493  }
2494  break;
2495 
2496  case DB_CURSOR_SEEK_CUR:
2497  {
2498  rel1 = curr_tplno + offset;
2499  rel2 = offset;
2500  rel3 = (curr_tplno + offset) - (tpl_cnt - 1);
2501  }
2502  break;
2503 
2504  case DB_CURSOR_SEEK_END:
2505  {
2506  rel1 = (tpl_cnt - 1) + offset;
2507  rel2 = (tpl_cnt - 1) + offset - curr_tplno;
2508  rel3 = offset;
2509  }
2510  break;
2511 
2512  default:
2513  {
2514  db_query_set_tplpos (result, tplpos);
2515  db_query_free_tplpos (tplpos);
2517  }
2518  return ER_GENERIC_ERROR;
2519  }
2520 
2521  if (abs (rel1) < abs (rel2) && abs (rel1) < abs (rel3))
2522  {
2523  /* move relative to the beginning */
2524  scan = db_query_first_tuple (result);
2525  if (scan != DB_CURSOR_SUCCESS)
2526  {
2527  if (scan != DB_CURSOR_END)
2528  {
2529  db_query_set_tplpos (result, tplpos);
2530  }
2531  db_query_free_tplpos (tplpos);
2532  if (scan != DB_CURSOR_END)
2533  {
2534  assert (er_errid () != NO_ERROR);
2535  return er_errid ();
2536  }
2537  else
2538  {
2539  return scan;
2540  }
2541  }
2542  rel_n = rel1;
2543  }
2544  else if (abs (rel3) < abs (rel2))
2545  {
2546  /* move relative to the last */
2547  scan = db_query_last_tuple (result);
2548  if (scan != DB_CURSOR_SUCCESS)
2549  {
2550  if (scan != DB_CURSOR_END)
2551  {
2552  db_query_set_tplpos (result, tplpos);
2553  }
2554  db_query_free_tplpos (tplpos);
2555  if (scan != DB_CURSOR_END)
2556  {
2557  assert (er_errid () != NO_ERROR);
2558  return er_errid ();
2559  }
2560  else
2561  {
2562  return scan;
2563  }
2564  }
2565  rel_n = rel3;
2566  }
2567  else
2568  {
2569  /* move relative to the current tuple */
2570  rel_n = rel2;
2571  }
2572 
2573  /* perform the actual scan operation in a relative manner */
2574  if (rel_n > 0)
2575  {
2576  while (rel_n--)
2577  {
2578  scan = db_query_next_tuple (result);
2579  if (scan != DB_CURSOR_SUCCESS)
2580  {
2581  if (scan != DB_CURSOR_END)
2582  {
2583  db_query_set_tplpos (result, tplpos);
2584  }
2585  db_query_free_tplpos (tplpos);
2586  if (scan != DB_CURSOR_END)
2587  {
2588  assert (er_errid () != NO_ERROR);
2589  return er_errid ();
2590  }
2591  else
2592  {
2593  return scan;
2594  }
2595  }
2596  }
2597  }
2598  else
2599  {
2600  while (rel_n++)
2601  {
2602  scan = db_query_prev_tuple (result);
2603  if (scan != DB_CURSOR_SUCCESS)
2604  {
2605  if (scan != DB_CURSOR_END)
2606  {
2607  db_query_set_tplpos (result, tplpos);
2608  }
2609  db_query_free_tplpos (tplpos);
2610  if (scan != DB_CURSOR_END)
2611  {
2612  assert (er_errid () != NO_ERROR);
2613  return er_errid ();
2614  }
2615  else
2616  {
2617  return scan;
2618  }
2619  }
2620  }
2621  }
2622  db_query_free_tplpos (tplpos);
2623  }
2624  break;
2625 
2626  case T_CALL:
2627  case T_OBJFETCH:
2628  switch (seek_mode)
2629  {
2630  case DB_CURSOR_SEEK_SET:
2631  case DB_CURSOR_SEEK_END:
2632  c_pos = ((result->type == T_CALL)
2633  ? (CURSOR_POSITION *) (&result->res.c.crs_pos) : (CURSOR_POSITION *) (&result->res.o.crs_pos));
2634  if (offset == 0)
2635  {
2636  *c_pos = C_ON;
2637  return DB_CURSOR_SUCCESS;
2638  }
2639  else if (offset > 0)
2640  {
2641  *c_pos = C_AFTER;
2642  return DB_CURSOR_END;
2643  }
2644  else
2645  {
2646  *c_pos = C_BEFORE;
2647  return DB_CURSOR_END;
2648  }
2649 
2650  case DB_CURSOR_SEEK_CUR:
2651  if (offset > 0)
2652  {
2653  return db_query_next_tuple (result);
2654  }
2655  else if (offset < 0)
2656  {
2657  return db_query_prev_tuple (result);
2658  }
2659  else
2660  {
2661  return DB_CURSOR_SUCCESS;
2662  }
2663 
2664  default:
2666  return ER_GENERIC_ERROR;
2667  }
2668 
2669 #if defined (ENABLE_UNUSED_FUNCTION)
2670  case T_GET:
2671  {
2672  int col_cnt, tpl_idx, n_tuple, index = 0;
2673 
2674  col_cnt = result->col_cnt;
2675  tpl_idx = result->res.g.tpl_idx;
2676  n_tuple = result->res.g.n_tuple;
2677 
2678  if (n_tuple == 0)
2679  {
2680  return DB_CURSOR_END;
2681  }
2682  else
2683  {
2684  switch (seek_mode)
2685  {
2686  case DB_CURSOR_SEEK_SET:
2687  index = offset * col_cnt;
2688  break;
2689  case DB_CURSOR_SEEK_CUR:
2690  index = tpl_idx + (offset * col_cnt);
2691  break;
2692  case DB_CURSOR_SEEK_END:
2693  index = ((n_tuple - 1) + offset) * col_cnt;
2694  break;
2695  }
2696 
2697  if (index < 0)
2698  {
2699  result->res.g.crs_pos = C_BEFORE;
2700  return DB_CURSOR_END;
2701  }
2702  else if (index >= (n_tuple * col_cnt))
2703  {
2704  result->res.g.crs_pos = C_AFTER;
2705  return DB_CURSOR_END;
2706  }
2707  else
2708  {
2709  result->res.g.tpl_idx = index;
2710  result->res.g.crs_pos = C_ON;
2711  return DB_CURSOR_SUCCESS;
2712  }
2713  }
2714  }
2715  break;
2716 #endif
2717  default:
2719  return ER_QPROC_INVALID_RESTYPE;
2720  }
2721 
2722  return DB_CURSOR_SUCCESS;
2723 }
2724 
2725 /*
2726  * db_query_get_tplpos() - This function returns the current tuple position
2727  * information.
2728  * return : DB_QUERY_TPLPOS*, or NULL
2729  * result(in): Query result structure
2730  *
2731  * note: Even though. db_query_seek_tuple() routine can be used to position
2732  * the cursor to a specific tuple, the combination of
2733  * db_query_get_tplpos() and db_query_set_tplpos() provides a much
2734  * faster way of accessing a specific tuple.
2735  */
2738 {
2739  DB_QUERY_TPLPOS *tplpos;
2740 
2741  CHECK_CONNECT_NULL ();
2742 
2743  CHECK_1ARG_NULL (result);
2744 
2745  if (result->status == T_CLOSED)
2746  {
2748  return NULL;
2749  }
2750 
2751  tplpos = (DB_QUERY_TPLPOS *) malloc (DB_SIZEOF (DB_QUERY_TPLPOS));
2752  if (tplpos == NULL)
2753  {
2755  return NULL;
2756  }
2757 
2758  switch (result->type)
2759  {
2760  case T_SELECT:
2761  tplpos->crs_pos = result->res.s.cursor_id.position;
2762  tplpos->vpid.pageid = result->res.s.cursor_id.current_vpid.pageid;
2763  tplpos->vpid.volid = result->res.s.cursor_id.current_vpid.volid;
2764  tplpos->tpl_no = result->res.s.cursor_id.current_tuple_no;
2765  tplpos->tpl_off = result->res.s.cursor_id.current_tuple_offset;
2766  break;
2767 
2768  case T_CALL:
2769  tplpos->crs_pos = result->res.c.crs_pos;
2770  break;
2771 
2772  case T_OBJFETCH:
2773  tplpos->crs_pos = result->res.o.crs_pos;
2774  break;
2775 
2776 #if defined (ENABLE_UNUSED_FUNCTION)
2777  case T_GET:
2778  tplpos->crs_pos = result->res.g.crs_pos;
2779  tplpos->tpl_off = result->res.g.tpl_idx / result->col_cnt;
2780  tplpos->tpl_no = result->res.g.n_tuple;
2781  break;
2782 #endif
2783  default:
2784  free_and_init (tplpos);
2786  return NULL;
2787  }
2788 
2789  return tplpos;
2790 }
2791 
2792 /*
2793  * db_query_set_tplpos() - This function set cursor to point to the indicated
2794  * tuple position.
2795  * return : error code
2796  * result(in): query result structure
2797  * tplpos(out): tuple position information
2798  */
2799 int
2801 {
2802  CHECK_1ARG_ERROR (result);
2803 
2804  if (result->status == T_CLOSED)
2805  {
2808  }
2809 
2810  switch (result->type)
2811  {
2812  case T_SELECT:
2813  /* reset cursor identifier */
2814  if (result->res.s.cursor_id.current_vpid.pageid != tplpos->vpid.pageid
2815  || result->res.s.cursor_id.current_vpid.volid != tplpos->vpid.volid)
2816  {
2817  /* needs to get another page */
2818  if (cursor_fetch_page_having_tuple (&result->res.s.cursor_id, &tplpos->vpid, tplpos->tpl_no, tplpos->tpl_off)
2819  != NO_ERROR)
2820  {
2821  return ER_FAILED;
2822  }
2823  result->res.s.cursor_id.current_vpid = tplpos->vpid;
2824  }
2825  result->res.s.cursor_id.position = tplpos->crs_pos;
2826  break;
2827 
2828  case T_CALL:
2829  result->res.c.crs_pos = tplpos->crs_pos;
2830  break;
2831 
2832  case T_OBJFETCH:
2833  result->res.o.crs_pos = tplpos->crs_pos;
2834  break;
2835 
2836 #if defined (ENABLE_UNUSED_FUNCTION)
2837  case T_GET:
2838  result->res.g.crs_pos = tplpos->crs_pos;
2839  result->res.g.tpl_idx = tplpos->tpl_off * result->col_cnt;
2840  result->res.g.n_tuple = tplpos->tpl_no;
2841  break;
2842 #endif
2843  default:
2845  return ER_QPROC_INVALID_RESTYPE;
2846  }
2847 
2848  return NO_ERROR;
2849 }
2850 
2851 /*
2852  * db_query_free_tplpos() - This function frees the area pointed by the tplpos
2853  * pointer.
2854  * return : void
2855  * tplpos(in): Tuple position information
2856  */
2857 void
2859 {
2860  free_and_init (tplpos);
2861 }
2862 
2863 /*
2864  * db_query_get_tuple_value() - This function is used to get the value for a
2865  * column in the current tuple of a query result. The current tuple is
2866  * specified by using the cursor control functions.
2867  * return : error code
2868  * result: pointer to the query result structure
2869  * index(in): position of the tuple value of interest (0 for the first one)
2870  * value(out): value container for column value
2871  */
2872 int
2874 {
2875  int retval;
2876  DB_VALUE *valp;
2877 #if defined (ENABLE_UNUSED_FUNCTION)
2878  int current;
2879 #endif
2880 
2882 
2883  CHECK_2ARGS_ERROR (result, value);
2884 
2885  if (result->status == T_CLOSED)
2886  {
2889  }
2890 
2891  switch (result->type)
2892  {
2893  case T_SELECT:
2894  if (DB_INVALID_INDEX (DB_OID_INCLUDED (result) ? index + 1 : index, result->col_cnt))
2895  {
2897  DB_OID_INCLUDED (result) ? index + 1 : index);
2899  }
2900 
2901  retval = cursor_get_tuple_value (&result->res.s.cursor_id, index, value);
2902  break;
2903 
2904  case T_OBJFETCH:
2905  if (DB_OID_INCLUDED (result))
2906  {
2907  index++;
2908  }
2909  if (DB_INVALID_INDEX (index, result->col_cnt))
2910  {
2913  }
2914  valp = result->res.o.valptr_list[index];
2915  pr_clone_value (valp, value);
2916  retval = NO_ERROR;
2917  break;
2918 
2919  case T_CALL:
2920  valp = result->res.c.val_ptr;
2921  pr_clone_value (valp, value);
2922  retval = NO_ERROR;
2923  break;
2924 
2925 #if defined (ENABLE_UNUSED_FUNCTION)
2926  case T_GET:
2927  if (DB_INVALID_INDEX (index, result->col_cnt))
2928  {
2931  break;
2932  }
2933  current = result->res.g.tpl_idx;
2934  valp = &result->res.g.tpl_list[current + index];
2935  pr_clone_value (valp, value);
2936  retval = NO_ERROR;
2937  break;
2938 #endif
2939  default:
2940  retval = ER_QPROC_INVALID_RESTYPE;
2942  break;
2943  }
2944 
2945  return (retval);
2946 }
2947 
2948 /*
2949  * db_query_get_tuple_value_by_name() - This function is used to get the value
2950  * for a column in the current tuple of a query result. The current tuple is
2951  * specified using the cursor control functions. In this function, the
2952  * desired column is specified by name.
2953  * return : error code
2954  * result(in): pointer to the query result structure
2955  * column_name(in): name of the desired column
2956  * value(out): value container for column value
2957  */
2958 int
2959 db_query_get_tuple_value_by_name (DB_QUERY_RESULT * result, char *column_name, DB_VALUE * value)
2960 {
2961  int retval;
2962  DB_QUERY_TYPE *typep;
2963  int ind;
2964 
2966  CHECK_3ARGS_ERROR (result, column_name, value);
2967 
2968  if (result->status == T_CLOSED)
2969  {
2972  }
2973 
2974  switch (result->type)
2975  {
2976  case T_SELECT:
2977  case T_OBJFETCH:
2978  case T_GET:
2979  typep = result->query_type;
2980  for (ind = 0; typep; ind++, typep = typep ? typep->next : NULL)
2981  {
2982  if (!ansisql_strcasecmp (column_name, typep->name))
2983  {
2984  break;
2985  }
2986  else if (typep->original_name)
2987  { /* retry with original name */
2988  if (!ansisql_strcasecmp (column_name, typep->original_name))
2989  {
2990  break;
2991  }
2992  }
2993  }
2994 
2995  if (typep == NULL)
2996  {
2998  return ER_QPROC_INVALID_COLNAME;
2999  }
3000  retval = db_query_get_tuple_value (result, ind, value);
3001  break;
3002 
3003  case T_CALL:
3004  default:
3006  return ER_QPROC_INVALID_RESTYPE;
3007  break;
3008  }
3009 
3010  return (retval);
3011 }
3012 
3013 /*
3014  * db_query_get_tuple_valuelist() - This function can be used to get all of the
3015  * column values for the current tuple of a query result. The current tuple
3016  * is specified using the cursor control functions. The values for the
3017  * columns up to the number specified by the size argument are copied into
3018  * the value array.
3019  * return : error code.
3020  * result(in): Pointer to the query result structure
3021  * size(in): Number of values in the value list
3022  * value_list(out): an array of DB_VALUE structures
3023  */
3024 int
3025 db_query_get_tuple_valuelist (DB_QUERY_RESULT * result, int size, DB_VALUE * value_list)
3026 {
3027  int retval;
3028  DB_VALUE *valp;
3029  int k;
3030 
3032 
3033  CHECK_2ARGS_ERROR (result, value_list);
3034 
3035  if (result->status == T_CLOSED)
3036  {
3039  }
3040 
3041  switch (result->type)
3042  {
3043  case T_SELECT:
3044  if (DB_INVALID_INDEX (DB_OID_INCLUDED (result) ? size : size - 1, result->col_cnt))
3045  {
3047  DB_OID_INCLUDED (result) ? size : size - 1);
3049  }
3050 
3051  retval = cursor_get_tuple_value_list (&result->res.s.cursor_id, size, value_list);
3052  break;
3053 
3054  case T_CALL:
3055  retval = db_query_get_tuple_value (result, 0, value_list);
3056  break;
3057 
3058  case T_GET:
3059  case T_OBJFETCH:
3060  for (k = 0, valp = value_list; k < size; k++, valp++)
3061  if ((db_query_get_tuple_value (result, k, valp)) < 0)
3062  {
3063  assert (er_errid () != NO_ERROR);
3064  retval = er_errid ();
3065  return (retval);
3066  }
3067  retval = NO_ERROR;
3068  break;
3069 
3070  default:
3071  retval = ER_QPROC_INVALID_RESTYPE;
3073  break;
3074  }
3075 
3076  return (retval);
3077 }
3078 
3079 /*
3080  * db_query_tuple_count() - This function calculates the total number of result
3081  * tuples in the query result.
3082  * return : number of tuples in the query result or -1 on error.
3083  * result(in): Pointer to the query result structure
3084  *
3085  * note : If an error is detected, the function returns -1 and the
3086  * db_error_string() function can be used to see a description of the error.
3087  */
3088 int
3090 {
3091  int retval;
3092 
3093  CHECK_1ARG_MINUSONE (result);
3094 
3095  if (result->status == T_CLOSED)
3096  {
3098  return -1;
3099  }
3100 
3101  switch (result->type)
3102  {
3103  case T_SELECT:
3104  retval = result->res.s.cursor_id.list_id.tuple_cnt;
3105  break;
3106 
3107  case T_CALL:
3108  case T_OBJFETCH:
3109  retval = 1;
3110  break;
3111 
3112 #if defined (ENABLE_UNUSED_FUNCTION)
3113  case T_GET:
3114  retval = result->res.g.n_tuple;
3115  break;
3116 #endif
3117 
3118  default:
3120  retval = -1;
3121  break;
3122  }
3123 
3124  return retval;
3125 }
3126 
3127 /*
3128  * db_query_column_count() - This function calculates the number of columns in
3129  * each tuple of the query result.
3130  * return : number of columns.
3131  * result(in): Pointer to the query result structure
3132  */
3133 int
3135 {
3136  CHECK_1ARG_MINUSONE (result);
3137 
3138  if (result->status == T_CLOSED)
3139  {
3141  return -1;
3142  }
3143 
3144  if (DB_INVALID_RESTYPE (result->type))
3145  {
3147  return -1;
3148  }
3149 
3150  return (DB_OID_INCLUDED (result)) ? (result->col_cnt - 1) : result->col_cnt;
3151 }
3152 
3153 #if defined(WINDOWS) || defined (ENABLE_UNUSED_FUNCTION)
3154 /*
3155  * db_query_stmt_id() - This function returns the statement identifier for the
3156  * query or -1 if the query is not select type.
3157  * return : statement id or -1
3158  * result(in): Pointer to the query result structure
3159  */
3160 int
3161 db_query_stmt_id (DB_QUERY_RESULT * result)
3162 {
3163  CHECK_1ARG_MINUSONE (result);
3164 
3165  if (result->status == T_CLOSED)
3166  {
3168  return -1;
3169  }
3170 
3171  if (DB_INVALID_RESTYPE (result->type))
3172  {
3174  return -1;
3175  }
3176 
3177  return result->res.s.stmt_id;
3178 }
3179 #endif
3180 
3181 /*
3182  * db_query_get_tuple_oid() - This function returns an OID in the form of a
3183  * DB_VALUE pointer.
3184  * return : error code
3185  * result(in): Pointer to the query result structure
3186  * db_value(out): contains the pointer to the cursor current OID
3187  *
3188  * note : For this function to process without error, the query that yields
3189  * the DB_QUERY_RESULT pointed to by result must be updatable.
3190  * The db_query_get_tuple_oid() function must be preceded by the
3191  * db_include_oid(), db_compile_statement() and the db_execute_statement()
3192  * functions, or simply by the db_execute_oid() function.
3193  */
3194 int
3196 {
3197  int retval;
3198 
3200 
3201  CHECK_2ARGS_ERROR (result, db_value);
3202 
3203  if (result->status == T_CLOSED)
3204  {
3207  }
3208 
3209  if (DB_INVALID_RESTYPE (result->type))
3210  {
3212  return ER_QPROC_INVALID_RESTYPE;
3213  }
3214 
3215  if (!DB_OID_INCLUDED (result))
3216  {
3218  return ER_QPROC_INVALID_CRSOPR;
3219  }
3220 
3221  retval = cursor_get_current_oid (&result->res.s.cursor_id, db_value);
3222 
3223  return (retval);
3224 }
3225 
3226 #if defined(WINDOWS) || defined (ENABLE_UNUSED_FUNCTION)
3227 /*
3228  * db_query_get_value_type() - This function returns the type of the specified
3229  * result column, or DB_TYPE_NULL on error
3230  * return : DB_TYPE
3231  * result(in) : pointer to query result structure
3232  * index(in) : column index
3233  */
3234 DB_TYPE
3235 db_query_get_value_type (DB_QUERY_RESULT * result, int index)
3236 {
3237  DB_QUERY_TYPE *typep;
3238  int k;
3239 
3241 
3242  if (result->status == T_CLOSED)
3243  {
3245  return DB_TYPE_NULL;
3246  }
3247 
3248  if (DB_INVALID_RESTYPE (result->type))
3249  {
3251  return DB_TYPE_NULL;
3252  }
3253 
3254  if (DB_INVALID_INDEX (index, result->type_cnt))
3255  {
3257  return DB_TYPE_NULL;
3258  }
3259 
3260  for (k = 0, typep = result->query_type; k < index && typep; k++, typep = typep->next)
3261 
3262  ;
3263 
3264  return typep ? typep->db_type : DB_TYPE_NULL;
3265 }
3266 
3267 /*
3268  * db_query_get_value_length() - This functionreturns the length of the
3269  * specified result column
3270  * return : length of column or -1 on error
3271  * result(in) : pointer to query result structure
3272  * index(in) : which result column
3273  */
3274 int
3275 db_query_get_value_length (DB_QUERY_RESULT * result, int index)
3276 {
3277  DB_QUERY_TYPE *typep;
3278  int k;
3279 
3280  CHECK_1ARG_MINUSONE (result);
3281 
3282  if (result->status == T_CLOSED)
3283  {
3285  return -1;
3286  }
3287 
3288  if (DB_INVALID_RESTYPE (result->type))
3289  {
3291  return -1;
3292  }
3293 
3294  if (DB_INVALID_INDEX (index, result->type_cnt))
3295  {
3297  return -1;
3298  }
3299 
3300  for (k = 0, typep = result->query_type; k < index; k++, typep = typep->next)
3301  {
3302  ; /* NULL */
3303  }
3304 
3305  return typep ? typep->size : -1;
3306 }
3307 #endif
3308 
3309 #if defined(WINDOWS) || defined (CUBRID_DEBUG)
3310 /*
3311  * db_sqlx_debug_print_result() - This function displays the result on
3312  * standard output.
3313  * return : void
3314  * result(in): result to be displayed
3315  *
3316  * note: this function is only for DEBUGGING purpose. No product can use
3317  * this function to display the result.
3318  */
3319 void
3320 db_sqlx_debug_print_result (DB_QUERY_RESULT * result)
3321 {
3322  if (result == NULL)
3323  {
3324  fprintf (stdout, "There is no result.\n\n");
3325  return;
3326  }
3327 
3328  switch (result->type)
3329  {
3330  case T_SELECT:
3331  cursor_print_list (result->res.s.query_id, &result->res.s.cursor_id.list_id);
3332  break;
3333 
3334  case T_CALL:
3335  db_value_print (result->res.c.val_ptr);
3336  break;
3337 
3338  default:
3339  (void) fprintf (stdout, "Invalid query result structure type: %d.\n", result->type);
3340  break;
3341  }
3342 
3343 }
3344 #endif
3345 
3346 /*
3347  * QUERY POST-PROCESSING ROUTINES
3348  */
3349 
3350 /*
3351  * db_query_end() - This function must be called when the application is
3352  * finished with the query result descriptor that was returned by either
3353  * db_execute() or db_execute_oid() function.
3354  * This frees the descriptor and all storage related to the query results.
3355  * Since query results can be of considerable size,
3356  * it is important that they be freed as soon as they are no longer necessary.
3357  * return : error code
3358  * result(in): Pointer to the query result structure
3359  *
3360  */
3361 int
3363 {
3364  bool notify_server;
3365 
3367  {
3368  /* Query ended with latest executed query. No need to notify server. */
3369  notify_server = false;
3370  }
3371  else
3372  {
3373  notify_server = true;
3374  }
3375 
3376  return db_query_end_internal (result, notify_server);
3377 }
3378 
3379 /*
3380  * db_query_set_copy_tplvalue() -
3381  * return : error code
3382  * result(in/out):
3383  * copy(in):
3384  */
3385 int
3387 {
3388  int retval = NO_ERROR;
3390 
3391  CHECK_1ARG_ERROR (result);
3392 
3393  if (result->status == T_CLOSED)
3394  {
3397  }
3398 
3399  switch (result->type)
3400  {
3401  case T_SELECT:
3402  (void) cursor_set_copy_tuple_value (&result->res.s.cursor_id, copy ? true : false);
3403  break;
3404 
3405  case T_CALL:
3406  break;
3407 
3408  case T_OBJFETCH:
3409  break;
3410 
3411 #if defined (ENABLE_UNUSED_FUNCTION)
3412  case T_GET:
3413  break;
3414 #endif
3415  default:
3416  {
3417  retval = ER_QPROC_INVALID_RESTYPE;
3419  }
3420  break;
3421  }
3422 
3423  return retval;
3424 }
3425 
3426 /*
3427  * db_is_client_cache_reusable() -
3428  * return :
3429  * result(in):
3430  */
3431 bool
3433 {
3434  if (result && result->type == T_CACHE_HIT)
3435  {
3436  return true;
3437  }
3438  else
3439  {
3440  return false;
3441  }
3442 }
3443 
3444 /*
3445  * db_query_get_cache_time() -
3446  * return :
3447  * result(in):
3448  * cache_time(out):
3449  */
3450 int
3452 {
3453  if (cache_time)
3454  {
3455  CACHE_TIME_RESET (cache_time);
3456  }
3457 
3458  if (result != NULL && result->status != T_CLOSED && result->type == T_SELECT && cache_time)
3459  {
3460  *cache_time = result->res.s.cache_time;
3461  }
3462 
3463  return NO_ERROR;
3464 }
3465 
3466 /*
3467  * db_query_end_internal() -
3468  * return :
3469  * result(in):
3470  * notify_server(in):
3471  */
3472 int
3473 db_query_end_internal (DB_QUERY_RESULT * result, bool notify_server)
3474 {
3475  int error = NO_ERROR;
3476 
3478  {
3479  error = ER_OBJ_NO_CONNECT;
3481  }
3482 
3483  /* Silently return if the result structure has already been freed */
3484  if ((result) && (result->status == T_CLOSED))
3485  {
3486  return NO_ERROR;
3487  }
3488 
3489  if (result)
3490  {
3491  if (result->type == T_SELECT)
3492  {
3493  if (notify_server && error == NO_ERROR)
3494  {
3495  if (qmgr_end_query (result->res.s.query_id) != NO_ERROR)
3496  {
3497  assert (er_errid () != NO_ERROR);
3498  error = er_errid ();
3499  }
3500  }
3501  cursor_close (&result->res.s.cursor_id);
3502  }
3503 
3504  db_free_query_result (result);
3505  }
3506 
3507  return error;
3508 }
3509 
3510 /*
3511  * db_query_prefetch_columns() -
3512  * return : error code
3513  * result(in):
3514  * columns(out):
3515  * col_count(in):
3516  *
3517  * note : This function was added in order to have reasonable performance.
3518  */
3519 int
3520 db_query_prefetch_columns (DB_QUERY_RESULT * result, int *columns, int col_count)
3521 {
3522  int error = NO_ERROR;
3523  int status;
3524 
3525  status = cursor_set_oid_columns (&result->res.s.cursor_id, columns, col_count);
3526  if (status != NO_ERROR)
3527  {
3528  /* should be setting an error */
3529  error = ER_GENERIC_ERROR;
3530  }
3531 
3532  return error;
3533 }
3534 
3535 /*
3536  * db_query_plan_dump_file() -
3537  * return :
3538  * filename(in):
3539  */
3540 int
3541 db_query_plan_dump_file (char *filename)
3542 {
3544  {
3545  free (query_Plan_dump_filename);
3546  }
3547 
3549 
3550  if (filename != NULL)
3551  {
3552  query_Plan_dump_filename = strdup (filename);
3553  }
3554 
3555  return NO_ERROR;
3556 }
3557 
3558 /*
3559  * db_set_execution_plan
3560  * plan(in):
3561  * length(in):
3562  *
3563  * return:
3564  *
3565  */
3566 void
3567 db_set_execution_plan (char *plan, int length)
3568 {
3569  int null_padded_length = 0;
3570 
3571  if (plan == NULL)
3572  {
3573  if (db_Execution_plan != NULL)
3574  {
3575  db_Execution_plan[0] = '\0';
3576  }
3577  return;
3578  }
3579 
3580  null_padded_length = length + 1;
3581 
3582  if (db_Execution_plan == NULL)
3583  {
3585  while (db_Execution_plan_length < null_padded_length)
3586  {
3588  }
3589  db_Execution_plan = (char *) malloc (db_Execution_plan_length * sizeof (char));
3590  }
3591  else if (db_Execution_plan_length < null_padded_length)
3592  {
3593  while (db_Execution_plan_length < null_padded_length)
3594  {
3596  }
3597 
3598  free (db_Execution_plan);
3599 
3600  db_Execution_plan = (char *) malloc (db_Execution_plan_length * sizeof (char));
3601  }
3602 
3603  if (db_Execution_plan == NULL)
3604  {
3607  return;
3608  }
3609 
3610  strncpy (db_Execution_plan, plan, length);
3611  db_Execution_plan[length] = '\0';
3612 }
3613 
3614 /*
3615  * db_get_execution_plan
3616  *
3617  * return:
3618  *
3619  */
3620 char *
3622 {
3623  if (db_Execution_plan == NULL)
3624  {
3625  return NULL;
3626  }
3627 
3628  return db_Execution_plan;
3629 }
3630 
3631 /*
3632  * db_free_execution_plan :
3633  *
3634  * return:
3635  *
3636  */
3637 void
3639 {
3640  if (db_Execution_plan != NULL)
3641  {
3644  }
3645 }
#define ER_QPROC_INVALID_RESTYPE
Definition: error_code.h:537
#define CHECK_1ARG_MINUSONE(obj)
Definition: db.h:192
int db_unpack_prepare_info(DB_PREPARE_INFO *info, char *buffer)
Definition: db_query.c:537
COL_VISIBLE_TYPE visible_type
Definition: db_query.h:64
int db_execute_statement_local(DB_SESSION *session, int stmt, DB_QUERY_RESULT **result)
Definition: db_vdb.c:2939
static char * or_unpack_query_format(char *buf, DB_QUERY_TYPE **q)
Definition: db_query.c:308
#define NO_ERROR
Definition: error_code.h:46
CURSOR_POSITION crs_pos
Definition: db_query.h:93
#define ER_QPROC_INVALID_TPLVAL_INDEX
Definition: error_code.h:523
SM_DOMAIN * src_domain
Definition: db_query.h:63
DB_QUERY_RESULT * db_alloc_query_result(DB_RESULT_TYPE r_type, int col_cnt)
Definition: db_query.c:868
void db_free_query_result(DB_QUERY_RESULT *r)
Definition: db_query.c:727
int cursor_get_tuple_value(CURSOR_ID *cursor_id_p, int index, DB_VALUE *value_p)
Definition: cursor.c:1734
DB_CALL_RESULT c
Definition: db_query.h:125
struct alloc_resource alloc_res
Definition: db_query.c:71
DB_OBJFETCH_RESULT o
Definition: db_query.h:126
static int or_packed_query_format_size(const DB_QUERY_TYPE *q, int *count)
Definition: db_query.c:194
DB_GET_RESULT g
Definition: db_query.h:127
#define CACHE_TIME_RESET(T)
Definition: cache_time.h:40
DB_VALUE * vals
Definition: dbtype_def.h:1100
CURSOR_ID cursor_id
Definition: db_query.h:74
int db_query_prefetch_columns(DB_QUERY_RESULT *result, int *columns, int col_count)
Definition: db_query.c:3520
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
int qres_cnt
Definition: db_query.c:67
void db_init_query_result(DB_QUERY_RESULT *r, DB_RESULT_TYPE r_type)
Definition: db_query.c:1011
int db_query_seek_tuple(DB_QUERY_RESULT *result, int offset, int seek_mode)
Definition: db_query.c:2455
#define CHECK_2ARGS_ERROR(obj1, obj2)
Definition: db.h:195
char ** into_list
Definition: db_query.h:152
static void free_query_result(DB_QUERY_RESULT *q_res)
Definition: db_query.c:131
int db_Connect_status
Definition: db_macro.c:88
int db_query_execute(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error)
Definition: db_query.c:1808
static DB_QUERY_TYPE * db_cp_query_type_helper(DB_QUERY_TYPE *src, DB_QUERY_TYPE *dest)
Definition: db_query.c:1238
int qmgr_end_query(QUERY_ID query_id)
DB_TYPE
Definition: dbtype_def.h:670
#define ER_FAILED
Definition: error_code.h:47
DB_TYPE db_type
Definition: db_query.h:60
DB_QUERY_RESULT * db_get_db_value_query_result(DB_VALUE *val)
Definition: db_query.c:1998
char * or_unpack_string_alloc(char *ptr, char **string)
char * or_pack_db_value(char *buffer, DB_VALUE *var)
int cursor_next_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1482
int db_query_set_tplpos(DB_QUERY_RESULT *result, DB_QUERY_TPLPOS *tplpos)
Definition: db_query.c:2800
int free_qres_cnt
Definition: db_query.c:60
char * or_pack_string(char *ptr, const char *string)
char * original_name
Definition: db_query.h:59
static int db_Execution_plan_length
Definition: db_query.c:85
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
Definition: cursor.h:47
void db_free_execution_plan(void)
Definition: db_query.c:3638
int entry_cnt
Definition: db_query.c:69
void db_query_format_free(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1723
bool tran_was_latest_query_ended(void)
static DB_QUERY_RESULT * allocate_query_result(void)
Definition: db_query.c:101
int32_t pageid
Definition: dbtype_def.h:879
CACHE_TIME cache_time
Definition: db_query.h:75
int er_errid(void)
void db_query_free_tplpos(DB_QUERY_TPLPOS *tplpos)
Definition: db_query.c:2858
int or_packed_domain_size(struct tp_domain *domain, int include_classoids)
int db_query_get_tuple_oid(DB_QUERY_RESULT *result, DB_VALUE *db_value)
Definition: db_query.c:3195
int db_open_buffer_and_compile_first_statement(const char *CSQL_query, DB_QUERY_ERROR *query_error, int include_oid, DB_SESSION **session, int *stmt_no)
Definition: db_vdb.c:3007
CURSOR_POSITION crs_pos
Definition: db_query.h:101
int cursor_fetch_page_having_tuple(CURSOR_ID *cursor_id_p, VPID *vpid_p, int position, int offset)
Definition: cursor.c:992
SM_DOMAIN * db_query_format_domain(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1661
int db_attribute_is_non_null(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1355
DB_RESULT_TYPE
Definition: db_query.h:107
#define ER_OBJ_NO_CONNECT
Definition: error_code.h:295
VPID current_vpid
Definition: cursor.h:60
DB_QUERY_TYPE * db_query_format_next(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1577
DB_QUERY_RESULT ** qres_list
Definition: db_query.c:70
DB_RESULT_STATUS status
Definition: db_query.h:116
char * db_query_format_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1609
#define DB_INVALID_RESTYPE(t)
Definition: db_query.c:48
int cursor_last_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1696
#define DB_CONNECTION_STATUS_CONNECTED
Definition: db.h:47
int max_qres_cnt
Definition: db_query.c:61
DB_ATTRIBUTE * db_get_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:791
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int db_query_prev_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2196
DB_SELECT_RESULT s
Definition: db_query.h:124
int db_query_get_cache_time(DB_QUERY_RESULT *result, CACHE_TIME *cache_time)
Definition: db_query.c:3451
char * db_get_execution_plan(void)
Definition: db_query.c:3621
#define assert(x)
int cursor_get_current_oid(CURSOR_ID *cursor_id_p, DB_VALUE *value_p)
Definition: cursor.c:1449
int db_query_last_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2374
#define ER_QPROC_INVALID_CRSOPR
Definition: error_code.h:521
CURSOR_POSITION
Definition: cursor.h:44
DB_COL_TYPE
Definition: dbtype_def.h:269
int or_packed_string_length(const char *string, int *strlen)
DB_QUERY_TYPE * query_type
Definition: db_query.h:119
char * spec_name
Definition: db_query.h:58
#define ER_GENERIC_ERROR
Definition: error_code.h:49
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
DB_QUERY_RESULT * free_qres_list
Definition: db_query.c:62
TP_DOMAIN ** host_var_expected_domains
Definition: db_query.h:148
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
DB_VALUE ** valptr_list
Definition: db_query.h:88
char * name
Definition: db_query.h:56
int db_get_query_format(const char *CSQL_query, DB_QUERY_TYPE **result, DB_QUERY_ERROR *query_error)
Definition: db_query.c:1558
#define OR_VALUE_ALIGNED_SIZE(value)
DB_VALUE_ARRAY host_variables
Definition: db_query.h:147
#define CHECK_1ARG_ERROR(obj)
Definition: db.h:186
int db_value_free(DB_VALUE *value)
Definition: db_macro.c:1610
char * query_Plan_dump_filename
SM_DOMAIN * domain
Definition: db_query.h:62
#define CHECK_1ARG_NULL(obj)
Definition: db.h:171
void db_init_prepare_info(DB_PREPARE_INFO *info)
Definition: db_query.c:411
CURSOR_POSITION crs_pos
Definition: db_query.h:87
char * attr_name
Definition: db_query.h:57
short volid
Definition: dbtype_def.h:880
int cursor_set_oid_columns(CURSOR_ID *cursor_id_p, int *oid_col_no_p, int oid_col_no_cnt)
Definition: cursor.c:1322
void db_clear_client_query_result(int notify_server, bool end_holdable)
Definition: db_query.c:1208
int db_query_get_tuple_value_by_name(DB_QUERY_RESULT *result, char *column_name, DB_VALUE *value)
Definition: db_query.c:2959
bool db_is_client_cache_reusable(DB_QUERY_RESULT *result)
Definition: db_query.c:3432
DB_VALUE * db_value_copy(DB_VALUE *value)
Definition: db_macro.c:1537
#define CHECK_3ARGS_ERROR(obj1, obj2, obj3)
Definition: db.h:198
bool oid_included
Definition: db_query.h:118
#define DB_SIZEOF(val)
Definition: memory_alloc.h:54
struct db_query_type * next
Definition: db_query.h:54
#define NULL
Definition: freelistheap.h:34
void db_value_print(const DB_VALUE *value)
Definition: db_macro.c:1663
#define ER_QPROC_UNKNOWN_CRSPOS
Definition: error_code.h:522
int db_query_plan_dump_file(char *filename)
Definition: db_query.c:3541
int db_execute(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error)
Definition: db_query.c:1836
int current_tuple_offset
Definition: cursor.h:71
void db_close_session_local(DB_SESSION *session)
Definition: db_vdb.c:3244
#define DB_OID_INCLUDED(r)
Definition: db_query.c:46
static const int QP_QRES_LIST_INIT_CNT
Definition: db_query.c:79
SM_DOMAIN * db_query_format_src_domain(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1675
#define ER_QPROC_OPR_ON_CLOSED_QRES
Definition: error_code.h:527
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
int db_value_clear_array(DB_VALUE_ARRAY *value_array)
Definition: db_macro.c:1633
bool cursor_set_copy_tuple_value(CURSOR_ID *cursor_id_p, bool is_copy)
Definition: cursor.c:1291
char * or_unpack_int(char *ptr, int *number)
void db_set_execution_plan(char *plan, int length)
Definition: db_query.c:3567
DB_QUERY_TYPE * db_alloc_query_format(int cnt)
Definition: db_query.c:807
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int db_query_get_tuple_valuelist(DB_QUERY_RESULT *result, int size, DB_VALUE *value_list)
Definition: db_query.c:3025
void db_free_query_format(DB_QUERY_TYPE *q)
Definition: db_query.c:154
#define CHECK_1ARG_RETURN_EXPR(obj, expr)
Definition: db.h:147
int tuple_no
Definition: cursor.h:64
DB_QUERY_TYPE * db_cp_query_type(DB_QUERY_TYPE *query_type, int copy_only_user)
Definition: db_query.c:1329
int db_query_column_count(DB_QUERY_RESULT *result)
Definition: db_query.c:3134
#define ER_OBJ_INVALID_ARGUMENT
Definition: error_code.h:946
static void error(const char *msg)
Definition: gencat.c:331
char * db_query_format_spec_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1635
char * or_pack_int(char *ptr, int number)
#define TP_TYPE_HAS_COLLATION(typeid)
int db_query_next_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2088
DB_VALUE * tpl_list
Definition: db_query.h:96
int db_execute_with_values(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error, int arg_count, DB_VALUE *vals)
Definition: db_query.c:1511
#define CHECK_CONNECT_NULL()
Definition: db.h:91
#define ARG_FILE_LINE
Definition: error_manager.h:44
const char * db_query_format_class_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1740
int qres_closed_cnt
Definition: db_query.c:68
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
Definition: dbi.h:57
int db_pack_prepare_info(const DB_PREPARE_INFO *info, char **buffer)
Definition: db_query.c:433
int db_query_format_size(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1704
static const float QP_QRES_LIST_INC_RATE
Definition: db_query.c:81
char * db_query_format_original_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1648
QUERY_ID query_id
Definition: db_query.h:71
DB_COL_TYPE col_type
Definition: db_query.h:55
CUBRID_STMT_TYPE
Definition: cas_dbms_util.h:40
int db_query_format_is_non_null(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1766
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
char * or_pack_string_with_length(char *ptr, const char *string, int length)
int db_push_values(DB_SESSION *session, int count, DB_VALUE *in_values)
Definition: db_vdb.c:1527
int db_query_end_internal(DB_QUERY_RESULT *result, bool notify_server)
Definition: db_query.c:3473
char * or_pack_domain(char *ptr, struct tp_domain *domain, int include_classoids, int is_null)
DB_COL_TYPE db_query_format_col_type(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1590
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
char * statement
Definition: db_query.h:144
DB_QUERY_TPLPOS * db_query_get_tplpos(DB_QUERY_RESULT *result)
Definition: db_query.c:2737
#define DB_INVALID_INDEX(i, cnt)
Definition: db_query.c:47
static struct @46 Qres_table
int db_get_query_result_format(DB_QUERY_RESULT *result, DB_QUERY_TYPE **type_list)
Definition: db_query.c:2055
int auto_param_count
Definition: db_query.h:149
int db_query_set_copy_tplvalue(DB_QUERY_RESULT *result, int copy)
Definition: db_query.c:3386
DB_RESULT_TYPE type
Definition: db_query.h:115
#define ER_QPROC_INVALID_COLNAME
Definition: error_code.h:524
int cursor_prev_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1568
void cursor_close(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1381
char * db_query_format_attr_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1622
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
DB_QUERY_TYPE * columns
Definition: db_query.h:145
#define PLAN_BUF_INITIAL_LENGTH
Definition: db_query.c:54
QFILE_LIST_ID list_id
Definition: cursor.h:55
int db_compile_and_execute_queries_internal(const char *CSQL_query, void *result, DB_QUERY_ERROR *query_error, int include_oid, int execute, bool is_new_statement)
Definition: db_vdb.c:3096
char * strdup(const char *str)
Definition: porting.c:901
DB_VALUE * val_ptr
Definition: db_query.h:82
int current_tuple_no
Definition: cursor.h:70
struct db_query_result * next
Definition: db_query.h:129
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_query_get_tuple_value(DB_QUERY_RESULT *result, int index, DB_VALUE *value)
Definition: db_query.c:2873
struct db_object * class_mop
Definition: object_domain.h:81
COL_VISIBLE_TYPE
Definition: db_query.h:45
DB_TYPE db_query_format_type(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1690
static char * db_Execution_plan
Definition: db_query.c:84
CURSOR_POSITION position
Definition: cursor.h:59
#define DB_CURSOR_END
Definition: dbtype_def.h:167
char * or_unpack_domain(char *ptr, struct tp_domain **domain_ptr, int *is_null)
Definition: cursor.h:48
void sm_domain_free(SM_DOMAIN *ptr)
int db_execute_oid(const char *CSQL_query, DB_QUERY_RESULT **result, DB_QUERY_ERROR *query_error)
Definition: db_query.c:1852
CUBRID_STMT_TYPE stmt_type
Definition: db_query.h:146
const char ** p
Definition: dynamic_load.c:945
char * or_unpack_db_value(char *buffer, DB_VALUE *val)
void tp_domain_free(TP_DOMAIN *dom)
static char * or_pack_query_format(char *buf, const DB_QUERY_TYPE *q, const int count)
Definition: db_query.c:244
CURSOR_POSITION crs_pos
Definition: db_query.h:81
int cursor_get_tuple_value_list(CURSOR_ID *cursor_id_p, int size, DB_VALUE *value_list_p)
Definition: cursor.c:1778
int db_query_tuple_count(DB_QUERY_RESULT *result)
Definition: db_query.c:3089
#define CHECK_CONNECT_ERROR()
Definition: db.h:88
int ansisql_strcasecmp(const char *s, const char *t)
Definition: memory_alloc.c:134
SM_DOMAIN * sm_domain_copy(SM_DOMAIN *ptr)
#define TP_DOMAIN_COLLATION_FLAG(dom)
union db_query_result::@47 res
int cursor_first_tuple(CURSOR_ID *cursor_id_p)
Definition: cursor.c:1652