LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - data.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 270 449 60.1 %
Date: 2020-06-05 19:06:29 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        1072 : 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        1072 :     if (isarray == ECPG_ARRAY_NONE)
      53             :     {
      54        1032 :         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        1032 :         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        1072 :     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         112 : ecpg_hex_enc_len(unsigned srclen)
     129             : {
     130         112 :     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       32456 : 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       32456 :     int         res = -1;
     153             : 
     154       32456 :     if (c > 0 && c < 127)
     155       32456 :         res = hexlookup[(unsigned char) c];
     156             : 
     157       32456 :     return (char) res;
     158             : }
     159             : 
     160             : static unsigned
     161          32 : 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          32 :     srcend = src + len;
     170          32 :     s = src;
     171          32 :     p = dst;
     172       16260 :     while (s < srcend)
     173             :     {
     174       16228 :         if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
     175             :         {
     176           0 :             s++;
     177           0 :             continue;
     178             :         }
     179       16228 :         v1 = get_hex(*s++) << 4;
     180       16228 :         if (s >= srcend)
     181           0 :             return -1;
     182             : 
     183       16228 :         v2 = get_hex(*s++);
     184       16228 :         *p++ = v1 | v2;
     185             :     }
     186             : 
     187          32 :     return p - dst;
     188             : }
     189             : 
     190             : unsigned
     191          40 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
     192             : {
     193             :     static const char hextbl[] = "0123456789abcdef";
     194          40 :     const char *end = src + len;
     195             : 
     196       20520 :     while (src < end)
     197             :     {
     198       20480 :         *dst++ = hextbl[(*src >> 4) & 0xF];
     199       20480 :         *dst++ = hextbl[*src & 0xF];
     200       20480 :         src++;
     201             :     }
     202          40 :     return len * 2;
     203             : }
     204             : 
     205             : bool
     206        5476 : 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        5476 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     212        5476 :     char       *pval = (char *) PQgetvalue(results, act_tuple, act_field);
     213        5476 :     int         binary = PQfformat(results, act_field);
     214        5476 :     int         size = PQgetlength(results, act_tuple, act_field);
     215        5476 :     int         value_for_indicator = 0;
     216             :     long        log_offset;
     217             : 
     218        5476 :     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        5476 :     if (ecpg_internal_regression_mode)
     230        2132 :         log_offset = -1;
     231             :     else
     232        3344 :         log_offset = offset;
     233             : 
     234        5476 :     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        5476 :     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        5476 :     if (PQgetisnull(results, act_tuple, act_field))
     254         176 :         value_for_indicator = -1;
     255             : 
     256        5476 :     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        4916 :         case ECPGt_NO_INDICATOR:
     275        4916 :             if (value_for_indicator == -1)
     276             :             {
     277          56 :                 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           8 :                     ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
     288             :                                ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
     289             :                                NULL);
     290           8 :                     return false;
     291             :                 }
     292             :             }
     293        4908 :             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        5468 :     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        5300 :     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        5456 :     }
     328             : 
     329             :     do
     330             :     {
     331        5480 :         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        5464 :             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         892 :                 case ECPGt_short:
     384             :                 case ECPGt_int:
     385             :                 case ECPGt_long:
     386         892 :                     res = strtol(pval, &scan_length, 10);
     387         892 :                     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         892 :                     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         776 :                         case ECPGt_int:
     401         776 :                             *((int *) (var + offset * act_tuple)) = (int) res;
     402         776 :                             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         892 :                     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             : #ifdef HAVE_STRTOLL
     442           0 :                 case ECPGt_long_long:
     443           0 :                     *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
     444           0 :                     if (garbage_left(isarray, &scan_length, compat))
     445             :                     {
     446           0 :                         ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     447           0 :                         return false;
     448             :                     }
     449           0 :                     pval = scan_length;
     450             : 
     451           0 :                     break;
     452             : #endif                          /* HAVE_STRTOLL */
     453             : #ifdef HAVE_STRTOULL
     454           0 :                 case ECPGt_unsigned_long_long:
     455           0 :                     *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
     456           0 :                     if (garbage_left(isarray, &scan_length, compat))
     457             :                     {
     458           0 :                         ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     459           0 :                         return false;
     460             :                     }
     461           0 :                     pval = scan_length;
     462             : 
     463           0 :                     break;
     464             : #endif                          /* HAVE_STRTOULL */
     465             : 
     466         180 :                 case ECPGt_float:
     467             :                 case ECPGt_double:
     468         180 :                     if (isarray && *pval == '"')
     469           0 :                         pval++;
     470             : 
     471         180 :                     if (!check_special_value(pval, &dres, &scan_length))
     472         132 :                         dres = strtod(pval, &scan_length);
     473             : 
     474         180 :                     if (isarray && *scan_length == '"')
     475           0 :                         scan_length++;
     476             : 
     477             :                     /* no special INFORMIX treatment for floats */
     478         180 :                     if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
     479             :                     {
     480           0 :                         ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
     481             :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     482           0 :                         return false;
     483             :                     }
     484         180 :                     pval = scan_length;
     485             : 
     486             :                     switch (type)
     487             :                     {
     488          28 :                         case ECPGt_float:
     489          28 :                             *((float *) (var + offset * act_tuple)) = dres;
     490          28 :                             break;
     491         152 :                         case ECPGt_double:
     492         152 :                             *((double *) (var + offset * act_tuple)) = dres;
     493         152 :                             break;
     494           0 :                         default:
     495             :                             /* Cannot happen */
     496           0 :                             break;
     497             :                     }
     498         180 :                     break;
     499             : 
     500          16 :                 case ECPGt_bool:
     501          16 :                     if (pval[0] == 'f' && pval[1] == '\0')
     502             :                     {
     503           4 :                         *((bool *) (var + offset * act_tuple)) = false;
     504           4 :                         pval++;
     505           4 :                         break;
     506             :                     }
     507          12 :                     else if (pval[0] == 't' && pval[1] == '\0')
     508             :                     {
     509          12 :                         *((bool *) (var + offset * act_tuple)) = true;
     510          12 :                         pval++;
     511          12 :                         break;
     512             :                     }
     513           0 :                     else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
     514             :                     {
     515             :                         /* NULL is valid */
     516           0 :                         break;
     517             :                     }
     518             : 
     519           0 :                     ecpg_raise(lineno, ECPG_CONVERT_BOOL,
     520             :                                ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     521           0 :                     return false;
     522             :                     break;
     523             : 
     524          32 :                 case ECPGt_bytea:
     525             :                     {
     526          32 :                         struct ECPGgeneric_varchar *variable =
     527          32 :                         (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
     528             :                         long        dst_size,
     529             :                                     src_size,
     530             :                                     dec_size;
     531             : 
     532          32 :                         dst_size = ecpg_hex_enc_len(varcharsize);
     533          32 :                         src_size = size - 2;    /* exclude backslash + 'x' */
     534          32 :                         dec_size = src_size < dst_size ? src_size : dst_size;
     535          32 :                         variable->len = hex_decode(pval + 2, dec_size, variable->arr);
     536             : 
     537          32 :                         if (dst_size < src_size)
     538             :                         {
     539          12 :                             long        rcv_size = ecpg_hex_dec_len(size - 2);
     540             : 
     541             :                             /* truncation */
     542             :                             switch (ind_type)
     543             :                             {
     544           0 :                                 case ECPGt_short:
     545             :                                 case ECPGt_unsigned_short:
     546           0 :                                     *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
     547           0 :                                     break;
     548          12 :                                 case ECPGt_int:
     549             :                                 case ECPGt_unsigned_int:
     550          12 :                                     *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
     551          12 :                                     break;
     552           0 :                                 case ECPGt_long:
     553             :                                 case ECPGt_unsigned_long:
     554           0 :                                     *((long *) (ind + ind_offset * act_tuple)) = rcv_size;
     555           0 :                                     break;
     556           0 :                                 case ECPGt_long_long:
     557             :                                 case ECPGt_unsigned_long_long:
     558           0 :                                     *((long long int *) (ind + ind_offset * act_tuple)) = rcv_size;
     559           0 :                                     break;
     560           0 :                                 default:
     561           0 :                                     break;
     562             :                             }
     563          12 :                             sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     564             :                         }
     565             : 
     566          32 :                         pval += size;
     567             : 
     568             :                     }
     569          32 :                     break;
     570             : 
     571        4028 :                 case ECPGt_char:
     572             :                 case ECPGt_unsigned_char:
     573             :                 case ECPGt_string:
     574             :                     {
     575        4028 :                         char       *str = (char *) (var + offset * act_tuple);
     576             : 
     577             :                         /*
     578             :                          * If varcharsize is unknown and the offset is that of
     579             :                          * char *, then this variable represents the array of
     580             :                          * character pointers. So, use extra indirection.
     581             :                          */
     582        4028 :                         if (varcharsize == 0 && offset == sizeof(char *))
     583           0 :                             str = *(char **) str;
     584             : 
     585        4028 :                         if (varcharsize == 0 || varcharsize > size)
     586             :                         {
     587             :                             /*
     588             :                              * compatibility mode, blank pad and null
     589             :                              * terminate char array
     590             :                              */
     591        3836 :                             if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
     592             :                             {
     593          36 :                                 memset(str, ' ', varcharsize);
     594          36 :                                 memcpy(str, pval, size);
     595          36 :                                 str[varcharsize - 1] = '\0';
     596             : 
     597             :                                 /*
     598             :                                  * compatibility mode empty string gets -1
     599             :                                  * indicator but no warning
     600             :                                  */
     601          72 :                                 if (size == 0)
     602             :                                 {
     603             :                                     /* truncation */
     604             :                                     switch (ind_type)
     605             :                                     {
     606           8 :                                         case ECPGt_short:
     607             :                                         case ECPGt_unsigned_short:
     608           8 :                                             *((short *) (ind + ind_offset * act_tuple)) = -1;
     609           8 :                                             break;
     610           0 :                                         case ECPGt_int:
     611             :                                         case ECPGt_unsigned_int:
     612           0 :                                             *((int *) (ind + ind_offset * act_tuple)) = -1;
     613           0 :                                             break;
     614           0 :                                         case ECPGt_long:
     615             :                                         case ECPGt_unsigned_long:
     616           0 :                                             *((long *) (ind + ind_offset * act_tuple)) = -1;
     617           0 :                                             break;
     618           0 :                                         case ECPGt_long_long:
     619             :                                         case ECPGt_unsigned_long_long:
     620           0 :                                             *((long long int *) (ind + ind_offset * act_tuple)) = -1;
     621           0 :                                             break;
     622           0 :                                         default:
     623           0 :                                             break;
     624             :                                     }
     625          28 :                                 }
     626             :                             }
     627             :                             else
     628             :                             {
     629        3800 :                                 strncpy(str, pval, size + 1);
     630             :                             }
     631             :                             /* do the rtrim() */
     632        3844 :                             if (type == ECPGt_string)
     633             :                             {
     634           8 :                                 char       *last = str + size;
     635             : 
     636          52 :                                 while (last > str && (*last == ' ' || *last == '\0'))
     637             :                                 {
     638          44 :                                     *last = '\0';
     639          44 :                                     last--;
     640             :                                 }
     641             :                             }
     642             :                         }
     643             :                         else
     644             :                         {
     645         192 :                             strncpy(str, pval, varcharsize);
     646             : 
     647             :                             /* compatibility mode, null terminate char array */
     648         192 :                             if (ORACLE_MODE(compat) && (varcharsize - 1) < size)
     649             :                             {
     650          12 :                                 if (type == ECPGt_char || type == ECPGt_unsigned_char)
     651          12 :                                     str[varcharsize - 1] = '\0';
     652             :                             }
     653             : 
     654         192 :                             if (varcharsize < size || (ORACLE_MODE(compat) && (varcharsize - 1) < size))
     655             :                             {
     656             :                                 /* truncation */
     657             :                                 switch (ind_type)
     658             :                                 {
     659          12 :                                     case ECPGt_short:
     660             :                                     case ECPGt_unsigned_short:
     661          12 :                                         *((short *) (ind + ind_offset * act_tuple)) = size;
     662          12 :                                         break;
     663           4 :                                     case ECPGt_int:
     664             :                                     case ECPGt_unsigned_int:
     665           4 :                                         *((int *) (ind + ind_offset * act_tuple)) = size;
     666           4 :                                         break;
     667           0 :                                     case ECPGt_long:
     668             :                                     case ECPGt_unsigned_long:
     669           0 :                                         *((long *) (ind + ind_offset * act_tuple)) = size;
     670           0 :                                         break;
     671           0 :                                     case ECPGt_long_long:
     672             :                                     case ECPGt_unsigned_long_long:
     673           0 :                                         *((long long int *) (ind + ind_offset * act_tuple)) = size;
     674           0 :                                         break;
     675           8 :                                     default:
     676           8 :                                         break;
     677             :                                 }
     678          24 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     679             :                             }
     680             :                         }
     681        4028 :                         pval += size;
     682             :                     }
     683        4028 :                     break;
     684             : 
     685          88 :                 case ECPGt_varchar:
     686             :                     {
     687          88 :                         struct ECPGgeneric_varchar *variable =
     688          88 :                         (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
     689             : 
     690          88 :                         variable->len = size;
     691          88 :                         if (varcharsize == 0)
     692           0 :                             strncpy(variable->arr, pval, variable->len);
     693             :                         else
     694             :                         {
     695          88 :                             strncpy(variable->arr, pval, varcharsize);
     696             : 
     697          88 :                             if (variable->len > varcharsize)
     698             :                             {
     699             :                                 /* truncation */
     700             :                                 switch (ind_type)
     701             :                                 {
     702           0 :                                     case ECPGt_short:
     703             :                                     case ECPGt_unsigned_short:
     704           0 :                                         *((short *) (ind + ind_offset * act_tuple)) = variable->len;
     705           0 :                                         break;
     706           0 :                                     case ECPGt_int:
     707             :                                     case ECPGt_unsigned_int:
     708           0 :                                         *((int *) (ind + ind_offset * act_tuple)) = variable->len;
     709           0 :                                         break;
     710           0 :                                     case ECPGt_long:
     711             :                                     case ECPGt_unsigned_long:
     712           0 :                                         *((long *) (ind + ind_offset * act_tuple)) = variable->len;
     713           0 :                                         break;
     714           0 :                                     case ECPGt_long_long:
     715             :                                     case ECPGt_unsigned_long_long:
     716           0 :                                         *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
     717           0 :                                         break;
     718           0 :                                     default:
     719           0 :                                         break;
     720             :                                 }
     721           0 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     722             : 
     723           0 :                                 variable->len = varcharsize;
     724             :                             }
     725             :                         }
     726          88 :                         pval += size;
     727             :                     }
     728          88 :                     break;
     729             : 
     730          92 :                 case ECPGt_decimal:
     731             :                 case ECPGt_numeric:
     732         388 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
     733          92 :                     endchar = *endptr;
     734          92 :                     *endptr = '\0';
     735          92 :                     nres = PGTYPESnumeric_from_asc(pval, &scan_length);
     736          92 :                     *endptr = endchar;
     737             : 
     738             :                     /* did we get an error? */
     739          92 :                     if (nres == NULL)
     740             :                     {
     741           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     742           0 :                                  lineno, pval, errno);
     743             : 
     744           0 :                         if (INFORMIX_MODE(compat))
     745             :                         {
     746             :                             /*
     747             :                              * Informix wants its own NULL value here instead
     748             :                              * of an error
     749             :                              */
     750           0 :                             nres = PGTYPESnumeric_new();
     751           0 :                             if (nres)
     752           0 :                                 ECPGset_noind_null(ECPGt_numeric, nres);
     753             :                             else
     754             :                             {
     755           0 :                                 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     756             :                                            ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     757           0 :                                 return false;
     758             :                             }
     759             :                         }
     760             :                         else
     761             :                         {
     762           0 :                             ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
     763             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     764           0 :                             return false;
     765             :                         }
     766             :                     }
     767             :                     else
     768             :                     {
     769          92 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     770             :                         {
     771           0 :                             free(nres);
     772           0 :                             ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
     773             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     774           0 :                             return false;
     775             :                         }
     776             :                     }
     777          92 :                     pval = scan_length;
     778             : 
     779          92 :                     if (type == ECPGt_numeric)
     780          60 :                         PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
     781             :                     else
     782          32 :                         PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
     783             : 
     784          92 :                     PGTYPESnumeric_free(nres);
     785          92 :                     break;
     786             : 
     787          40 :                 case ECPGt_interval:
     788          40 :                     if (*pval == '"')
     789          40 :                         pval++;
     790             : 
     791         440 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     792          40 :                     endchar = *endptr;
     793          40 :                     *endptr = '\0';
     794          40 :                     ires = PGTYPESinterval_from_asc(pval, &scan_length);
     795          40 :                     *endptr = endchar;
     796             : 
     797             :                     /* did we get an error? */
     798          40 :                     if (ires == NULL)
     799             :                     {
     800           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     801           0 :                                  lineno, pval, errno);
     802             : 
     803           0 :                         if (INFORMIX_MODE(compat))
     804             :                         {
     805             :                             /*
     806             :                              * Informix wants its own NULL value here instead
     807             :                              * of an error
     808             :                              */
     809           0 :                             ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
     810           0 :                             if (!ires)
     811           0 :                                 return false;
     812             : 
     813           0 :                             ECPGset_noind_null(ECPGt_interval, ires);
     814             :                         }
     815             :                         else
     816             :                         {
     817           0 :                             ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
     818             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     819           0 :                             return false;
     820             :                         }
     821             :                     }
     822             :                     else
     823             :                     {
     824          40 :                         if (*scan_length == '"')
     825          40 :                             scan_length++;
     826             : 
     827          40 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     828             :                         {
     829           0 :                             free(ires);
     830           0 :                             ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
     831             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     832           0 :                             return false;
     833             :                         }
     834             :                     }
     835          40 :                     pval = scan_length;
     836             : 
     837          40 :                     PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
     838          40 :                     free(ires);
     839          40 :                     break;
     840             : 
     841          44 :                 case ECPGt_date:
     842          44 :                     if (*pval == '"')
     843           0 :                         pval++;
     844             : 
     845         484 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     846          44 :                     endchar = *endptr;
     847          44 :                     *endptr = '\0';
     848          44 :                     ddres = PGTYPESdate_from_asc(pval, &scan_length);
     849          44 :                     *endptr = endchar;
     850             : 
     851             :                     /* did we get an error? */
     852          44 :                     if (errno != 0)
     853             :                     {
     854           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     855           0 :                                  lineno, pval, errno);
     856             : 
     857           0 :                         if (INFORMIX_MODE(compat))
     858             :                         {
     859             :                             /*
     860             :                              * Informix wants its own NULL value here instead
     861             :                              * of an error
     862             :                              */
     863           0 :                             ECPGset_noind_null(ECPGt_date, &ddres);
     864             :                         }
     865             :                         else
     866             :                         {
     867           0 :                             ecpg_raise(lineno, ECPG_DATE_FORMAT,
     868             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     869           0 :                             return false;
     870             :                         }
     871             :                     }
     872             :                     else
     873             :                     {
     874          44 :                         if (*scan_length == '"')
     875           0 :                             scan_length++;
     876             : 
     877          44 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     878             :                         {
     879           0 :                             ecpg_raise(lineno, ECPG_DATE_FORMAT,
     880             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     881           0 :                             return false;
     882             :                         }
     883             :                     }
     884             : 
     885          44 :                     *((date *) (var + offset * act_tuple)) = ddres;
     886          44 :                     pval = scan_length;
     887          44 :                     break;
     888             : 
     889          52 :                 case ECPGt_timestamp:
     890          52 :                     if (*pval == '"')
     891          40 :                         pval++;
     892             : 
     893        1280 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     894          52 :                     endchar = *endptr;
     895          52 :                     *endptr = '\0';
     896          52 :                     tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
     897          52 :                     *endptr = endchar;
     898             : 
     899             :                     /* did we get an error? */
     900          52 :                     if (errno != 0)
     901             :                     {
     902           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     903           0 :                                  lineno, pval, errno);
     904             : 
     905           0 :                         if (INFORMIX_MODE(compat))
     906             :                         {
     907             :                             /*
     908             :                              * Informix wants its own NULL value here instead
     909             :                              * of an error
     910             :                              */
     911           0 :                             ECPGset_noind_null(ECPGt_timestamp, &tres);
     912             :                         }
     913             :                         else
     914             :                         {
     915           0 :                             ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
     916             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     917           0 :                             return false;
     918             :                         }
     919             :                     }
     920             :                     else
     921             :                     {
     922          52 :                         if (*scan_length == '"')
     923          40 :                             scan_length++;
     924             : 
     925          52 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     926             :                         {
     927           0 :                             ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
     928             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     929           0 :                             return false;
     930             :                         }
     931             :                     }
     932             : 
     933          52 :                     *((timestamp *) (var + offset * act_tuple)) = tres;
     934          52 :                     pval = scan_length;
     935          52 :                     break;
     936             : 
     937           0 :                 default:
     938           0 :                     ecpg_raise(lineno, ECPG_UNSUPPORTED,
     939             :                                ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
     940             :                                ecpg_type_name(type));
     941           0 :                     return false;
     942             :                     break;
     943             :             }
     944        5464 :             if (ECPG_IS_ARRAY(isarray))
     945             :             {
     946         204 :                 bool        string = false;
     947             : 
     948             :                 /* set array to next entry */
     949         204 :                 ++act_tuple;
     950             : 
     951             :                 /* set pval to the next entry */
     952             : 
     953             :                 /*
     954             :                  * *pval != '\0' should not be needed, but is used as a safety
     955             :                  * guard
     956             :                  */
     957         204 :                 for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
     958           0 :                     if (*pval == '"')
     959           0 :                         string = string ? false : true;
     960             : 
     961         204 :                 if (array_delimiter(isarray, *pval))
     962         180 :                     ++pval;
     963             :             }
     964             :         }
     965        5480 :     } while (*pval != '\0' && !array_boundary(isarray, *pval));
     966             : 
     967        5300 :     return true;
     968             : }

Generated by: LCOV version 1.13