]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/ecpglib/data.c
- Added Dave patch for Informix handling of numeric/int conversion.
[postgresql] / src / interfaces / ecpg / ecpglib / data.c
1 /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.17 2003/09/09 10:46:37 meskes Exp $ */
2
3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
5
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "ecpgtype.h"
10 #include "ecpglib.h"
11 #include "ecpgerrno.h"
12 #include "extern.h"
13 #include "sqlca.h"
14 #include "pgtypes_numeric.h"
15 #include "pgtypes_date.h"
16 #include "pgtypes_timestamp.h"
17 #include "pgtypes_interval.h"
18
19 bool
20 ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
21                          enum ECPGttype type, enum ECPGttype ind_type,
22                          char *var, char *ind, long varcharsize, long offset,
23                          long ind_offset, bool isarray, enum COMPAT_MODE compat, bool force_indicator)
24 {
25         struct sqlca_t *sqlca = ECPGget_sqlca();
26         char       *pval = (char *) PQgetvalue(results, act_tuple, act_field);
27         int                     value_for_indicator = 0;
28
29         ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset);
30
31         /* pval is a pointer to the value */
32         /* let's check is it really is an array if it should be one */
33         if (isarray)
34         {
35                 if (*pval != '{')
36                 {
37                         ECPGraise(lineno, ECPG_DATA_NOT_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
38                         return (false);
39                 }
40
41                 switch (type)
42                 {
43                         case ECPGt_char:
44                         case ECPGt_unsigned_char:
45                         case ECPGt_varchar:
46                                 break;
47
48                         default:
49                                 pval++;
50                                 break;
51                 }
52         }
53
54         /* We will have to decode the value */
55
56         /*
57          * check for null value and set indicator accordingly, i.e. -1 if NULL
58          * and 0 if not
59          */
60         if (PQgetisnull(results, act_tuple, act_field))
61                 value_for_indicator = -1;
62
63         switch (ind_type)
64         {
65                 case ECPGt_short:
66                 case ECPGt_unsigned_short:
67                         *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
68                         break;
69                 case ECPGt_int:
70                 case ECPGt_unsigned_int:
71                         *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
72                         break;
73                 case ECPGt_long:
74                 case ECPGt_unsigned_long:
75                         *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
76                         break;
77 #ifdef HAVE_LONG_LONG_INT_64
78                 case ECPGt_long_long:
79                 case ECPGt_unsigned_long_long:
80                         *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
81                         break;
82 #endif   /* HAVE_LONG_LONG_INT_64 */
83                 case ECPGt_NO_INDICATOR:
84                         if (value_for_indicator == -1)
85                         {
86                                 if (force_indicator == false)
87                                 {
88                                         /*
89                                          * Informix has an additional way to specify NULLs
90                                          * note that this uses special values to denote NULL
91                                          */
92                                         ECPGset_informix_null(type, var + offset * act_tuple);
93                                 }
94                                 else
95                                 {
96                                         ECPGraise(lineno, ECPG_MISSING_INDICATOR, ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER, NULL);
97                                         return (false);
98                                 }
99                         }
100                         break;
101                 default:
102                         ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(ind_type));
103                         return (false);
104                         break;
105         }
106
107         if (value_for_indicator == -1)
108                 return (true);
109
110         do
111         {
112                 switch (type)
113                 {
114                                 long            res;
115                                 unsigned long ures;
116                                 double          dres;
117                                 char       *scan_length;
118                                 numeric    *nres;
119                                 date            ddres;
120                                 timestamp       tres;
121                                 interval   *ires;
122
123                         case ECPGt_short:
124                         case ECPGt_int:
125                         case ECPGt_long:
126                                 if (pval)
127                                 {
128                                         res = strtol(pval, &scan_length, 10);
129                                         /* INFORMIX allows for selecting a numeric into an int, the result is truncated */
130                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
131                                                 || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' '))        /* Garbage left */
132                                         {
133                                                 ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
134                                                 return (false);
135                                         }
136                                 }
137                                 else
138                                         res = 0L;
139
140                                 switch (type)
141                                 {
142                                         case ECPGt_short:
143                                                 *((short *) (var + offset * act_tuple)) = (short) res;
144                                                 break;
145                                         case ECPGt_int:
146                                                 *((int *) (var + offset * act_tuple)) = (int) res;
147                                                 break;
148                                         case ECPGt_long:
149                                                 *((long *) (var + offset * act_tuple)) = (long) res;
150                                                 break;
151                                         default:
152                                                 /* Cannot happen */
153                                                 break;
154                                 }
155                                 break;
156
157                         case ECPGt_unsigned_short:
158                         case ECPGt_unsigned_int:
159                         case ECPGt_unsigned_long:
160                                 if (pval)
161                                 {
162                                         ures = strtoul(pval, &scan_length, 10);
163                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
164                                                 || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' '))        /* Garbage left */
165                                         {
166                                                 ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
167                                                 return (false);
168                                         }
169                                 }
170                                 else
171                                         ures = 0L;
172
173                                 switch (type)
174                                 {
175                                         case ECPGt_unsigned_short:
176                                                 *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
177                                                 break;
178                                         case ECPGt_unsigned_int:
179                                                 *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
180                                                 break;
181                                         case ECPGt_unsigned_long:
182                                                 *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
183                                                 break;
184                                         default:
185                                                 /* Cannot happen */
186                                                 break;
187                                 }
188                                 break;
189
190 #ifdef HAVE_LONG_LONG_INT_64
191 #ifdef HAVE_STRTOLL
192                         case ECPGt_long_long:
193                                 if (pval)
194                                 {
195                                         *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
196                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
197                                                 || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' '))        /* Garbage left */
198                                         {
199                                                 ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
200                                                 return (false);
201                                         }
202                                 }
203                                 else
204                                         *((long long int *) (var + offset * act_tuple)) = (long long) 0;
205
206                                 break;
207 #endif   /* HAVE_STRTOLL */
208 #ifdef HAVE_STRTOULL
209                         case ECPGt_unsigned_long_long:
210                                 if (pval)
211                                 {
212                                         *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
213                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
214                                                 || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' '))        /* Garbage left */
215                                         {
216                                                 ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
217                                                 return (false);
218                                         }
219                                 }
220                                 else
221                                         *((unsigned long long int *) (var + offset * act_tuple)) = (long long) 0;
222
223                                 break;
224 #endif   /* HAVE_STRTOULL */
225 #endif   /* HAVE_LONG_LONG_INT_64 */
226
227                         case ECPGt_float:
228                         case ECPGt_double:
229                                 if (pval)
230                                 {
231                                         if (isarray && *pval == '"')
232                                                 dres = strtod(pval + 1, &scan_length);
233                                         else
234                                                 dres = strtod(pval, &scan_length);
235
236                                         if (isarray && *scan_length == '"')
237                                                 scan_length++;
238
239                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
240                                                 || (!isarray && *scan_length != '\0' && *scan_length != ' '))   /* Garbage left */
241                                         {
242                                                 ECPGraise(lineno, ECPG_FLOAT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
243                                                 return (false);
244                                         }
245                                 }
246                                 else
247                                         dres = 0.0;
248
249                                 switch (type)
250                                 {
251                                         case ECPGt_float:
252                                                 *((float *) (var + offset * act_tuple)) = dres;
253                                                 break;
254                                         case ECPGt_double:
255                                                 *((double *) (var + offset * act_tuple)) = dres;
256                                                 break;
257                                         default:
258                                                 /* Cannot happen */
259                                                 break;
260                                 }
261                                 break;
262
263                         case ECPGt_bool:
264                                 if (pval)
265                                 {
266                                         if (pval[0] == 'f' && pval[1] == '\0')
267                                         {
268                                                 if (offset == sizeof(char))
269                                                         *((char *) (var + offset * act_tuple)) = false;
270                                                 else if (offset == sizeof(int))
271                                                         *((int *) (var + offset * act_tuple)) = false;
272                                                 else
273                                                         ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
274                                                 break;
275                                         }
276                                         else if (pval[0] == 't' && pval[1] == '\0')
277                                         {
278                                                 if (offset == sizeof(char))
279                                                         *((char *) (var + offset * act_tuple)) = true;
280                                                 else if (offset == sizeof(int))
281                                                         *((int *) (var + offset * act_tuple)) = true;
282                                                 else
283                                                         ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
284                                                 break;
285                                         }
286                                         else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
287                                         {
288                                                 /* NULL is valid */
289                                                 break;
290                                         }
291                                 }
292
293                                 ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
294                                 return (false);
295                                 break;
296
297                         case ECPGt_char:
298                         case ECPGt_unsigned_char:
299                                 {
300                                         if (varcharsize == 0)
301                                                 strncpy((char *) ((long) var + offset * act_tuple), pval, strlen(pval) + 1);
302                                         else
303                                         {
304                                                 strncpy((char *) ((long) var + offset * act_tuple), pval, varcharsize);
305
306                                                 if (varcharsize < strlen(pval))
307                                                 {
308                                                         /* truncation */
309                                                         switch (ind_type)
310                                                         {
311                                                                 case ECPGt_short:
312                                                                 case ECPGt_unsigned_short:
313                                                                         *((short *) (ind + ind_offset * act_tuple)) = strlen(pval);
314                                                                         break;
315                                                                 case ECPGt_int:
316                                                                 case ECPGt_unsigned_int:
317                                                                         *((int *) (ind + ind_offset * act_tuple)) = strlen(pval);
318                                                                         break;
319                                                                 case ECPGt_long:
320                                                                 case ECPGt_unsigned_long:
321                                                                         *((long *) (ind + ind_offset * act_tuple)) = strlen(pval);
322                                                                         break;
323 #ifdef HAVE_LONG_LONG_INT_64
324                                                                 case ECPGt_long_long:
325                                                                 case ECPGt_unsigned_long_long:
326                                                                         *((long long int *) (ind + ind_offset * act_tuple)) = strlen(pval);
327                                                                         break;
328 #endif   /* HAVE_LONG_LONG_INT_64 */
329                                                                 default:
330                                                                         break;
331                                                         }
332                                                         sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
333                                                 }
334                                         }
335                                 }
336                                 break;
337
338                         case ECPGt_varchar:
339                                 {
340                                         struct ECPGgeneric_varchar *variable =
341                                         (struct ECPGgeneric_varchar *) ((long) var + offset * act_tuple);
342
343                                         variable->len = strlen(pval);
344                                         if (varcharsize == 0)
345                                                 strncpy(variable->arr, pval, variable->len);
346                                         else
347                                         {
348                                                 strncpy(variable->arr, pval, varcharsize);
349
350                                                 if (variable->len > varcharsize)
351                                                 {
352                                                         /* truncation */
353                                                         switch (ind_type)
354                                                         {
355                                                                 case ECPGt_short:
356                                                                 case ECPGt_unsigned_short:
357                                                                         *((short *) (ind + offset * act_tuple)) = variable->len;
358                                                                         break;
359                                                                 case ECPGt_int:
360                                                                 case ECPGt_unsigned_int:
361                                                                         *((int *) (ind + offset * act_tuple)) = variable->len;
362                                                                         break;
363                                                                 case ECPGt_long:
364                                                                 case ECPGt_unsigned_long:
365                                                                         *((long *) (ind + offset * act_tuple)) = variable->len;
366                                                                         break;
367 #ifdef HAVE_LONG_LONG_INT_64
368                                                                 case ECPGt_long_long:
369                                                                 case ECPGt_unsigned_long_long:
370                                                                         *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
371                                                                         break;
372 #endif   /* HAVE_LONG_LONG_INT_64 */
373                                                                 default:
374                                                                         break;
375                                                         }
376                                                         sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
377
378                                                         variable->len = varcharsize;
379                                                 }
380                                         }
381                                 }
382                                 break;
383
384                         case ECPGt_decimal:
385                         case ECPGt_numeric:
386                                 if (pval)
387                                 {
388                                         if (isarray && *pval == '"')
389                                                 nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length);
390                                         else
391                                                 nres = PGTYPESnumeric_from_asc(pval, &scan_length);
392
393                                         if (isarray && *scan_length == '"')
394                                                 scan_length++;
395
396                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
397                                                 || (!isarray && *scan_length != '\0' && *scan_length != ' '))   /* Garbage left */
398                                         {
399                                                 ECPGraise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
400                                                 return (false);
401                                         }
402                                 }
403                                 else
404                                         nres = PGTYPESnumeric_from_asc("0.0", &scan_length);
405
406                                 if (type == ECPGt_numeric)
407                                         PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
408                                 else
409                                         PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
410                                 break;
411
412                         case ECPGt_interval:
413                                 if (pval)
414                                 {
415                                         if (isarray && *pval == '"')
416                                                 ires = PGTYPESinterval_from_asc(pval + 1, &scan_length);
417                                         else
418                                                 ires = PGTYPESinterval_from_asc(pval, &scan_length);
419
420                                         if (isarray && *scan_length == '"')
421                                                 scan_length++;
422
423                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
424                                                 || (!isarray && *scan_length != '\0' && *scan_length != ' '))   /* Garbage left */
425                                         {
426                                                 ECPGraise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
427                                                 return (false);
428                                         }
429                                 }
430                                 else
431                                         ires = PGTYPESinterval_from_asc("0 seconds", NULL);
432
433                                 PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
434                                 break;
435                         case ECPGt_date:
436                                 if (pval)
437                                 {
438                                         if (isarray && *pval == '"')
439                                                 ddres = PGTYPESdate_from_asc(pval + 1, &scan_length);
440                                         else
441                                                 ddres = PGTYPESdate_from_asc(pval, &scan_length);
442
443                                         if (isarray && *scan_length == '"')
444                                                 scan_length++;
445
446                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
447                                                 || (!isarray && *scan_length != '\0' && *scan_length != ' '))   /* Garbage left */
448                                         {
449                                                 ECPGraise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
450                                                 return (false);
451                                         }
452
453                                         *((date *) (var + offset * act_tuple)) = ddres;
454                                 }
455                                 break;
456
457                         case ECPGt_timestamp:
458                                 if (pval)
459                                 {
460                                         if (isarray && *pval == '"')
461                                                 tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length);
462                                         else
463                                                 tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
464
465                                         if (isarray && *scan_length == '"')
466                                                 scan_length++;
467
468                                         if ((isarray && *scan_length != ',' && *scan_length != '}')
469                                                 || (!isarray && *scan_length != '\0' && *scan_length != ' '))   /* Garbage left */
470                                         {
471                                                 ECPGraise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
472                                                 return (false);
473                                         }
474
475                                         *((timestamp *) (var + offset * act_tuple)) = tres;
476                                 }
477                                 break;
478
479                         default:
480                                 ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(type));
481                                 return (false);
482                                 break;
483                 }
484                 if (isarray)
485                 {
486                         bool            string = false;
487
488                         /* set array to next entry */
489                         ++act_tuple;
490
491                         /* set pval to the next entry */
492                         for (; string || (*pval != ',' && *pval != '}'); ++pval)
493                                 if (*pval == '"')
494                                         string = string ? false : true;
495
496                         if (*pval == ',')
497                                 ++pval;
498                 }
499         } while (isarray && *pval != '}');
500
501         return (true);
502 }