CUBRID Engine  latest
esql_cli.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  * esql_cli.c - CUBRID Call Interface
21  */
22 
23 #ident "$Id$"
24 
25 #include "system.h"
26 #include "dbi.h"
27 #include "db.h"
28 #include "config.h"
29 
30 #if !defined(WINDOWS)
31 #include <unistd.h>
32 #include <libgen.h>
33 #endif
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <limits.h>
38 #include <time.h>
39 #include <errno.h>
40 #include <assert.h>
41 
42 #include "misc_string.h"
43 #include "error_manager.h"
44 #include "system_parameter.h"
45 
46 #define _ESQL_KERNEL_
47 #include "cubrid_esql.h"
48 
49 #include "memory_alloc.h"
50 #include "parser.h"
51 #include "esql_gadget.h"
52 #include "environment_variable.h"
53 #include "authenticate.h"
54 #include "dbtype.h"
55 #include "object_primitive.h"
56 
57 #define UCI_OPT_UNSAFE_NULL 0x0001
58 
59 /* # of entries at every expansion of monotonically increasing tables */
60 #define REPETITIVE_EXPANSION_UNIT 100 /* repetitive stmt table */
61 #define DYNAMIC_EXPANSION_UNIT 20 /* dynamically prepared stmts */
62 #define POINTER_EXPANSION_UNIT 10 /* pointers from DBI */
63 #define CS_STMT_ID_EXPANSION_UNIT 5 /* cs stmt ids for a cursor */
64 #define UCI_ENV_STACK_EXPANSION_UNIT 4 /* stack expansion unit */
65 #define DB_VALS_STCK_EXPANSION_UNIT 4 /* db values stack */
66 
67 #define IS_NULL_INDICATED(ind) ((ind) < 0) /* negative */
68 
69 /* macro to check if there was a error.
70  * execution of an Embedded CSQL statement is stopped upon error.
71  * But, a user can specify 'CONTINUE' even though there is an error.
72  * To implement such behaviour, every statement calls uci_start() function
73  * first to clear current error code (if any set) and call successive
74  * uci_ functions. Every uci_ function (except uci_stop()) will return
75  * if there was an error in previous uci function.
76  */
77 #define CHK_SQLCODE() \
78  do { \
79  if(SQLCODE < 0) \
80  { \
81  return; \
82  } \
83  } while(0)
84 
85 /* macro to check if there was a warning in the previous DBI function call.
86  * If it was, set the warning code to sqlca area.
87  */
88 #define CHK_DBI_WARN() \
89  do { \
90  if (sql_warn.is_warning) \
91  { \
92  if (sql_warn.null_in_agg) \
93  { \
94  SET_WARN_NULL_IN_AGG (); \
95  sql_warn.null_in_agg = false; \
96  } \
97  else if (sql_warn.no_where) \
98  { \
99  SET_WARN_NO_WHERE (); \
100  sql_warn.no_where = false; \
101  } \
102  sql_warn.is_warning = false; \
103  } \
104  } \
105 while (0)
106 
107 /*
108  * for short usage of frequent DBI function call result check.
109  * NOTE: every dbi function call should use this macro for
110  * consistent error processing
111  */
112 #define CHECK_DBI(predicate, err_action) \
113  do { \
114  if(predicate) { /* error from dbi */ \
115  { \
116  set_sqlca_err(); \
117  } \
118  if(SQLCODE == ER_LK_UNILATERALLY_ABORTED || \
119  SQLCODE == ER_TM_SERVER_DOWN_UNILATERALLY_ABORTED) \
120  { \
121  clean_up(); \
122  } \
123  err_action; \
124  } \
125  CHK_DBI_WARN(); \
126  } while(0)
127 
128 /* to check if the given type belongs to legal esql DB_TYPE.
129  * Note that some of DB_TYPE are not supported in esql
130  */
131 #define IS_USER_DB_TYPE(t) ((t) >= DB_TYPE_FIRST && (t) <= DB_TYPE_LAST)
132 
133 /* to check if the given C type is a string type */
134 #define STRING_C_TYPE(s) (((s)==DB_TYPE_C_CHAR) || \
135  ((s)==DB_TYPE_C_VARCHAR) || \
136  ((s)==DB_TYPE_C_NCHAR) || \
137  ((s)==DB_TYPE_C_VARNCHAR) || \
138  ((s)==DB_TYPE_C_BIT) || \
139  ((s)==DB_TYPE_C_VARBIT))
140 
141 /* to check if the stmt type has connection to WHERE-clause */
142 #define AFFECT_OBJECTS(stmt_type) (stmt_type == CUBRID_STMT_SELECT || \
143  stmt_type == CUBRID_STMT_UPDATE || \
144  stmt_type == CUBRID_STMT_DELETE || \
145  stmt_type == CUBRID_STMT_INSERT)
146 
147 /* to check if the stmt type will bring result or not */
148 #define HAS_RESULT(stmt_type) (stmt_type == CUBRID_STMT_SELECT || \
149  stmt_type == CUBRID_STMT_CALL || \
150  stmt_type == CUBRID_STMT_INSERT || \
151  stmt_type == CUBRID_STMT_GET_ISO_LVL || \
152  stmt_type == CUBRID_STMT_GET_TIMEOUT || \
153  stmt_type == CUBRID_STMT_GET_OPT_LVL || \
154  stmt_type == CUBRID_STMT_GET_STATS)
155 
156 /* redefinition of readability of used SQLCA members */
157 #define SQLCA_NUM_AFFECTED_OBJECTS sqlca.sqlerrd[2]
158 #define SQLCA_IS_WARNING SQLWARN0
159 #define SQLCA_OUTPUT_TRUNC SQLWARN1
160 #define SQLCA_NULL_IN_AGG SQLWARN2
161 #define SQLCA_VARS_MISMATCH SQLWARN3
162 #define SQLCA_NO_WHERE SQLWARN4
163 
164 /* macros to set warnings */
165 
166 /* string truncation in output */
167 #define SET_WARN_OUTPUT_TRUNC() SQLCA_OUTPUT_TRUNC = \
168  SQLCA_IS_WARNING = SQL_WARNING_CHAR
169 
170 /* null is ignored in evaluation of aggregation function */
171 #define SET_WARN_NULL_IN_AGG() SQLCA_NULL_IN_AGG = \
172  SQLCA_IS_WARNING = SQL_WARNING_CHAR
173 
174 /* too many input vars or too few output vars */
175 #define SET_WARN_VARS_MISMATCH() \
176  SQLCA_VARS_MISMATCH = \
177  SQLCA_IS_WARNING = SQL_WARNING_CHAR
178 
179 /* update/delete without WHERE-clause is compiled */
180 #define SET_WARN_NO_WHERE() SQLCA_NO_WHERE = \
181  SQLCA_IS_WARNING = SQL_WARNING_CHAR
182 
183 /* error codes introduced by esql_cli module */
184 
185 /* no more memory */
186 #define PUT_UCI_ERR_NOMOREMEMORY(size) \
187  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
188  ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) (size))
189 
190 /* input host variables is given less than # of positional markers */
191 #define PUT_UCI_ERR_TOOFEWHOSTVARS(num_markers) \
192  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
193  ER_UCI_TOO_FEW_HOST_VARS, 0)
194 
195 /* output host variables is given more than # of positional markers */
196 #define PUT_UCI_ERR_TOOMANYHOSTVARS(num_cols) \
197  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
198  ER_UCI_TOO_MANY_HOST_VARS, 0)
199 
200 /* db value is null but indicator is not given */
201 #define PUT_UCI_ERR_NULLINDNEEDED() \
202  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
203  ER_UCI_NULL_IND_NEEDED, 0)
204 
205 /* the stmt on which a cursor declared is not prepared when open the cursor */
206 #define PUT_UCI_ERR_NOTPREPAREDSTMT() \
207  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
208  ER_UCI_NOT_PREPARED_STMT, 0)
209 
210 /* the stmt should be SELECT */
211 #define PUT_UCI_ERR_NOTSELECTSTMT() \
212  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
213  ER_UCI_NOT_SELECT_STMT, 0)
214 
215 /* the cursor is not opened yet */
216 #define PUT_UCI_ERR_CURSORNOTOPENED() \
217  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
218  ER_UCI_CURSOR_NOT_OPENED, 0)
219 
220 /* attempt to open a cursor which is still open */
221 #define PUT_UCI_ERR_CURSORSTILLOPEN() \
222  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
223  ER_UCI_CURSOR_STILL_OPEN, 0)
224 
225 /* more than one instances in result of static statement */
226 #define PUT_UCI_ERR_MULTIPLEOBJECTS() \
227  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
228  ER_UCI_MULTIPLE_OBJECTS, 0)
229 
230 /* more than one statement is given */
231 #define PUT_UCI_ERR_NOMARKALLOWED() \
232  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
233  ER_UCI_NO_MARK_ALLOWED, 0)
234 
235 /* invalid data type is given */
236 #define PUT_UCI_ERR_INVALIDDATATYPE() \
237  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
238  ER_UCI_INVALID_DATA_TYPE, 0)
239 
240 /* invalid cursor position */
241 #define PUT_UCI_ERR_INVALIDCSPOS() \
242  er_set(ER_ERROR_SEVERITY, __FILE__, __LINE__, \
243  ER_QPROC_INVALID_CRSPOS, 0)
244 
245 #if defined(UCI_TEMPORARY)
246 typedef struct sql_warn_type
247 {
248  unsigned int is_warning:1;
249  unsigned int null_in_agg:1;
250  unsigned int no_where:1;
251 } SQL_WARN_TYPE;
252 #endif
253 
254 /* every pointer value returned from db_query_get_value_to_pointer()
255  * should be kept until next SELECT or FETCH statement
256  */
257 typedef struct pointer
258 {
260 } POINTER;
261 
262 /* descriptors for repetitive statement
263  * during life-time of the process, it is increasing (never shrinking).
264  */
265 typedef struct repetitive
266 {
267  void *file_id; /* source file identifier */
268  int no; /* stmt no in the file */
269  DB_SESSION *session; /* query compile/execute context */
270  STATEMENT_ID stmt_id; /* compiled stmt number */
271  CUBRID_STMT_TYPE stmt_type; /* true if the stmt is SELECT */
273 } REPETITIVE;
274 
275 /* structure of a dynamic statement prepared.
276  * during life-time of a transaction, it is increasing (never shrinking).
277  * NOTE: currently, query result library function to get result column
278  * information requires statement contents itself. `stmt' member is only
279  * for this function. if the function is changed to get the information
280  * using compiled stmt, then, `stmt' is no longer required.
281  */
282 typedef struct dynamic
283 {
284  void *file_id; /* source file identifier */
285  int stmt_no; /* statement no */
286  CUBRID_STMT_TYPE stmt_type; /* statement type */
287  DB_SESSION *session; /* query compile/execute context */
288  STATEMENT_ID stmt_id; /* compiled stmt number */
289  int num_markers; /* # of input markers */
290  DB_QUERY_TYPE *column_spec; /* result column descriptor */
291  char *saved_stmt;
293 } DYNAMIC;
294 
295 /* simple structure to maintain compiled stmt identifiers of update/delete
296  * through cursor stmts which is belong to a cursor.
297  */
298 typedef struct cs_stmt_id
299 {
300  int no; /* serial number given by pre-processor */
301  DB_SESSION *session; /* query compile/execute context */
302  STATEMENT_ID stmt_id; /* compiled stmt id */
303 } CS_STMT_ID;
304 
305 /* run-time cursor information.
306  * this is a linked-list structure because it is dynamically increased
307  * and shrinked during run-time by OPEN/CLOSE cursor statement.
308  */
309 typedef struct cursor
310 {
311  void *file_id; /* file of the cursor */
312 #if defined(UCI_TEMPORARY)
313  DB_SESSION *static_session;
314  STATEMENT_ID static_stmt_id;
315 #endif
316  int no; /* sequential number */
317  int num_stmt_ids; /* # of element in `stmt_ids' */
318  CS_STMT_ID *stmt_ids; /* array of stmt id for update/ delete cursor stmts which belongs to this cursor */
319  int last_stmt_id; /* last searched stmt_id */
320  DB_QUERY_RESULT *result; /* result pointer */
321  long fetched_tuples; /* # of fetched tuples */
322  int num_columns; /* # of result cols */
323  int curr_column; /* current column */
324  POINTER *pointers; /* pointers to be free */
325  int num_pointers; /* # of pointers to be free */
326  struct cursor *next; /* pointer to next entry */
327 } CURSOR;
328 
329 /* structure of an entry of the stack */
330 typedef struct uci_env_stack_entry
331 {
332  char saved_sqlca_sqlwarn[sizeof (((CUBRIDCA *) 0)->sqlwarn)];
337  const char *saved_curr_filename;
340 
341 #if defined(UCI_TEMPORARY)
342 SQL_WARN_TYPE sql_warn;
343 #endif
344 
345 unsigned int _uci_opt;
349 
350 /* executable file name of this process */
351 static char program_name[PATH_MAX];
352 
353 /* information of table for db values (bound on host variables) to CUBRID */
354 static struct
355 {
356  DB_VALUE *db_values; /* table */
357  int num_db_values; /* # of db_value */
358  int db_value_top; /* top index */
360 
361 /* pointer to the head of cursor list */
363 
364 /* repetitive statements table */
365 static REPETITIVE *repetitive_stmts; /* table */
366 static int num_repetitive_stmts = 0; /* # of entries */
367 
368 /* the index of repetitive stmt table most recently searched. it is used to
369  * minimize the cost of succeeding search trial for the same stmt entry.
370  */
371 static int last_repetitive;
372 
373 /* dynamically prepared statements table */
374 static DYNAMIC *dynamic_stmts; /* table */
375 static int num_dynamic_stmts = 0; /* # of entries */
376 
377 /* the index of dynamic stmt table most recently searched. it is used to
378  * minimize the cost of succeeding search trial for the same stmt entry.
379  */
380 static int last_dynamic;
381 
382 /* pointer table from DBI */
383 static POINTER *pointers; /* table */
384 static int num_pointers = 0; /* # of entries */
385 
386 /* source file identifier which is executing esql_cli functions currently.
387  * it is set by uci_start() function.
388  */
389 static void *curr_file;
390 static const char *curr_filename;
391 static int curr_lineno;
392 
393 /* result container for statement most recently executed */
394 static DB_QUERY_RESULT *curr_result = (DB_QUERY_RESULT *) NULL; /* result */
395 static int num_curr_result_columns = 0; /* # of columns */
396 static int curr_result_column = 0; /* current column */
397 
398 /* flags to identify status of client process */
399 static bool connected = false;
400 
401 /* to indicate which of uci_start()/uci_end() is called more recently */
402 static bool is_uci_start_state = false;
403 
404 /* varaibles for stack and its description */
407 static int uci_env_stack_top = -1;
408 
409 static void check_stack_size (void);
410 static void free_db_values (void);
411 static int uci_get_next_column (int cs_no, DB_VALUE * dbval);
412 static void uci_get_value_indirect (int cs_no, DB_INDICATOR * ind, void **bufp, int *sizep);
413 static REPETITIVE *alloc_repetitive (int no, DB_SESSION * session, STATEMENT_ID stmt_id, CUBRID_STMT_TYPE stmt_type,
414  DB_GADGET * gadget);
415 static REPETITIVE *get_repetitive (int no);
416 static void free_repetitive (void);
417 static DYNAMIC *alloc_dynamic (int stmt_no, CUBRID_STMT_TYPE stmt_type, DB_SESSION * session, STATEMENT_ID stmt_id,
418  int num_markers, DB_QUERY_TYPE * col_spec, char *stmt, int length);
419 static DYNAMIC *get_dynamic (int stmt_no);
420 static void free_dynamic (void);
421 #if defined(UCI_TEMPORARY)
422 static CURSOR *alloc_cursor (int no, DB_SESSION * static_session, STATEMENT_ID static_stmt_id,
423  DB_QUERY_RESULT * result);
424 #else /* UCI_TEMPORARY */
425 static CURSOR *alloc_cursor (int no, DB_QUERY_RESULT * result);
426 #endif /* UCI_TEMPORARY */
427 static CURSOR *get_cursor (int no);
428 static void free_cursor (int no);
429 static POINTER *put_pointer (CURSOR * cs, DB_VALUE * addr);
430 static void free_pointers (CURSOR * cs);
431 static void copy_column_spec_to_sqlda (DB_QUERY_TYPE * col_spec, CUBRIDDA * desc);
432 static void set_sqlca_err (void);
433 static int push_uci_environment (void);
434 static void pop_uci_environment (void);
435 static void drop_uci_env_stack (void);
436 static void clean_up (void);
437 
438 /*
439  * uci_startup() - tell esql_cli the `pgm_name' is the executable file name
440  * return : void
441  * pgm_name(in) : executable file name of this process
442  * note : it will be used for db_restart(), see uci_connect()).
443  * initialize some esql_cli global variables.
444  */
445 void
446 uci_startup (const char *pgm_name)
447 {
448  unsigned int i;
449 
450  strcpy (program_name, (pgm_name != NULL) ? pgm_name : "");
451 
452  sqlca.sqlcode = 0;
453  sqlca.sqlfile = NULL;
454  sqlca.sqlline = 0;
455  strcpy (sqlca.sqlcaid, "SQLCA ");
456  sqlca.sqlcabc = sizeof (CUBRIDCA);
457  sqlca.sqlerrm.sqlerrml = 0;
458  sqlca.sqlerrm.sqlerrmc[0] = '\0';
459  sqlca.sqlerrp[0] = '\0';
460  for (i = 0; i < DIM (sqlca.sqlerrd); i++)
461  {
462  sqlca.sqlerrd[i] = 0L;
463  }
464  sqlca.sqlwarn.sqlwarn0 = '\0';
465  sqlca.sqlwarn.sqlwarn1 = '\0';
466  sqlca.sqlwarn.sqlwarn2 = '\0';
467  sqlca.sqlwarn.sqlwarn3 = '\0';
468  sqlca.sqlwarn.sqlwarn4 = '\0';
469  sqlca.sqlwarn.sqlwarn5 = '\0';
470  sqlca.sqlwarn.sqlwarn6 = '\0';
471  sqlca.sqlwarn.sqlwarn7 = '\0';
472  for (i = 0; i < sizeof (sqlca.sqlext); i++)
473  {
474  sqlca.sqlext[i] = ' ';
475  }
476 
477  uci_null_ind = 0;
478  db_Value_table.db_values = NULL;
479  db_Value_table.num_db_values = 0;
480  db_Value_table.db_value_top = 0;
481 }
482 
483 /*
484  * uci_start() - This function tells esql_cli the start of new esql C statement.
485  * initialize sqlca variable, C source file identifier,
486  * db_Value_table.db_value_top.
487  * return : void
488  * file_id(in) : C source file identifier
489  */
490 void
491 uci_start (void *file_id, const char *filename, int lineno, unsigned int opt)
492 {
493  int i;
494  bool is_new_environ = is_uci_start_state;
495 
496  is_uci_start_state = true;
497 
498  if (is_new_environ && push_uci_environment () != NO_ERROR)
499  {
500  return;
501  }
502 
503  SQLCODE = 0;
504  SQLFILE = filename;
505  SQLLINE = lineno;
506  if (SQLERRML > 0)
507  {
508  SQLERRML = 0;
509  SQLERRMC[0] = '\0';
510  }
512  SQLCA_IS_WARNING = '\0';
513  SQLCA_OUTPUT_TRUNC = '\0';
514  SQLCA_NULL_IN_AGG = '\0';
515  SQLCA_VARS_MISMATCH = '\0';
516  SQLCA_NO_WHERE = '\0';
517 
518  curr_file = file_id;
519  curr_filename = filename;
520  curr_lineno = lineno;
521 
522  /* reset any current db value entries */
523  for (i = 0; i < db_Value_table.db_value_top; i++)
524  {
525  db_value_clear (&db_Value_table.db_values[i]);
526  }
527  db_Value_table.db_value_top = 0;
528 
529  /* set UCI runtime option */
530  _uci_opt = opt;
531 }
532 
533 /*
534  * uci_end() - This function finalizes stuffs which is specific to the current
535  * statement (i.e. effective from the very previous uci_start().
536  * return : void
537  *
538  * note : Be sure to defer CHECK_DBI() until the end to make sure that we NULL
539  * out the curr_result pointer.
540  */
541 void
542 uci_end (void)
543 {
544  int status = 0;
545 
546  if (curr_result != NULL)
547  {
548  status = db_query_end (curr_result);
549  curr_result = (DB_QUERY_RESULT *) NULL;
550  }
551 
552  is_uci_start_state = false;
553  CHECK_DBI (status < 0, return);
554 }
555 
556 /*
557  * uci_stop() - This function is used only for exiting upon failure. Rolls back
558  * the current transaction and disconnect, exit the process with displaying
559  * the current error msg.
560  * return : none
561  */
562 void
563 uci_stop (void)
564 {
565  fprintf (stderr, "%s\n", SQLERRMC);
566  fflush (stderr);
567 
568  if (connected)
569  {
570  uci_start ((void *) NULL, NULL, 0, 0); /* clear current error status */
571  uci_rollback ();
572  uci_disconnect ();
573  }
574 
575  exit (EXIT_FAILURE);
576 }
577 
578 /*
579  * uci_get_sqlcode() - Get UCI SQL Code
580  * return : sql code
581  */
582 long
584 {
585  return sqlca.sqlcode;
586 }
587 
588 /*
589  * uci_get_sqlwarn_0() - Get UCI SQL warning 0
590  * return : warning
591  */
592 char
594 {
595  return sqlca.sqlwarn.sqlwarn0;
596 }
597 
598 
599 
600 /*
601  * uci_connect() - Connect to a database. if already connected, disconnect
602  * from the current database and connect.
603  * return : void
604  * db_name(in) : database name
605  * user_name(in) : user name
606  * passwd(in) : password string
607  *
608  * note : Connect as user 'PUBLIC' if no username is specified.
609  */
610 void
611 uci_connect (const char *db_name, const char *user_name, const char *passwd)
612 {
613  int error;
614 
615  CHK_SQLCODE ();
616  if (connected)
617  {
618  /* already connected to some database */
619  uci_disconnect ();
620  CHK_SQLCODE ();
621  }
622 
623  error = db_login ((user_name ? user_name : au_get_public_user_name ()), passwd);
624  CHECK_DBI (error < 0, return);
625 
626  /* error handling option will be initialized by db_restart */
627  error = db_restart (program_name, false, db_name);
628  CHECK_DBI (error < 0, return);
629 
630  connected = true;
631 }
632 
633 /*
634  * uci_disconnect() - disconnect from the current database server.
635  * Free repetitive plans and binding table.
636  * return : void
637  */
638 void
640 {
641  int status = 0;
642 
643  CHK_SQLCODE ();
644 
645  if (connected)
646  {
648  {
649  uci_commit ();
650  }
651  else
652  {
653  uci_rollback ();
654  }
655  CHK_SQLCODE ();
656 
657  free_repetitive (); /* free all memory for repetitive statements */
658  free_db_values (); /* free binding table */
659  drop_uci_env_stack (); /* free env stack */
660 
661  /* shutdown server */
662  status = db_shutdown ();
663  connected = false;
664 
665  CHECK_DBI (status < 0, return);
666  }
667 }
668 
669 /*
670  * uci_commit() - commit the current transaction and remove all cursors and
671  * prepared statements. free values spaces of previous non-cursor statement
672  * results.
673  * return : none
674  */
675 void
677 {
678  int error;
679 
680  CHK_SQLCODE ();
681 
682  free_cursor (-1);
683  free_pointers ((CURSOR *) NULL);
684  free_dynamic ();
685 
686  error = db_commit_transaction ();
687  CHECK_DBI (error < 0, return);
688 }
689 
690 /*
691  * uci_rollback() - rollback current transaction and remove all cursors
692  * and prepared statements. free values spaces of previous non-cursor
693  * statement results.
694  * return : void
695  */
696 void
698 {
699  int error;
700 
701  CHK_SQLCODE ();
702 
703  free_cursor (-1);
704  free_pointers ((CURSOR *) NULL);
705  free_dynamic ();
706 
707  error = db_abort_transaction ();
708  CHECK_DBI (error < 0, return);
709 }
710 
711 /*
712  * uci_static() - execute static statement (not cursor/dynamic stmt).
713  * if stmt_no is negative, the stmt is regarded as ad hoc stmt.
714  * otherwise, it is regarded as repetitive. if `num_out_vars' is negative,
715  * it does not set warning when # of out vars mismatches # of output
716  * columns.
717  * return : none
718  * stmt_no(in) : constitute unique stmt id
719  * stmt(in) : pointer to statement
720  * length(in) : length of stmt
721  * num_out_vars(in) : # of output host variables
722  *
723  * note : uci_static should only be called with a nonnegative, repetitive
724  * stmt_no when the preprocessor has determined that the statement is an
725  * INSERT statement which is a candidate for execution through the
726  * db_gadget interface (i.e. it is not a nested insert and does not have a
727  * subquery and does not insert multiple tuples). Other usages of
728  * repetitive statements will not be successful, and repetitive statements
729  * which can't be translated into valid gadgets will be run as ad hoc
730  * statements.
731  */
732 void
733 uci_static (int stmt_no, const char *stmt, int length, int num_out_vars)
734 {
735  STATEMENT_ID stmt_id;
736  REPETITIVE *rt;
737  CUBRID_STMT_TYPE stmt_type;
738  int e;
739  DB_SESSION *session;
740  DB_GADGET *gadget = NULL;
741  DB_NODE *statement;
742  int error;
743 
744  CHK_SQLCODE ();
745 
746  session = NULL;
747  stmt_id = -1;
748  stmt_type = (CUBRID_STMT_TYPE) 0;
749 
750  if (stmt_no >= 0)
751  {
752  rt = get_repetitive (stmt_no);
753  if (rt != NULL)
754  {
755  session = rt->session;
756  stmt_id = rt->stmt_id;
757  stmt_type = rt->stmt_type;
758  gadget = rt->gadget;
759  }
760  }
761 
762  if (stmt_id != -1)
763  {
764  /* must be a repetition */
765  if (!gadget)
766  {
767  db_push_values (session, db_Value_table.db_value_top, db_Value_table.db_values);
768  }
769  }
770  else
771  {
772  /* ad hoc or first trial of repetitive */
773  session = db_open_buffer (stmt);
774  if (session == NULL)
775  {
776  /* alwarys er_error() < 0 */
777  CHECK_DBI (true, return);
778  }
779 
780  statement = db_get_statement (session, 0);
781 
782  /* create gadget if possible */
783  if (stmt_no >= 0 && statement->node_type == PT_INSERT)
784  {
785  DB_NODE *att = NULL, *val = NULL, *val_list = NULL;
786  int attrlist_len = pt_length_of_list (pt_attrs_part (statement)), i;
787  const char *cname = pt_get_name (pt_from_entity_part (pt_class_part (statement)));
788  char **attrs;
789 
790  /* build attribute name array */
791  attrs = (char **) malloc ((attrlist_len + 1) * sizeof (char *));
792  if (attrs == NULL)
793  {
794  PUT_UCI_ERR_NOMOREMEMORY ((attrlist_len + 1) * sizeof (char *));
795  db_close_session (session);
796  CHECK_DBI (true, return);
797  }
798 
799  for (i = 0, att = pt_attrs_part (statement); att; i++, att = att->next)
800  {
801  attrs[i] = (char *) pt_get_name (att);
802  }
803  attrs[i] = NULL;
804 
805  val_list = pt_values_part (statement);
806  assert (val_list != NULL);
807  if (val_list != NULL)
808  {
809  val = val_list->info.node_list.list;
810  }
811  if (val_list == NULL || val_list->next == NULL)
812  {
813  /* This is a single tuple insert. */
814  /* If gadget cannot be created, attempt to handle it as a regular insert statement. */
815  gadget = db_gadget_create (cname, (const char **) attrs);
816  }
817  else
818  {
819  /* If the this is a multiple tuples insert handle it as a regular insert statement. */
820  assert (gadget == NULL);
821  }
822 
823  if (gadget)
824  {
825  PARSER_CONTEXT *parser = db_get_parser (session);
826  DB_VALUE tmp_val, *insert_value = NULL;
827 
828  /* bind literal values */
829  for (i = 0; val != NULL; i++, val = val->next, insert_value = NULL)
830  {
831  if (val->node_type == PT_HOST_VAR)
832  {
833  continue;
834  }
835  if (pt_is_value_node (val))
836  {
837  insert_value = pt_value_to_db (parser, val);
838  }
839  else if (pt_is_expr_node (val))
840  {
841  /* Try to handle simple expressions so we don't choke on things like negative numbers */
842  if (pt_is_value_node (val->info.expr.arg1)
843  && (!val->info.expr.arg2 || pt_is_value_node (val->info.expr.arg2))
844  && (!val->info.expr.arg3 || pt_is_value_node (val->info.expr.arg3)))
845  {
846  pt_evaluate_tree_having_serial (parser, val, &tmp_val, 1);
847  if (!parser->error_msgs)
848  {
849  insert_value = &tmp_val;
850  }
851  }
852  }
853 
854  if (insert_value == NULL
855  || (db_gadget_bind (gadget, gadget->attrs[i].attr_desc->name, insert_value)) != NO_ERROR)
856  {
857  /* If we've had a binding error or encountered a node type we can't handle, free gadget and run a
858  * regular insert statement */
859  db_gadget_destroy (gadget);
860  gadget = NULL;
861  break;
862  }
863  }
864 
865  /* fake these, which would have been obtained from compiled statement */
866  stmt_id = 0;
867  stmt_type = CUBRID_STMT_INSERT;
868  }
869 
870  free_and_init (attrs);
871  }
872 
873  if (!gadget)
874  {
875  /* non-repetitive or non-insert, or failed gadget */
876  db_push_values (session, db_Value_table.db_value_top, db_Value_table.db_values);
877  stmt_id = db_compile_statement (session);
878  if (stmt_id < 0)
879  {
880  db_close_session (session);
881  CHECK_DBI (true, return);
882  }
883 
884  stmt_type = (CUBRID_STMT_TYPE) db_get_statement_type (session, stmt_id);
885  }
886 
887  if (gadget && alloc_repetitive (stmt_no, session, stmt_id, stmt_type, gadget) == NULL)
888  {
889  db_close_session (session);
890  assert (er_errid () != NO_ERROR);
891  error = er_errid ();
892  CHECK_DBI (error < 0, return);
893  return;
894  }
895  }
896 
897  /* if it brings result, free pointers of previous results */
898  if (HAS_RESULT (stmt_type))
899  {
900  free_pointers ((CURSOR *) NULL);
901  }
902 
903  /* execute the compiled stmt */
904  if (gadget)
905  {
906  DB_VALUE val;
907  DB_OBJECT *obj;
908 
909  /* manufacture query result from object returned from db_gadget_exec */
910  obj = db_gadget_exec (gadget, db_Value_table.db_value_top, db_Value_table.db_values);
911  if (obj)
912  {
913  e = 1;
914  db_make_object (&val, obj);
915  curr_result = db_get_db_value_query_result (&val);
916  }
917  else
918  {
919  assert (er_errid () != NO_ERROR);
920  e = er_errid ();
921  }
922  }
923  else
924  {
925  /* non-repetitive, non-insert, or failed gadget */
926  e = db_execute_statement (session, stmt_id, &curr_result);
927  db_push_values (session, 0, NULL);
928  db_close_session (session);
929  }
930 
931  if (!is_uci_start_state) /* nested stmt was executed */
932  {
934  }
935 
936  CHECK_DBI (e < 0, return);
937 
938  if (AFFECT_OBJECTS (stmt_type))
939  {
941  if (e == 0)
942  {
944  }
945  }
946 
947  if (HAS_RESULT (stmt_type) && curr_result != NULL)
948  {
949 
950  e = db_query_tuple_count (curr_result);
951  if (e < 0)
952  {
953  CHECK_DBI (1, return);
954  }
955  else if (e == 0)
956  {
958  return;
959  }
960  else if (e > 1)
961  {
963  set_sqlca_err ();
964  return;
965  }
966 
967  /* locate the first result object */
968  error = db_query_first_tuple (curr_result);
969  CHECK_DBI (error < 0, return);
970 
972  CHECK_DBI (num_curr_result_columns < 0, return);
973 
974  if (num_out_vars >= 0 && num_out_vars < num_curr_result_columns)
975  {
976  SET_WARN_VARS_MISMATCH (); /* two few output vars */
977  }
978 
979  curr_result_column = 0;
980  }
981 }
982 
983 /*
984  * uci_open_cs() - Execute a statement and create a cursor on the results.
985  * if `stmt' is NULL, it is assumed that the cursor is declared on a prepared
986  * stmt and `stmt_no' indicates the prepared stmt number. otherwise, `stmt'
987  * should points to the stmt string to be executed.
988  * return : void
989  * cs_no(in) : constitute unique cursor id
990  * stmt(in) : statement string if it is not prepared stmt
991  * stmt_no(in) : prepared dynamic statement no
992  * readonly(in) : true if readonly results.
993  */
994 void
995 uci_open_cs (int cs_no, const char *stmt, int length, int stmt_no, int readonly)
996 {
997  DB_SESSION *session;
998  STATEMENT_ID stmt_id;
999  DYNAMIC *dt;
1000  CUBRID_STMT_TYPE stmt_type;
1001  int num_markers;
1002  DB_QUERY_RESULT *tmp_result;
1003  int n;
1004  int error;
1005 
1006  CHK_SQLCODE ();
1007 
1008  if (get_cursor (cs_no) != NULL)
1009  {
1010  /* not closed */
1012  set_sqlca_err ();
1013  return;
1014  }
1015 
1016  if (stmt == NULL)
1017  {
1018  /* prepared statement */
1019  dt = get_dynamic (stmt_no);
1020  if (dt == NULL)
1021  {
1022  /* not prepared yet */
1024  set_sqlca_err ();
1025  return;
1026  }
1027  session = dt->session;
1028  stmt_id = dt->stmt_id;
1029  stmt_type = dt->stmt_type;
1030  num_markers = dt->num_markers;
1031  db_push_values (session, db_Value_table.db_value_top, db_Value_table.db_values);
1032  }
1033  else
1034  {
1035  /* directly given statement */
1036  session = db_open_buffer (stmt);
1037  if (!session)
1038  {
1039  assert (er_errid () != NO_ERROR);
1040  error = er_errid ();
1041  CHECK_DBI (error < 0, return);
1042  }
1043 
1044  db_push_values (session, db_Value_table.db_value_top, db_Value_table.db_values);
1045  db_include_oid (session, !readonly);
1046  stmt_id = db_compile_statement (session);
1047  if (stmt_id < 0)
1048  {
1049  db_close_session (session);
1050  CHECK_DBI (true, return);
1051  }
1052 
1053  num_markers = db_number_of_input_markers (session, stmt_id);
1054  stmt_type = (CUBRID_STMT_TYPE) db_get_statement_type (session, stmt_id);
1055  }
1056 
1057  if (stmt_type != CUBRID_STMT_SELECT)
1058  {
1059  /* cursor stmt should be SELECT */
1061  set_sqlca_err ();
1062  goto error;
1063  }
1064 
1065  if (db_Value_table.db_value_top < num_markers)
1066  {
1067  /* too few input vars */
1068  PUT_UCI_ERR_TOOFEWHOSTVARS (num_markers);
1069  set_sqlca_err ();
1070  goto error;
1071  }
1072  else if (db_Value_table.db_value_top > num_markers) /* too many input vars */
1073  {
1075  }
1076 
1077  /* execute the compiled stmt */
1078  tmp_result = (DB_QUERY_RESULT *) NULL;
1079  n = db_execute_and_keep_statement (session, stmt_id, &tmp_result);
1080  db_push_values (session, 0, NULL);
1081 
1082  if (!is_uci_start_state) /* nested stmt was executed */
1083  {
1085  }
1086 
1087  if (n < 0)
1088  {
1089  goto error;
1090  }
1091 
1093  if (n == 0)
1094  {
1096  }
1097 
1098 #if defined(UCI_TEMPORARY)
1099  alloc_cursor (cs_no, (stmt == NULL) ? 0 : session, (stmt == NULL) ? -1 : stmt_id, tmp_result);
1100 #else
1101  alloc_cursor (cs_no, tmp_result); /* create a cursor */
1102 #endif
1103  return;
1104 
1105 error:
1106  if (stmt != NULL)
1107  {
1108  /* static cursor statement open fail */
1109  db_close_session (session);
1110  }
1111  assert (er_errid () != NO_ERROR);
1112  error = er_errid ();
1113  CHECK_DBI (error < 0, return);
1114 }
1115 
1116 /*
1117  * uci_fetch_cs() - Advance the current result object to next.
1118  * If `num_out_vars' is negative, it does not set warning when # of out
1119  * vars mismatches # of output columns.
1120  * return : void
1121  * cs_no(in) : constitute unique cursor id
1122  * num_out_vars(in) : # of output variables
1123  */
1124 void
1125 uci_fetch_cs (int cs_no, int num_out_vars)
1126 {
1127  CURSOR *cs;
1128  int e;
1129 
1130  CHK_SQLCODE ();
1131  cs = get_cursor (cs_no);
1132  if (cs == NULL)
1133  {
1135  set_sqlca_err ();
1136  return;
1137  }
1138 
1139  free_pointers (cs); /* free previous results if any */
1140 
1141  if (cs->result == NULL)
1142  {
1144  return;
1145  }
1146 
1147  /* advance to next tuple */
1148  e = db_query_next_tuple (cs->result);
1149  CHECK_DBI (e < 0, return);
1150 
1151  if (e == DB_CURSOR_END)
1152  {
1154  return;
1155  }
1156 
1157  cs->fetched_tuples++;
1159 
1161  CHECK_DBI (cs->num_columns < 0, return);
1162  cs->curr_column = 0;
1163 
1164  if (num_out_vars >= 0 && num_out_vars < cs->num_columns)
1165  {
1166  SET_WARN_VARS_MISMATCH (); /* too few output vars */
1167  }
1168 }
1169 
1170 /*
1171  * uci_delete_cs() - Perform delete current object through cursor.
1172  * return : void
1173  * cs_no(in) : cursor number
1174  */
1175 void
1176 uci_delete_cs (int cs_no)
1177 {
1178  CURSOR *cs;
1179  int e;
1180  DB_VALUE oid;
1181 
1182  CHK_SQLCODE ();
1183  cs = get_cursor (cs_no);
1184  if (cs == NULL)
1185  {
1187  set_sqlca_err ();
1188  return;
1189  }
1190 
1191  if (cs->result == NULL)
1192  {
1194  return;
1195  }
1196 
1197  e = db_query_get_tuple_oid (cs->result, &oid);
1198  CHECK_DBI (e < 0, return);
1199 
1200  e = db_drop (db_get_object (&oid));
1201  CHECK_DBI (e < 0, return);
1202 }
1203 
1204 /*
1205  * uci_close_cs() - Remove the specified cursor. if cs_no is negative,
1206  * this function closes all the current cursors
1207  * return : void
1208  * cs_no(in) : cursor identifier
1209  */
1210 void
1211 uci_close_cs (int cs_no)
1212 {
1213  CURSOR *cs;
1214 
1215  CHK_SQLCODE ();
1216 
1217  cs = get_cursor (cs_no);
1218  if (cs == NULL)
1219  {
1221  set_sqlca_err ();
1222  return;
1223  }
1225  free_cursor (cs_no);
1226 }
1227 
1228 /*
1229  * uci_psh_curr_csr_oid() - Push the oid of the current object pointed to
1230  * by the cursor on the stack.
1231  * return : void
1232  * cs_no(in) : constitute unique cursor id
1233  */
1234 void
1236 {
1237  CURSOR *cs;
1238  int e;
1239  DB_VALUE oid;
1240 
1241  CHK_SQLCODE ();
1242 
1243  cs = get_cursor (cs_no);
1244  if (cs == NULL)
1245  {
1247  set_sqlca_err ();
1248  return;
1249  }
1250 
1251  if (cs->result == NULL)
1252  {
1254  return;
1255  }
1256 
1257  e = db_query_get_tuple_oid (cs->result, &oid);
1258  CHECK_DBI (e < 0, return);
1259 
1260  check_stack_size ();
1261  db_Value_table.db_values[db_Value_table.db_value_top++] = oid;
1262 }
1263 
1264 /*
1265  * uci_prepare() - Prepare (compile) a statement. if the statement is already
1266  * exist, replace it by the new statement
1267  * return : void
1268  * stmt_no(in) : statement identifier
1269  * stmt(in) : pointer to statement contents
1270  * length : length of stmt
1271  */
1272 void
1273 uci_prepare (int stmt_no, const char *stmt, int length)
1274 {
1275  DYNAMIC *dt;
1276  int markers;
1277  CUBRID_STMT_TYPE stmt_type;
1278  DB_QUERY_TYPE *col_spec;
1279  DB_SESSION *session;
1280  STATEMENT_ID stmt_id;
1281  int error;
1282 
1283  CHK_SQLCODE ();
1284 
1285  col_spec = (DB_QUERY_TYPE *) NULL;
1286  session = db_open_buffer (stmt);
1287  if (session == NULL)
1288  {
1289  assert (er_errid () != NO_ERROR);
1290  error = er_errid ();
1291  CHECK_DBI (error < 0, return);
1292  }
1293 
1294  stmt_id = db_compile_statement (session);
1295  if (stmt_id < 0)
1296  {
1297  db_close_session (session);
1298  CHECK_DBI (true, return);
1299  }
1300 
1301  markers = db_number_of_input_markers (session, stmt_id);
1302  stmt_type = (CUBRID_STMT_TYPE) db_get_statement_type (session, stmt_id);
1303  col_spec = db_get_query_type_list (session, stmt_id);
1304 
1305  /* register into dynamic stmt table */
1306  dt = alloc_dynamic (stmt_no, stmt_type, session, stmt_id, markers, col_spec, (char *) stmt, length);
1307  if (dt == NULL)
1308  {
1309  if (col_spec != NULL)
1310  {
1311  db_query_format_free (col_spec);
1312  }
1313  db_close_session (session);
1314  assert (er_errid () != NO_ERROR);
1315  error = er_errid ();
1316  CHECK_DBI (error < 0, return);
1317  return;
1318  }
1319 }
1320 
1321 /*
1322  * uci_describe() - Get result attribute information and put it via `desc'
1323  * return : void
1324  * stmt_no(in) : stmt identifier
1325  * desc(out) : pointer to descriptor to be filled with the result column info
1326  */
1327 void
1328 uci_describe (int stmt_no, CUBRIDDA * desc)
1329 {
1330  DYNAMIC *dt;
1331 
1332  CHK_SQLCODE ();
1333 
1334  if (desc == NULL)
1335  {
1336  return;
1337  }
1338 
1339  dt = get_dynamic (stmt_no);
1340  if (dt == NULL)
1341  {
1343  set_sqlca_err ();
1344  return;
1345  }
1346 
1347  desc->sqlcmd = dt->stmt_type;
1348 
1349  if (!HAS_RESULT (dt->stmt_type))
1350  {
1351  desc->sqldesc = 0;
1352  return;
1353  }
1354 
1356 }
1357 
1358 /*
1359  * uci_execute() - Execute the specified stmt. if `num_out_vars' is negative,
1360  * it does not set warning when # of out vars mismatches # of output
1361  * columns.
1362  * return : void
1363  * stmt_no(in) : stmt identifier
1364  * num_out_vars(in) : # of output variables
1365  */
1366 void
1367 uci_execute (int stmt_no, int num_out_vars)
1368 {
1369  DYNAMIC *dt;
1370  int e;
1371 
1372  CHK_SQLCODE ();
1373 
1374  dt = get_dynamic (stmt_no);
1375  if (dt == NULL)
1376  {
1378  set_sqlca_err ();
1379  return;
1380  }
1381 
1382  if (db_Value_table.db_value_top < dt->num_markers)
1383  {
1385  set_sqlca_err ();
1386  return;
1387  }
1388  else if (db_Value_table.db_value_top > dt->num_markers)
1389  {
1391  }
1392 
1393  /* if it brings result, free pointers of previous results */
1394  if (HAS_RESULT (dt->stmt_type))
1395  {
1396  free_pointers ((CURSOR *) NULL);
1397  }
1398 
1399  /* execute the compiled stmt */
1400  db_push_values (dt->session, db_Value_table.db_value_top, db_Value_table.db_values);
1401  e = db_execute_and_keep_statement (dt->session, dt->stmt_id, &curr_result);
1402  db_push_values (dt->session, 0, NULL);
1403 
1404  if (!is_uci_start_state) /* nested stmt was executed */
1405  {
1407  }
1408 
1409  /*
1410  * It is evidently ok to return here without closing dt->session, since
1411  * it will be closed by alloc_dynamic() the next time we need a
1412  * statement.
1413  */
1414  CHECK_DBI (e < 0, return);
1415 
1416  if (AFFECT_OBJECTS (dt->stmt_type))
1417  {
1419  if (e == 0)
1420  {
1422  }
1423  }
1424 
1425  if (HAS_RESULT (dt->stmt_type) && curr_result != NULL)
1426  {
1427 
1428  e = db_query_tuple_count (curr_result);
1429  CHECK_DBI (e < 0, return);
1430  if (e > 1)
1431  {
1433  set_sqlca_err ();
1434  return;
1435  }
1436 
1437  /* locate the first result object */
1438  e = db_query_first_tuple (curr_result);
1439  CHECK_DBI (e < 0, return);
1440 
1442  CHECK_DBI (num_curr_result_columns < 0, return);
1443 
1444  if (num_out_vars >= 0 && num_out_vars < num_curr_result_columns)
1445  {
1447  }
1448 
1449  curr_result_column = 0;
1450  }
1451 }
1452 
1453 /*
1454  * uci_execute_immediate() - Execute statement without using host variables.
1455  * return : void
1456  * stmt(in) : pointer to statement contents
1457  * length(in) : length of stmt
1458  */
1459 void
1460 uci_execute_immediate (const char *stmt, int length)
1461 {
1462  DB_SESSION *session;
1463  STATEMENT_ID stmt_id;
1464  int markers;
1465  CUBRID_STMT_TYPE stmt_type;
1466  int e;
1467  DB_QUERY_RESULT *dummy_result;
1468 
1469  CHK_SQLCODE ();
1470 
1471  session = db_open_buffer (stmt);
1472  if (!session)
1473  {
1474  assert (er_errid () != NO_ERROR);
1475  e = er_errid ();
1476  CHECK_DBI (e < 0, return);
1477  }
1478 
1479  db_push_values (session, 0, NULL);
1480  stmt_id = db_compile_statement (session);
1481  if (stmt_id < 0)
1482  {
1483  db_close_session (session);
1484  CHECK_DBI (true, return);
1485  }
1486 
1487  markers = db_number_of_input_markers (session, stmt_id);
1488  stmt_type = (CUBRID_STMT_TYPE) db_get_statement_type (session, stmt_id);
1489 
1490  if (markers > 0)
1491  {
1492  /* no marks are allowed */
1494  set_sqlca_err ();
1495  goto error;
1496  }
1497 
1498  /* execute the compiled stmt */
1499  dummy_result = (DB_QUERY_RESULT *) NULL;
1500  e = db_execute_statement (session, stmt_id, &dummy_result);
1501 
1502  db_close_session (session);
1503 
1504  if (!is_uci_start_state) /* nested stmt was executed */
1505  {
1507  }
1508 
1509  CHECK_DBI (e < 0, return);
1510 
1511  if (AFFECT_OBJECTS (stmt_type))
1512  {
1514  if (e == 0)
1515  {
1517  }
1518  }
1519 
1520  if (dummy_result != NULL) /* throw away the results */
1521  {
1522  e = db_query_end (dummy_result);
1523  CHECK_DBI (e < 0, return);
1524  }
1525 
1526  return;
1527 
1528 error:
1529  /* drop the stmt */
1530  db_close_session (session);
1531  assert (er_errid () != NO_ERROR);
1532  e = er_errid ();
1533  CHECK_DBI (e < 0, return);
1534 }
1535 
1536 /*
1537  * uci_object_describe() - Get the attribute information of the given object
1538  * and pass it via `desc'.
1539  * return : `desc' will be filled with the specified attribute information of
1540  * the object.
1541  *
1542  * obj(in) : pointer to object to be described
1543  * num_attrs(in) : # of attribute names
1544  * attr_names(in) : array of attribute names
1545  * desc(out) : SQLDA where the description will be stored.
1546  */
1547 void
1548 uci_object_describe (DB_OBJECT * obj, int num_attrs, const char **attr_names, CUBRIDDA * desc)
1549 {
1550  DB_QUERY_TYPE *object_col_spec = NULL;
1551  int error;
1552 
1553  CHK_SQLCODE ();
1554 
1555  if (desc == NULL)
1556  {
1557  return;
1558  }
1559 
1560  error = db_object_describe (obj, num_attrs, attr_names, &object_col_spec);
1561  CHECK_DBI (error < 0, return);
1562  copy_column_spec_to_sqlda (object_col_spec, desc);
1563  if (object_col_spec != NULL)
1564  {
1565  db_query_format_free (object_col_spec);
1566  }
1567 }
1568 
1569 /*
1570  * uci_object_fetch() - Get the specified attribute values of the given object.
1571  * if `num_out_vars' is negative, it does not set warning when # of out vars
1572  * mismatches # of output columns.
1573  * return : void
1574  * obj(out) : pointer to the object to be fetched
1575  * num_attrs(in) : # of attribute names
1576  * attr_names(in) : array of attribute names
1577  * num_out_vars(in) : # of output host variables
1578  */
1579 void
1580 uci_object_fetch (DB_OBJECT * obj, int num_attrs, const char **attr_names, int num_out_vars)
1581 {
1582  int error;
1583 
1584  CHK_SQLCODE ();
1585  error = db_object_fetch (obj, num_attrs, attr_names, &curr_result);
1586  CHECK_DBI (error < 0, return);
1587 
1588  error = db_query_first_tuple (curr_result);
1589  CHECK_DBI (error < 0, return);
1590 
1592  CHECK_DBI (num_curr_result_columns < 0, return);
1593  if (num_out_vars >= 0 && num_out_vars < num_curr_result_columns)
1594  {
1595  SET_WARN_VARS_MISMATCH (); /* two few output vars */
1596  }
1597 
1598  curr_result_column = 0;
1599 }
1600 
1601 /*
1602  * check_stack_size() - allocates a new data values stack if needed
1603  * return : void
1604  *
1605  * note : For performance, this function never shrinks the table size.
1606  */
1607 static void
1609 {
1610  DB_VALUE *tmp;
1611  int old_num;
1612 
1613  CHK_SQLCODE ();
1614 
1615  if (db_Value_table.db_value_top < db_Value_table.num_db_values)
1616  {
1617  return;
1618  }
1619 
1620  old_num = db_Value_table.num_db_values;
1621 
1622  if (db_Value_table.num_db_values == 0)
1623  {
1625  tmp = (DB_VALUE *) malloc (sizeof (DB_VALUE) * db_Value_table.num_db_values);
1626  if (tmp == NULL)
1627  {
1628  PUT_UCI_ERR_NOMOREMEMORY (sizeof (DB_VALUE) * db_Value_table.num_db_values);
1629  set_sqlca_err ();
1630  return;
1631  }
1632  }
1633  else
1634  {
1636  tmp = (DB_VALUE *) malloc (sizeof (DB_VALUE) * db_Value_table.num_db_values);
1637  if (tmp == NULL)
1638  {
1639  PUT_UCI_ERR_NOMOREMEMORY (sizeof (DB_VALUE) * db_Value_table.num_db_values);
1640  set_sqlca_err ();
1641  return;
1642  }
1643 
1644  (void) memcpy ((void *) tmp, (const void *) db_Value_table.db_values, sizeof (DB_VALUE) * old_num);
1645  free (db_Value_table.db_values);
1646  }
1647 
1648  db_Value_table.db_values = tmp;
1649 }
1650 
1651 /*
1652  * free_db_values() - free `db_Value_table.db_values' table
1653  * return : void
1654  */
1655 static void
1657 {
1658  while (db_Value_table.db_value_top)
1659  {
1660  db_value_clear (&db_Value_table.db_values[--db_Value_table.db_value_top]);
1661  }
1662 
1663  /*
1664  * free() used intentionally here (rather than free_and_init()) to avoid
1665  * misleading shutdown messages about space leaks.
1666  */
1667  if (db_Value_table.num_db_values > 0)
1668  {
1669  free (db_Value_table.db_values);
1670  db_Value_table.num_db_values = 0;
1671  }
1672 }
1673 
1674 /*
1675  * uci_put_value() - Translates the given C data into a DB_VALUE and stores
1676  * it in the internal db_Value_table.db_values stack. Uses db_value_put
1677  * to take advantage of automatic coercion, etc.
1678  * return : void
1679  *
1680  * indicator(in) : pointer to NULL/non-NULL indicator var
1681  * type(in) : intended DB_TYPE of the input variable
1682  * precision(in) : intended precision of the input variable
1683  * scale(in) : intended scale of the input variable
1684  * ctype(in) : the actual C type of the supplied buffer
1685  * buf(in) : pointer to the actual C data
1686  * bufsize(in) : length of the actual C data
1687  */
1688 void
1689 uci_put_value (DB_INDICATOR * indicator, DB_TYPE type, int precision, int scale, DB_TYPE_C ctype, void *buf,
1690  int bufsize)
1691 {
1692  DB_VALUE *dbval;
1693 
1694  CHK_SQLCODE ();
1695  check_stack_size ();
1696  dbval = &db_Value_table.db_values[db_Value_table.db_value_top++];
1697 
1698  if (indicator && IS_NULL_INDICATED (*indicator))
1699  {
1700  db_make_null (dbval);
1701  return;
1702  }
1703 
1704  if (type == DB_TYPE_DB_VALUE)
1705  {
1706  (void) db_value_clone ((DB_VALUE *) buf, dbval);
1707  return;
1708  }
1709 
1710  /*
1711  * (char *) pointers cause special problems, because there is no way
1712  * for the preprocessor to guess the precision or buffer length.
1713  * Instead, we simply have it emit 0 for those things and then we
1714  * compute them at runtime. strlen() isn't wonderful, but it's all
1715  * we've got. That means that users can't transfer strings with
1716  * embedded nulls using (char *) host vars.
1717  */
1718  if (ctype == DB_TYPE_C_CHAR || ctype == DB_TYPE_C_NCHAR || ctype == DB_TYPE_C_VARCHAR || ctype == DB_TYPE_C_VARNCHAR)
1719  {
1720  int tmp_len = (int) strlen ((char *) buf);
1721  if (precision == 0)
1722  {
1723  precision = (tmp_len ? tmp_len : DB_DEFAULT_PRECISION);
1724  }
1725  if (bufsize == 0)
1726  {
1727  bufsize = tmp_len;
1728  }
1729  if (bufsize > precision)
1730  {
1731  bufsize = precision;
1732  }
1733  }
1734 
1735  if (db_value_domain_init (dbval, type, precision, scale) != NO_ERROR
1736  || db_value_put (dbval, ctype, buf, bufsize) != NO_ERROR)
1737  {
1738  set_sqlca_err ();
1739  }
1740 }
1741 
1742 /*
1743  * uci_get_next_column() - Using DBI interface, get the current column value of
1744  * the result which is specified by `cs_no'. if `cs_no' is negative,
1745  * the `curr_result' is assumed, otherwise, the result which belongs to the
1746  * specified cursor will be used.
1747  * return : error state.
1748  * cs_no(in) : cursor to which result belongs
1749  * dbval(out) : pointer to DB_VALUE struct to be filled
1750  *
1751  * note : contents of `dbval' will be changed to hold
1752  * data from the next column; internal column state of
1753  * the appropriate cursor will be advanced.
1754  *
1755  * description: Using DBI interface, get the current column value of
1756  * the result which is specified by `cs_no'.
1757  * if `cs_no' is negative, the `curr_result' is assumed,
1758  * otherwise, the result which belongs to the specified
1759  * cursor will be used.
1760  */
1761 static int
1762 uci_get_next_column (int cs_no, DB_VALUE * dbval)
1763 {
1764  CURSOR *ct;
1765  DB_QUERY_RESULT *r;
1766  int num_cols;
1767  int current_column;
1768  int error;
1769 
1770  if (SQLCODE == SQL_NOT_FOUND) /* check if NOT FOUND is set */
1771  {
1772  return 1;
1773  }
1774 
1775  if (cs_no >= 0)
1776  {
1777  ct = get_cursor (cs_no);
1778  if (ct == NULL)
1779  {
1781  set_sqlca_err ();
1782  return 1;
1783  }
1784  r = ct->result;
1785  num_cols = ct->num_columns;
1786  current_column = ct->curr_column++;
1787  }
1788  else
1789  {
1790  ct = (CURSOR *) NULL;
1791  r = curr_result;
1792  num_cols = num_curr_result_columns;
1793  current_column = curr_result_column++;
1794  }
1795 
1796  if (r == NULL)
1797  {
1799  return 1;
1800  }
1801  if (current_column >= num_cols)
1802  {
1803  PUT_UCI_ERR_TOOMANYHOSTVARS (num_cols);
1804  set_sqlca_err ();
1805  return 1;
1806  }
1807 
1808  error = db_query_get_tuple_value (r, current_column, dbval);
1809  CHECK_DBI (error < 0, return 1);
1810 
1811  put_pointer (ct, dbval);
1812 
1813  return 0;
1814 }
1815 
1816 /*
1817  * uci_get_value() - Using DBI interface, get the current column value of
1818  * the result which is specified by `cs_no'. If `cs_no' is negative, the
1819  * `curr_result' is assumed, otherwise, the result which belongs to the
1820  * specified cursor will be used.
1821  * return : void
1822  * cs_no(in) - cursor to which result belongs.
1823  * ind(in) - pointer to indicator variable.
1824  * buf(out) - pionter to a C buffer.
1825  * type(in) - type of the host variable in terms of CUBRID.
1826  * size(in) - # of bytes in host variable
1827  * xferlen(out) -
1828  */
1829 void
1830 uci_get_value (int cs_no, DB_INDICATOR * ind, void *buf, DB_TYPE_C type, int size, int *xferlen)
1831 {
1832  DB_VALUE val;
1833  int outlen, tmp_xferlen;
1834  int error;
1835 
1836  CHK_SQLCODE (); /* check previous error */
1837 
1838  if (uci_get_next_column (cs_no, &val))
1839  {
1840  return;
1841  }
1842 
1843  if (xferlen == NULL)
1844  {
1845  xferlen = &tmp_xferlen;
1846  }
1847 
1848  (void) memset (buf, 0, size);
1849  error = db_value_get (&val, type, buf, size, xferlen, &outlen);
1850  CHECK_DBI (error < 0, return);
1851 
1852 #if 0
1853  if (type == DB_TYPE_C_VARCHAR || type == DB_TYPE_C_CHAR)
1854  {
1855  if (outlen != -1)
1856  {
1857  *xferlen += 1;
1858  }
1859  }
1860 #endif
1861 
1862  if (outlen > 0)
1863  {
1864  /*
1865  * If truncation occurred, set the truncation warning flag in the
1866  * SQLCA regardless of whether an indicator variable has been
1867  * supplied.
1868  */
1870  }
1871 
1872  if (ind)
1873  {
1874  /*
1875  * If no truncation occurred (and there's no NULL value), the
1876  * indicator should be set to zero. Truncation will be indicated
1877  * by an outlen that's greater than the buffer size. If truncation
1878  * occurred, the indicator should be set to the original size of
1879  * the truncated value.
1880  */
1881  *ind = outlen;
1882  }
1883  else if (outlen == -1)
1884  {
1885  if (!(_uci_opt & UCI_OPT_UNSAFE_NULL))
1886  {
1888  set_sqlca_err ();
1889  }
1890  }
1891 }
1892 
1893 /*
1894  * uci_get_value_indirect() - Used only from uci_get_descriptor() context,
1895  * and only when the user has declined to give us a buffer area.
1896  * We go ahead and tell him where our internal buffer area is by storing
1897  * its address in *bufp and its size in sizep.
1898  * return : void
1899  * cs_no(in) : cursor to which result belongs
1900  * ind(in) : pointer to indicator variable.
1901  * bufp(out) : pointer to char pointer to receive result
1902  * sizep(out) : pointer to int to receive size of result
1903  */
1904 static void
1905 uci_get_value_indirect (int cs_no, DB_INDICATOR * ind, void **bufp, int *sizep)
1906 {
1907  DB_VALUE val;
1908  DB_TYPE sqltype;
1909 
1910  CHK_SQLCODE ();
1911 
1912  if (uci_get_next_column (cs_no, &val))
1913  {
1914  return;
1915  }
1916 
1917  if (DB_IS_NULL (&val))
1918  {
1919  if (ind)
1920  {
1921  *ind = -1;
1922  }
1923  else
1924  {
1925  if (!(_uci_opt & UCI_OPT_UNSAFE_NULL))
1926  {
1928  set_sqlca_err ();
1929  }
1930  }
1931  return;
1932  }
1933  else if (ind)
1934  {
1935  *ind = 0;
1936  }
1937 
1938  sqltype = DB_VALUE_TYPE (&val);
1939  switch (sqltype)
1940  {
1941  case DB_TYPE_CHAR:
1942  case DB_TYPE_VARCHAR:
1943  {
1944  /*
1945  * Why doesn't this cause us storage management problems?
1946  * It would if the user tried to hang on to the pointer
1947  * for more than a row.
1948  */
1949  *bufp = CONST_CAST (char *, db_get_string (&val));
1950  *sizep = db_get_string_size (&val);
1951  }
1952  break;
1953  case DB_TYPE_NCHAR:
1954  case DB_TYPE_VARNCHAR:
1955  {
1956  *bufp = CONST_CAST (char *, db_get_string (&val));
1957  *sizep = db_get_string_size (&val);
1958  }
1959  break;
1960  case DB_TYPE_BIT:
1961  case DB_TYPE_VARBIT:
1962  {
1963  *bufp = CONST_CAST (char *, db_get_string (&val));
1964  *sizep = db_get_string_size (&val);
1965  }
1966  break;
1967  default:
1968  {
1970  set_sqlca_err ();
1971  }
1972  break;
1973  }
1974 }
1975 
1976 /*
1977  * uci_get_db_value() - This function is special case of 'uci_get_value()'
1978  * when the host variable type is not DB_TYPE, but DB_VALUE
1979  * itself. See uci_get_value().
1980  * return/side-effects: `*db_value_ptr' will be filled with result *
1981  * cs_no(in) : cursor identifier
1982  * db_value_ptr(out) : pointer to user's host variable
1983  */
1984 void
1985 uci_get_db_value (int cs_no, DB_VALUE * db_value_ptr)
1986 {
1987  CURSOR *ct;
1988  DB_QUERY_RESULT *r;
1989  int num_cols;
1990  int *curr_col;
1991  int error;
1992 
1993  CHK_SQLCODE ();
1994 
1995  if (SQLCODE == SQL_NOT_FOUND)
1996  {
1997  return;
1998  }
1999 
2000  if (cs_no >= 0)
2001  {
2002  ct = get_cursor (cs_no);
2003  if (ct == NULL)
2004  {
2006  set_sqlca_err ();
2007  return;
2008  }
2009  r = ct->result;
2010  num_cols = ct->num_columns;
2011  curr_col = &ct->curr_column;
2012  }
2013  else
2014  {
2015  ct = (CURSOR *) NULL;
2016  r = curr_result;
2017  num_cols = num_curr_result_columns;
2018  curr_col = &curr_result_column;
2019  }
2020 
2021  if (r == NULL)
2022  {
2024  return;
2025  }
2026  if (*curr_col >= num_cols)
2027  {
2028  PUT_UCI_ERR_TOOMANYHOSTVARS (num_cols);
2029  set_sqlca_err ();
2030  return;
2031  }
2032 
2033  error = db_query_get_tuple_value (r, *curr_col, db_value_ptr);
2034  CHECK_DBI (error < 0, return);
2035 
2036  if (put_pointer (ct, db_value_ptr) == NULL)
2037  {
2038  return;
2039  }
2040 
2041  (*curr_col)++;
2042 }
2043 
2044 /*
2045  * uci_put_descriptor() - Put user variable information in the given
2046  * 'desc' into 'db_Value_table.db_values' table.
2047  * return : void
2048  * desc(in) : pointer to SQLDA
2049  */
2050 void
2052 {
2053  int i; /* loop counter */
2054  int num_values; /* # of values in SQLDA */
2055  CUBRIDVAR *var; /* alias to sqlca.sqlvar */
2056 
2057  num_values = (desc->sqldesc < 0) ? 0 : desc->sqldesc;
2058 
2059  for (i = 0, var = desc->sqlvar; i < num_values; i++, var++)
2060  {
2061  uci_put_value (var->sqlind, var->sqltype, var->sqlprec, var->sqlscale, var->sqlctype, var->sqldata, var->sqllen);
2062  }
2063 }
2064 
2065 /*
2066  * uci_get_descriptor() - get the current result into the given descriptor.
2067  * return : void
2068  * cs_no(in) : cursor identifier
2069  * desc(out) : pointer to SQLDA variable.
2070  */
2071 void
2072 uci_get_descriptor (int cs_no, CUBRIDDA * desc)
2073 {
2074  int i;
2075  CUBRIDVAR *var;
2076 
2077  for (i = 0, var = desc->sqlvar; i < desc->sqldesc; i++, var++)
2078  {
2079  if (STRING_C_TYPE (var->sqlctype) && (var->sqldata == NULL || var->sqllen == 0))
2080  {
2081  uci_get_value_indirect (cs_no, var->sqlind, &var->sqldata, &var->sqllen);
2082  }
2083  else
2084  {
2085  uci_get_value (cs_no, var->sqlind, (void *) var->sqldata, var->sqlctype, var->sqllen, NULL);
2086  }
2087  }
2088 }
2089 
2090 /*
2091  * alloc_repetitive() - register a new repetitive statement. Since the life
2092  * time of a repetitive statement is not given explicitly
2093  * by users, esql_cli keeps all such statements until
2094  * uci_disconnect() only increasingly.
2095  * return : newly registered entry pointer or NULL on error
2096  * no(in) : repetitive stmt identifier
2097  * session(in) : query compile/execute context
2098  * stmt_id(in) : compiled plan number
2099  * stmt_type(in) : type of the statement
2100  * gadget(in) :
2101  */
2102 static REPETITIVE *
2103 alloc_repetitive (int no, DB_SESSION * session, STATEMENT_ID stmt_id, CUBRID_STMT_TYPE stmt_type, DB_GADGET * gadget)
2104 {
2105  int new_num;
2106  REPETITIVE *rt;
2107  REPETITIVE *t_repetitive;
2108 
2110  {
2111  /* expansion is needed */
2113  t_repetitive =
2115  0) ? (REPETITIVE *) malloc (sizeof (REPETITIVE) * new_num) : (REPETITIVE *) realloc (repetitive_stmts,
2116  sizeof (REPETITIVE) *
2117  new_num);
2118  if (t_repetitive == NULL)
2119  {
2120  PUT_UCI_ERR_NOMOREMEMORY (sizeof (REPETITIVE) * new_num);
2121  set_sqlca_err ();
2122  return ((REPETITIVE *) NULL);
2123  }
2124  else
2125  {
2126  repetitive_stmts = t_repetitive;
2127  }
2128  }
2129 
2130  /* here, the entry indicated by `num_repetitive_stmts' is free */
2131  rt = repetitive_stmts + num_repetitive_stmts;
2132 
2133  /* fill this entry with given information */
2134  rt->file_id = curr_file;
2135  rt->no = no;
2136  rt->session = session;
2137  rt->stmt_id = stmt_id;
2138  rt->stmt_type = stmt_type;
2139  rt->gadget = gadget;
2140 
2141  /* mark the last searched index (`last_repetitive') so that the immediately succeeding get_repetitive() can find this
2142  * entry with minimum cost. And increment # of repetitive statements. */
2143  last_repetitive = num_repetitive_stmts++;
2144 
2145  return (rt);
2146 }
2147 
2148 /*
2149  * get_repetitive() - Search repetitive stmt table to locate the specified
2150  * stmt and return the entry pointer.
2151  * return : an entry of repetitive stmt table or NULL on error.
2152  * no(in) : repetitive stmt identifier
2153  */
2154 static REPETITIVE *
2156 {
2157  int i;
2158  REPETITIVE *rt;
2159  bool found = true;
2160 
2161  if (num_repetitive_stmts <= 0)
2162  {
2163  return ((REPETITIVE *) NULL);
2164  }
2165 
2166  rt = repetitive_stmts;
2167 
2168  i = last_repetitive;
2169  while (rt[i].no != no || rt[i].file_id != curr_file)
2170  {
2171  if (++i == num_repetitive_stmts)
2172  {
2173  i = 0; /* circular search */
2174  }
2175  if (i == last_repetitive)
2176  {
2177  found = false;
2178  break;
2179  }
2180  }
2181  if (found)
2182  {
2183  last_repetitive = i;
2184  return (rt + i);
2185  }
2186  else
2187  {
2188  return ((REPETITIVE *) NULL);
2189  }
2190 }
2191 
2192 /*
2193  * free_repetitive() - free all repetitive stmt entries.
2194  * return : void
2195  */
2196 static void
2198 {
2199  if (num_repetitive_stmts > 0)
2200  {
2201  int i;
2202  REPETITIVE *r;
2203  for (i = 0, r = repetitive_stmts; i < num_repetitive_stmts; i++, r++)
2204  {
2206  if (r->gadget)
2207  {
2209  r->gadget = NULL;
2210  }
2211  }
2212  free_and_init (repetitive_stmts);
2213  num_repetitive_stmts = 0;
2214  }
2215 }
2216 
2217 /*
2218  * alloc_dynamic() - Register a new dynamic statement. Since the life
2219  * time of a dynamic statement is not given explicitly by users, esql_cli
2220  * keeps all such statements until uci_commit/uci_rollback() only
2221  * increasingly.
2222  * return : newly registered entry pointer or NULL on error
2223  * stmt_no(in) : dynamic stmt identifier
2224  * stmt_type(in) : type of the statement
2225  * session(in) : query compile/execute context
2226  * stmt_id(in) : compiled plan number
2227  * num_markers(in) : # of input positional markers
2228  * column_spec(in) : result column spec.
2229  * stmt(in) : statement buffer.
2230  * length(in) : length of stmt.
2231  */
2232 static DYNAMIC *
2233 alloc_dynamic (int stmt_no, CUBRID_STMT_TYPE stmt_type, DB_SESSION * session, STATEMENT_ID stmt_id, int num_markers,
2234  DB_QUERY_TYPE * column_spec, char *stmt, int length)
2235 {
2236  int new_num;
2237  DYNAMIC *dt;
2238  DYNAMIC *t_dynamic;
2239 
2240  dt = get_dynamic (stmt_no);
2241  if (dt != NULL)
2242  {
2243  /* already exist, overwrite */
2245  dt->column_spec = NULL;
2246  db_close_session (dt->session);
2247  if (dt->saved_stmt)
2248  {
2249  free ((void *) dt->saved_stmt);
2250  dt->saved_stmt = NULL;
2251  }
2252  }
2253  else
2254  {
2256  {
2257  /* expansion is needed */
2259  t_dynamic =
2260  (num_dynamic_stmts ==
2261  0) ? (DYNAMIC *) malloc (sizeof (DYNAMIC) * new_num) : (DYNAMIC *) realloc (dynamic_stmts,
2262  sizeof (DYNAMIC) * new_num);
2263  if (t_dynamic == NULL)
2264  {
2265  PUT_UCI_ERR_NOMOREMEMORY (sizeof (DYNAMIC) * new_num);
2266  set_sqlca_err ();
2267  return ((DYNAMIC *) NULL);
2268  }
2269  else
2270  {
2271  dynamic_stmts = t_dynamic;
2272  }
2273  }
2274 
2275  /* here, the entry indicated by `num_dynamic_stmts' is free */
2276  dt = dynamic_stmts + num_dynamic_stmts;
2277  (void) memset (dt, 0, sizeof (DYNAMIC));
2278 
2279  /* mark the last searched index (`last_dynamic') so that the immediately succeeding get_dynamic() can find this
2280  * entry with minimum cost. And increment # of dynamic statements. */
2281  last_dynamic = num_dynamic_stmts++;
2282  }
2283 
2284  /* fill this entry with given information */
2285  dt->file_id = curr_file;
2286  dt->stmt_no = stmt_no;
2287  dt->stmt_type = stmt_type;
2288  dt->session = session;
2289  dt->stmt_id = stmt_id;
2290  dt->num_markers = num_markers;
2291  dt->column_spec = column_spec;
2292 
2293  dt->saved_stmt = strdup (stmt);
2294  dt->saved_length = length;
2295  return (dt);
2296 }
2297 
2298 /*
2299  * get_dynamic() - Search dynamic stmt table to locate the specified
2300  * stmt and return the entry pointer.
2301  * return : An entry of dynamic stmt table or NULL on error.
2302  * stmt_no(in) : dynamic stmt identifier
2303  */
2304 static DYNAMIC *
2305 get_dynamic (int stmt_no)
2306 {
2307  int i;
2308  DYNAMIC *dt;
2309 
2310  if (num_dynamic_stmts <= 0)
2311  {
2312  return ((DYNAMIC *) NULL);
2313  }
2314 
2315  dt = dynamic_stmts;
2316 
2317  i = last_dynamic;
2318  while (dt[i].stmt_no != stmt_no || dt[i].file_id != curr_file)
2319  {
2320  if (++i == num_dynamic_stmts)
2321  {
2322  i = 0; /* circular search */
2323  }
2324  if (i == last_dynamic)
2325  {
2326  return ((DYNAMIC *) NULL);
2327  }
2328  }
2329 
2330  last_dynamic = i;
2331  return (dt + i);
2332 }
2333 
2334 /*
2335  * free_dynamic() - Free all dynamic stmt entries.
2336  * return : void
2337  */
2338 static void
2340 {
2341  int i;
2342  DYNAMIC *dt;
2343 
2344  if (num_dynamic_stmts <= 0)
2345  {
2346  return;
2347  }
2348 
2349  for (i = 0, dt = dynamic_stmts; i < num_dynamic_stmts; i++, dt++)
2350  {
2351  if (dt->column_spec != NULL)
2352  {
2354  dt->column_spec = NULL;
2355  }
2356  db_close_session (dt->session);
2357  if (dt->saved_stmt)
2358  {
2359  free ((void *) dt->saved_stmt);
2360  dt->saved_stmt = NULL;
2361  }
2362  }
2363  free_and_init (dynamic_stmts);
2364 
2365  num_dynamic_stmts = 0;
2366 }
2367 
2368 /*
2369  * alloc_cursor() - create a new cursor structure with the given result and
2370  * returns the newly built entry.
2371  * return : newly registered entry pointer or NULL on error
2372  * no - cursor identifier
2373  * result - pointer to query result structure
2374  */
2375 #if defined(UCI_TEMPORARY)
2376 static CURSOR *
2377 alloc_cursor (int no, DB_SESSION * static_session, STATEMENT_ID static_stmt_id, DB_QUERY_RESULT * result)
2378 #else
2379 static CURSOR *
2380 alloc_cursor (int no, DB_QUERY_RESULT * result)
2381 #endif
2382 {
2383  CURSOR *cs;
2384 
2385  cs = (CURSOR *) malloc (sizeof (CURSOR));
2386  if (cs == NULL)
2387  {
2388  PUT_UCI_ERR_NOMOREMEMORY (sizeof (CURSOR));
2389  set_sqlca_err ();
2390  return ((CURSOR *) NULL);
2391  }
2392 
2393  cs->file_id = curr_file;
2394  cs->no = no;
2395 #if defined(UCI_TEMPORARY)
2396  cs->static_session = static_session;
2397  cs->static_stmt_id = static_stmt_id;
2398 #endif
2399  cs->num_stmt_ids = 0;
2400  cs->result = result;
2401  cs->fetched_tuples = 0;
2402  cs->num_pointers = 0;
2403 
2404  /* insert this node at the front of cursor list so that rightly succeeding get_cursor() function (OPEN followed by
2405  * FETCH statement) can find this entry with minimum cost. */
2406  cs->next = cursor_list;
2407  cursor_list = cs;
2408 
2409  return (cs);
2410 }
2411 
2412 /*
2413  * get_cursor() - Search cursor list to locate the specified cursor and
2414  * return the entry pointer.
2415  * return : An entry of cursor stmt table or NULL on error.
2416  * no(in) : cursor identifier
2417  */
2418 static CURSOR *
2419 get_cursor (int no)
2420 {
2421  CURSOR *cs;
2422 
2423  for (cs = cursor_list; cs != NULL; cs = cs->next)
2424  {
2425  if (cs->no == no && cs->file_id == curr_file)
2426  {
2427  break;
2428  }
2429  }
2430  return (cs);
2431 }
2432 
2433 /*
2434  * free_cursor() - free the specified cursor entry. If 'no' is negative,
2435  * free all cursors.
2436  * return : void
2437  * no(in) - cursor identifier
2438  *
2439  * note: this function does not set error code even though the cursor
2440  * is not found (i.e., it's assumed already removed).
2441  */
2442 static void
2443 free_cursor (int no)
2444 {
2445  CURSOR *cs;
2446  CURSOR **p_cs;
2447  int i;
2448 
2449  for (p_cs = &cursor_list; *p_cs != NULL;)
2450  {
2451 
2452  if ((no < 0) || ((*p_cs)->no == no && (*p_cs)->file_id == curr_file))
2453  {
2454  cs = *p_cs; /* set alias to speed up */
2455 
2456  /* free compiled plans */
2457  if (cs->num_stmt_ids > 0)
2458  {
2459  for (i = 0; i < cs->num_stmt_ids; i++)
2460  {
2462  }
2463  free_and_init (cs->stmt_ids);
2464  }
2465 
2466  /* free results */
2467  if (cs->result != NULL)
2468  {
2469  /*
2470  * db_query_end() may "fail" if if there was a runtime error in
2471  * the statement it is associated with. That is of no concern
2472  * here, and we need to make sure that we continue on to clean up
2473  * the various structures.
2474  */
2475  (void) db_query_end (cs->result);
2476  }
2477 
2478 #if defined(UCI_TEMPORARY)
2479  if (cs->static_session && cs->static_stmt_id >= 0)
2480  {
2481  db_close_session (cs->static_session);
2482  }
2483 #endif
2484 
2485  /* free pointers */
2486  free_pointers (cs);
2487 
2488  /* remove the entry, but, p_cs is not changed */
2489  *p_cs = (*p_cs)->next;
2490  free_and_init (cs);
2491 
2492  /* the specified entry is removed? */
2493  if (no >= 0)
2494  {
2495  return;
2496  }
2497  }
2498  else
2499  {
2500  p_cs = &(*p_cs)->next;
2501  }
2502  }
2503 }
2504 
2505 /*
2506  * put_pointer() - Put an address which should be freed when the result
2507  * pointed by the address is not used any more into the pointer table.
2508  * 'cs' will indicate the cursor with which the result is associated.
2509  * If cs' is NULL, it is assumed that the result is associated with
2510  * non-cursor statement.
2511  * return : newly registered entry pointer or NULL on error
2512  * cs(in) : pointer to cursor
2513  * value(in) : pointer to the space where the result is stored.
2514  */
2515 static POINTER *
2516 put_pointer (CURSOR * cs, DB_VALUE * value)
2517 {
2518  int new_num;
2519  POINTER **p_p;
2520  int *p_n;
2521  POINTER *pt;
2522  POINTER *t_pointer;
2523 
2524  if (cs == NULL)
2525  {
2526  /* non-cursor related */
2527  p_p = &pointers;
2528  p_n = &num_pointers;
2529  }
2530  else
2531  {
2532  p_p = &cs->pointers;
2533  p_n = &cs->num_pointers;
2534  }
2535 
2536  if (*p_n % POINTER_EXPANSION_UNIT == 0)
2537  {
2538  /* expansion is needed */
2539  new_num = *p_n + POINTER_EXPANSION_UNIT;
2540  if (*p_n == 0)
2541  {
2542  t_pointer = (POINTER *) malloc (sizeof (POINTER) * new_num);
2543  }
2544  else
2545  {
2546  t_pointer = (POINTER *) realloc (*p_p, sizeof (POINTER) * new_num);
2547  }
2548  if (t_pointer == NULL)
2549  {
2550  PUT_UCI_ERR_NOMOREMEMORY (sizeof (POINTER) * new_num);
2551  set_sqlca_err ();
2552  return ((POINTER *) NULL);
2553  }
2554  else
2555  {
2556  *p_p = t_pointer;
2557  }
2558  }
2559 
2560  /* here, the entry indicated by `*p_n' is free */
2561  pt = *p_p + *p_n;
2562 
2563  /* fill this entry with given information */
2564  pt->value_copy = *value;
2565 
2566  (*p_n)++;
2567 
2568  return (pt);
2569 }
2570 
2571 /*
2572  * free_pointers() - Free all spaces to be alloated to store the result values
2573  * which is associated with the given cursor. if `cs' is NULL, free the
2574  * spaces which is associated with non-cursor statements.
2575  * return : void
2576  * cs : pointer to cursor table entry
2577  */
2578 static void
2580 {
2581  int i;
2582  POINTER *p;
2583  int *pn;
2584 
2585  if (cs == NULL)
2586  {
2587  /* non-cursor related */
2588  p = pointers;
2589  pn = &num_pointers;
2590  }
2591  else
2592  {
2593  p = cs->pointers;
2594  pn = &cs->num_pointers;
2595  }
2596 
2597  if (*pn > 0)
2598  {
2599  for (i = 0; i < *pn; i++)
2600  {
2601  db_value_clear (&p[i].value_copy);
2602  }
2603  free_and_init (p);
2604  *pn = 0;
2605  }
2606 }
2607 
2608 /*
2609  * copy_column_spec_to_sqlda() - Fill SQLDA information from the given result
2610  * column information. If `col_spec' is NULL, it is assumed that there is
2611  * no result column.
2612  * return : void
2613  * col_spec(in) : result column spec
2614  * desc(out) : SQLDA pointer
2615  *
2616  * NOTE: desc->sqlmax should notifies # of sqlvars entries which are
2617  * allocated by users. After this function, desc->sqldesc will
2618  * have the # of sqlvars which is described.
2619  */
2620 static void
2622 {
2623  int i;
2624  DB_DOMAIN *domain;
2625 
2626  for (i = 0; col_spec != NULL; col_spec = db_query_format_next (col_spec), i++)
2627  {
2628 
2629  if (i >= desc->sqlmax) /* not suffcient sqlvars */
2630  {
2631  continue;
2632  }
2633 
2634  domain = db_query_format_domain (col_spec);
2635 
2636  desc->sqlvar[i].sqltype = TP_DOMAIN_TYPE (domain);
2637  desc->sqlvar[i].sqlprec = db_domain_precision (domain);
2638  desc->sqlvar[i].sqlscale = db_domain_scale (domain);
2639  desc->sqlvar[i].sqllen = db_query_format_size (col_spec);
2640  desc->sqlvar[i].sqlname = db_query_format_name (col_spec);
2641 
2642  /* for undefined type, we'd better tell users to use DB_VALUE itself instead of just DB_TYPE_NULL. */
2643  if (desc->sqlvar[i].sqltype == DB_TYPE_NULL)
2644  {
2645  desc->sqlvar[i].sqltype = DB_TYPE_DB_VALUE;
2646  desc->sqlvar[i].sqllen = sizeof (DB_VALUE);
2647  }
2648  }
2649  desc->sqldesc = i;
2650 }
2651 
2652 /*
2653  * set_sqlca_err() - get the current error information from CUBRID. And
2654  * copy them into SQLCA.
2655  * return : void
2656  */
2657 static void
2659 {
2660  const char *msg;
2661 
2662  if (SQLCODE != 0)
2663  {
2664  return;
2665  }
2666 
2667  assert (er_errid () != NO_ERROR);
2668  SQLCODE = er_errid ();
2669  msg = er_msg ();
2670  strncpy (SQLERRMC, (msg == NULL) ? "" : msg, sizeof (SQLERRMC) - 1);
2671  SQLERRMC[sizeof (SQLERRMC) - 1] = '\0';
2672  SQLERRML = (int) strlen (SQLERRMC);
2673 }
2674 
2675 /*
2676  * push_uci_environment() - push the stmt-sensitive global variables into
2677  * the top of stack. In order to see what variables are pushed, see the
2678  * documentation in this file.
2679  * return : NO_ERROR or error code
2680  */
2681 static int
2683 {
2685  int new_size;
2686 
2688  {
2689  /* expansion is needed */
2691  t =
2692  (UCI_ENV_STACK_ENTRY *) ((num_uci_env_stack_entries == 0) ? malloc (new_size) :
2693  realloc (uci_env_stack, new_size));
2694  if (t == NULL)
2695  {
2696  PUT_UCI_ERR_NOMOREMEMORY (new_size);
2697  set_sqlca_err ();
2698  return (ER_OUT_OF_VIRTUAL_MEMORY);
2699  }
2700  uci_env_stack = t;
2702  }
2703 
2705  t = uci_env_stack + uci_env_stack_top;
2706 
2707  /* save stmt-sentisive variables */
2708 
2709  /* special treatement of SQLCA fields. For many field except warning do not have to be saved because they are all
2710  * initial status before execute a statement. Therefore, they'll not be saved, but will be re-initialized at the pop
2711  * operation time. */
2712  memmove (&t->saved_sqlca_sqlwarn, &sqlca.sqlwarn, sizeof (sqlca.sqlwarn));
2713  t->saved_db_values = db_Value_table.db_values;
2714  t->saved_num_db_values = db_Value_table.num_db_values;
2715  t->saved_db_value_top = db_Value_table.db_value_top;
2719 
2720  /* special consideration of db_Value_table.db_values array - since uci functions would re-use the array for
2721  * performance, we should reset the db_Value_table.num_db_values to allocate new table. */
2722  db_Value_table.num_db_values = 0;
2723  db_Value_table.db_value_top = 0;
2724 
2725  return (NO_ERROR);
2726 }
2727 
2728 /*
2729  * pop_uci_environment() - pop the variables from the top of stack. In order
2730  * to see what variables are popped, see the documentation in this file.
2731  * the global variables will be changed to the original value.
2732  * return : return void.
2733  */
2734 static void
2736 {
2738 
2739  t = uci_env_stack + uci_env_stack_top;
2740 
2741  /* special consideration of db_Value_table.db_values array - since it will not be accessed any more, it should be
2742  * freed. */
2743  free_db_values ();
2744 
2745  memmove (&sqlca.sqlwarn, &t->saved_sqlca_sqlwarn, sizeof (sqlca.sqlwarn));
2746  db_Value_table.db_values = (DB_VALUE *) t->saved_db_values;
2747  db_Value_table.num_db_values = t->saved_num_db_values;
2748  db_Value_table.db_value_top = t->saved_db_value_top;
2752 
2753  /* the followings were not saved because we already know the previous status (initially all zeros). */
2754  SQLCODE = 0;
2755  if (SQLERRML > 0)
2756  {
2757  SQLERRML = 0;
2758  SQLERRMC[0] = '\0';
2759  }
2761 
2762  uci_env_stack_top--;
2763 }
2764 
2765 /*
2766  * drop_uci_env_stack() - Free the statement environment stack.
2767  * return : void.
2768  */
2769 static void
2771 {
2772  if (num_uci_env_stack_entries > 0)
2773  {
2774  free_and_init (uci_env_stack);
2776  uci_env_stack_top = -1;
2777  }
2778 }
2779 
2780 /*
2781  * clean_up() - take care of clean-up esql_cli stuffs if abmornal things happen.
2782  * return : return void.
2783  *
2784  * NOTE: currently, this function takes care of only the followings
2785  * ER_LK_UNILATERALLY_ABORTED
2786  * ER_TM_SERVER_DOWN_UNILATERALLY_ABORTED
2787  */
2788 static void
2789 clean_up (void)
2790 {
2791  switch (er_errid ())
2792  {
2793 
2795  {
2796  /* transaction aborted unilaterally, but, server is running */
2797  free_cursor (-1);
2798  free_pointers ((CURSOR *) NULL);
2799  free_dynamic ();
2800  }
2801  break;
2802 
2804  {
2805  /* server down */
2806  free_cursor (-1);
2807  free_pointers ((CURSOR *) NULL);
2808  free_dynamic ();
2809  free_repetitive ();
2810  free_db_values ();
2811  drop_uci_env_stack ();
2812  connected = false;
2813  }
2814  break;
2815 
2816  default:
2817  break;
2818  }
2819 }
2820 
2821 #if !defined(UCI_TEMPORARY)
2822 #error "We should move READONLY_SELECT flag to db_execute() \
2823 for reduce overhead of cursor on dynamic stmts."
2824 #endif
2825 
2826 #if !defined(UCI_TEMPORARY)
2827 #error "We should provide another function/language to get \
2828 Full error message"
2829 #endif
void uci_close_cs(int cs_no)
Definition: esql_cli.c:1211
#define pt_is_expr_node(n)
Definition: parse_tree.h:261
int no
Definition: esql_cli.c:316
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
PT_NODE * next
Definition: parse_tree.h:3447
struct cubridca::@69 sqlwarn
int saved_num_db_values
Definition: esql_cli.c:334
static void copy_column_spec_to_sqlda(DB_QUERY_TYPE *col_spec, CUBRIDDA *desc)
Definition: esql_cli.c:2621
struct db_value DB_VALUE
Definition: dbtype_def.h:1079
#define PUT_UCI_ERR_CURSORSTILLOPEN()
Definition: esql_cli.c:221
DB_OBJECT * db_gadget_exec(DB_GADGET *gadget, int num_dbvals, DB_VALUE dbvals[])
Definition: esql_gadget.c:255
#define NO_ERROR
Definition: error_code.h:46
CUBRID_STMT_TYPE sqlcmd
Definition: cubrid_esql.h:93
#define HAS_RESULT(stmt_type)
Definition: esql_cli.c:148
struct uci_env_stack_entry UCI_ENV_STACK_ENTRY
long sqlerrd[6]
Definition: cubrid_esql.h:111
#define SQLFILE
Definition: cubrid_esql.h:61
int db_gadget_bind(DB_GADGET *gadget, const char *attribute_name, DB_VALUE *dbval)
Definition: esql_gadget.c:205
void uci_startup(const char *pgm_name)
Definition: esql_cli.c:446
static void set_sqlca_err(void)
Definition: esql_cli.c:2658
void uci_execute(int stmt_no, int num_out_vars)
Definition: esql_cli.c:1367
int saved_length
Definition: esql_cli.c:292
int db_domain_scale(const DB_DOMAIN *domain)
Definition: db_macro.c:4098
int db_login(const char *name, const char *password)
Definition: db_admin.c:804
#define SET_WARN_VARS_MISMATCH()
Definition: esql_cli.c:175
static int num_curr_result_columns
Definition: esql_cli.c:395
char sqlwarn0
Definition: cubrid_esql.h:115
int db_domain_precision(const DB_DOMAIN *domain)
Definition: db_macro.c:4079
#define POINTER_EXPANSION_UNIT
Definition: esql_cli.c:62
long sqlcabc
Definition: cubrid_esql.h:101
static REPETITIVE * alloc_repetitive(int no, DB_SESSION *session, STATEMENT_ID stmt_id, CUBRID_STMT_TYPE stmt_type, DB_GADGET *gadget)
Definition: esql_cli.c:2103
void uci_describe(int stmt_no, CUBRIDDA *desc)
Definition: esql_cli.c:1328
DB_TYPE
Definition: dbtype_def.h:670
void uci_disconnect(void)
Definition: esql_cli.c:639
#define PUT_UCI_ERR_NOMARKALLOWED()
Definition: esql_cli.c:231
DB_QUERY_RESULT * db_get_db_value_query_result(DB_VALUE *val)
Definition: db_query.c:1998
void uci_fetch_cs(int cs_no, int num_out_vars)
Definition: esql_cli.c:1125
struct cursor * next
Definition: esql_cli.c:326
static int curr_lineno
Definition: esql_cli.c:391
struct repetitive REPETITIVE
#define SQLLINE
Definition: cubrid_esql.h:62
int db_value_clone(DB_VALUE *src, DB_VALUE *dest)
Definition: db_macro.c:1564
void uci_put_value(DB_INDICATOR *indicator, DB_TYPE type, int precision, int scale, DB_TYPE_C ctype, void *buf, int bufsize)
Definition: esql_cli.c:1689
static REPETITIVE * repetitive_stmts
Definition: esql_cli.c:365
static REPETITIVE * get_repetitive(int no)
Definition: esql_cli.c:2155
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
static int uci_env_stack_top
Definition: esql_cli.c:407
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
void * file_id
Definition: esql_cli.c:284
#define SQLCA_NULL_IN_AGG
Definition: esql_cli.c:160
char sqlwarn1
Definition: cubrid_esql.h:116
int db_shutdown(void)
Definition: db_admin.c:964
#define PUT_UCI_ERR_INVALIDDATATYPE()
Definition: esql_cli.c:236
#define PUT_UCI_ERR_NOMOREMEMORY(size)
Definition: esql_cli.c:186
static CURSOR * cursor_list
Definition: esql_cli.c:362
static int curr_result_column
Definition: esql_cli.c:396
static void pop_uci_environment(void)
Definition: esql_cli.c:2735
static void free_repetitive(void)
Definition: esql_cli.c:2197
void uci_object_describe(DB_OBJECT *obj, int num_attrs, const char **attr_names, CUBRIDDA *desc)
Definition: esql_cli.c:1548
PARSER_CONTEXT * db_get_parser(DB_SESSION *session)
Definition: db_vdb.c:3714
static int push_uci_environment(void)
Definition: esql_cli.c:2682
void * saved_curr_file
Definition: esql_cli.c:336
int saved_curr_lineno
Definition: esql_cli.c:338
void uci_execute_immediate(const char *stmt, int length)
Definition: esql_cli.c:1460
int sqllen
Definition: cubrid_esql.h:83
#define AFFECT_OBJECTS(stmt_type)
Definition: esql_cli.c:142
void db_query_format_free(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1723
static CURSOR * alloc_cursor(int no, DB_QUERY_RESULT *result)
Definition: esql_cli.c:2380
DB_SESSION * session
Definition: esql_cli.c:301
static DYNAMIC * get_dynamic(int stmt_no)
Definition: esql_cli.c:2305
#define PUT_UCI_ERR_CURSORNOTOPENED()
Definition: esql_cli.c:216
#define PUT_UCI_ERR_NOTPREPAREDSTMT()
Definition: esql_cli.c:206
unsigned int _uci_opt
Definition: esql_cli.c:345
#define SQLCODE
Definition: cubrid_esql.h:60
void uci_get_value(int cs_no, DB_INDICATOR *ind, void *buf, DB_TYPE_C type, int size, int *xferlen)
Definition: esql_cli.c:1830
int er_errid(void)
DB_INDICATOR * sqlind
Definition: cubrid_esql.h:84
void * file_id
Definition: esql_cli.c:267
static int last_dynamic
Definition: esql_cli.c:380
void uci_get_db_value(int cs_no, DB_VALUE *db_value_ptr)
Definition: esql_cli.c:1985
static bool is_uci_start_state
Definition: esql_cli.c:402
int db_query_get_tuple_oid(DB_QUERY_RESULT *result, DB_VALUE *db_value)
Definition: db_query.c:3195
struct cursor CURSOR
int curr_column
Definition: esql_cli.c:323
DB_ATTDESC * attr_desc
Definition: esql_gadget.h:37
const char * saved_curr_filename
Definition: esql_cli.c:337
SM_DOMAIN * db_query_format_domain(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1661
const char * pt_get_name(PT_NODE *nam)
#define PUT_UCI_ERR_TOOMANYHOSTVARS(num_cols)
Definition: esql_cli.c:196
struct dynamic DYNAMIC
DB_SESSION * session
Definition: esql_cli.c:269
#define SQLERRMC
Definition: cubrid_esql.h:64
static int num_repetitive_stmts
Definition: esql_cli.c:366
char * saved_stmt
Definition: esql_cli.c:291
#define PUT_UCI_ERR_NOTSELECTSTMT()
Definition: esql_cli.c:211
#define SQLCA_OUTPUT_TRUNC
Definition: esql_cli.c:159
DB_QUERY_TYPE * db_query_format_next(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1577
static void free_db_values(void)
Definition: esql_cli.c:1656
int db_value_top
Definition: esql_cli.c:358
char * db_query_format_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1609
DB_NODE * db_get_statement(DB_SESSION *session, int id)
Definition: db_vdb.c:3729
int STATEMENT_ID
Definition: dbtype_def.h:302
void db_gadget_destroy(DB_GADGET *gadget)
Definition: esql_gadget.c:163
#define DYNAMIC_EXPANSION_UNIT
Definition: esql_cli.c:61
char sqlwarn3
Definition: cubrid_esql.h:118
int db_restart(const char *program, int print_version, const char *volume)
Definition: db_admin.c:868
#define STRING_C_TYPE(s)
Definition: esql_cli.c:134
char sqlwarn5
Definition: cubrid_esql.h:120
char sqlcaid[8]
Definition: cubrid_esql.h:100
CUBRIDVAR sqlvar[1]
Definition: cubrid_esql.h:94
DB_QUERY_TYPE * column_spec
Definition: esql_cli.c:290
int db_object_fetch(DB_OBJECT *obj, int num_attrs, const char **attrs, DB_QUERY_RESULT **result)
char sqlwarn7
Definition: cubrid_esql.h:122
static void check_stack_size(void)
Definition: esql_cli.c:1608
char * sqlname
Definition: cubrid_esql.h:85
Definition: esql_cli.c:330
#define assert(x)
void * saved_db_values
Definition: esql_cli.c:333
#define CHECK_DBI(predicate, err_action)
Definition: esql_cli.c:112
STATEMENT_ID stmt_id
Definition: esql_cli.c:270
static CURSOR * get_cursor(int no)
Definition: esql_cli.c:2419
void * file_id
Definition: esql_cli.c:311
struct cs_stmt_id CS_STMT_ID
static int last_repetitive
Definition: esql_cli.c:371
DB_TYPE_C
Definition: dbtype_def.h:1116
CUBRIDCA sqlca
Definition: esql_cli.c:346
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
char sqlwarn6
Definition: cubrid_esql.h:121
PT_NODE * pt_class_part(const PT_NODE *statement)
PT_NODE * pt_attrs_part(const PT_NODE *insert_statement)
#define SQLERRML
Definition: cubrid_esql.h:63
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define UCI_OPT_UNSAFE_NULL
Definition: esql_cli.c:57
int db_execute_and_keep_statement(DB_SESSION *session, int stmt_ndx, DB_QUERY_RESULT **result)
Definition: db_vdb.c:2906
void uci_put_descriptor(CUBRIDDA *desc)
Definition: esql_cli.c:2051
#define SQLCA_NO_WHERE
Definition: esql_cli.c:162
void uci_get_descriptor(int cs_no, CUBRIDDA *desc)
Definition: esql_cli.c:2072
static const char * curr_filename
Definition: esql_cli.c:390
void pt_evaluate_tree_having_serial(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *db_value, int vals_cnt)
const char * sqlfile
Definition: cubrid_esql.h:103
static void uci_get_value_indirect(int cs_no, DB_INDICATOR *ind, void **bufp, int *sizep)
Definition: esql_cli.c:1905
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
long sqlline
Definition: cubrid_esql.h:104
void uci_start(void *file_id, const char *filename, int lineno, unsigned int opt)
Definition: esql_cli.c:491
long sqlcode
Definition: cubrid_esql.h:102
DB_GADGET * db_gadget_create(const char *class_name, const char *attribute_names[])
Definition: esql_gadget.c:51
CUBRID_STMT_TYPE stmt_type
Definition: esql_cli.c:286
static int num_dynamic_stmts
Definition: esql_cli.c:375
#define DB_VALS_STCK_EXPANSION_UNIT
Definition: esql_cli.c:65
POINTER * pointers
Definition: esql_cli.c:324
void uci_prepare(int stmt_no, const char *stmt, int length)
Definition: esql_cli.c:1273
static bool connected
Definition: esql_cli.c:399
DB_OBJECT * db_get_object(const DB_VALUE *value)
void uci_rollback(void)
Definition: esql_cli.c:697
int db_abort_transaction(void)
Definition: db_admin.c:1114
#define TP_DOMAIN_TYPE(dom)
short DB_INDICATOR
Definition: cubrid_esql.h:73
int saved_db_value_top
Definition: esql_cli.c:335
int db_execute_statement(DB_SESSION *session, int stmt_ndx, DB_QUERY_RESULT **result)
Definition: db_vdb.c:2978
DB_VALUE value_copy
Definition: esql_cli.c:259
#define IS_NULL_INDICATED(ind)
Definition: esql_cli.c:67
SP_PARSER_CTX * parser
#define NULL
Definition: freelistheap.h:34
const char * er_msg(void)
#define SET_WARN_OUTPUT_TRUNC()
Definition: esql_cli.c:167
int db_drop(DB_OBJECT *obj)
Definition: db_obj.c:190
if(extra_options)
Definition: dynamic_load.c:958
DB_SESSION * db_open_buffer(const char *buffer)
Definition: db_vdb.c:232
bool prm_get_commit_on_shutdown(void)
char sqlerrp[8]
Definition: cubrid_esql.h:110
DB_TYPE sqltype
Definition: cubrid_esql.h:78
void db_include_oid(DB_SESSION *session, int include_oid)
Definition: db_vdb.c:1508
int db_compile_statement(DB_SESSION *session)
Definition: db_vdb.c:766
void db_close_session(DB_SESSION *session)
Definition: db_vdb.c:3319
#define SQLCA_NUM_AFFECTED_OBJECTS
Definition: esql_cli.c:157
#define SQLCA_VARS_MISMATCH
Definition: esql_cli.c:161
int last_stmt_id
Definition: esql_cli.c:319
void uci_commit(void)
Definition: esql_cli.c:676
struct cubridca CUBRIDCA
void uci_psh_curr_csr_oid(int cs_no)
Definition: esql_cli.c:1235
void uci_end(void)
Definition: esql_cli.c:542
#define CONST_CAST(dest_type, expr)
Definition: porting.h:1060
int num_stmt_ids
Definition: esql_cli.c:317
char * db_name
int num_pointers
Definition: esql_cli.c:325
#define PUT_UCI_ERR_NULLINDNEEDED()
Definition: esql_cli.c:201
CS_STMT_ID * stmt_ids
Definition: esql_cli.c:318
PT_NODE * pt_from_entity_part(const PT_NODE *node)
char sqlext[8]
Definition: cubrid_esql.h:124
void uci_static(int stmt_no, const char *stmt, int length, int num_out_vars)
Definition: esql_cli.c:733
int db_query_column_count(DB_QUERY_RESULT *result)
Definition: db_query.c:3134
#define pt_is_value_node(n)
Definition: parse_tree.h:266
static void error(const char *msg)
Definition: gencat.c:331
short sqlerrml
Definition: cubrid_esql.h:107
DB_SESSION * session
Definition: esql_cli.c:287
int db_get_statement_type(DB_SESSION *session, int stmt)
Definition: db_vdb.c:1473
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
int db_query_next_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2088
static void clean_up(void)
Definition: esql_cli.c:2789
struct pointer POINTER
void uci_delete_cs(int cs_no)
Definition: esql_cli.c:1176
int db_query_format_size(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1704
STATEMENT_ID stmt_id
Definition: esql_cli.c:288
const char * au_get_public_user_name(void)
static void free_dynamic(void)
Definition: esql_cli.c:2339
int stmt_no
Definition: esql_cli.c:285
CUBRID_STMT_TYPE
Definition: cas_dbms_util.h:40
#define PUT_UCI_ERR_MULTIPLEOBJECTS()
Definition: esql_cli.c:226
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
static int num_pointers
Definition: esql_cli.c:384
int num_db_values
Definition: esql_cli.c:357
DB_QUERY_RESULT * result
Definition: esql_cli.c:320
CUBRID_STMT_TYPE stmt_type
Definition: esql_cli.c:271
int db_push_values(DB_SESSION *session, int count, DB_VALUE *in_values)
Definition: db_vdb.c:1527
STATEMENT_ID stmt_id
Definition: esql_cli.c:302
DB_GADGET * gadget
Definition: esql_cli.c:272
static void free_pointers(CURSOR *cs)
Definition: esql_cli.c:2579
long uci_get_sqlcode(void)
Definition: esql_cli.c:583
int db_value_put(DB_VALUE *value, const DB_TYPE_C c_type, void *input, const int input_length)
Definition: db_macro.c:1256
void * sqldata
Definition: cubrid_esql.h:82
PT_NODE * pt_values_part(const PT_NODE *insert_statement)
int sqlprec
Definition: cubrid_esql.h:79
void uci_connect(const char *db_name, const char *user_name, const char *passwd)
Definition: esql_cli.c:611
int db_object_describe(DB_OBJECT *obj, int num_attrs, const char **attrs, DB_QUERY_TYPE **col_spec)
int db_get_string_size(const DB_VALUE *value)
int db_value_get(DB_VALUE *value, const DB_TYPE_C c_type, void *buf, const int buflen, int *xflen, int *outlen)
Definition: db_macro.c:2077
DB_QUERY_TYPE * db_get_query_type_list(DB_SESSION *session, int stmt_ndx)
Definition: db_vdb.c:1341
#define SQLCA_IS_WARNING
Definition: esql_cli.c:158
static POINTER * put_pointer(CURSOR *cs, DB_VALUE *addr)
Definition: esql_cli.c:2516
#define ER_TM_SERVER_DOWN_UNILATERALLY_ABORTED
Definition: error_code.h:171
PT_NODE * error_msgs
Definition: parse_tree.h:3550
static UCI_ENV_STACK_ENTRY * uci_env_stack
Definition: esql_cli.c:405
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int sqldesc
Definition: cubrid_esql.h:92
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
DB_TYPE_C sqlctype
Definition: cubrid_esql.h:81
#define DB_IS_NULL(value)
Definition: dbtype.h:63
for(p=libs;*p;p++)
Definition: dynamic_load.c:968
char * strdup(const char *str)
Definition: porting.c:901
ATTR_VAL * attrs
Definition: esql_gadget.h:45
static DYNAMIC * alloc_dynamic(int stmt_no, CUBRID_STMT_TYPE stmt_type, DB_SESSION *session, STATEMENT_ID stmt_id, int num_markers, DB_QUERY_TYPE *col_spec, char *stmt, int length)
Definition: esql_cli.c:2233
int num_markers
Definition: esql_cli.c:289
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
char saved_sqlca_sqlwarn[sizeof(((CUBRIDCA *) 0) ->sqlwarn)]
Definition: esql_cli.c:332
int num_columns
Definition: esql_cli.c:322
#define SQL_NOT_FOUND
Definition: cubrid_esql.h:43
static char program_name[PATH_MAX]
Definition: esql_cli.c:351
static DB_QUERY_RESULT * curr_result
Definition: esql_cli.c:394
static int num_uci_env_stack_entries
Definition: esql_cli.c:406
long fetched_tuples
Definition: esql_cli.c:321
DB_INDICATOR uci_null_ind
Definition: esql_cli.c:347
struct cubridca::@68 sqlerrm
static struct @70 db_Value_table
static POINTER * pointers
Definition: esql_cli.c:383
void uci_object_fetch(DB_OBJECT *obj, int num_attrs, const char **attr_names, int num_out_vars)
Definition: esql_cli.c:1580
DB_VALUE * default_value
Definition: esql_cli.c:348
int pt_length_of_list(const PT_NODE *list)
#define CHK_SQLCODE()
Definition: esql_cli.c:77
#define DB_CURSOR_END
Definition: dbtype_def.h:167
#define UCI_ENV_STACK_EXPANSION_UNIT
Definition: esql_cli.c:64
static void free_cursor(int no)
Definition: esql_cli.c:2443
DB_VALUE * pt_value_to_db(PARSER_CONTEXT *parser, PT_NODE *value)
Definition: parse_dbi.c:1088
int db_number_of_input_markers(DB_SESSION *session, int stmt)
Definition: db_vdb.c:1125
static void drop_uci_env_stack(void)
Definition: esql_cli.c:2770
char uci_get_sqlwarn_0(void)
Definition: esql_cli.c:593
int sqlscale
Definition: cubrid_esql.h:80
char sqlwarn4
Definition: cubrid_esql.h:119
char sqlerrmc[512]
Definition: cubrid_esql.h:108
void uci_open_cs(int cs_no, const char *stmt, int length, int stmt_no, int readonly)
Definition: esql_cli.c:995
#define REPETITIVE_EXPANSION_UNIT
Definition: esql_cli.c:60
const char ** p
Definition: dynamic_load.c:945
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define PUT_UCI_ERR_TOOFEWHOSTVARS(num_markers)
Definition: esql_cli.c:191
static DYNAMIC * dynamic_stmts
Definition: esql_cli.c:374
int db_query_tuple_count(DB_QUERY_RESULT *result)
Definition: db_query.c:3089
int db_commit_transaction(void)
Definition: db_admin.c:1091
static void * curr_file
Definition: esql_cli.c:389
DB_VALUE * db_values
Definition: esql_cli.c:356
int sqlmax
Definition: cubrid_esql.h:91
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
char sqlwarn2
Definition: cubrid_esql.h:117
void uci_stop(void)
Definition: esql_cli.c:563
static int uci_get_next_column(int cs_no, DB_VALUE *dbval)
Definition: esql_cli.c:1762