Header And Logo

PostgreSQL
| The world's most advanced open source database.

data.c

Go to the documentation of this file.
00001 /* src/interfaces/ecpg/ecpglib/data.c */
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 /* returns true if character c is a delimiter for the given array type */
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 /* returns true if character c marks the boundary for the given array type */
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 /* returns true if some garbage is found at the end of the scanned string */
00048 static bool
00049 garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat)
00050 {
00051     /*
00052      * INFORMIX allows for selecting a numeric into an int, the result is
00053      * truncated
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 /* stolen code from src/backend/utils/adt/float.c */
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     /* (double) NAN doesn't work on some NetBSD/MIPS releases */
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      * If we are running in a regression test, do not log the offset variable,
00137      * it depends on the machine's alignment.
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     /* pval is a pointer to the value */
00147     if (!pval)
00148     {
00149         /*
00150          * This should never happen because we already checked that we found
00151          * at least one tuple, but let's play it safe.
00152          */
00153         ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
00154         return (false);
00155     }
00156 
00157     /* We will have to decode the value */
00158 
00159     /*
00160      * check for null value and set indicator accordingly, i.e. -1 if NULL and
00161      * 0 if not
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   /* HAVE_LONG_LONG_INT */
00186         case ECPGt_NO_INDICATOR:
00187             if (value_for_indicator == -1)
00188             {
00189                 if (force_indicator == false)
00190                 {
00191                     /*
00192                      * Informix has an additional way to specify NULLs note
00193                      * that this uses special values to denote NULL
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     /* let's check if it really is an array if it should be one */
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                     /* truncation */
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   /* HAVE_LONG_LONG_INT */
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                             /* Cannot happen */
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                             /* Cannot happen */
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   /* HAVE_STRTOLL */
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 != ' '))        /* Garbage left */
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   /* HAVE_STRTOULL */
00379 #endif   /* HAVE_LONG_LONG_INT */
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                             /* Cannot happen */
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                         /* NULL is valid */
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                             /* do the rtrim() */
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                                 /* truncation */
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   /* HAVE_LONG_LONG_INT */
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                                 /* truncation */
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   /* HAVE_LONG_LONG_INT */
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                     /* did we get an error? */
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                              * Informix wants its own NULL value here instead
00574                              * of an error
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                     /* did we get an error? */
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                              * Informix wants its own NULL value here instead
00632                              * of an error
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                     /* did we get an error? */
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                              * Informix wants its own NULL value here instead
00682                              * of an error
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                     /* did we get an error? */
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                              * Informix wants its own NULL value here instead
00726                              * of an error
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                 /* set array to next entry */
00766                 ++act_tuple;
00767 
00768                 /* set pval to the next entry */
00769 
00770                 /*
00771                  * *pval != '\0' should not be needed, but is used as a safety
00772                  * guard
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 }