LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - data.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 60.4 % 457 276
Test Date: 2026-03-03 18:14:56 Functions: 100.0 % 12 12
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* src/interfaces/ecpg/ecpglib/data.c */
       2              : 
       3              : #define POSTGRES_ECPG_INTERNAL
       4              : #include "postgres_fe.h"
       5              : 
       6              : #include <math.h>
       7              : 
       8              : #include "ecpgerrno.h"
       9              : #include "ecpglib.h"
      10              : #include "ecpglib_extern.h"
      11              : #include "ecpgtype.h"
      12              : #include "pgtypes_date.h"
      13              : #include "pgtypes_interval.h"
      14              : #include "pgtypes_numeric.h"
      15              : #include "pgtypes_timestamp.h"
      16              : #include "sqlca.h"
      17              : 
      18              : /* returns true if character c is a delimiter for the given array type */
      19              : static bool
      20          222 : array_delimiter(enum ARRAY_TYPE isarray, char c)
      21              : {
      22          222 :     if (isarray == ECPG_ARRAY_ARRAY && c == ',')
      23          198 :         return true;
      24              : 
      25           24 :     if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
      26            0 :         return true;
      27              : 
      28           24 :     return false;
      29              : }
      30              : 
      31              : /* returns true if character c marks the boundary for the given array type */
      32              : static bool
      33          112 : array_boundary(enum ARRAY_TYPE isarray, char c)
      34              : {
      35          112 :     if (isarray == ECPG_ARRAY_ARRAY && c == '}')
      36           22 :         return true;
      37              : 
      38           90 :     if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
      39            0 :         return true;
      40              : 
      41           90 :     return false;
      42              : }
      43              : 
      44              : /* returns true if some garbage is found at the end of the scanned string */
      45              : static bool
      46          574 : garbage_left(enum ARRAY_TYPE isarray, char **scan_length, enum COMPAT_MODE compat)
      47              : {
      48              :     /*
      49              :      * INFORMIX allows for selecting a numeric into an int, the result is
      50              :      * truncated
      51              :      */
      52          574 :     if (isarray == ECPG_ARRAY_NONE)
      53              :     {
      54          554 :         if (INFORMIX_MODE(compat) && **scan_length == '.')
      55              :         {
      56              :             /* skip invalid characters */
      57              :             do
      58              :             {
      59            0 :                 (*scan_length)++;
      60            0 :             } while (isdigit((unsigned char) **scan_length));
      61              :         }
      62              : 
      63          554 :         if (**scan_length != ' ' && **scan_length != '\0')
      64            0 :             return true;
      65              :     }
      66           20 :     else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
      67            0 :         return true;
      68              : 
      69          574 :     return false;
      70              : }
      71              : 
      72              : 
      73              : /*
      74              :  * Portability wrappers borrowed from src/include/utils/float.h
      75              :  */
      76              : static double
      77           16 : get_float8_infinity(void)
      78              : {
      79           16 :     return (double) INFINITY;
      80              : }
      81              : 
      82              : static double
      83            8 : get_float8_nan(void)
      84              : {
      85            8 :     return (double) NAN;
      86              : }
      87              : 
      88              : 
      89              : static bool
      90           90 : check_special_value(char *ptr, double *retval, char **endptr)
      91              : {
      92           90 :     if (pg_strncasecmp(ptr, "NaN", 3) == 0)
      93              :     {
      94            8 :         *retval = get_float8_nan();
      95            8 :         *endptr = ptr + 3;
      96            8 :         return true;
      97              :     }
      98           82 :     else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
      99              :     {
     100            8 :         *retval = get_float8_infinity();
     101            8 :         *endptr = ptr + 8;
     102            8 :         return true;
     103              :     }
     104           74 :     else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
     105              :     {
     106            8 :         *retval = -get_float8_infinity();
     107            8 :         *endptr = ptr + 9;
     108            8 :         return true;
     109              :     }
     110              : 
     111           66 :     return false;
     112              : }
     113              : 
     114              : /* imported from src/backend/utils/adt/encode.c */
     115              : 
     116              : unsigned
     117           70 : ecpg_hex_enc_len(unsigned srclen)
     118              : {
     119           70 :     return srclen << 1;
     120              : }
     121              : 
     122              : unsigned
     123            6 : ecpg_hex_dec_len(unsigned srclen)
     124              : {
     125            6 :     return srclen >> 1;
     126              : }
     127              : 
     128              : static inline char
     129        18276 : get_hex(char c)
     130              : {
     131              :     static const int8 hexlookup[128] = {
     132              :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     133              :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     134              :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     135              :         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
     136              :         -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     137              :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     138              :         -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     139              :         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     140              :     };
     141        18276 :     int         res = -1;
     142              : 
     143        18276 :     if (c > 0 && c < 127)
     144        18276 :         res = hexlookup[(unsigned char) c];
     145              : 
     146        18276 :     return (char) res;
     147              : }
     148              : 
     149              : static unsigned
     150           18 : hex_decode(const char *src, unsigned len, char *dst)
     151              : {
     152              :     const char *s,
     153              :                *srcend;
     154              :     char        v1,
     155              :                 v2,
     156              :                *p;
     157              : 
     158           18 :     srcend = src + len;
     159           18 :     s = src;
     160           18 :     p = dst;
     161         9156 :     while (s < srcend)
     162              :     {
     163         9138 :         if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
     164              :         {
     165            0 :             s++;
     166            0 :             continue;
     167              :         }
     168         9138 :         v1 = get_hex(*s++) << 4;
     169         9138 :         if (s >= srcend)
     170            0 :             return -1;
     171              : 
     172         9138 :         v2 = get_hex(*s++);
     173         9138 :         *p++ = v1 | v2;
     174              :     }
     175              : 
     176           18 :     return p - dst;
     177              : }
     178              : 
     179              : unsigned
     180           26 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
     181              : {
     182              :     static const char hextbl[] = "0123456789abcdef";
     183           26 :     const char *end = src + len;
     184              : 
     185        13338 :     while (src < end)
     186              :     {
     187        13312 :         *dst++ = hextbl[(*src >> 4) & 0xF];
     188        13312 :         *dst++ = hextbl[*src & 0xF];
     189        13312 :         src++;
     190              :     }
     191           26 :     return len * 2;
     192              : }
     193              : 
     194              : bool
     195         2856 : ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
     196              :               enum ECPGttype type, enum ECPGttype ind_type,
     197              :               char *var, char *ind, long varcharsize, long offset,
     198              :               long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
     199              : {
     200         2856 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     201         2856 :     char       *pval = (char *) PQgetvalue(results, act_tuple, act_field);
     202         2856 :     int         binary = PQfformat(results, act_field);
     203         2856 :     int         size = PQgetlength(results, act_tuple, act_field);
     204         2856 :     int         value_for_indicator = 0;
     205              :     long        log_offset;
     206              : 
     207         2856 :     if (sqlca == NULL)
     208              :     {
     209            0 :         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     210              :                    ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     211            0 :         return false;
     212              :     }
     213              : 
     214              :     /*
     215              :      * If we are running in a regression test, do not log the offset variable,
     216              :      * it depends on the machine's alignment.
     217              :      */
     218         2856 :     if (ecpg_internal_regression_mode)
     219         1184 :         log_offset = -1;
     220              :     else
     221         1672 :         log_offset = offset;
     222              : 
     223         2856 :     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");
     224              : 
     225              :     /* pval is a pointer to the value */
     226         2856 :     if (!pval)
     227              :     {
     228              :         /*
     229              :          * This should never happen because we already checked that we found
     230              :          * at least one tuple, but let's play it safe.
     231              :          */
     232            0 :         ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
     233            0 :         return false;
     234              :     }
     235              : 
     236              :     /* We will have to decode the value */
     237              : 
     238              :     /*
     239              :      * check for null value and set indicator accordingly, i.e. -1 if NULL and
     240              :      * 0 if not
     241              :      */
     242         2856 :     if (PQgetisnull(results, act_tuple, act_field))
     243           96 :         value_for_indicator = -1;
     244              : 
     245         2856 :     switch (ind_type)
     246              :     {
     247          100 :         case ECPGt_short:
     248              :         case ECPGt_unsigned_short:
     249          100 :             *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     250          100 :             break;
     251          160 :         case ECPGt_int:
     252              :         case ECPGt_unsigned_int:
     253          160 :             *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     254          160 :             break;
     255           20 :         case ECPGt_long:
     256              :         case ECPGt_unsigned_long:
     257           20 :             *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     258           20 :             break;
     259            0 :         case ECPGt_long_long:
     260              :         case ECPGt_unsigned_long_long:
     261            0 :             *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     262            0 :             break;
     263         2576 :         case ECPGt_NO_INDICATOR:
     264         2576 :             if (value_for_indicator == -1)
     265              :             {
     266           36 :                 if (force_indicator == false)
     267              :                 {
     268              :                     /*
     269              :                      * Informix has an additional way to specify NULLs note
     270              :                      * that this uses special values to denote NULL
     271              :                      */
     272           24 :                     ECPGset_noind_null(type, var + offset * act_tuple);
     273              :                 }
     274              :                 else
     275              :                 {
     276           12 :                     ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
     277              :                                ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
     278              :                                NULL);
     279           12 :                     return false;
     280              :                 }
     281              :             }
     282         2564 :             break;
     283            0 :         default:
     284            0 :             ecpg_raise(lineno, ECPG_UNSUPPORTED,
     285              :                        ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
     286              :                        ecpg_type_name(ind_type));
     287            0 :             return false;
     288              :             break;
     289              :     }
     290              : 
     291         2844 :     if (value_for_indicator == -1)
     292           84 :         return true;
     293              : 
     294              :     /* let's check if it really is an array if it should be one */
     295         2760 :     if (isarray == ECPG_ARRAY_ARRAY)
     296              :     {
     297           12 :         if (*pval != '{')
     298              :         {
     299            0 :             ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
     300              :                        ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
     301            0 :             return false;
     302              :         }
     303              : 
     304           12 :         switch (type)
     305              :         {
     306            2 :             case ECPGt_char:
     307              :             case ECPGt_unsigned_char:
     308              :             case ECPGt_varchar:
     309              :             case ECPGt_string:
     310            2 :                 break;
     311              : 
     312           10 :             default:
     313           10 :                 pval++;
     314           10 :                 break;
     315              :         }
     316              :     }
     317              : 
     318              :     do
     319              :     {
     320         2850 :         if (binary)
     321              :         {
     322            8 :             if (varcharsize == 0 || varcharsize * offset >= size)
     323            8 :                 memcpy(var + offset * act_tuple, pval, size);
     324              :             else
     325              :             {
     326            0 :                 memcpy(var + offset * act_tuple, pval, varcharsize * offset);
     327              : 
     328            0 :                 if (varcharsize * offset < size)
     329              :                 {
     330              :                     /* truncation */
     331            0 :                     switch (ind_type)
     332              :                     {
     333            0 :                         case ECPGt_short:
     334              :                         case ECPGt_unsigned_short:
     335            0 :                             *((short *) (ind + ind_offset * act_tuple)) = size;
     336            0 :                             break;
     337            0 :                         case ECPGt_int:
     338              :                         case ECPGt_unsigned_int:
     339            0 :                             *((int *) (ind + ind_offset * act_tuple)) = size;
     340            0 :                             break;
     341            0 :                         case ECPGt_long:
     342              :                         case ECPGt_unsigned_long:
     343            0 :                             *((long *) (ind + ind_offset * act_tuple)) = size;
     344            0 :                             break;
     345            0 :                         case ECPGt_long_long:
     346              :                         case ECPGt_unsigned_long_long:
     347            0 :                             *((long long int *) (ind + ind_offset * act_tuple)) = size;
     348            0 :                             break;
     349            0 :                         default:
     350            0 :                             break;
     351              :                     }
     352            0 :                     sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     353              :                 }
     354              :             }
     355            8 :             pval += size;
     356              :         }
     357              :         else
     358              :         {
     359         2842 :             switch (type)
     360              :             {
     361              :                     long        res;
     362              :                     unsigned long ures;
     363              :                     double      dres;
     364              :                     char       *scan_length;
     365              :                     numeric    *nres;
     366              :                     date        ddres;
     367              :                     timestamp   tres;
     368              :                     interval   *ires;
     369              :                     char       *endptr,
     370              :                                 endchar;
     371              : 
     372          484 :                 case ECPGt_short:
     373              :                 case ECPGt_int:
     374              :                 case ECPGt_long:
     375          484 :                     res = strtol(pval, &scan_length, 10);
     376          484 :                     if (garbage_left(isarray, &scan_length, compat))
     377              :                     {
     378            0 :                         ecpg_raise(lineno, ECPG_INT_FORMAT,
     379              :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     380            0 :                         return false;
     381              :                     }
     382          484 :                     pval = scan_length;
     383              : 
     384          484 :                     switch (type)
     385              :                     {
     386           32 :                         case ECPGt_short:
     387           32 :                             *((short *) (var + offset * act_tuple)) = (short) res;
     388           32 :                             break;
     389          426 :                         case ECPGt_int:
     390          426 :                             *((int *) (var + offset * act_tuple)) = (int) res;
     391          426 :                             break;
     392           26 :                         case ECPGt_long:
     393           26 :                             *((long *) (var + offset * act_tuple)) = (long) res;
     394           26 :                             break;
     395            0 :                         default:
     396              :                             /* Cannot happen */
     397            0 :                             break;
     398              :                     }
     399          484 :                     break;
     400              : 
     401            0 :                 case ECPGt_unsigned_short:
     402              :                 case ECPGt_unsigned_int:
     403              :                 case ECPGt_unsigned_long:
     404            0 :                     ures = strtoul(pval, &scan_length, 10);
     405            0 :                     if (garbage_left(isarray, &scan_length, compat))
     406              :                     {
     407            0 :                         ecpg_raise(lineno, ECPG_UINT_FORMAT,
     408              :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     409            0 :                         return false;
     410              :                     }
     411            0 :                     pval = scan_length;
     412              : 
     413            0 :                     switch (type)
     414              :                     {
     415            0 :                         case ECPGt_unsigned_short:
     416            0 :                             *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
     417            0 :                             break;
     418            0 :                         case ECPGt_unsigned_int:
     419            0 :                             *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
     420            0 :                             break;
     421            0 :                         case ECPGt_unsigned_long:
     422            0 :                             *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
     423            0 :                             break;
     424            0 :                         default:
     425              :                             /* Cannot happen */
     426            0 :                             break;
     427              :                     }
     428            0 :                     break;
     429              : 
     430            0 :                 case ECPGt_long_long:
     431            0 :                     *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
     432            0 :                     if (garbage_left(isarray, &scan_length, compat))
     433              :                     {
     434            0 :                         ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     435            0 :                         return false;
     436              :                     }
     437            0 :                     pval = scan_length;
     438              : 
     439            0 :                     break;
     440              : 
     441            0 :                 case ECPGt_unsigned_long_long:
     442            0 :                     *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
     443            0 :                     if (garbage_left(isarray, &scan_length, compat))
     444              :                     {
     445            0 :                         ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     446            0 :                         return false;
     447              :                     }
     448            0 :                     pval = scan_length;
     449              : 
     450            0 :                     break;
     451              : 
     452           90 :                 case ECPGt_float:
     453              :                 case ECPGt_double:
     454           90 :                     if (isarray && *pval == '"')
     455            0 :                         pval++;
     456              : 
     457           90 :                     if (!check_special_value(pval, &dres, &scan_length))
     458           66 :                         dres = strtod(pval, &scan_length);
     459              : 
     460           90 :                     if (isarray && *scan_length == '"')
     461            0 :                         scan_length++;
     462              : 
     463              :                     /* no special INFORMIX treatment for floats */
     464           90 :                     if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
     465              :                     {
     466            0 :                         ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
     467              :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     468            0 :                         return false;
     469              :                     }
     470           90 :                     pval = scan_length;
     471              : 
     472           90 :                     switch (type)
     473              :                     {
     474           14 :                         case ECPGt_float:
     475           14 :                             *((float *) (var + offset * act_tuple)) = dres;
     476           14 :                             break;
     477           76 :                         case ECPGt_double:
     478           76 :                             *((double *) (var + offset * act_tuple)) = dres;
     479           76 :                             break;
     480            0 :                         default:
     481              :                             /* Cannot happen */
     482            0 :                             break;
     483              :                     }
     484           90 :                     break;
     485              : 
     486           24 :                 case ECPGt_bool:
     487           24 :                     if (pval[0] == 'f' && pval[1] == '\0')
     488              :                     {
     489           10 :                         *((bool *) (var + offset * act_tuple)) = false;
     490           10 :                         pval++;
     491           10 :                         break;
     492              :                     }
     493           14 :                     else if (pval[0] == 't' && pval[1] == '\0')
     494              :                     {
     495           14 :                         *((bool *) (var + offset * act_tuple)) = true;
     496           14 :                         pval++;
     497           14 :                         break;
     498              :                     }
     499            0 :                     else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
     500              :                     {
     501              :                         /* NULL is valid */
     502            0 :                         break;
     503              :                     }
     504              : 
     505            0 :                     ecpg_raise(lineno, ECPG_CONVERT_BOOL,
     506              :                                ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     507            0 :                     return false;
     508              :                     break;
     509              : 
     510           18 :                 case ECPGt_bytea:
     511              :                     {
     512           18 :                         struct ECPGgeneric_bytea *variable =
     513           18 :                             (struct ECPGgeneric_bytea *) (var + offset * act_tuple);
     514              :                         long        dst_size,
     515              :                                     src_size,
     516              :                                     dec_size;
     517              : 
     518           18 :                         dst_size = ecpg_hex_enc_len(varcharsize);
     519           18 :                         src_size = size - 2;    /* exclude backslash + 'x' */
     520           18 :                         dec_size = src_size < dst_size ? src_size : dst_size;
     521           18 :                         variable->len = hex_decode(pval + 2, dec_size, variable->arr);
     522              : 
     523           18 :                         if (dst_size < src_size)
     524              :                         {
     525            6 :                             long        rcv_size = ecpg_hex_dec_len(size - 2);
     526              : 
     527              :                             /* truncation */
     528            6 :                             switch (ind_type)
     529              :                             {
     530            0 :                                 case ECPGt_short:
     531              :                                 case ECPGt_unsigned_short:
     532            0 :                                     *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
     533            0 :                                     break;
     534            6 :                                 case ECPGt_int:
     535              :                                 case ECPGt_unsigned_int:
     536            6 :                                     *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
     537            6 :                                     break;
     538            0 :                                 case ECPGt_long:
     539              :                                 case ECPGt_unsigned_long:
     540            0 :                                     *((long *) (ind + ind_offset * act_tuple)) = rcv_size;
     541            0 :                                     break;
     542            0 :                                 case ECPGt_long_long:
     543              :                                 case ECPGt_unsigned_long_long:
     544            0 :                                     *((long long int *) (ind + ind_offset * act_tuple)) = rcv_size;
     545            0 :                                     break;
     546            0 :                                 default:
     547            0 :                                     break;
     548              :                             }
     549            6 :                             sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     550              :                         }
     551              : 
     552           18 :                         pval += size;
     553              :                     }
     554           18 :                     break;
     555              : 
     556         2068 :                 case ECPGt_char:
     557              :                 case ECPGt_unsigned_char:
     558              :                 case ECPGt_string:
     559              :                     {
     560         2068 :                         char       *str = (char *) (var + offset * act_tuple);
     561              : 
     562              :                         /*
     563              :                          * If varcharsize is unknown and the offset is that of
     564              :                          * char *, then this variable represents the array of
     565              :                          * character pointers. So, use extra indirection.
     566              :                          */
     567         2068 :                         if (varcharsize == 0 && offset == sizeof(char *))
     568            0 :                             str = *(char **) str;
     569              : 
     570         2068 :                         if (varcharsize > size)
     571              :                         {
     572              :                             /*
     573              :                              * compatibility mode, blank pad and null
     574              :                              * terminate char array
     575              :                              */
     576         1904 :                             if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
     577              :                             {
     578           18 :                                 memset(str, ' ', varcharsize);
     579           18 :                                 memcpy(str, pval, size);
     580           18 :                                 str[varcharsize - 1] = '\0';
     581              : 
     582              :                                 /*
     583              :                                  * compatibility mode empty string gets -1
     584              :                                  * indicator but no warning
     585              :                                  */
     586           18 :                                 if (size == 0)
     587              :                                 {
     588              :                                     /* truncation */
     589            4 :                                     switch (ind_type)
     590              :                                     {
     591            4 :                                         case ECPGt_short:
     592              :                                         case ECPGt_unsigned_short:
     593            4 :                                             *((short *) (ind + ind_offset * act_tuple)) = -1;
     594            4 :                                             break;
     595            0 :                                         case ECPGt_int:
     596              :                                         case ECPGt_unsigned_int:
     597            0 :                                             *((int *) (ind + ind_offset * act_tuple)) = -1;
     598            0 :                                             break;
     599            0 :                                         case ECPGt_long:
     600              :                                         case ECPGt_unsigned_long:
     601            0 :                                             *((long *) (ind + ind_offset * act_tuple)) = -1;
     602            0 :                                             break;
     603            0 :                                         case ECPGt_long_long:
     604              :                                         case ECPGt_unsigned_long_long:
     605            0 :                                             *((long long int *) (ind + ind_offset * act_tuple)) = -1;
     606            0 :                                             break;
     607            0 :                                         default:
     608            0 :                                             break;
     609              :                                     }
     610              :                                 }
     611              :                             }
     612              :                             else
     613              :                             {
     614         1886 :                                 strncpy(str, pval, size + 1);
     615              :                             }
     616              :                             /* do the rtrim() */
     617         1904 :                             if (type == ECPGt_string)
     618              :                             {
     619            4 :                                 char       *last = str + size;
     620              : 
     621           26 :                                 while (last > str && (*last == ' ' || *last == '\0'))
     622              :                                 {
     623           22 :                                     *last = '\0';
     624           22 :                                     last--;
     625              :                                 }
     626              :                             }
     627              :                         }
     628              :                         else
     629              :                         {
     630          164 :                             int         charsize = varcharsize;
     631              : 
     632              :                             /*
     633              :                              * assume that the caller provided storage exactly
     634              :                              * fit when varcharsize is zero.
     635              :                              */
     636          164 :                             if (varcharsize == 0)
     637           68 :                                 charsize = size + 1;
     638              : 
     639          164 :                             strncpy(str, pval, charsize);
     640              : 
     641              :                             /* compatibility mode, null terminate char array */
     642          164 :                             if (ORACLE_MODE(compat) && (charsize - 1) < size)
     643              :                             {
     644            6 :                                 if (type == ECPGt_char || type == ECPGt_unsigned_char)
     645            6 :                                     str[charsize - 1] = '\0';
     646              :                             }
     647              : 
     648          164 :                             if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
     649              :                             {
     650              :                                 /* truncation */
     651           12 :                                 switch (ind_type)
     652              :                                 {
     653            6 :                                     case ECPGt_short:
     654              :                                     case ECPGt_unsigned_short:
     655            6 :                                         *((short *) (ind + ind_offset * act_tuple)) = size;
     656            6 :                                         break;
     657            2 :                                     case ECPGt_int:
     658              :                                     case ECPGt_unsigned_int:
     659            2 :                                         *((int *) (ind + ind_offset * act_tuple)) = size;
     660            2 :                                         break;
     661            0 :                                     case ECPGt_long:
     662              :                                     case ECPGt_unsigned_long:
     663            0 :                                         *((long *) (ind + ind_offset * act_tuple)) = size;
     664            0 :                                         break;
     665            0 :                                     case ECPGt_long_long:
     666              :                                     case ECPGt_unsigned_long_long:
     667            0 :                                         *((long long int *) (ind + ind_offset * act_tuple)) = size;
     668            0 :                                         break;
     669            4 :                                     default:
     670            4 :                                         break;
     671              :                                 }
     672           12 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     673              :                             }
     674              :                         }
     675         2068 :                         pval += size;
     676              :                     }
     677         2068 :                     break;
     678              : 
     679           44 :                 case ECPGt_varchar:
     680              :                     {
     681           44 :                         struct ECPGgeneric_varchar *variable =
     682           44 :                             (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
     683              : 
     684           44 :                         variable->len = size;
     685           44 :                         if (varcharsize == 0)
     686            0 :                             strncpy(variable->arr, pval, variable->len);
     687              :                         else
     688              :                         {
     689           44 :                             strncpy(variable->arr, pval, varcharsize);
     690              : 
     691           44 :                             if (variable->len > varcharsize)
     692              :                             {
     693              :                                 /* truncation */
     694            0 :                                 switch (ind_type)
     695              :                                 {
     696            0 :                                     case ECPGt_short:
     697              :                                     case ECPGt_unsigned_short:
     698            0 :                                         *((short *) (ind + ind_offset * act_tuple)) = variable->len;
     699            0 :                                         break;
     700            0 :                                     case ECPGt_int:
     701              :                                     case ECPGt_unsigned_int:
     702            0 :                                         *((int *) (ind + ind_offset * act_tuple)) = variable->len;
     703            0 :                                         break;
     704            0 :                                     case ECPGt_long:
     705              :                                     case ECPGt_unsigned_long:
     706            0 :                                         *((long *) (ind + ind_offset * act_tuple)) = variable->len;
     707            0 :                                         break;
     708            0 :                                     case ECPGt_long_long:
     709              :                                     case ECPGt_unsigned_long_long:
     710            0 :                                         *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
     711            0 :                                         break;
     712            0 :                                     default:
     713            0 :                                         break;
     714              :                                 }
     715            0 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     716              : 
     717            0 :                                 variable->len = varcharsize;
     718              :                             }
     719              :                         }
     720           44 :                         pval += size;
     721              :                     }
     722           44 :                     break;
     723              : 
     724           46 :                 case ECPGt_decimal:
     725              :                 case ECPGt_numeric:
     726          194 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
     727           46 :                     endchar = *endptr;
     728           46 :                     *endptr = '\0';
     729           46 :                     nres = PGTYPESnumeric_from_asc(pval, &scan_length);
     730           46 :                     *endptr = endchar;
     731              : 
     732              :                     /* did we get an error? */
     733           46 :                     if (nres == NULL)
     734              :                     {
     735            0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     736            0 :                                  lineno, pval, errno);
     737              : 
     738            0 :                         if (INFORMIX_MODE(compat))
     739              :                         {
     740              :                             /*
     741              :                              * Informix wants its own NULL value here instead
     742              :                              * of an error
     743              :                              */
     744            0 :                             nres = PGTYPESnumeric_new();
     745            0 :                             if (nres)
     746            0 :                                 ECPGset_noind_null(ECPGt_numeric, nres);
     747              :                             else
     748              :                             {
     749            0 :                                 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     750              :                                            ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     751            0 :                                 return false;
     752              :                             }
     753              :                         }
     754              :                         else
     755              :                         {
     756            0 :                             ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
     757              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     758            0 :                             return false;
     759              :                         }
     760              :                     }
     761              :                     else
     762              :                     {
     763           46 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     764              :                         {
     765            0 :                             free(nres);
     766            0 :                             ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
     767              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     768            0 :                             return false;
     769              :                         }
     770              :                     }
     771           46 :                     pval = scan_length;
     772              : 
     773           46 :                     if (type == ECPGt_numeric)
     774           30 :                         PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
     775              :                     else
     776           16 :                         PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
     777              : 
     778           46 :                     PGTYPESnumeric_free(nres);
     779           46 :                     break;
     780              : 
     781           20 :                 case ECPGt_interval:
     782           20 :                     if (*pval == '"')
     783           20 :                         pval++;
     784              : 
     785          220 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     786           20 :                     endchar = *endptr;
     787           20 :                     *endptr = '\0';
     788           20 :                     ires = PGTYPESinterval_from_asc(pval, &scan_length);
     789           20 :                     *endptr = endchar;
     790              : 
     791              :                     /* did we get an error? */
     792           20 :                     if (ires == NULL)
     793              :                     {
     794            0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     795            0 :                                  lineno, pval, errno);
     796              : 
     797            0 :                         if (INFORMIX_MODE(compat))
     798              :                         {
     799              :                             /*
     800              :                              * Informix wants its own NULL value here instead
     801              :                              * of an error
     802              :                              */
     803            0 :                             ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
     804            0 :                             if (!ires)
     805            0 :                                 return false;
     806              : 
     807            0 :                             ECPGset_noind_null(ECPGt_interval, ires);
     808              :                         }
     809              :                         else
     810              :                         {
     811            0 :                             ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
     812              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     813            0 :                             return false;
     814              :                         }
     815              :                     }
     816              :                     else
     817              :                     {
     818           20 :                         if (*scan_length == '"')
     819           20 :                             scan_length++;
     820              : 
     821           20 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     822              :                         {
     823            0 :                             free(ires);
     824            0 :                             ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
     825              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     826            0 :                             return false;
     827              :                         }
     828              :                     }
     829           20 :                     pval = scan_length;
     830              : 
     831           20 :                     PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
     832           20 :                     free(ires);
     833           20 :                     break;
     834              : 
     835           22 :                 case ECPGt_date:
     836           22 :                     if (*pval == '"')
     837            0 :                         pval++;
     838              : 
     839          242 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     840           22 :                     endchar = *endptr;
     841           22 :                     *endptr = '\0';
     842           22 :                     ddres = PGTYPESdate_from_asc(pval, &scan_length);
     843           22 :                     *endptr = endchar;
     844              : 
     845              :                     /* did we get an error? */
     846           22 :                     if (errno != 0)
     847              :                     {
     848            0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     849            0 :                                  lineno, pval, errno);
     850              : 
     851            0 :                         if (INFORMIX_MODE(compat))
     852              :                         {
     853              :                             /*
     854              :                              * Informix wants its own NULL value here instead
     855              :                              * of an error
     856              :                              */
     857            0 :                             ECPGset_noind_null(ECPGt_date, &ddres);
     858              :                         }
     859              :                         else
     860              :                         {
     861            0 :                             ecpg_raise(lineno, ECPG_DATE_FORMAT,
     862              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     863            0 :                             return false;
     864              :                         }
     865              :                     }
     866              :                     else
     867              :                     {
     868           22 :                         if (*scan_length == '"')
     869            0 :                             scan_length++;
     870              : 
     871           22 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     872              :                         {
     873            0 :                             ecpg_raise(lineno, ECPG_DATE_FORMAT,
     874              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     875            0 :                             return false;
     876              :                         }
     877              :                     }
     878              : 
     879           22 :                     *((date *) (var + offset * act_tuple)) = ddres;
     880           22 :                     pval = scan_length;
     881           22 :                     break;
     882              : 
     883           26 :                 case ECPGt_timestamp:
     884           26 :                     if (*pval == '"')
     885           20 :                         pval++;
     886              : 
     887          640 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     888           26 :                     endchar = *endptr;
     889           26 :                     *endptr = '\0';
     890           26 :                     tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
     891           26 :                     *endptr = endchar;
     892              : 
     893              :                     /* did we get an error? */
     894           26 :                     if (errno != 0)
     895              :                     {
     896            0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     897            0 :                                  lineno, pval, errno);
     898              : 
     899            0 :                         if (INFORMIX_MODE(compat))
     900              :                         {
     901              :                             /*
     902              :                              * Informix wants its own NULL value here instead
     903              :                              * of an error
     904              :                              */
     905            0 :                             ECPGset_noind_null(ECPGt_timestamp, &tres);
     906              :                         }
     907              :                         else
     908              :                         {
     909            0 :                             ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
     910              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     911            0 :                             return false;
     912              :                         }
     913              :                     }
     914              :                     else
     915              :                     {
     916           26 :                         if (*scan_length == '"')
     917           20 :                             scan_length++;
     918              : 
     919           26 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     920              :                         {
     921            0 :                             ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
     922              :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     923            0 :                             return false;
     924              :                         }
     925              :                     }
     926              : 
     927           26 :                     *((timestamp *) (var + offset * act_tuple)) = tres;
     928           26 :                     pval = scan_length;
     929           26 :                     break;
     930              : 
     931            0 :                 default:
     932            0 :                     ecpg_raise(lineno, ECPG_UNSUPPORTED,
     933              :                                ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
     934              :                                ecpg_type_name(type));
     935            0 :                     return false;
     936              :                     break;
     937              :             }
     938         2842 :             if (ECPG_IS_ARRAY(isarray))
     939              :             {
     940          102 :                 bool        string = false;
     941              : 
     942              :                 /* set array to next entry */
     943          102 :                 ++act_tuple;
     944              : 
     945              :                 /* set pval to the next entry */
     946              : 
     947              :                 /*
     948              :                  * *pval != '\0' should not be needed, but is used as a safety
     949              :                  * guard
     950              :                  */
     951          102 :                 for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
     952            0 :                     if (*pval == '"')
     953            0 :                         string = string ? false : true;
     954              : 
     955          102 :                 if (array_delimiter(isarray, *pval))
     956           90 :                     ++pval;
     957              :             }
     958              :         }
     959         2850 :     } while (*pval != '\0' && !array_boundary(isarray, *pval));
     960              : 
     961         2760 :     return true;
     962              : }
        

Generated by: LCOV version 2.0-1