PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
data.c
Go to the documentation of this file.
1 /* src/interfaces/ecpg/ecpglib/data.c */
2 
3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
5 
6 #include <stdlib.h>
7 #include <string.h>
8 #include <float.h>
9 #include <math.h>
10 
11 #include "ecpgtype.h"
12 #include "ecpglib.h"
13 #include "ecpgerrno.h"
14 #include "extern.h"
15 #include "sqlca.h"
16 #include "pgtypes_numeric.h"
17 #include "pgtypes_date.h"
18 #include "pgtypes_timestamp.h"
19 #include "pgtypes_interval.h"
20 
21 /* returns true if character c is a delimiter for the given array type */
22 static bool
23 array_delimiter(enum ARRAY_TYPE isarray, char c)
24 {
25  if (isarray == ECPG_ARRAY_ARRAY && c == ',')
26  return true;
27 
28  if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
29  return true;
30 
31  return false;
32 }
33 
34 /* returns true if character c marks the boundary for the given array type */
35 static bool
36 array_boundary(enum ARRAY_TYPE isarray, char c)
37 {
38  if (isarray == ECPG_ARRAY_ARRAY && c == '}')
39  return true;
40 
41  if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
42  return true;
43 
44  return false;
45 }
46 
47 /* returns true if some garbage is found at the end of the scanned string */
48 static bool
49 garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat)
50 {
51  /*
52  * INFORMIX allows for selecting a numeric into an int, the result is
53  * truncated
54  */
55  if (isarray == ECPG_ARRAY_NONE)
56  {
57  if (INFORMIX_MODE(compat) && *scan_length == '.')
58  return false;
59 
60  if (*scan_length != ' ' && *scan_length != '\0')
61  return true;
62  }
63  else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, *scan_length) && !array_boundary(isarray, *scan_length))
64  return true;
65 
66  return false;
67 }
68 
69 /* stolen code from src/backend/utils/adt/float.c */
70 #if defined(WIN32) && !defined(NAN)
71 static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
72 
73 #define NAN (*(const double *) nan)
74 #endif
75 
76 static double
78 {
79 #ifdef INFINITY
80  return (double) INFINITY;
81 #else
82  return (double) (HUGE_VAL * HUGE_VAL);
83 #endif
84 }
85 
86 static double
88 {
89  /* (double) NAN doesn't work on some NetBSD/MIPS releases */
90 #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
91  return (double) NAN;
92 #else
93  return (double) (0.0 / 0.0);
94 #endif
95 }
96 
97 static bool
98 check_special_value(char *ptr, double *retval, char **endptr)
99 {
100  if (pg_strncasecmp(ptr, "NaN", 3) == 0)
101  {
102  *retval = get_float8_nan();
103  *endptr = ptr + 3;
104  return true;
105  }
106  else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
107  {
108  *retval = get_float8_infinity();
109  *endptr = ptr + 8;
110  return true;
111  }
112  else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
113  {
114  *retval = -get_float8_infinity();
115  *endptr = ptr + 9;
116  return true;
117  }
118 
119  return false;
120 }
121 
122 bool
123 ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
124  enum ECPGttype type, enum ECPGttype ind_type,
125  char *var, char *ind, long varcharsize, long offset,
126  long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
127 {
128  struct sqlca_t *sqlca = ECPGget_sqlca();
129  char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
130  int binary = PQfformat(results, act_field);
131  int size = PQgetlength(results, act_tuple, act_field);
132  int value_for_indicator = 0;
133  long log_offset;
134 
135  if (sqlca == NULL)
136  {
139  return (false);
140  }
141 
142  /*
143  * If we are running in a regression test, do not log the offset variable,
144  * it depends on the machine's alignment.
145  */
147  log_offset = -1;
148  else
149  log_offset = offset;
150 
151  ecpg_log("ecpg_get_data on line %d: RESULT: %s offset: %ld; array: %s\n", lineno, pval ? (binary ? "BINARY" : pval) : "EMPTY", log_offset, ECPG_IS_ARRAY(isarray) ? "yes" : "no");
152 
153  /* pval is a pointer to the value */
154  if (!pval)
155  {
156  /*
157  * This should never happen because we already checked that we found
158  * at least one tuple, but let's play it safe.
159  */
161  return (false);
162  }
163 
164  /* We will have to decode the value */
165 
166  /*
167  * check for null value and set indicator accordingly, i.e. -1 if NULL and
168  * 0 if not
169  */
170  if (PQgetisnull(results, act_tuple, act_field))
171  value_for_indicator = -1;
172 
173  switch (ind_type)
174  {
175  case ECPGt_short:
177  *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
178  break;
179  case ECPGt_int:
180  case ECPGt_unsigned_int:
181  *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
182  break;
183  case ECPGt_long:
184  case ECPGt_unsigned_long:
185  *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
186  break;
187 #ifdef HAVE_LONG_LONG_INT
188  case ECPGt_long_long:
190  *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
191  break;
192 #endif /* HAVE_LONG_LONG_INT */
193  case ECPGt_NO_INDICATOR:
194  if (value_for_indicator == -1)
195  {
196  if (force_indicator == false)
197  {
198  /*
199  * Informix has an additional way to specify NULLs note
200  * that this uses special values to denote NULL
201  */
202  ECPGset_noind_null(type, var + offset * act_tuple);
203  }
204  else
205  {
208  NULL);
209  return (false);
210  }
211  }
212  break;
213  default:
216  ecpg_type_name(ind_type));
217  return (false);
218  break;
219  }
220 
221  if (value_for_indicator == -1)
222  return (true);
223 
224  /* let's check if it really is an array if it should be one */
225  if (isarray == ECPG_ARRAY_ARRAY)
226  {
227  if (*pval != '{')
228  {
231  return (false);
232  }
233 
234  switch (type)
235  {
236  case ECPGt_char:
237  case ECPGt_unsigned_char:
238  case ECPGt_varchar:
239  case ECPGt_string:
240  break;
241 
242  default:
243  pval++;
244  break;
245  }
246  }
247 
248  do
249  {
250  if (binary)
251  {
252  if (varcharsize == 0 || varcharsize * offset >= size)
253  memcpy(var + offset * act_tuple, pval, size);
254  else
255  {
256  memcpy(var + offset * act_tuple, pval, varcharsize * offset);
257 
258  if (varcharsize * offset < size)
259  {
260  /* truncation */
261  switch (ind_type)
262  {
263  case ECPGt_short:
265  *((short *) (ind + ind_offset * act_tuple)) = size;
266  break;
267  case ECPGt_int:
268  case ECPGt_unsigned_int:
269  *((int *) (ind + ind_offset * act_tuple)) = size;
270  break;
271  case ECPGt_long:
272  case ECPGt_unsigned_long:
273  *((long *) (ind + ind_offset * act_tuple)) = size;
274  break;
275 #ifdef HAVE_LONG_LONG_INT
276  case ECPGt_long_long:
278  *((long long int *) (ind + ind_offset * act_tuple)) = size;
279  break;
280 #endif /* HAVE_LONG_LONG_INT */
281  default:
282  break;
283  }
284  sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
285  }
286  }
287  pval += size;
288  }
289  else
290  {
291  switch (type)
292  {
293  long res;
294  unsigned long ures;
295  double dres;
296  char *scan_length;
297  numeric *nres;
298  date ddres;
299  timestamp tres;
300  interval *ires;
301  char *endptr,
302  endchar;
303 
304  case ECPGt_short:
305  case ECPGt_int:
306  case ECPGt_long:
307  res = strtol(pval, &scan_length, 10);
308  if (garbage_left(isarray, scan_length, compat))
309  {
310  ecpg_raise(lineno, ECPG_INT_FORMAT,
312  return (false);
313  }
314  pval = scan_length;
315 
316  switch (type)
317  {
318  case ECPGt_short:
319  *((short *) (var + offset * act_tuple)) = (short) res;
320  break;
321  case ECPGt_int:
322  *((int *) (var + offset * act_tuple)) = (int) res;
323  break;
324  case ECPGt_long:
325  *((long *) (var + offset * act_tuple)) = (long) res;
326  break;
327  default:
328  /* Cannot happen */
329  break;
330  }
331  break;
332 
334  case ECPGt_unsigned_int:
335  case ECPGt_unsigned_long:
336  ures = strtoul(pval, &scan_length, 10);
337  if (garbage_left(isarray, scan_length, compat))
338  {
341  return (false);
342  }
343  pval = scan_length;
344 
345  switch (type)
346  {
348  *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
349  break;
350  case ECPGt_unsigned_int:
351  *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
352  break;
353  case ECPGt_unsigned_long:
354  *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
355  break;
356  default:
357  /* Cannot happen */
358  break;
359  }
360  break;
361 
362 #ifdef HAVE_LONG_LONG_INT
363 #ifdef HAVE_STRTOLL
364  case ECPGt_long_long:
365  *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
366  if (garbage_left(isarray, scan_length, compat))
367  {
369  return (false);
370  }
371  pval = scan_length;
372 
373  break;
374 #endif /* HAVE_STRTOLL */
375 #ifdef HAVE_STRTOULL
377  *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
378  if (garbage_left(isarray, scan_length, compat))
379  {
381  return (false);
382  }
383  pval = scan_length;
384 
385  break;
386 #endif /* HAVE_STRTOULL */
387 #endif /* HAVE_LONG_LONG_INT */
388 
389  case ECPGt_float:
390  case ECPGt_double:
391  if (isarray && *pval == '"')
392  pval++;
393 
394  if (!check_special_value(pval, &dres, &scan_length))
395  dres = strtod(pval, &scan_length);
396 
397  if (isarray && *scan_length == '"')
398  scan_length++;
399 
400  if (garbage_left(isarray, scan_length, compat))
401  {
404  return (false);
405  }
406  pval = scan_length;
407 
408  switch (type)
409  {
410  case ECPGt_float:
411  *((float *) (var + offset * act_tuple)) = dres;
412  break;
413  case ECPGt_double:
414  *((double *) (var + offset * act_tuple)) = dres;
415  break;
416  default:
417  /* Cannot happen */
418  break;
419  }
420  break;
421 
422  case ECPGt_bool:
423  if (pval[0] == 'f' && pval[1] == '\0')
424  {
425  *((bool *) (var + offset * act_tuple)) = false;
426  pval++;
427  break;
428  }
429  else if (pval[0] == 't' && pval[1] == '\0')
430  {
431  *((bool *) (var + offset * act_tuple)) = true;
432  pval++;
433  break;
434  }
435  else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
436  {
437  /* NULL is valid */
438  break;
439  }
440 
443  return (false);
444  break;
445 
446  case ECPGt_char:
447  case ECPGt_unsigned_char:
448  case ECPGt_string:
449  {
450  char *str = (char *) (var + offset * act_tuple);
451 
452  /*
453  * If varcharsize is unknown and the offset is that of
454  * char *, then this variable represents the array of
455  * character pointers. So, use extra indirection.
456  */
457  if (varcharsize == 0 && offset == sizeof(char *))
458  str = *(char **) str;
459 
460  if (varcharsize == 0 || varcharsize > size)
461  {
462  strncpy(str, pval, size + 1);
463  /* do the rtrim() */
464  if (type == ECPGt_string)
465  {
466  char *last = str + size;
467 
468  while (last > str && (*last == ' ' || *last == '\0'))
469  {
470  *last = '\0';
471  last--;
472  }
473  }
474  }
475  else
476  {
477  strncpy(str, pval, varcharsize);
478 
479  if (varcharsize < size)
480  {
481  /* truncation */
482  switch (ind_type)
483  {
484  case ECPGt_short:
486  *((short *) (ind + ind_offset * act_tuple)) = size;
487  break;
488  case ECPGt_int:
489  case ECPGt_unsigned_int:
490  *((int *) (ind + ind_offset * act_tuple)) = size;
491  break;
492  case ECPGt_long:
493  case ECPGt_unsigned_long:
494  *((long *) (ind + ind_offset * act_tuple)) = size;
495  break;
496 #ifdef HAVE_LONG_LONG_INT
497  case ECPGt_long_long:
499  *((long long int *) (ind + ind_offset * act_tuple)) = size;
500  break;
501 #endif /* HAVE_LONG_LONG_INT */
502  default:
503  break;
504  }
505  sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
506  }
507  }
508  pval += size;
509  }
510  break;
511 
512  case ECPGt_varchar:
513  {
514  struct ECPGgeneric_varchar *variable =
515  (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
516 
517  variable->len = size;
518  if (varcharsize == 0)
519  strncpy(variable->arr, pval, variable->len);
520  else
521  {
522  strncpy(variable->arr, pval, varcharsize);
523 
524  if (variable->len > varcharsize)
525  {
526  /* truncation */
527  switch (ind_type)
528  {
529  case ECPGt_short:
531  *((short *) (ind + ind_offset * act_tuple)) = variable->len;
532  break;
533  case ECPGt_int:
534  case ECPGt_unsigned_int:
535  *((int *) (ind + ind_offset * act_tuple)) = variable->len;
536  break;
537  case ECPGt_long:
538  case ECPGt_unsigned_long:
539  *((long *) (ind + ind_offset * act_tuple)) = variable->len;
540  break;
541 #ifdef HAVE_LONG_LONG_INT
542  case ECPGt_long_long:
544  *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
545  break;
546 #endif /* HAVE_LONG_LONG_INT */
547  default:
548  break;
549  }
550  sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
551 
552  variable->len = varcharsize;
553  }
554  }
555  pval += size;
556  }
557  break;
558 
559  case ECPGt_decimal:
560  case ECPGt_numeric:
561  for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
562  endchar = *endptr;
563  *endptr = '\0';
564  nres = PGTYPESnumeric_from_asc(pval, &scan_length);
565  *endptr = endchar;
566 
567  /* did we get an error? */
568  if (nres == NULL)
569  {
570  ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
571  lineno, pval, errno);
572 
573  if (INFORMIX_MODE(compat))
574  {
575  /*
576  * Informix wants its own NULL value here instead
577  * of an error
578  */
579  nres = PGTYPESnumeric_new();
580  if (nres)
582  else
583  {
586  return (false);
587  }
588  }
589  else
590  {
593  return (false);
594  }
595  }
596  else
597  {
598  if (!isarray && garbage_left(isarray, scan_length, compat))
599  {
600  free(nres);
603  return (false);
604  }
605  }
606  pval = scan_length;
607 
608  if (type == ECPGt_numeric)
609  PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
610  else
611  PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
612 
613  PGTYPESnumeric_free(nres);
614  break;
615 
616  case ECPGt_interval:
617  if (*pval == '"')
618  pval++;
619 
620  for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
621  endchar = *endptr;
622  *endptr = '\0';
623  ires = PGTYPESinterval_from_asc(pval, &scan_length);
624  *endptr = endchar;
625 
626  /* did we get an error? */
627  if (ires == NULL)
628  {
629  ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
630  lineno, pval, errno);
631 
632  if (INFORMIX_MODE(compat))
633  {
634  /*
635  * Informix wants its own NULL value here instead
636  * of an error
637  */
638  ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
639  if (!ires)
640  return (false);
641 
643  }
644  else
645  {
648  return (false);
649  }
650  }
651  else
652  {
653  if (*scan_length == '"')
654  scan_length++;
655 
656  if (!isarray && garbage_left(isarray, scan_length, compat))
657  {
658  free(ires);
661  return (false);
662  }
663  }
664  pval = scan_length;
665 
666  PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
667  free(ires);
668  break;
669 
670  case ECPGt_date:
671  if (*pval == '"')
672  pval++;
673 
674  for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
675  endchar = *endptr;
676  *endptr = '\0';
677  ddres = PGTYPESdate_from_asc(pval, &scan_length);
678  *endptr = endchar;
679 
680  /* did we get an error? */
681  if (errno != 0)
682  {
683  ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
684  lineno, pval, errno);
685 
686  if (INFORMIX_MODE(compat))
687  {
688  /*
689  * Informix wants its own NULL value here instead
690  * of an error
691  */
693  }
694  else
695  {
698  return (false);
699  }
700  }
701  else
702  {
703  if (*scan_length == '"')
704  scan_length++;
705 
706  if (!isarray && garbage_left(isarray, scan_length, compat))
707  {
710  return (false);
711  }
712  }
713 
714  *((date *) (var + offset * act_tuple)) = ddres;
715  pval = scan_length;
716  break;
717 
718  case ECPGt_timestamp:
719  if (*pval == '"')
720  pval++;
721 
722  for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
723  endchar = *endptr;
724  *endptr = '\0';
725  tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
726  *endptr = endchar;
727 
728  /* did we get an error? */
729  if (errno != 0)
730  {
731  ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
732  lineno, pval, errno);
733 
734  if (INFORMIX_MODE(compat))
735  {
736  /*
737  * Informix wants its own NULL value here instead
738  * of an error
739  */
741  }
742  else
743  {
746  return (false);
747  }
748  }
749  else
750  {
751  if (*scan_length == '"')
752  scan_length++;
753 
754  if (!isarray && garbage_left(isarray, scan_length, compat))
755  {
758  return (false);
759  }
760  }
761 
762  *((timestamp *) (var + offset * act_tuple)) = tres;
763  pval = scan_length;
764  break;
765 
766  default:
769  ecpg_type_name(type));
770  return (false);
771  break;
772  }
773  if (ECPG_IS_ARRAY(isarray))
774  {
775  bool string = false;
776 
777  /* set array to next entry */
778  ++act_tuple;
779 
780  /* set pval to the next entry */
781 
782  /*
783  * *pval != '\0' should not be needed, but is used as a safety
784  * guard
785  */
786  for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
787  if (*pval == '"')
788  string = string ? false : true;
789 
790  if (array_delimiter(isarray, *pval))
791  ++pval;
792  }
793  }
794  } while (*pval != '\0' && !array_boundary(isarray, *pval));
795 
796  return (true);
797 }
#define ECPG_DATA_NOT_ARRAY
Definition: ecpgerrno.h:33
int PQgetlength(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3078
date PGTYPESdate_from_asc(char *, char **)
Definition: datetime.c:48
#define ECPG_SQLSTATE_DATATYPE_MISMATCH
Definition: extern.h:216
int PGTYPESnumeric_copy(numeric *, numeric *)
Definition: numeric.c:1475
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
Definition: extern.h:220
char arr[FLEXIBLE_ARRAY_MEMBER]
Definition: extern.h:36
ARRAY_TYPE
Definition: extern.h:25
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3067
#define INFORMIX_MODE(X)
Definition: extern.h:23
int PGTYPESinterval_copy(interval *, interval *)
Definition: interval.c:1104
#define ECPG_NUMERIC_FORMAT
Definition: ecpgerrno.h:25
#define sqlca
Definition: sqlca.h:59
int64 timestamp
#define ECPG_INTERVAL_FORMAT
Definition: ecpgerrno.h:26
char sqlwarn[8]
Definition: sqlca.h:39
static bool array_delimiter(enum ARRAY_TYPE isarray, char c)
Definition: data.c:23
#define ECPG_CONVERT_BOOL
Definition: ecpgerrno.h:29
int PGTYPESnumeric_to_decimal(numeric *, decimal *)
Definition: numeric.c:1629
static bool array_boundary(enum ARRAY_TYPE isarray, char c)
Definition: data.c:36
long date
Definition: pgtypes_date.h:8
#define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY
Definition: extern.h:221
#define ECPG_UINT_FORMAT
Definition: ecpgerrno.h:23
#define ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER
Definition: extern.h:209
#define ECPG_SQLSTATE_NO_DATA
Definition: extern.h:200
void PGTYPESnumeric_free(numeric *)
Definition: numeric.c:470
numeric * PGTYPESnumeric_new(void)
Definition: numeric.c:127
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void ecpg_log(const char *format,...) pg_attribute_printf(1
#define ECPG_OUT_OF_MEMORY
Definition: ecpgerrno.h:15
struct sqlca_t * ECPGget_sqlca(void)
Definition: misc.c:142
#define ECPG_DATE_FORMAT
Definition: ecpgerrno.h:27
const char * ecpg_type_name(enum ECPGttype)
Definition: typename.c:18
Definition: sqlca.h:19
char * c
interval * PGTYPESinterval_from_asc(char *, char **)
Definition: interval.c:1021
static double get_float8_infinity(void)
Definition: data.c:77
static double get_float8_nan(void)
Definition: data.c:87
unsigned int uint32
Definition: c.h:265
char * ecpg_alloc(long, int)
Definition: memory.c:19
#define ECPG_FLOAT_FORMAT
Definition: ecpgerrno.h:24
#define ECPG_UNSUPPORTED
Definition: ecpgerrno.h:18
void ecpg_raise(int line, int code, const char *sqlstate, const char *str)
Definition: error.c:13
enum COMPAT_MODE compat
Definition: ecpg.c:25
bool ecpg_internal_regression_mode
Definition: misc.c:30
#define ECPG_MISSING_INDICATOR
Definition: ecpgerrno.h:31
bool ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno, enum ECPGttype type, enum ECPGttype ind_type, char *var, char *ind, long varcharsize, long offset, long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
Definition: data.c:123
#define ECPG_NOT_FOUND
Definition: ecpgerrno.h:10
#define ECPG_IS_ARRAY(X)
Definition: extern.h:30
static bool check_special_value(char *ptr, double *retval, char **endptr)
Definition: data.c:98
numeric * PGTYPESnumeric_from_asc(char *, char **)
Definition: numeric.c:406
#define free(a)
Definition: header.h:60
#define NULL
Definition: c.h:226
void ECPGset_noind_null(enum ECPGttype type, void *ptr)
Definition: misc.c:314
static bool garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat)
Definition: data.c:49
#define ECPG_TIMESTAMP_FORMAT
Definition: ecpgerrno.h:28
bool force_indicator
Definition: ecpg.c:18
#define ECPG_INT_FORMAT
Definition: ecpgerrno.h:22
COMPAT_MODE
Definition: extern.h:16
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3092
int PQfformat(const PGresult *res, int field_num)
Definition: fe-exec.c:2900
timestamp PGTYPEStimestamp_from_asc(char *, char **)
Definition: timestamp.c:209
ECPGttype
Definition: ecpgtype.h:41