00001
00002
00003 #define POSTGRES_ECPG_INTERNAL
00004 #include "postgres_fe.h"
00005
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <float.h>
00009 #include <math.h>
00010
00011 #include "ecpgtype.h"
00012 #include "ecpglib.h"
00013 #include "ecpgerrno.h"
00014 #include "extern.h"
00015 #include "sqlca.h"
00016 #include "pgtypes_numeric.h"
00017 #include "pgtypes_date.h"
00018 #include "pgtypes_timestamp.h"
00019 #include "pgtypes_interval.h"
00020
00021
00022 static bool
00023 array_delimiter(enum ARRAY_TYPE isarray, char c)
00024 {
00025 if (isarray == ECPG_ARRAY_ARRAY && c == ',')
00026 return true;
00027
00028 if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
00029 return true;
00030
00031 return false;
00032 }
00033
00034
00035 static bool
00036 array_boundary(enum ARRAY_TYPE isarray, char c)
00037 {
00038 if (isarray == ECPG_ARRAY_ARRAY && c == '}')
00039 return true;
00040
00041 if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
00042 return true;
00043
00044 return false;
00045 }
00046
00047
00048 static bool
00049 garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat)
00050 {
00051
00052
00053
00054
00055 if (isarray == ECPG_ARRAY_NONE)
00056 {
00057 if (INFORMIX_MODE(compat) && *scan_length == '.')
00058 return false;
00059
00060 if (*scan_length != ' ' && *scan_length != '\0')
00061 return true;
00062 }
00063 else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, *scan_length) && !array_boundary(isarray, *scan_length))
00064 return true;
00065
00066 return false;
00067 }
00068
00069
00070 #if defined(WIN32) && !defined(NAN)
00071 static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
00072
00073 #define NAN (*(const double *) nan)
00074 #endif
00075
00076 static double
00077 get_float8_infinity(void)
00078 {
00079 #ifdef INFINITY
00080 return (double) INFINITY;
00081 #else
00082 return (double) (HUGE_VAL * HUGE_VAL);
00083 #endif
00084 }
00085
00086 static double
00087 get_float8_nan(void)
00088 {
00089
00090 #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
00091 return (double) NAN;
00092 #else
00093 return (double) (0.0 / 0.0);
00094 #endif
00095 }
00096
00097 static bool
00098 check_special_value(char *ptr, double *retval, char **endptr)
00099 {
00100 if (pg_strncasecmp(ptr, "NaN", 3) == 0)
00101 {
00102 *retval = get_float8_nan();
00103 *endptr = ptr + 3;
00104 return true;
00105 }
00106 else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
00107 {
00108 *retval = get_float8_infinity();
00109 *endptr = ptr + 8;
00110 return true;
00111 }
00112 else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
00113 {
00114 *retval = -get_float8_infinity();
00115 *endptr = ptr + 9;
00116 return true;
00117 }
00118
00119 return false;
00120 }
00121
00122 bool
00123 ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
00124 enum ECPGttype type, enum ECPGttype ind_type,
00125 char *var, char *ind, long varcharsize, long offset,
00126 long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
00127 {
00128 struct sqlca_t *sqlca = ECPGget_sqlca();
00129 char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
00130 int binary = PQfformat(results, act_field);
00131 int size = PQgetlength(results, act_tuple, act_field);
00132 int value_for_indicator = 0;
00133 long log_offset;
00134
00135
00136
00137
00138
00139 if (ecpg_internal_regression_mode)
00140 log_offset = -1;
00141 else
00142 log_offset = offset;
00143
00144 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");
00145
00146
00147 if (!pval)
00148 {
00149
00150
00151
00152
00153 ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
00154 return (false);
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 if (PQgetisnull(results, act_tuple, act_field))
00164 value_for_indicator = -1;
00165
00166 switch (ind_type)
00167 {
00168 case ECPGt_short:
00169 case ECPGt_unsigned_short:
00170 *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
00171 break;
00172 case ECPGt_int:
00173 case ECPGt_unsigned_int:
00174 *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
00175 break;
00176 case ECPGt_long:
00177 case ECPGt_unsigned_long:
00178 *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
00179 break;
00180 #ifdef HAVE_LONG_LONG_INT
00181 case ECPGt_long_long:
00182 case ECPGt_unsigned_long_long:
00183 *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
00184 break;
00185 #endif
00186 case ECPGt_NO_INDICATOR:
00187 if (value_for_indicator == -1)
00188 {
00189 if (force_indicator == false)
00190 {
00191
00192
00193
00194
00195 ECPGset_noind_null(type, var + offset * act_tuple);
00196 }
00197 else
00198 {
00199 ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
00200 ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
00201 NULL);
00202 return (false);
00203 }
00204 }
00205 break;
00206 default:
00207 ecpg_raise(lineno, ECPG_UNSUPPORTED,
00208 ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
00209 ecpg_type_name(ind_type));
00210 return (false);
00211 break;
00212 }
00213
00214 if (value_for_indicator == -1)
00215 return (true);
00216
00217
00218 if (isarray == ECPG_ARRAY_ARRAY)
00219 {
00220 if (*pval != '{')
00221 {
00222 ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
00223 ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
00224 return (false);
00225 }
00226
00227 switch (type)
00228 {
00229 case ECPGt_char:
00230 case ECPGt_unsigned_char:
00231 case ECPGt_varchar:
00232 case ECPGt_string:
00233 break;
00234
00235 default:
00236 pval++;
00237 break;
00238 }
00239 }
00240
00241 do
00242 {
00243 if (binary)
00244 {
00245 if (varcharsize == 0 || varcharsize * offset >= size)
00246 memcpy(var + offset * act_tuple, pval, size);
00247 else
00248 {
00249 memcpy(var + offset * act_tuple, pval, varcharsize * offset);
00250
00251 if (varcharsize * offset < size)
00252 {
00253
00254 switch (ind_type)
00255 {
00256 case ECPGt_short:
00257 case ECPGt_unsigned_short:
00258 *((short *) (ind + ind_offset * act_tuple)) = size;
00259 break;
00260 case ECPGt_int:
00261 case ECPGt_unsigned_int:
00262 *((int *) (ind + ind_offset * act_tuple)) = size;
00263 break;
00264 case ECPGt_long:
00265 case ECPGt_unsigned_long:
00266 *((long *) (ind + ind_offset * act_tuple)) = size;
00267 break;
00268 #ifdef HAVE_LONG_LONG_INT
00269 case ECPGt_long_long:
00270 case ECPGt_unsigned_long_long:
00271 *((long long int *) (ind + ind_offset * act_tuple)) = size;
00272 break;
00273 #endif
00274 default:
00275 break;
00276 }
00277 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
00278 }
00279 }
00280 pval += size;
00281 }
00282 else
00283 {
00284 switch (type)
00285 {
00286 long res;
00287 unsigned long ures;
00288 double dres;
00289 char *scan_length;
00290 numeric *nres;
00291 date ddres;
00292 timestamp tres;
00293 interval *ires;
00294
00295 case ECPGt_short:
00296 case ECPGt_int:
00297 case ECPGt_long:
00298 res = strtol(pval, &scan_length, 10);
00299 if (garbage_left(isarray, scan_length, compat))
00300 {
00301 ecpg_raise(lineno, ECPG_INT_FORMAT,
00302 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00303 return (false);
00304 }
00305 pval = scan_length;
00306
00307 switch (type)
00308 {
00309 case ECPGt_short:
00310 *((short *) (var + offset * act_tuple)) = (short) res;
00311 break;
00312 case ECPGt_int:
00313 *((int *) (var + offset * act_tuple)) = (int) res;
00314 break;
00315 case ECPGt_long:
00316 *((long *) (var + offset * act_tuple)) = (long) res;
00317 break;
00318 default:
00319
00320 break;
00321 }
00322 break;
00323
00324 case ECPGt_unsigned_short:
00325 case ECPGt_unsigned_int:
00326 case ECPGt_unsigned_long:
00327 ures = strtoul(pval, &scan_length, 10);
00328 if (garbage_left(isarray, scan_length, compat))
00329 {
00330 ecpg_raise(lineno, ECPG_UINT_FORMAT,
00331 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00332 return (false);
00333 }
00334 pval = scan_length;
00335
00336 switch (type)
00337 {
00338 case ECPGt_unsigned_short:
00339 *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
00340 break;
00341 case ECPGt_unsigned_int:
00342 *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
00343 break;
00344 case ECPGt_unsigned_long:
00345 *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
00346 break;
00347 default:
00348
00349 break;
00350 }
00351 break;
00352
00353 #ifdef HAVE_LONG_LONG_INT
00354 #ifdef HAVE_STRTOLL
00355 case ECPGt_long_long:
00356 *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
00357 if (garbage_left(isarray, scan_length, compat))
00358 {
00359 ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00360 return (false);
00361 }
00362 pval = scan_length;
00363
00364 break;
00365 #endif
00366 #ifdef HAVE_STRTOULL
00367 case ECPGt_unsigned_long_long:
00368 *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
00369 if ((isarray && *scan_length != ',' && *scan_length != '}')
00370 || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' '))
00371 {
00372 ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00373 return (false);
00374 }
00375 pval = scan_length;
00376
00377 break;
00378 #endif
00379 #endif
00380
00381 case ECPGt_float:
00382 case ECPGt_double:
00383 if (isarray && *pval == '"')
00384 pval++;
00385
00386 if (!check_special_value(pval, &dres, &scan_length))
00387 dres = strtod(pval, &scan_length);
00388
00389 if (isarray && *scan_length == '"')
00390 scan_length++;
00391
00392 if (garbage_left(isarray, scan_length, compat))
00393 {
00394 ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
00395 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00396 return (false);
00397 }
00398 pval = scan_length;
00399
00400 switch (type)
00401 {
00402 case ECPGt_float:
00403 *((float *) (var + offset * act_tuple)) = dres;
00404 break;
00405 case ECPGt_double:
00406 *((double *) (var + offset * act_tuple)) = dres;
00407 break;
00408 default:
00409
00410 break;
00411 }
00412 break;
00413
00414 case ECPGt_bool:
00415 if (pval[0] == 'f' && pval[1] == '\0')
00416 {
00417 if (offset == sizeof(char))
00418 *((char *) (var + offset * act_tuple)) = false;
00419 else if (offset == sizeof(int))
00420 *((int *) (var + offset * act_tuple)) = false;
00421 else
00422 ecpg_raise(lineno, ECPG_CONVERT_BOOL,
00423 ECPG_SQLSTATE_DATATYPE_MISMATCH,
00424 NULL);
00425 pval++;
00426 break;
00427 }
00428 else if (pval[0] == 't' && pval[1] == '\0')
00429 {
00430 if (offset == sizeof(char))
00431 *((char *) (var + offset * act_tuple)) = true;
00432 else if (offset == sizeof(int))
00433 *((int *) (var + offset * act_tuple)) = true;
00434 else
00435 ecpg_raise(lineno, ECPG_CONVERT_BOOL,
00436 ECPG_SQLSTATE_DATATYPE_MISMATCH,
00437 NULL);
00438 pval++;
00439 break;
00440 }
00441 else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
00442 {
00443
00444 break;
00445 }
00446
00447 ecpg_raise(lineno, ECPG_CONVERT_BOOL,
00448 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00449 return (false);
00450 break;
00451
00452 case ECPGt_char:
00453 case ECPGt_unsigned_char:
00454 case ECPGt_string:
00455 {
00456 char *str = (char *) (var + offset * act_tuple);
00457
00458 if (varcharsize == 0 || varcharsize > size)
00459 {
00460 strncpy(str, pval, size + 1);
00461
00462 if (type == ECPGt_string)
00463 {
00464 char *last = str + size;
00465
00466 while (last > str && (*last == ' ' || *last == '\0'))
00467 {
00468 *last = '\0';
00469 last--;
00470 }
00471 }
00472 }
00473 else
00474 {
00475 strncpy(str, pval, varcharsize);
00476
00477 if (varcharsize < size)
00478 {
00479
00480 switch (ind_type)
00481 {
00482 case ECPGt_short:
00483 case ECPGt_unsigned_short:
00484 *((short *) (ind + ind_offset * act_tuple)) = size;
00485 break;
00486 case ECPGt_int:
00487 case ECPGt_unsigned_int:
00488 *((int *) (ind + ind_offset * act_tuple)) = size;
00489 break;
00490 case ECPGt_long:
00491 case ECPGt_unsigned_long:
00492 *((long *) (ind + ind_offset * act_tuple)) = size;
00493 break;
00494 #ifdef HAVE_LONG_LONG_INT
00495 case ECPGt_long_long:
00496 case ECPGt_unsigned_long_long:
00497 *((long long int *) (ind + ind_offset * act_tuple)) = size;
00498 break;
00499 #endif
00500 default:
00501 break;
00502 }
00503 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
00504 }
00505 }
00506 pval += size;
00507 }
00508 break;
00509
00510 case ECPGt_varchar:
00511 {
00512 struct ECPGgeneric_varchar *variable =
00513 (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
00514
00515 variable->len = size;
00516 if (varcharsize == 0)
00517 strncpy(variable->arr, pval, variable->len);
00518 else
00519 {
00520 strncpy(variable->arr, pval, varcharsize);
00521
00522 if (variable->len > varcharsize)
00523 {
00524
00525 switch (ind_type)
00526 {
00527 case ECPGt_short:
00528 case ECPGt_unsigned_short:
00529 *((short *) (ind + offset * act_tuple)) = variable->len;
00530 break;
00531 case ECPGt_int:
00532 case ECPGt_unsigned_int:
00533 *((int *) (ind + offset * act_tuple)) = variable->len;
00534 break;
00535 case ECPGt_long:
00536 case ECPGt_unsigned_long:
00537 *((long *) (ind + offset * act_tuple)) = variable->len;
00538 break;
00539 #ifdef HAVE_LONG_LONG_INT
00540 case ECPGt_long_long:
00541 case ECPGt_unsigned_long_long:
00542 *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
00543 break;
00544 #endif
00545 default:
00546 break;
00547 }
00548 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
00549
00550 variable->len = varcharsize;
00551 }
00552 }
00553 pval += size;
00554 }
00555 break;
00556
00557 case ECPGt_decimal:
00558 case ECPGt_numeric:
00559 if (isarray && *pval == '"')
00560 nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length);
00561 else
00562 nres = PGTYPESnumeric_from_asc(pval, &scan_length);
00563
00564
00565 if (nres == NULL)
00566 {
00567 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
00568 lineno, pval ? pval : "", errno);
00569
00570 if (INFORMIX_MODE(compat))
00571 {
00572
00573
00574
00575
00576 nres = PGTYPESnumeric_new();
00577 if (nres)
00578 ECPGset_noind_null(ECPGt_numeric, nres);
00579 else
00580 {
00581 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
00582 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
00583 return (false);
00584 }
00585 }
00586 else
00587 {
00588 ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
00589 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00590 return (false);
00591 }
00592 }
00593 else
00594 {
00595 if (isarray && *scan_length == '"')
00596 scan_length++;
00597
00598 if (garbage_left(isarray, scan_length, compat))
00599 {
00600 free(nres);
00601 ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
00602 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00603 return (false);
00604 }
00605 }
00606 pval = scan_length;
00607
00608 if (type == ECPGt_numeric)
00609 PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
00610 else
00611 PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
00612
00613 PGTYPESnumeric_free(nres);
00614 break;
00615
00616 case ECPGt_interval:
00617 if (isarray && *pval == '"')
00618 ires = PGTYPESinterval_from_asc(pval + 1, &scan_length);
00619 else
00620 ires = PGTYPESinterval_from_asc(pval, &scan_length);
00621
00622
00623 if (ires == NULL)
00624 {
00625 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
00626 lineno, pval ? pval : "", errno);
00627
00628 if (INFORMIX_MODE(compat))
00629 {
00630
00631
00632
00633
00634 ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
00635 if (!ires)
00636 return (false);
00637
00638 ECPGset_noind_null(ECPGt_interval, ires);
00639 }
00640 else
00641 {
00642 ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
00643 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00644 return (false);
00645 }
00646 }
00647 else
00648 {
00649 if (isarray && *scan_length == '"')
00650 scan_length++;
00651
00652 if (garbage_left(isarray, scan_length, compat))
00653 {
00654 free(ires);
00655 ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
00656 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00657 return (false);
00658 }
00659 }
00660 pval = scan_length;
00661
00662 PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
00663 free(ires);
00664 break;
00665
00666 case ECPGt_date:
00667 if (isarray && *pval == '"')
00668 ddres = PGTYPESdate_from_asc(pval + 1, &scan_length);
00669 else
00670 ddres = PGTYPESdate_from_asc(pval, &scan_length);
00671
00672
00673 if (errno != 0)
00674 {
00675 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
00676 lineno, pval ? pval : "", errno);
00677
00678 if (INFORMIX_MODE(compat))
00679 {
00680
00681
00682
00683
00684 ECPGset_noind_null(ECPGt_date, &ddres);
00685 }
00686 else
00687 {
00688 ecpg_raise(lineno, ECPG_DATE_FORMAT,
00689 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00690 return (false);
00691 }
00692 }
00693 else
00694 {
00695 if (isarray && *scan_length == '"')
00696 scan_length++;
00697
00698 if (garbage_left(isarray, scan_length, compat))
00699 {
00700 ecpg_raise(lineno, ECPG_DATE_FORMAT,
00701 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00702 return (false);
00703 }
00704 }
00705
00706 *((date *) (var + offset * act_tuple)) = ddres;
00707 pval = scan_length;
00708 break;
00709
00710 case ECPGt_timestamp:
00711 if (isarray && *pval == '"')
00712 tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length);
00713 else
00714 tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
00715
00716
00717 if (errno != 0)
00718 {
00719 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
00720 lineno, pval ? pval : "", errno);
00721
00722 if (INFORMIX_MODE(compat))
00723 {
00724
00725
00726
00727
00728 ECPGset_noind_null(ECPGt_timestamp, &tres);
00729 }
00730 else
00731 {
00732 ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
00733 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00734 return (false);
00735 }
00736 }
00737 else
00738 {
00739 if (isarray && *scan_length == '"')
00740 scan_length++;
00741
00742 if (garbage_left(isarray, scan_length, compat))
00743 {
00744 ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
00745 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
00746 return (false);
00747 }
00748 }
00749
00750 *((timestamp *) (var + offset * act_tuple)) = tres;
00751 pval = scan_length;
00752 break;
00753
00754 default:
00755 ecpg_raise(lineno, ECPG_UNSUPPORTED,
00756 ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
00757 ecpg_type_name(type));
00758 return (false);
00759 break;
00760 }
00761 if (ECPG_IS_ARRAY(isarray))
00762 {
00763 bool string = false;
00764
00765
00766 ++act_tuple;
00767
00768
00769
00770
00771
00772
00773
00774 for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
00775 if (*pval == '"')
00776 string = string ? false : true;
00777
00778 if (array_delimiter(isarray, *pval))
00779 ++pval;
00780 }
00781 }
00782 } while (*pval != '\0' && !array_boundary(isarray, *pval));
00783
00784 return (true);
00785 }