LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - data.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 271 450 60.2 %
Date: 2025-10-10 18:17:38 Functions: 12 12 100.0 %
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         444 : array_delimiter(enum ARRAY_TYPE isarray, char c)
      21             : {
      22         444 :     if (isarray == ECPG_ARRAY_ARRAY && c == ',')
      23         396 :         return true;
      24             : 
      25          48 :     if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
      26           0 :         return true;
      27             : 
      28          48 :     return false;
      29             : }
      30             : 
      31             : /* returns true if character c marks the boundary for the given array type */
      32             : static bool
      33         224 : array_boundary(enum ARRAY_TYPE isarray, char c)
      34             : {
      35         224 :     if (isarray == ECPG_ARRAY_ARRAY && c == '}')
      36          44 :         return true;
      37             : 
      38         180 :     if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
      39           0 :         return true;
      40             : 
      41         180 :     return false;
      42             : }
      43             : 
      44             : /* returns true if some garbage is found at the end of the scanned string */
      45             : static bool
      46        1156 : 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        1156 :     if (isarray == ECPG_ARRAY_NONE)
      53             :     {
      54        1116 :         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        1116 :         if (**scan_length != ' ' && **scan_length != '\0')
      64           0 :             return true;
      65             :     }
      66          40 :     else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
      67           0 :         return true;
      68             : 
      69        1156 :     return false;
      70             : }
      71             : 
      72             : 
      73             : /*
      74             :  * Portability wrappers borrowed from src/include/utils/float.h
      75             :  */
      76             : static double
      77          32 : get_float8_infinity(void)
      78             : {
      79          32 :     return (double) INFINITY;
      80             : }
      81             : 
      82             : static double
      83          16 : get_float8_nan(void)
      84             : {
      85          16 :     return (double) NAN;
      86             : }
      87             : 
      88             : 
      89             : static bool
      90         180 : check_special_value(char *ptr, double *retval, char **endptr)
      91             : {
      92         180 :     if (pg_strncasecmp(ptr, "NaN", 3) == 0)
      93             :     {
      94          16 :         *retval = get_float8_nan();
      95          16 :         *endptr = ptr + 3;
      96          16 :         return true;
      97             :     }
      98         164 :     else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
      99             :     {
     100          16 :         *retval = get_float8_infinity();
     101          16 :         *endptr = ptr + 8;
     102          16 :         return true;
     103             :     }
     104         148 :     else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
     105             :     {
     106          16 :         *retval = -get_float8_infinity();
     107          16 :         *endptr = ptr + 9;
     108          16 :         return true;
     109             :     }
     110             : 
     111         132 :     return false;
     112             : }
     113             : 
     114             : /* imported from src/backend/utils/adt/encode.c */
     115             : 
     116             : unsigned
     117         140 : ecpg_hex_enc_len(unsigned srclen)
     118             : {
     119         140 :     return srclen << 1;
     120             : }
     121             : 
     122             : unsigned
     123          12 : ecpg_hex_dec_len(unsigned srclen)
     124             : {
     125          12 :     return srclen >> 1;
     126             : }
     127             : 
     128             : static inline char
     129       36552 : 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       36552 :     int         res = -1;
     142             : 
     143       36552 :     if (c > 0 && c < 127)
     144       36552 :         res = hexlookup[(unsigned char) c];
     145             : 
     146       36552 :     return (char) res;
     147             : }
     148             : 
     149             : static unsigned
     150          36 : 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          36 :     srcend = src + len;
     159          36 :     s = src;
     160          36 :     p = dst;
     161       18312 :     while (s < srcend)
     162             :     {
     163       18276 :         if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
     164             :         {
     165           0 :             s++;
     166           0 :             continue;
     167             :         }
     168       18276 :         v1 = get_hex(*s++) << 4;
     169       18276 :         if (s >= srcend)
     170           0 :             return -1;
     171             : 
     172       18276 :         v2 = get_hex(*s++);
     173       18276 :         *p++ = v1 | v2;
     174             :     }
     175             : 
     176          36 :     return p - dst;
     177             : }
     178             : 
     179             : unsigned
     180          52 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
     181             : {
     182             :     static const char hextbl[] = "0123456789abcdef";
     183          52 :     const char *end = src + len;
     184             : 
     185       26676 :     while (src < end)
     186             :     {
     187       26624 :         *dst++ = hextbl[(*src >> 4) & 0xF];
     188       26624 :         *dst++ = hextbl[*src & 0xF];
     189       26624 :         src++;
     190             :     }
     191          52 :     return len * 2;
     192             : }
     193             : 
     194             : bool
     195        5732 : 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        5732 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     201        5732 :     char       *pval = (char *) PQgetvalue(results, act_tuple, act_field);
     202        5732 :     int         binary = PQfformat(results, act_field);
     203        5732 :     int         size = PQgetlength(results, act_tuple, act_field);
     204        5732 :     int         value_for_indicator = 0;
     205             :     long        log_offset;
     206             : 
     207        5732 :     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        5732 :     if (ecpg_internal_regression_mode)
     219        2388 :         log_offset = -1;
     220             :     else
     221        3344 :         log_offset = offset;
     222             : 
     223        5732 :     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        5732 :     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        5732 :     if (PQgetisnull(results, act_tuple, act_field))
     243         192 :         value_for_indicator = -1;
     244             : 
     245        5732 :     switch (ind_type)
     246             :     {
     247         200 :         case ECPGt_short:
     248             :         case ECPGt_unsigned_short:
     249         200 :             *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     250         200 :             break;
     251         320 :         case ECPGt_int:
     252             :         case ECPGt_unsigned_int:
     253         320 :             *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     254         320 :             break;
     255          40 :         case ECPGt_long:
     256             :         case ECPGt_unsigned_long:
     257          40 :             *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     258          40 :             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        5172 :         case ECPGt_NO_INDICATOR:
     264        5172 :             if (value_for_indicator == -1)
     265             :             {
     266          72 :                 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          48 :                     ECPGset_noind_null(type, var + offset * act_tuple);
     273             :                 }
     274             :                 else
     275             :                 {
     276          24 :                     ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
     277             :                                ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
     278             :                                NULL);
     279          24 :                     return false;
     280             :                 }
     281             :             }
     282        5148 :             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        5708 :     if (value_for_indicator == -1)
     292         168 :         return true;
     293             : 
     294             :     /* let's check if it really is an array if it should be one */
     295        5540 :     if (isarray == ECPG_ARRAY_ARRAY)
     296             :     {
     297          24 :         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          24 :         switch (type)
     305             :         {
     306           4 :             case ECPGt_char:
     307             :             case ECPGt_unsigned_char:
     308             :             case ECPGt_varchar:
     309             :             case ECPGt_string:
     310           4 :                 break;
     311             : 
     312          20 :             default:
     313          20 :                 pval++;
     314          20 :                 break;
     315             :         }
     316             :     }
     317             : 
     318             :     do
     319             :     {
     320        5720 :         if (binary)
     321             :         {
     322          16 :             if (varcharsize == 0 || varcharsize * offset >= size)
     323          16 :                 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          16 :             pval += size;
     356             :         }
     357             :         else
     358             :         {
     359        5704 :             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         976 :                 case ECPGt_short:
     373             :                 case ECPGt_int:
     374             :                 case ECPGt_long:
     375         976 :                     res = strtol(pval, &scan_length, 10);
     376         976 :                     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         976 :                     pval = scan_length;
     383             : 
     384             :                     switch (type)
     385             :                     {
     386          64 :                         case ECPGt_short:
     387          64 :                             *((short *) (var + offset * act_tuple)) = (short) res;
     388          64 :                             break;
     389         860 :                         case ECPGt_int:
     390         860 :                             *((int *) (var + offset * act_tuple)) = (int) res;
     391         860 :                             break;
     392          52 :                         case ECPGt_long:
     393          52 :                             *((long *) (var + offset * act_tuple)) = (long) res;
     394          52 :                             break;
     395           0 :                         default:
     396             :                             /* Cannot happen */
     397           0 :                             break;
     398             :                     }
     399         976 :                     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             :                     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         180 :                 case ECPGt_float:
     453             :                 case ECPGt_double:
     454         180 :                     if (isarray && *pval == '"')
     455           0 :                         pval++;
     456             : 
     457         180 :                     if (!check_special_value(pval, &dres, &scan_length))
     458         132 :                         dres = strtod(pval, &scan_length);
     459             : 
     460         180 :                     if (isarray && *scan_length == '"')
     461           0 :                         scan_length++;
     462             : 
     463             :                     /* no special INFORMIX treatment for floats */
     464         180 :                     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         180 :                     pval = scan_length;
     471             : 
     472             :                     switch (type)
     473             :                     {
     474          28 :                         case ECPGt_float:
     475          28 :                             *((float *) (var + offset * act_tuple)) = dres;
     476          28 :                             break;
     477         152 :                         case ECPGt_double:
     478         152 :                             *((double *) (var + offset * act_tuple)) = dres;
     479         152 :                             break;
     480           0 :                         default:
     481             :                             /* Cannot happen */
     482           0 :                             break;
     483             :                     }
     484         180 :                     break;
     485             : 
     486          48 :                 case ECPGt_bool:
     487          48 :                     if (pval[0] == 'f' && pval[1] == '\0')
     488             :                     {
     489          20 :                         *((bool *) (var + offset * act_tuple)) = false;
     490          20 :                         pval++;
     491          20 :                         break;
     492             :                     }
     493          28 :                     else if (pval[0] == 't' && pval[1] == '\0')
     494             :                     {
     495          28 :                         *((bool *) (var + offset * act_tuple)) = true;
     496          28 :                         pval++;
     497          28 :                         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          36 :                 case ECPGt_bytea:
     511             :                     {
     512          36 :                         struct ECPGgeneric_bytea *variable =
     513          36 :                             (struct ECPGgeneric_bytea *) (var + offset * act_tuple);
     514             :                         long        dst_size,
     515             :                                     src_size,
     516             :                                     dec_size;
     517             : 
     518          36 :                         dst_size = ecpg_hex_enc_len(varcharsize);
     519          36 :                         src_size = size - 2;    /* exclude backslash + 'x' */
     520          36 :                         dec_size = src_size < dst_size ? src_size : dst_size;
     521          36 :                         variable->len = hex_decode(pval + 2, dec_size, variable->arr);
     522             : 
     523          36 :                         if (dst_size < src_size)
     524             :                         {
     525          12 :                             long        rcv_size = ecpg_hex_dec_len(size - 2);
     526             : 
     527             :                             /* truncation */
     528             :                             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          12 :                                 case ECPGt_int:
     535             :                                 case ECPGt_unsigned_int:
     536          12 :                                     *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
     537          12 :                                     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          12 :                             sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     550             :                         }
     551             : 
     552          36 :                         pval += size;
     553             :                     }
     554          36 :                     break;
     555             : 
     556        4148 :                 case ECPGt_char:
     557             :                 case ECPGt_unsigned_char:
     558             :                 case ECPGt_string:
     559             :                     {
     560        4148 :                         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        4148 :                         if (varcharsize == 0 && offset == sizeof(char *))
     568           0 :                             str = *(char **) str;
     569             : 
     570        4148 :                         if (varcharsize > size)
     571             :                         {
     572             :                             /*
     573             :                              * compatibility mode, blank pad and null
     574             :                              * terminate char array
     575             :                              */
     576        3820 :                             if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
     577             :                             {
     578          36 :                                 memset(str, ' ', varcharsize);
     579          36 :                                 memcpy(str, pval, size);
     580          36 :                                 str[varcharsize - 1] = '\0';
     581             : 
     582             :                                 /*
     583             :                                  * compatibility mode empty string gets -1
     584             :                                  * indicator but no warning
     585             :                                  */
     586          36 :                                 if (size == 0)
     587             :                                 {
     588             :                                     /* truncation */
     589             :                                     switch (ind_type)
     590             :                                     {
     591           8 :                                         case ECPGt_short:
     592             :                                         case ECPGt_unsigned_short:
     593           8 :                                             *((short *) (ind + ind_offset * act_tuple)) = -1;
     594           8 :                                             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        3784 :                                 strncpy(str, pval, size + 1);
     615             :                             }
     616             :                             /* do the rtrim() */
     617        3820 :                             if (type == ECPGt_string)
     618             :                             {
     619           8 :                                 char       *last = str + size;
     620             : 
     621          52 :                                 while (last > str && (*last == ' ' || *last == '\0'))
     622             :                                 {
     623          44 :                                     *last = '\0';
     624          44 :                                     last--;
     625             :                                 }
     626             :                             }
     627             :                         }
     628             :                         else
     629             :                         {
     630         328 :                             int         charsize = varcharsize;
     631             : 
     632             :                             /*
     633             :                              * assume that the caller provided storage exactly
     634             :                              * fit when varcharsize is zero.
     635             :                              */
     636         328 :                             if (varcharsize == 0)
     637         136 :                                 charsize = size + 1;
     638             : 
     639         328 :                             strncpy(str, pval, charsize);
     640             : 
     641             :                             /* compatibility mode, null terminate char array */
     642         328 :                             if (ORACLE_MODE(compat) && (charsize - 1) < size)
     643             :                             {
     644          12 :                                 if (type == ECPGt_char || type == ECPGt_unsigned_char)
     645          12 :                                     str[charsize - 1] = '\0';
     646             :                             }
     647             : 
     648         328 :                             if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
     649             :                             {
     650             :                                 /* truncation */
     651             :                                 switch (ind_type)
     652             :                                 {
     653          12 :                                     case ECPGt_short:
     654             :                                     case ECPGt_unsigned_short:
     655          12 :                                         *((short *) (ind + ind_offset * act_tuple)) = size;
     656          12 :                                         break;
     657           4 :                                     case ECPGt_int:
     658             :                                     case ECPGt_unsigned_int:
     659           4 :                                         *((int *) (ind + ind_offset * act_tuple)) = size;
     660           4 :                                         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           8 :                                     default:
     670           8 :                                         break;
     671             :                                 }
     672          24 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     673             :                             }
     674             :                         }
     675        4148 :                         pval += size;
     676             :                     }
     677        4148 :                     break;
     678             : 
     679          88 :                 case ECPGt_varchar:
     680             :                     {
     681          88 :                         struct ECPGgeneric_varchar *variable =
     682          88 :                             (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
     683             : 
     684          88 :                         variable->len = size;
     685          88 :                         if (varcharsize == 0)
     686           0 :                             strncpy(variable->arr, pval, variable->len);
     687             :                         else
     688             :                         {
     689          88 :                             strncpy(variable->arr, pval, varcharsize);
     690             : 
     691          88 :                             if (variable->len > varcharsize)
     692             :                             {
     693             :                                 /* truncation */
     694             :                                 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          88 :                         pval += size;
     721             :                     }
     722          88 :                     break;
     723             : 
     724          92 :                 case ECPGt_decimal:
     725             :                 case ECPGt_numeric:
     726         388 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
     727          92 :                     endchar = *endptr;
     728          92 :                     *endptr = '\0';
     729          92 :                     nres = PGTYPESnumeric_from_asc(pval, &scan_length);
     730          92 :                     *endptr = endchar;
     731             : 
     732             :                     /* did we get an error? */
     733          92 :                     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          92 :                         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          92 :                     pval = scan_length;
     772             : 
     773          92 :                     if (type == ECPGt_numeric)
     774          60 :                         PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
     775             :                     else
     776          32 :                         PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
     777             : 
     778          92 :                     PGTYPESnumeric_free(nres);
     779          92 :                     break;
     780             : 
     781          40 :                 case ECPGt_interval:
     782          40 :                     if (*pval == '"')
     783          40 :                         pval++;
     784             : 
     785         440 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     786          40 :                     endchar = *endptr;
     787          40 :                     *endptr = '\0';
     788          40 :                     ires = PGTYPESinterval_from_asc(pval, &scan_length);
     789          40 :                     *endptr = endchar;
     790             : 
     791             :                     /* did we get an error? */
     792          40 :                     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          40 :                         if (*scan_length == '"')
     819          40 :                             scan_length++;
     820             : 
     821          40 :                         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          40 :                     pval = scan_length;
     830             : 
     831          40 :                     PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
     832          40 :                     free(ires);
     833          40 :                     break;
     834             : 
     835          44 :                 case ECPGt_date:
     836          44 :                     if (*pval == '"')
     837           0 :                         pval++;
     838             : 
     839         484 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     840          44 :                     endchar = *endptr;
     841          44 :                     *endptr = '\0';
     842          44 :                     ddres = PGTYPESdate_from_asc(pval, &scan_length);
     843          44 :                     *endptr = endchar;
     844             : 
     845             :                     /* did we get an error? */
     846          44 :                     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          44 :                         if (*scan_length == '"')
     869           0 :                             scan_length++;
     870             : 
     871          44 :                         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          44 :                     *((date *) (var + offset * act_tuple)) = ddres;
     880          44 :                     pval = scan_length;
     881          44 :                     break;
     882             : 
     883          52 :                 case ECPGt_timestamp:
     884          52 :                     if (*pval == '"')
     885          40 :                         pval++;
     886             : 
     887        1280 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     888          52 :                     endchar = *endptr;
     889          52 :                     *endptr = '\0';
     890          52 :                     tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
     891          52 :                     *endptr = endchar;
     892             : 
     893             :                     /* did we get an error? */
     894          52 :                     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          52 :                         if (*scan_length == '"')
     917          40 :                             scan_length++;
     918             : 
     919          52 :                         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          52 :                     *((timestamp *) (var + offset * act_tuple)) = tres;
     928          52 :                     pval = scan_length;
     929          52 :                     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        5704 :             if (ECPG_IS_ARRAY(isarray))
     939             :             {
     940         204 :                 bool        string = false;
     941             : 
     942             :                 /* set array to next entry */
     943         204 :                 ++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         204 :                 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         204 :                 if (array_delimiter(isarray, *pval))
     956         180 :                     ++pval;
     957             :             }
     958             :         }
     959        5720 :     } while (*pval != '\0' && !array_boundary(isarray, *pval));
     960             : 
     961        5540 :     return true;
     962             : }

Generated by: LCOV version 1.16