CUBRID Engine  latest
csql_result.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  * csql_result.c : Query execution / result handling routine
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <assert.h>
28 #include <float.h>
29 #include <setjmp.h>
30 #include <signal.h>
31 
32 #include "csql.h"
33 #include "dbtran_def.h"
34 #include "dbtype.h"
35 #include "memory_alloc.h"
36 #include "object_primitive.h"
37 #include "porting.h"
38 #include "transaction_cl.h"
39 
40 #if defined (SUPPRESS_STRLEN_WARNING)
41 #define strlen(s1) ((int) strlen(s1))
42 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
43 
44 /* max columns to display each data type
45  * NOTE: some of these are totally dependent on report-writer's
46  * rendering library.
47  */
48 #define MAX_SHORT_DISPLAY_LENGTH 6
49 #define MAX_INTEGER_DISPLAY_LENGTH 11
50 #define MAX_BIGINT_DISPLAY_LENGTH 20
51 #define MAX_FLOAT_DISPLAY_LENGTH (FLT_DIG + 7)
52 #define MAX_DOUBLE_DISPLAY_LENGTH (DBL_DIG + 9)
53 #define MAX_TIME_DISPLAY_LENGTH 11
54 #define MAX_TIMEZONE_DISPLAY_LENGTH 18
55 #define MAX_UTIME_DISPLAY_LENGTH 25
56 #define MAX_TIMESTAMPTZ_DISPLAY_LENGTH \
57  (MAX_UTIME_DISPLAY_LENGTH + MAX_TIMEZONE_DISPLAY_LENGTH)
58 #define MAX_DATETIME_DISPLAY_LENGTH 29
59 #define MAX_DATETIMETZ_DISPLAY_LENGTH \
60  (MAX_DATETIME_DISPLAY_LENGTH + MAX_TIMEZONE_DISPLAY_LENGTH)
61 #define MAX_DATE_DISPLAY_LENGTH 10
62 #define MAX_MONETARY_DISPLAY_LENGTH 20
63 #define MAX_DEFAULT_DISPLAY_LENGTH 20
64 #define STRING_TYPE_PREFIX_SUFFIX_LENGTH 2
65 #define NSTRING_TYPE_PREFIX_SUFFIX_LENGTH 3
66 #define BIT_TYPE_PREFIX_SUFFIX_LENGTH 3
67 
68 /* structure for current query result information */
69 typedef struct
70 {
72  int num_attrs;
73  char **attr_names;
80 
81 typedef struct
82 {
84  const char *cmd_string;
86 
88  {CUBRID_STMT_SELECT, "SELECT"},
89  {CUBRID_STMT_SELECT_UPDATE, "SELECT"},
90  {CUBRID_STMT_CALL, "CALL"},
91  {CUBRID_STMT_EVALUATE, "EVALUATE"},
92  {CUBRID_STMT_GET_ISO_LVL, "GET ISOLATION LEVEL"},
93  {CUBRID_STMT_GET_TIMEOUT, "GET LOCK TIMEOUT"},
94  {CUBRID_STMT_GET_OPT_LVL, "GET OPTIMIZATION"},
95  {CUBRID_STMT_GET_TRIGGER, "GET TRIGGER"},
96  {CUBRID_STMT_UPDATE, "UPDATE"},
97  {CUBRID_STMT_DELETE, "DELETE"},
98  {CUBRID_STMT_INSERT, "INSERT"},
99  {CUBRID_STMT_ALTER_CLASS, "ALTER"},
100  {CUBRID_STMT_COMMIT_WORK, "COMMIT"},
101  {CUBRID_STMT_CREATE_CLASS, "CREATE"},
102  {CUBRID_STMT_CREATE_INDEX, "CREATE INDEX"},
103  {CUBRID_STMT_DROP_DATABASE, "DROP LDB"},
104  {CUBRID_STMT_DROP_CLASS, "DROP"},
105  {CUBRID_STMT_DROP_INDEX, "DROP INDEX"},
106  {CUBRID_STMT_ALTER_INDEX, "ALTER INDEX"},
107  {CUBRID_STMT_DROP_LABEL, "DROP "},
108  {CUBRID_STMT_RENAME_CLASS, "RENAME"},
109  {CUBRID_STMT_ROLLBACK_WORK, "ROLLBACK"},
110  {CUBRID_STMT_GRANT, "GRANT"},
111  {CUBRID_STMT_REVOKE, "REVOKE"},
112  {CUBRID_STMT_CREATE_USER, "CREATE USER"},
113  {CUBRID_STMT_DROP_USER, "DROP USER"},
114  {CUBRID_STMT_ALTER_USER, "ALTER USER"},
115  {CUBRID_STMT_UPDATE_STATS, "UPDATE STATISTICS"},
116  {CUBRID_STMT_GET_STATS, "GET STATISTICS"},
117  {CUBRID_STMT_SCOPE, "SCOPE"},
118  {CUBRID_STMT_REGISTER_DATABASE, "REGISTER"},
119  {CUBRID_STMT_CREATE_TRIGGER, "CREATE TRIGGER"},
120  {CUBRID_STMT_DROP_TRIGGER, "DROP TRIGGER"},
121  {CUBRID_STMT_SET_OPT_LVL, "SET OPTIMIZATION"},
122  {CUBRID_STMT_SET_SYS_PARAMS, "SET SYSTEM PARAMETERS"},
123  {CUBRID_STMT_SET_TRIGGER, "SET TRIGGER"},
124  {CUBRID_STMT_SAVEPOINT, "SAVEPOINT"},
125  {CUBRID_STMT_PREPARE, "PREPARE"},
126  {CUBRID_STMT_ATTACH, "ATTACH"},
127  {CUBRID_STMT_USE, "USE/EXCLUDE"},
128  {CUBRID_STMT_REMOVE_TRIGGER, "REMOVE TRIGGER"},
129  {CUBRID_STMT_RENAME_TRIGGER, "RENAME TRIGGER"},
130  {CUBRID_STMT_ON_LDB, "ON LDB"},
131  {CUBRID_STMT_GET_LDB, "GET LDB"},
132  {CUBRID_STMT_SET_LDB, "SET LDB"},
133  {CUBRID_STMT_ALTER_SERIAL, "ALTER SERIAL"},
134  {CUBRID_STMT_CREATE_SERIAL, "CREATE SERIAL"},
135  {CUBRID_STMT_DROP_SERIAL, "DROP SERIAL"},
136  {CUBRID_STMT_CREATE_STORED_PROCEDURE, "CREATE PROCEDURE"},
137  {CUBRID_STMT_DROP_STORED_PROCEDURE, "DROP PROCEDURE"},
138  {CUBRID_STMT_TRUNCATE, "TRUNCATE"},
140  {CUBRID_STMT_DROP_SESSION_VARIABLES, "DROP VARIABLE"},
141  {CUBRID_STMT_DO, "DO"},
142  {CUBRID_STMT_SET_NAMES, "SET NAMES"},
143  {CUBRID_STMT_VACUUM, "VACUUM"},
144  {CUBRID_STMT_SET_TIMEZONE, "SET TIMEZONE"}
145 };
146 
147 static const char *csql_Isolation_level_string[] = {
148  "UNKNOWN",
149  "UNKNOWN",
150  "UNKNOWN",
151  "UNKNOWN",
152  "READ COMMITTED",
153  "REPEATABLE READ",
154  "SERIALIZABLE"
155 };
156 
157 static jmp_buf csql_Jmp_buf;
158 
159 static const char *csql_cmd_string (CUBRID_STMT_TYPE stmt_type, const char *default_string);
160 static void display_empty_result (int stmt_type, int line_no);
161 static char **get_current_result (int **len, const CUR_RESULT_INFO * result_info, bool plain_output, bool query_output,
162  bool loaddb_output, char column_enclosure);
163 static int write_results_to_stream (const CSQL_ARGUMENT * csql_arg, FILE * fp, const CUR_RESULT_INFO * result_info);
164 static char *uncontrol_strdup (const char *from);
165 static char *uncontrol_strndup (const char *from, int length);
166 static int calculate_width (int column_width, int string_width, int origin_width, DB_TYPE attr_type, bool is_null);
167 static bool is_string_type (DB_TYPE type);
168 static bool is_nstring_type (DB_TYPE type);
169 static bool is_bit_type (DB_TYPE type);
170 static bool is_cuttable_type_by_string_width (DB_TYPE type);
171 static bool is_type_that_has_suffix (DB_TYPE type);
172 
173 /*
174  * csql_results() - display the result
175  * return: none
176  * csql_arg(in): csql argument
177  * result(in): query result structure.
178  * attr_spec(in): result attribute spec structure
179  * line_no(in): line number on which the statement appears
180  * stmt_type(in): query statement type
181  *
182  * Note: If `result' is NULL, no results is assumed.
183  */
184 void
185 csql_results (const CSQL_ARGUMENT * csql_arg, DB_QUERY_RESULT * result, DB_QUERY_TYPE * attr_spec, int line_no,
186  CUBRID_STMT_TYPE stmt_type)
187 {
188  int i;
189  DB_QUERY_TYPE *t; /* temp ptr for attr_spec */
190  int err;
191  int *attr_name_lengths = NULL; /* attribute name length array */
192  CUR_RESULT_INFO result_info;
193  int num_attrs = 0;
194  char **attr_names = NULL;
195  int *attr_lengths = NULL;
196  DB_TYPE *attr_types = NULL;
197  int max_attr_name_length = 0;
198 
199  /* trivial case - no results */
200  if (result == NULL || (err = db_query_first_tuple (result)) == DB_CURSOR_END)
201  {
202  if (csql_arg->plain_output == false && csql_arg->query_output == false && csql_arg->loaddb_output == false)
203  {
204  display_empty_result (stmt_type, line_no);
205  }
206  return;
207  }
208 
209  if (err < 0)
210  {
212  goto error;
213  }
214 
215  for (t = attr_spec; t != NULL; t = db_query_format_next (t), num_attrs++)
216  {
217  ;
218  }
219 
220  /* allocate pointer array for attr names and int array for attr lengths */
221  attr_names = (char **) malloc (sizeof (char *) * num_attrs);
222  if (attr_names == NULL)
223  {
225  goto error;
226  }
227  for (i = 0; i < num_attrs; i++)
228  {
229  attr_names[i] = (char *) NULL;
230  }
231  attr_name_lengths = (int *) malloc (sizeof (int) * num_attrs);
232  attr_lengths = (int *) malloc (sizeof (int) * num_attrs);
233  attr_types = (DB_TYPE *) malloc (sizeof (DB_TYPE) * num_attrs);
234  if (attr_name_lengths == NULL || attr_lengths == NULL || attr_types == NULL)
235  {
237  goto error;
238  }
239 
240  /* get the result attribute names */
241 
242  max_attr_name_length = 0;
243 
244  for (i = 0, t = attr_spec; t != NULL; t = db_query_format_next (t), i++)
245  {
246  const char *temp;
247 
248  temp = db_query_format_name (t);
249  if (temp == NULL)
250  {
251  attr_names[i] = (char *) malloc (7);
252  if (attr_names[i] == NULL)
253  {
255  goto error;
256  }
257  strcpy (attr_names[0], "Result");
258  }
259  else
260  {
261  bool is_console_conv = false;
262 
263  /* console encoded attribute name */
265  {
266  char *attr_name_console_encoded = NULL;
267  int attr_name_console_length = -1;
268 
269  /* try to convert attribute name from utf-8 to console */
271  (temp, strlen (temp), &attr_name_console_encoded, &attr_name_console_length) == NO_ERROR)
272  {
273  if (attr_name_console_encoded != NULL)
274  {
275  free_and_init (attr_names[i]);
276  attr_names[i] = attr_name_console_encoded;
277  is_console_conv = true;
278  }
279  }
280  }
281 
282  if (!is_console_conv)
283  {
284  attr_names[i] = uncontrol_strdup (temp);
285  if (attr_names[i] == NULL)
286  {
287  goto error;
288  }
289  }
290  }
291  attr_name_lengths[i] = strlen (attr_names[i]);
292  max_attr_name_length = MAX (max_attr_name_length, attr_name_lengths[i]);
293  attr_types[i] = db_query_format_type (t);
294 
295  switch (attr_types[i])
296  {
297  case DB_TYPE_SHORT:
298  attr_lengths[i] = MAX (MAX_SHORT_DISPLAY_LENGTH, attr_name_lengths[i]);
299  break;
300  case DB_TYPE_INTEGER:
301  attr_lengths[i] = MAX (MAX_INTEGER_DISPLAY_LENGTH, attr_name_lengths[i]);
302  break;
303  case DB_TYPE_BIGINT:
304  attr_lengths[i] = MAX (MAX_BIGINT_DISPLAY_LENGTH, attr_name_lengths[i]);
305  break;
306  case DB_TYPE_FLOAT:
307  attr_lengths[i] = MAX (MAX_FLOAT_DISPLAY_LENGTH, attr_name_lengths[i]);
308  break;
309  case DB_TYPE_DOUBLE:
310  attr_lengths[i] = MAX (MAX_DOUBLE_DISPLAY_LENGTH, attr_name_lengths[i]);
311  break;
312  case DB_TYPE_TIME:
313  attr_lengths[i] = -MAX (MAX_TIME_DISPLAY_LENGTH, attr_name_lengths[i]);
314  break;
315  case DB_TYPE_TIMESTAMP:
316  attr_lengths[i] = -MAX (MAX_UTIME_DISPLAY_LENGTH, attr_name_lengths[i]);
317  break;
318  case DB_TYPE_TIMESTAMPTZ:
320  attr_lengths[i] = -MAX (MAX_TIMESTAMPTZ_DISPLAY_LENGTH, attr_name_lengths[i]);
321  break;
322  case DB_TYPE_DATETIME:
323  attr_lengths[i] = -MAX (MAX_DATETIME_DISPLAY_LENGTH, attr_name_lengths[i]);
324  break;
325  case DB_TYPE_DATETIMETZ:
326  case DB_TYPE_DATETIMELTZ:
327  attr_lengths[i] = -MAX (MAX_DATETIMETZ_DISPLAY_LENGTH, attr_name_lengths[i]);
328  break;
329  case DB_TYPE_DATE:
330  attr_lengths[i] = -MAX (MAX_DATE_DISPLAY_LENGTH, attr_name_lengths[i]);
331  break;
332  case DB_TYPE_MONETARY:
333  attr_lengths[i] = MAX (MAX_MONETARY_DISPLAY_LENGTH, attr_name_lengths[i]);
334  break;
335  default:
336  attr_lengths[i] = -MAX_DEFAULT_DISPLAY_LENGTH;
337  break;
338  }
339  }
340 
341  result_info.query_result = result;
342  result_info.num_attrs = num_attrs;
343  result_info.attr_names = attr_names;
344  result_info.attr_lengths = attr_lengths;
345  result_info.attr_types = attr_types;
346  result_info.max_attr_name_length = max_attr_name_length;
347  result_info.curr_stmt_type = stmt_type;
348  result_info.curr_stmt_line_no = line_no;
349 
350  /*
351  * Write_results_to_stream may need to fetch instances if value type is object or set of objects.
352  * Make sure fetch type is not set to current version since all the versions are identified by
353  * the same OID and snapshot must be considered to reach the visible version again. */
355  if (write_results_to_stream (csql_arg, csql_Output_fp, &result_info) == CSQL_FAILURE)
356  {
358  {
359  goto error;
360  }
361  else
362  {
364  }
365  }
366 
367  /* free memories */
368  if (attr_names != NULL)
369  {
370  for (i = 0; i < num_attrs; i++)
371  {
372  if (attr_names[i] != NULL)
373  {
374  free_and_init (attr_names[i]);
375  }
376  }
377  free_and_init (attr_names);
378  }
379  if (attr_name_lengths != NULL)
380  {
381  free_and_init (attr_name_lengths);
382  }
383  if (attr_lengths != NULL)
384  {
385  free_and_init (attr_lengths);
386  }
387  if (attr_types != NULL)
388  {
389  free_and_init (attr_types);
390  }
391 
392  return;
393 
394 error:
395 
397  {
398  csql_display_csql_err (line_no, 0);
400  /* for correct csql return code */
402  }
403 
404  /* free memories */
405  if (attr_names != NULL)
406  {
407  for (i = 0; i < num_attrs; i++)
408  {
409  if (attr_names[i] != NULL)
410  {
411  free_and_init (attr_names[i]);
412  }
413  }
414  free_and_init (attr_names);
415  }
416  if (attr_name_lengths != NULL)
417  {
418  free_and_init (attr_name_lengths);
419  }
420  if (attr_lengths != NULL)
421  {
422  free_and_init (attr_lengths);
423  }
424  if (attr_types != NULL)
425  {
426  free_and_init (attr_types);
427  }
428 }
429 
430 /*
431  * csql_cmd_string() - return the command string associated with a statement enum
432  * return: const char*
433  * stmt_type(in): statement enum
434  * default_string(in): default command string if stmt_type is invallid
435  */
436 static const char *
437 csql_cmd_string (CUBRID_STMT_TYPE stmt_type, const char *default_string)
438 {
439  int i;
440  int table_size = DIM (csql_Cmd_string_table);
441 
442  for (i = 0; i < table_size; i++)
443  {
444  if (csql_Cmd_string_table[i].stmt_type == stmt_type)
445  {
446  return (csql_Cmd_string_table[i].cmd_string);
447  }
448  }
449  return default_string;
450 }
451 
452 /*
453  * display_empty_result() - display the empty result message
454  * return: none
455  * stmt_type(in): current statement type
456  * line_no(in): current statement line number
457  */
458 static void
459 display_empty_result (int stmt_type, int line_no)
460 {
461  FILE *pf; /* pipe stream to pager */
462 
465  csql_cmd_string ((CUBRID_STMT_TYPE) stmt_type, ""), line_no);
466 
468 
469  csql_fputs ("\n=== ", pf);
471  csql_fputs (" ===\n\n", pf);
474  csql_fputs ("\n", pf);
475 
477 
478  return;
479 }
480 
481 /*
482  * get_current_result() - get the attribute values of the current result
483  * return: pointer newly allocated value array. On error, NULL.
484  * lengths(out): lengths of returned values
485  * result_info(in): pointer to current query result info structure
486  * plain_output(in): refine string for plain output
487  * query_output(in): refine string for query output
488  * loaddb_output(in): refine string for loaddb output
489  * column_enclosure(in): column enclosure for query output
490  *
491  * Note:
492  * Caller should be responsible for free the return array and its elements.
493  */
494 static char **
495 get_current_result (int **lengths, const CUR_RESULT_INFO * result_info, bool plain_output, bool query_output,
496  bool loaddb_output, char column_enclosure)
497 {
498  int i;
499  char **val = NULL; /* temporary array for values */
500  int *len = NULL; /* temporary array for lengths */
502  CUBRID_STMT_TYPE stmt_type = result_info->curr_stmt_type;
503  DB_QUERY_RESULT *result = result_info->query_result;
504  int num_attrs = result_info->num_attrs;
505 
506  db_make_null (&db_value);
507 
508  val = (char **) malloc (sizeof (char *) * num_attrs);
509  if (val == NULL)
510  {
512  goto error;
513  }
514  memset (val, 0, sizeof (char *) * num_attrs);
515 
516  len = (int *) malloc (sizeof (int) * num_attrs);
517  if (len == NULL)
518  {
520  goto error;
521  }
522  memset (len, 0, sizeof (int) * num_attrs);
523 
524  (void) db_query_set_copy_tplvalue (result, 0 /* peek */ );
525 
526  /* get attribute values */
527  for (i = 0; i < num_attrs; i++)
528  {
529  DB_TYPE value_type;
530 
531  if (db_query_get_tuple_value (result, i, &db_value) < 0)
532  {
534  goto error;
535  }
536 
537  value_type = DB_VALUE_TYPE (&db_value);
538 
539  /*
540  * This assert is intended to validate that the server returned the
541  * expected types for the query results. See the note in
542  * pt_print_value () regarding XASL caching.
543  */
544  /*
545  * TODO fix this assert if it fails in valid cases. Perhaps it should
546  * allow DB_TYPE_POINTER? What about DB_TYPE_ERROR?
547  */
548  /*
549  * TODO add a similar check to the ux_* and/or cci_* and/or the server
550  * functions so that the results' types returned through sockets in
551  * CS_MODE are validated.
552  */
553  assert (value_type == DB_TYPE_NULL
554  /* UNKNOWN, maybe host variable */
555  || result_info->attr_types[i] == DB_TYPE_NULL || result_info->attr_types[i] == DB_TYPE_VARIABLE
556  || value_type == result_info->attr_types[i]);
557 
558  switch (value_type)
559  {
560  case DB_TYPE_NULL: /* null value */
561  val[i] = (char *) malloc (5);
562  if (val[i] == NULL)
563  {
565  goto error;
566  }
567  strcpy (val[i], "NULL");
568  break;
569 
570  case DB_TYPE_POINTER: /* pointer type */
571  val[i] = (char *) malloc (40);
572  if (val[i] == NULL)
573  {
575  goto error;
576  }
577  sprintf (val[i], "pointer value (%p)", (void *) db_get_pointer (&db_value));
578  break;
579 
580  case DB_TYPE_ERROR: /* error type */
581  val[i] = (char *) malloc (40);
582  if (val[i] == NULL)
583  {
585  goto error;
586  }
587  sprintf (val[i], "error code (%d)", db_get_error (&db_value));
588  break;
589 
590  default: /* other types */
591  /*
592  * If we are printing the isolation level, we need to
593  * interpret it for the user, not just return a meaningless number.
594  *
595  * Also interpret a lock timeout value of -1
596  */
597  if (stmt_type == CUBRID_STMT_GET_ISO_LVL)
598  {
599  int async_ws, iso_lvl;
600 
601  async_ws = db_get_int (&db_value) & TRAN_ASYNC_WS_BIT;
602  iso_lvl = db_get_int (&db_value) & TRAN_ISO_LVL_BITS;
603 
604  val[i] = (char *) malloc (128);
605  if (val[i] == NULL)
606  {
608  goto error;
609  }
610 
611  if (iso_lvl < 1 || iso_lvl > 6)
612  {
613  iso_lvl = 0;
614  async_ws = false;
615  }
616 
617  sprintf (val[i], "%s%s", csql_Isolation_level_string[iso_lvl], (async_ws ? ", ASYNC WORKSPACE" : ""));
618  }
619  else if ((stmt_type == CUBRID_STMT_GET_TIMEOUT) && (db_get_float (&db_value) == -1.0))
620  {
621  val[i] = (char *) malloc (9);
622  if (val[i] == NULL)
623  {
625  goto error;
626  }
627  strcpy (val[i], "INFINITE");
628  }
629  else
630  {
631  char *temp;
632  CSQL_OUTPUT_TYPE output_type;
633 
634  if (query_output == true)
635  {
636  output_type = CSQL_QUERY_OUTPUT;
637  }
638  else if (loaddb_output == true)
639  {
640  output_type = CSQL_LOADDB_OUTPUT;;
641  }
642  else
643  {
644  output_type = CSQL_UNKNOWN_OUTPUT;
645  }
646 
647  temp = csql_db_value_as_string (&db_value, &len[i], plain_output, output_type, column_enclosure);
648  if (temp == NULL)
649  {
651  goto error;
652  }
653  temp[len[i]] = '\0';
654  val[i] = temp;
655  }
656  }
657 
658  if (len[i] == 0 && val[i])
659  {
660  len[i] = strlen (val[i]);
661  }
662 
663  if (db_value.need_clear)
664  {
665  pr_clear_value (&db_value);
666  }
667  }
668 
669  if (lengths)
670  {
671  *lengths = len;
672  }
673  return (val);
674 
675 error:
676  if (val != NULL)
677  {
678  for (i = 0; i < num_attrs; i++)
679  {
680  if (val[i] != NULL)
681  {
682  free_and_init (val[i]);
683  }
684  }
685  free_and_init (val);
686  }
687  if (len != NULL)
688  {
689  free_and_init (len);
690  }
691  if (db_value.need_clear)
692  {
693  pr_clear_value (&db_value);
694  }
695  return ((char **) NULL);
696 }
697 
698 /*
699  * csql_pipe_handler() - Generic longjmp'ing signal handler used
700  * where we need to catch broken pipe.
701  * return: none
702  * sig(in): signal number
703  */
704 static void
705 csql_pipe_handler (int sig_no)
706 {
707  longjmp (csql_Jmp_buf, 1);
708 }
709 
710 static void (*csql_pipe_save) (int sig);
711 /*
712  * write_results_to_stream()
713  * return: CSQL_FAILURE/CSQL_SUCCESS
714  * csql_arg(in): csql argument
715  * fp(in): file stream pointer
716  * result_info(in): pointer to current query result info structure
717  *
718  * Note: This function may set csql_Error_code CSQL_ERR_SQL_ERROR to indicate
719  * the error
720  */
721 static int
722 write_results_to_stream (const CSQL_ARGUMENT * csql_arg, FILE * fp, const CUR_RESULT_INFO * result_info)
723 {
724  /*
725  * These are volatile to avoid dangerous interaction with the longjmp
726  * handler for SIGPIPE problems. The typedef is necessary so that we
727  * can tell the compiler that the top POINTER is volatile, not the
728  * characters that it eventually points to.
729  */
730  typedef char **value_array;
731  volatile value_array val; /* attribute values array */
732  volatile int error; /* to switch return of CSQL_FAILURE/CSQL_SUCCESS */
733  int i; /* loop counter */
734  int object_no; /* result object count */
735  int e; /* error code from DBI */
736  FILE *pf; /* pipe stream to pager */
737  int n; /* # of cols for a line */
738  CUBRID_STMT_TYPE stmt_type = result_info->curr_stmt_type;
739  DB_QUERY_RESULT *result = result_info->query_result;
740  DB_TYPE *attr_types = result_info->attr_types;
741  int line_no = result_info->curr_stmt_line_no;
742  int num_attrs = result_info->num_attrs;
743  int *attr_lengths = result_info->attr_lengths;
744  char **attr_names = result_info->attr_names;
745  char *refined_attr_name = NULL;
746  char *value = NULL;
747  int max_attr_name_length = result_info->max_attr_name_length;
748  int column_width;
749  int csql_string_width = csql_arg->string_width;
750  char csql_column_delimiter;
751  int value_width;
752  bool is_null;
753 
754  val = (char **) NULL;
755  error = FALSE;
756 
757  /*
758  * Do this *before* the setjmp to avoid the possibility of the value
759  * being clobbered by a longjmp. Even if some internal thing longjmps
760  * to the end of the next block we still need to be able to close the
761  * pipe, so we can't risk having pf set back to some unknown value.
762  */
763  pf = csql_popen (csql_Pager_cmd, fp);
764 
765  if (setjmp (csql_Jmp_buf) == 0)
766  {
767 #if !defined(WINDOWS)
769 #endif /* !WINDOWS */
770 
771  if (csql_arg->plain_output == false && csql_arg->query_output == false && csql_arg->loaddb_output == false)
772  {
773  csql_fputs ("\n=== ", pf);
775  csql_cmd_string (stmt_type, "UNKNOWN"), line_no);
777  csql_fputs (" ===\n\n", pf);
778  }
779 
780  if (db_query_first_tuple (result) < 0)
781  {
783  error = TRUE;
784  }
785  else
786  {
787  if (csql_arg->skip_column_names == true || csql_arg->line_output == true)
788  {
789  ;
790  }
791  else if (csql_arg->plain_output == true || csql_arg->query_output == true)
792  {
793  csql_column_delimiter = (csql_arg->query_output == true) ? csql_arg->column_delimiter : '\t';
794 
795  for (i = 0; i < num_attrs; i++)
796  {
797  refined_attr_name = csql_string_to_plain_string (attr_names[i], strlen (attr_names[i]), NULL);
798  if (refined_attr_name != NULL)
799  {
800  fprintf (pf, "%s", refined_attr_name);
801  free_and_init (refined_attr_name);
802  }
803  else
804  {
805  fprintf (pf, "UNKNOWN");
806  }
807 
808  if (i == num_attrs - 1)
809  {
810  fprintf (pf, "\n");
811  }
812  else
813  {
814  fprintf (pf, "%c", csql_column_delimiter);
815  }
816  }
817  }
818  else if (csql_arg->loaddb_output == true)
819  {
820  fprintf (pf, "%%class [ ] (");
821  for (i = 0; i < num_attrs; i++)
822  {
823  refined_attr_name = csql_string_to_plain_string (attr_names[i], strlen (attr_names[i]), NULL);
824  if (refined_attr_name != NULL)
825  {
826  fprintf (pf, "[%s]", refined_attr_name);
827  free_and_init (refined_attr_name);
828  }
829  else
830  {
831  fprintf (pf, "UNKNOWN");
832  }
833 
834  if (i == num_attrs - 1)
835  {
836  fprintf (pf, ")\n");
837  }
838  else
839  {
840  fprintf (pf, " ");
841  }
842  }
843  }
844  else
845  {
846  for (n = i = 0; i < num_attrs; i++)
847  {
848  fprintf (pf, " %*s", (int) (attr_lengths[i]), attr_names[i]);
849  n += 2 + ((attr_lengths[i] > 0) ? attr_lengths[i] : -attr_lengths[i]);
850  }
851  putc ('\n', pf);
852  for (; n > 0; n--)
853  {
854  putc ('=', pf);
855  }
856  putc ('\n', pf);
857  }
858 
859  for (object_no = 1;; object_no++)
860  {
861  csql_Row_count = object_no;
862  /* free previous result */
863  if (val != NULL)
864  {
865  for (i = 0; i < num_attrs; i++)
866  {
867  free_and_init (val[i]);
868  }
869  free_and_init (val);
870  }
871  int *len = NULL;
872 
873  val =
874  get_current_result (&len, result_info, csql_arg->plain_output, csql_arg->query_output,
875  csql_arg->loaddb_output, csql_arg->column_enclosure);
876  if (val == NULL)
877  {
879  error = TRUE;
880  if (len != NULL)
881  {
882  free (len);
883  }
884  break;
885  }
886 
887  if (csql_arg->line_output == true)
888  {
889  fprintf (pf, "<%05d>", object_no);
890  for (i = 0; i < num_attrs; i++)
891  {
892  fprintf (pf, "%*c", (int) ((i == 0) ? 1 : 8), ' ');
893  fprintf (pf, "%*s: %s\n", (int) (-max_attr_name_length), attr_names[i], val[i]);
894  }
895  /* fflush(pf); */
896  }
897  else if (csql_arg->plain_output == true)
898  {
899  for (i = 0; i < num_attrs - 1; i++)
900  {
901  fprintf (pf, "%s\t", val[i]);
902  }
903  fprintf (pf, "%s\n", val[i]);
904  }
905  else if (csql_arg->query_output == true || csql_arg->loaddb_output == true)
906  {
907  for (i = 0; i < num_attrs - 1; i++)
908  {
909  fprintf (pf, "%s%c", val[i], csql_arg->column_delimiter);
910  }
911  fprintf (pf, "%s\n", val[i]);
912  }
913  else
914  {
915  int padding_size;
916 
917  for (i = 0; i < num_attrs; i++)
918  {
919  if (strcmp ("NULL", val[i]) == 0)
920  {
921  is_null = true;
922  }
923  else
924  {
925  is_null = false;
926  }
927 
928  column_width = csql_get_column_width (attr_names[i]);
929  value_width = calculate_width (column_width, csql_string_width, len[i], attr_types[i], is_null);
930 
931  padding_size =
932  (attr_lengths[i] > 0) ? MAX (attr_lengths[i] - (value_width),
933  0) : MIN (attr_lengths[i] + (value_width), 0);
934 
935  fprintf (pf, " ");
936  if (padding_size > 0)
937  {
938  /* right justified */
939  fprintf (pf, "%*s", (int) padding_size, "");
940  }
941 
942  value = val[i];
943  if (is_type_that_has_suffix (attr_types[i]) && is_null == false)
944  {
945  value[value_width - 1] = '\'';
946  }
947 
948  fwrite (value, 1, value_width, pf);
949 
950  if (padding_size < 0)
951  {
952  /* left justified */
953  fprintf (pf, "%*s", (int) (-padding_size), "");
954  }
955  }
956  putc ('\n', pf);
957  /* fflush(pf); */
958  }
959  if (len != NULL)
960  {
961  free (len);
962  }
963 
964  /* advance to next */
965  e = db_query_next_tuple (result);
966  if (e < 0)
967  {
969  error = TRUE;
970  break;
971  }
972  else if (e == DB_CURSOR_END)
973  {
974  break;
975  }
976  }
977  if (error != TRUE)
978  {
979  putc ('\n', pf);
980  }
981  }
982  }
983 
984  if (pf)
985  {
986  /*
987  * Don't care for a sig pipe error when closing pipe.
988  *
989  * NOTE if I restore to previous signal handler which could be the
990  * system default, the program could exit.
991  * I cannot use the old error handler since I could not longjmp
992  */
993 #if !defined(WINDOWS)
994  (void) os_set_signal_handler (SIGPIPE, SIG_IGN);
995 #endif /* !WINDOWS */
996  csql_pclose (pf, fp);
997  }
998 
999 #if !defined(WINDOWS)
1000  (void) os_set_signal_handler (SIGPIPE, csql_pipe_save);
1001 #endif /* !WINDOWS */
1002 
1003  /* free result */
1004  if (val != NULL)
1005  {
1006  for (i = 0; i < num_attrs; i++)
1007  {
1008  free_and_init (val[i]);
1009  }
1010  free_and_init (val);
1011  }
1012 
1013  return ((error) ? CSQL_FAILURE : CSQL_SUCCESS);
1014 }
1015 
1016 /*
1017  * calcluate_width() - calculate column's width
1018  * return: width
1019  * column_width(in): column width
1020  * string_width(in): string width
1021  * origin_width(in): real width
1022  * attr_type(in): type
1023  * is_null(in): check null
1024  */
1025 int
1026 calculate_width (int column_width, int string_width, int origin_width, DB_TYPE attr_type, bool is_null)
1027 {
1028  int result = 0;
1029 
1030  if (column_width > 0)
1031  {
1032  if (is_null)
1033  {
1034  result = column_width;
1035  }
1036  else if (is_string_type (attr_type))
1037  {
1038  result = column_width + STRING_TYPE_PREFIX_SUFFIX_LENGTH;
1039  }
1040  else if (is_nstring_type (attr_type))
1041  {
1042  result = column_width + NSTRING_TYPE_PREFIX_SUFFIX_LENGTH;
1043  }
1044  else if (is_bit_type (attr_type))
1045  {
1046  result = column_width + BIT_TYPE_PREFIX_SUFFIX_LENGTH;
1047  }
1048  else
1049  {
1050  result = column_width;
1051  }
1052  }
1053  else if (is_cuttable_type_by_string_width (attr_type) && string_width > 0)
1054  {
1055  if (is_null)
1056  {
1057  result = string_width;
1058  }
1059  else if (is_string_type (attr_type))
1060  {
1061  result = string_width + STRING_TYPE_PREFIX_SUFFIX_LENGTH;
1062  }
1063  else if (is_nstring_type (attr_type))
1064  {
1065  result = string_width + NSTRING_TYPE_PREFIX_SUFFIX_LENGTH;
1066  }
1067  else if (is_bit_type (attr_type))
1068  {
1069  result = string_width + BIT_TYPE_PREFIX_SUFFIX_LENGTH;
1070  }
1071  else
1072  {
1073  result = string_width;
1074  }
1075  }
1076  else
1077  {
1078  result = origin_width;
1079  }
1080 
1081  if (result > origin_width)
1082  {
1083  result = origin_width;
1084  }
1085  if (result < 0)
1086  {
1087  result = 0;
1088  }
1089 
1090  return result;
1091 }
1092 
1093 /*
1094  * is_string_type() - check whether it is a string type or not
1095  * return: bool
1096  * type(in): type
1097  */
1098 static bool
1100 {
1101  switch (type)
1102  {
1103  case DB_TYPE_STRING:
1104  return true;
1105  case DB_TYPE_CHAR:
1106  return true;
1107  default:
1108  return false;
1109  }
1110  return false;
1111 }
1112 
1113 /*
1114  * is_nstring_type() - check whether it is a nstring type or not
1115  * return: bool
1116  * type(in): type
1117  */
1118 static bool
1120 {
1121  switch (type)
1122  {
1123  case DB_TYPE_NCHAR:
1124  return true;
1125  case DB_TYPE_VARNCHAR:
1126  return true;
1127  default:
1128  return false;
1129  }
1130  return false;
1131 }
1132 
1133 /*
1134  * is_bit_type() - check whether it is a bit type or not
1135  * return: bool
1136  * type(in): type
1137  */
1138 static bool
1140 {
1141  switch (type)
1142  {
1143  case DB_TYPE_BIT:
1144  return true;
1145  case DB_TYPE_VARBIT:
1146  return true;
1147  default:
1148  return false;
1149  }
1150  return false;
1151 }
1152 
1153 /*
1154  * is_cuttable_type_by_string_width() - check whether it is cuttable type by string_width or not
1155  * return: bool
1156  * type(in): type
1157  */
1158 static bool
1160 {
1161  return (is_string_type (type) || is_nstring_type (type) || is_bit_type (type));
1162 }
1163 
1164 /*
1165  * is_type_that_has_suffix() - check whether this type has suffix or not
1166  * return: bool
1167  * type(in): type
1168  */
1169 static bool
1171 {
1172  return (is_string_type (type) || is_nstring_type (type) || is_bit_type (type));
1173 }
1174 
1175 /*
1176  * uncontrol_strndup() - variation of strdup()
1177  * return: newly allocated string
1178  * from(in): source string
1179  * length(in): length of source string
1180  */
1181 static char *
1182 uncontrol_strndup (const char *from, int length)
1183 {
1184  char *to;
1185 
1186  /* allocate memory for `to' */
1187  to = (char *) malloc (length + 1);
1188  if (to == NULL)
1189  {
1191  return ((char *) NULL);
1192  }
1193 
1194  memcpy (to, from, length);
1195  to[length] = 0;
1196 
1197  return to;
1198 }
1199 
1200 /*
1201  * uncontrol_strdup() - variation of strdup()
1202  * return: newly allocated string
1203  * from(in): source string
1204  */
1205 static char *
1206 uncontrol_strdup (const char *from)
1207 {
1208  return uncontrol_strndup (from, strlen (from));
1209 }
const char * csql_get_message(int message_index)
Definition: csql.c:2954
DB_C_FLOAT db_get_float(const DB_VALUE *value)
#define NO_ERROR
Definition: error_code.h:46
bool line_output
Definition: csql.h:266
#define TRUE
Definition: broker_admin.c:49
int string_width
Definition: csql.h:277
const char * cmd_string
Definition: csql_result.c:84
#define TRAN_ISO_LVL_BITS
Definition: dbtran_def.h:61
#define MSGCAT_CATALOG_CSQL
static int calculate_width(int column_width, int string_width, int origin_width, DB_TYPE attr_type, bool is_null)
Definition: csql_result.c:1026
static char * uncontrol_strdup(const char *from)
Definition: csql_result.c:1206
static bool is_string_type(DB_TYPE type)
Definition: csql_result.c:1099
int db_get_int(const DB_VALUE *value)
DB_TYPE
Definition: dbtype_def.h:670
char * csql_string_to_plain_string(const char *string_value, int length, int *result_length)
void csql_fputs_console_conv(const char *str, FILE *fp)
Definition: csql_support.c:357
char * csql_db_value_as_string(DB_VALUE *value, int *length, bool plain_string, CSQL_OUTPUT_TYPE output_type, char cloumn_enclosure)
char column_enclosure
Definition: csql.h:280
static CSQL_CMD_STRING_TABLE csql_Cmd_string_table[]
Definition: csql_result.c:87
CSQL_OUTPUT_TYPE
Definition: csql.h:247
int max_attr_name_length
Definition: csql_result.c:76
static char ** get_current_result(int **len, const CUR_RESULT_INFO *result_info, bool plain_output, bool query_output, bool loaddb_output, char column_enclosure)
Definition: csql_result.c:495
DB_QUERY_TYPE * db_query_format_next(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1577
void csql_fputs(const char *str, FILE *fp)
Definition: csql_support.c:322
#define MAX_UTIME_DISPLAY_LENGTH
Definition: csql_result.c:55
char * db_query_format_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1609
#define SCRATCH_TEXT_LEN
Definition: csql.h:152
static bool is_nstring_type(DB_TYPE type)
Definition: csql_result.c:1119
static bool is_bit_type(DB_TYPE type)
Definition: csql_result.c:1139
#define assert(x)
void csql_check_server_down(void)
Definition: csql_support.c:753
bool plain_output
Definition: csql.h:274
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
static bool is_type_that_has_suffix(DB_TYPE type)
Definition: csql_result.c:1170
static bool is_cuttable_type_by_string_width(DB_TYPE type)
Definition: csql_result.c:1159
static int write_results_to_stream(const CSQL_ARGUMENT *csql_arg, FILE *fp, const CUR_RESULT_INFO *result_info)
Definition: csql_result.c:722
#define MAX_DOUBLE_DISPLAY_LENGTH
Definition: csql_result.c:52
#define MAX_DATETIMETZ_DISPLAY_LENGTH
Definition: csql_result.c:59
bool skip_column_names
Definition: csql.h:275
void csql_display_csql_err(int line_no, int col_no)
Definition: csql_support.c:490
#define NULL
Definition: freelistheap.h:34
bool query_output
Definition: csql.h:278
bool loaddb_output
Definition: csql.h:281
CUBRID_STMT_TYPE stmt_type
Definition: csql_result.c:83
#define err(fd,...)
Definition: porting.h:431
CUBRID_STMT_TYPE curr_stmt_type
Definition: csql_result.c:77
#define MSGCAT_CSQL_SET_CSQL
Definition: csql.h:49
#define TM_TRAN_READ_FETCH_VERSION()
static jmp_buf csql_Jmp_buf
Definition: csql_result.c:157
#define MAX_INTEGER_DISPLAY_LENGTH
Definition: csql_result.c:49
#define STRING_TYPE_PREFIX_SUFFIX_LENGTH
Definition: csql_result.c:64
char csql_Scratch_text[SCRATCH_TEXT_LEN]
Definition: csql.c:146
int csql_Num_failures
Definition: csql.c:118
need_clear_type need_clear
Definition: dbtype_def.h:1084
int pr_clear_value(DB_VALUE *value)
FILE * csql_popen(const char *cmd, FILE *fd)
Definition: csql_support.c:396
static char * uncontrol_strndup(const char *from, int length)
Definition: csql_result.c:1182
#define MAX_MONETARY_DISPLAY_LENGTH
Definition: csql_result.c:62
static const char * csql_Isolation_level_string[]
Definition: csql_result.c:147
#define MAX_SHORT_DISPLAY_LENGTH
Definition: csql_result.c:48
void csql_pclose(FILE *pf, FILE *fd)
Definition: csql_support.c:444
static void(* csql_pipe_save)(int sig)
Definition: csql_result.c:710
char column_delimiter
Definition: csql.h:279
static void display_empty_result(int stmt_type, int line_no)
Definition: csql_result.c:459
DB_QUERY_RESULT * query_result
Definition: csql_result.c:71
DB_TYPE * attr_types
Definition: csql_result.c:75
static void error(const char *msg)
Definition: gencat.c:331
#define MAX_FLOAT_DISPLAY_LENGTH
Definition: csql_result.c:51
int db_query_next_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2088
char csql_Pager_cmd[PATH_MAX]
Definition: csql.c:125
char ** attr_names
Definition: csql_result.c:73
int(* csql_text_utf8_to_console)(const char *, const int, char **, int *)
Definition: csql.c:113
int csql_get_column_width(const char *column_name)
Definition: csql.c:3052
CUBRID_STMT_TYPE
Definition: cas_dbms_util.h:40
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
#define BIT_TYPE_PREFIX_SUFFIX_LENGTH
Definition: csql_result.c:66
#define FALSE
Definition: broker_admin.c:50
#define MAX_DATETIME_DISPLAY_LENGTH
Definition: csql_result.c:58
#define MAX_BIGINT_DISPLAY_LENGTH
Definition: csql_result.c:50
int db_query_set_copy_tplvalue(DB_QUERY_RESULT *result, int copy)
Definition: db_query.c:3386
#define MAX_DATE_DISPLAY_LENGTH
Definition: csql_result.c:61
#define MAX_DEFAULT_DISPLAY_LENGTH
Definition: csql_result.c:63
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
void nonscr_display_error(char *buffer, int buf_length)
Definition: csql_support.c:830
int i
Definition: dynamic_load.c:954
FILE * csql_Output_fp
Definition: csql.c:157
static void csql_pipe_handler(int sig_no)
Definition: csql_result.c:705
int db_make_null(DB_VALUE *value)
char * msgcat_message(int cat_id, int set_id, int msg_id)
#define MAX_TIME_DISPLAY_LENGTH
Definition: csql_result.c:53
for(p=libs;*p;p++)
Definition: dynamic_load.c:968
int * attr_lengths
Definition: csql_result.c:74
int db_get_error(const DB_VALUE *value)
int csql_Row_count
Definition: csql.c:117
int db_query_get_tuple_value(DB_QUERY_RESULT *result, int index, DB_VALUE *value)
Definition: db_query.c:2873
void csql_results(const CSQL_ARGUMENT *csql_arg, DB_QUERY_RESULT *result, DB_QUERY_TYPE *attr_spec, int line_no, CUBRID_STMT_TYPE stmt_type)
Definition: csql_result.c:185
int csql_Error_code
Definition: csql.c:148
DB_TYPE db_query_format_type(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1690
#define TRAN_ASYNC_WS_BIT
Definition: dbtran_def.h:60
static const char * csql_cmd_string(CUBRID_STMT_TYPE stmt_type, const char *default_string)
Definition: csql_result.c:437
DB_C_POINTER db_get_pointer(const DB_VALUE *value)
#define DB_CURSOR_END
Definition: dbtype_def.h:167
#define NSTRING_TYPE_PREFIX_SUFFIX_LENGTH
Definition: csql_result.c:65
#define MAX_TIMESTAMPTZ_DISPLAY_LENGTH
Definition: csql_result.c:56
SIGNAL_HANDLER_FUNCTION os_set_signal_handler(const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
Definition: porting.c:1333