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

Generated by: LCOV version 1.14