LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - data.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 247 396 62.4 %
Date: 2019-08-24 16:07:17 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 "ecpgtype.h"
       9             : #include "ecpglib.h"
      10             : #include "ecpgerrno.h"
      11             : #include "ecpglib_extern.h"
      12             : #include "sqlca.h"
      13             : #include "pgtypes_numeric.h"
      14             : #include "pgtypes_date.h"
      15             : #include "pgtypes_timestamp.h"
      16             : #include "pgtypes_interval.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        1152 : 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        1152 :     if (isarray == ECPG_ARRAY_NONE)
      53             :     {
      54        1112 :         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        1112 :         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        1152 :     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       16292 :     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       20560 :     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        5596 : 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        5596 :     struct sqlca_t *sqlca = ECPGget_sqlca();
     212        5596 :     char       *pval = (char *) PQgetvalue(results, act_tuple, act_field);
     213        5596 :     int         binary = PQfformat(results, act_field);
     214        5596 :     int         size = PQgetlength(results, act_tuple, act_field);
     215        5596 :     int         value_for_indicator = 0;
     216             :     long        log_offset;
     217             : 
     218        5596 :     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        5596 :     if (ecpg_internal_regression_mode)
     230        2252 :         log_offset = -1;
     231             :     else
     232        3344 :         log_offset = offset;
     233             : 
     234        5596 :     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        5596 :     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        5596 :     if (PQgetisnull(results, act_tuple, act_field))
     254         176 :         value_for_indicator = -1;
     255             : 
     256        5596 :     switch (ind_type)
     257             :     {
     258             :         case ECPGt_short:
     259             :         case ECPGt_unsigned_short:
     260         200 :             *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     261         200 :             break;
     262             :         case ECPGt_int:
     263             :         case ECPGt_unsigned_int:
     264         320 :             *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     265         320 :             break;
     266             :         case ECPGt_long:
     267             :         case ECPGt_unsigned_long:
     268          40 :             *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     269          40 :             break;
     270             : #ifdef HAVE_LONG_LONG_INT
     271             :         case ECPGt_long_long:
     272             :         case ECPGt_unsigned_long_long:
     273           0 :             *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
     274           0 :             break;
     275             : #endif                          /* HAVE_LONG_LONG_INT */
     276             :         case ECPGt_NO_INDICATOR:
     277        5036 :             if (value_for_indicator == -1)
     278             :             {
     279          56 :                 if (force_indicator == false)
     280             :                 {
     281             :                     /*
     282             :                      * Informix has an additional way to specify NULLs note
     283             :                      * that this uses special values to denote NULL
     284             :                      */
     285          48 :                     ECPGset_noind_null(type, var + offset * act_tuple);
     286             :                 }
     287             :                 else
     288             :                 {
     289           8 :                     ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
     290             :                                ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
     291             :                                NULL);
     292           8 :                     return false;
     293             :                 }
     294             :             }
     295        5028 :             break;
     296             :         default:
     297           0 :             ecpg_raise(lineno, ECPG_UNSUPPORTED,
     298             :                        ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
     299             :                        ecpg_type_name(ind_type));
     300           0 :             return false;
     301             :             break;
     302             :     }
     303             : 
     304        5588 :     if (value_for_indicator == -1)
     305         168 :         return true;
     306             : 
     307             :     /* let's check if it really is an array if it should be one */
     308        5420 :     if (isarray == ECPG_ARRAY_ARRAY)
     309             :     {
     310          24 :         if (*pval != '{')
     311             :         {
     312           0 :             ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
     313             :                        ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
     314           0 :             return false;
     315             :         }
     316             : 
     317          24 :         switch (type)
     318             :         {
     319             :             case ECPGt_char:
     320             :             case ECPGt_unsigned_char:
     321             :             case ECPGt_varchar:
     322             :             case ECPGt_string:
     323           4 :                 break;
     324             : 
     325             :             default:
     326          20 :                 pval++;
     327          20 :                 break;
     328             :         }
     329             :     }
     330             : 
     331             :     do
     332             :     {
     333        5600 :         if (binary)
     334             :         {
     335          16 :             if (varcharsize == 0 || varcharsize * offset >= size)
     336          16 :                 memcpy(var + offset * act_tuple, pval, size);
     337             :             else
     338             :             {
     339           0 :                 memcpy(var + offset * act_tuple, pval, varcharsize * offset);
     340             : 
     341           0 :                 if (varcharsize * offset < size)
     342             :                 {
     343             :                     /* truncation */
     344           0 :                     switch (ind_type)
     345             :                     {
     346             :                         case ECPGt_short:
     347             :                         case ECPGt_unsigned_short:
     348           0 :                             *((short *) (ind + ind_offset * act_tuple)) = size;
     349           0 :                             break;
     350             :                         case ECPGt_int:
     351             :                         case ECPGt_unsigned_int:
     352           0 :                             *((int *) (ind + ind_offset * act_tuple)) = size;
     353           0 :                             break;
     354             :                         case ECPGt_long:
     355             :                         case ECPGt_unsigned_long:
     356           0 :                             *((long *) (ind + ind_offset * act_tuple)) = size;
     357           0 :                             break;
     358             : #ifdef HAVE_LONG_LONG_INT
     359             :                         case ECPGt_long_long:
     360             :                         case ECPGt_unsigned_long_long:
     361           0 :                             *((long long int *) (ind + ind_offset * act_tuple)) = size;
     362           0 :                             break;
     363             : #endif                          /* HAVE_LONG_LONG_INT */
     364             :                         default:
     365           0 :                             break;
     366             :                     }
     367           0 :                     sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     368             :                 }
     369             :             }
     370          16 :             pval += size;
     371             :         }
     372             :         else
     373             :         {
     374        5584 :             switch (type)
     375             :             {
     376             :                     long        res;
     377             :                     unsigned long ures;
     378             :                     double      dres;
     379             :                     char       *scan_length;
     380             :                     numeric    *nres;
     381             :                     date        ddres;
     382             :                     timestamp   tres;
     383             :                     interval   *ires;
     384             :                     char       *endptr,
     385             :                                 endchar;
     386             : 
     387             :                 case ECPGt_short:
     388             :                 case ECPGt_int:
     389             :                 case ECPGt_long:
     390         972 :                     res = strtol(pval, &scan_length, 10);
     391         972 :                     if (garbage_left(isarray, &scan_length, compat))
     392             :                     {
     393           0 :                         ecpg_raise(lineno, ECPG_INT_FORMAT,
     394             :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     395           0 :                         return false;
     396             :                     }
     397         972 :                     pval = scan_length;
     398             : 
     399         972 :                     switch (type)
     400             :                     {
     401             :                         case ECPGt_short:
     402          64 :                             *((short *) (var + offset * act_tuple)) = (short) res;
     403          64 :                             break;
     404             :                         case ECPGt_int:
     405         856 :                             *((int *) (var + offset * act_tuple)) = (int) res;
     406         856 :                             break;
     407             :                         case ECPGt_long:
     408          52 :                             *((long *) (var + offset * act_tuple)) = (long) res;
     409          52 :                             break;
     410             :                         default:
     411             :                             /* Cannot happen */
     412           0 :                             break;
     413             :                     }
     414        6556 :                     break;
     415             : 
     416             :                 case ECPGt_unsigned_short:
     417             :                 case ECPGt_unsigned_int:
     418             :                 case ECPGt_unsigned_long:
     419           0 :                     ures = strtoul(pval, &scan_length, 10);
     420           0 :                     if (garbage_left(isarray, &scan_length, compat))
     421             :                     {
     422           0 :                         ecpg_raise(lineno, ECPG_UINT_FORMAT,
     423             :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     424           0 :                         return false;
     425             :                     }
     426           0 :                     pval = scan_length;
     427             : 
     428           0 :                     switch (type)
     429             :                     {
     430             :                         case ECPGt_unsigned_short:
     431           0 :                             *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
     432           0 :                             break;
     433             :                         case ECPGt_unsigned_int:
     434           0 :                             *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
     435           0 :                             break;
     436             :                         case ECPGt_unsigned_long:
     437           0 :                             *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
     438           0 :                             break;
     439             :                         default:
     440             :                             /* Cannot happen */
     441           0 :                             break;
     442             :                     }
     443           0 :                     break;
     444             : 
     445             : #ifdef HAVE_LONG_LONG_INT
     446             : #ifdef HAVE_STRTOLL
     447             :                 case ECPGt_long_long:
     448           0 :                     *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
     449           0 :                     if (garbage_left(isarray, &scan_length, compat))
     450             :                     {
     451           0 :                         ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     452           0 :                         return false;
     453             :                     }
     454           0 :                     pval = scan_length;
     455             : 
     456           0 :                     break;
     457             : #endif                          /* HAVE_STRTOLL */
     458             : #ifdef HAVE_STRTOULL
     459             :                 case ECPGt_unsigned_long_long:
     460           0 :                     *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
     461           0 :                     if (garbage_left(isarray, &scan_length, compat))
     462             :                     {
     463           0 :                         ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     464           0 :                         return false;
     465             :                     }
     466           0 :                     pval = scan_length;
     467             : 
     468           0 :                     break;
     469             : #endif                          /* HAVE_STRTOULL */
     470             : #endif                          /* HAVE_LONG_LONG_INT */
     471             : 
     472             :                 case ECPGt_float:
     473             :                 case ECPGt_double:
     474         180 :                     if (isarray && *pval == '"')
     475           0 :                         pval++;
     476             : 
     477         180 :                     if (!check_special_value(pval, &dres, &scan_length))
     478         132 :                         dres = strtod(pval, &scan_length);
     479             : 
     480         180 :                     if (isarray && *scan_length == '"')
     481           0 :                         scan_length++;
     482             : 
     483             :                     /* no special INFORMIX treatment for floats */
     484         180 :                     if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
     485             :                     {
     486           0 :                         ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
     487             :                                    ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     488           0 :                         return false;
     489             :                     }
     490         180 :                     pval = scan_length;
     491             : 
     492         180 :                     switch (type)
     493             :                     {
     494             :                         case ECPGt_float:
     495          28 :                             *((float *) (var + offset * act_tuple)) = dres;
     496          28 :                             break;
     497             :                         case ECPGt_double:
     498         152 :                             *((double *) (var + offset * act_tuple)) = dres;
     499         152 :                             break;
     500             :                         default:
     501             :                             /* Cannot happen */
     502           0 :                             break;
     503             :                     }
     504         180 :                     break;
     505             : 
     506             :                 case ECPGt_bool:
     507          16 :                     if (pval[0] == 'f' && pval[1] == '\0')
     508             :                     {
     509           4 :                         *((bool *) (var + offset * act_tuple)) = false;
     510           4 :                         pval++;
     511           4 :                         break;
     512             :                     }
     513          12 :                     else if (pval[0] == 't' && pval[1] == '\0')
     514             :                     {
     515          12 :                         *((bool *) (var + offset * act_tuple)) = true;
     516          12 :                         pval++;
     517          12 :                         break;
     518             :                     }
     519           0 :                     else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
     520             :                     {
     521             :                         /* NULL is valid */
     522           0 :                         break;
     523             :                     }
     524             : 
     525           0 :                     ecpg_raise(lineno, ECPG_CONVERT_BOOL,
     526             :                                ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     527           0 :                     return false;
     528             :                     break;
     529             : 
     530             :                 case ECPGt_bytea:
     531             :                     {
     532          32 :                         struct ECPGgeneric_varchar *variable =
     533          32 :                         (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
     534             :                         long        dst_size,
     535             :                                     src_size,
     536             :                                     dec_size;
     537             : 
     538          32 :                         dst_size = ecpg_hex_enc_len(varcharsize);
     539          32 :                         src_size = size - 2;    /* exclude backslash + 'x' */
     540          32 :                         dec_size = src_size < dst_size ? src_size : dst_size;
     541          32 :                         variable->len = hex_decode(pval + 2, dec_size, variable->arr);
     542             : 
     543          32 :                         if (dst_size < src_size)
     544             :                         {
     545          12 :                             long        rcv_size = ecpg_hex_dec_len(size - 2);
     546             : 
     547             :                             /* truncation */
     548          12 :                             switch (ind_type)
     549             :                             {
     550             :                                 case ECPGt_short:
     551             :                                 case ECPGt_unsigned_short:
     552           0 :                                     *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
     553           0 :                                     break;
     554             :                                 case ECPGt_int:
     555             :                                 case ECPGt_unsigned_int:
     556          12 :                                     *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
     557          12 :                                     break;
     558             :                                 case ECPGt_long:
     559             :                                 case ECPGt_unsigned_long:
     560           0 :                                     *((long *) (ind + ind_offset * act_tuple)) = rcv_size;
     561           0 :                                     break;
     562             : #ifdef HAVE_LONG_LONG_INT
     563             :                                 case ECPGt_long_long:
     564             :                                 case ECPGt_unsigned_long_long:
     565           0 :                                     *((long long int *) (ind + ind_offset * act_tuple)) = rcv_size;
     566           0 :                                     break;
     567             : #endif                          /* HAVE_LONG_LONG_INT */
     568             :                                 default:
     569           0 :                                     break;
     570             :                             }
     571          12 :                             sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     572             :                         }
     573             : 
     574          32 :                         pval += size;
     575             : 
     576             :                     }
     577          32 :                     break;
     578             : 
     579             :                 case ECPGt_char:
     580             :                 case ECPGt_unsigned_char:
     581             :                 case ECPGt_string:
     582             :                     {
     583        4068 :                         char       *str = (char *) (var + offset * act_tuple);
     584             : 
     585             :                         /*
     586             :                          * If varcharsize is unknown and the offset is that of
     587             :                          * char *, then this variable represents the array of
     588             :                          * character pointers. So, use extra indirection.
     589             :                          */
     590        4068 :                         if (varcharsize == 0 && offset == sizeof(char *))
     591           0 :                             str = *(char **) str;
     592             : 
     593        4068 :                         if (varcharsize == 0 || varcharsize > size)
     594             :                         {
     595             :                             /*
     596             :                              * compatibility mode, blank pad and null
     597             :                              * terminate char array
     598             :                              */
     599        3876 :                             if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
     600             :                             {
     601          36 :                                 memset(str, ' ', varcharsize);
     602          36 :                                 memcpy(str, pval, size);
     603          36 :                                 str[varcharsize - 1] = '\0';
     604             : 
     605             :                                 /*
     606             :                                  * compatibility mode empty string gets -1
     607             :                                  * indicator but no warning
     608             :                                  */
     609          72 :                                 if (size == 0)
     610             :                                 {
     611             :                                     /* truncation */
     612           8 :                                     switch (ind_type)
     613             :                                     {
     614             :                                         case ECPGt_short:
     615             :                                         case ECPGt_unsigned_short:
     616           8 :                                             *((short *) (ind + ind_offset * act_tuple)) = -1;
     617           8 :                                             break;
     618             :                                         case ECPGt_int:
     619             :                                         case ECPGt_unsigned_int:
     620           0 :                                             *((int *) (ind + ind_offset * act_tuple)) = -1;
     621           0 :                                             break;
     622             :                                         case ECPGt_long:
     623             :                                         case ECPGt_unsigned_long:
     624           0 :                                             *((long *) (ind + ind_offset * act_tuple)) = -1;
     625           0 :                                             break;
     626             : #ifdef HAVE_LONG_LONG_INT
     627             :                                         case ECPGt_long_long:
     628             :                                         case ECPGt_unsigned_long_long:
     629           0 :                                             *((long long int *) (ind + ind_offset * act_tuple)) = -1;
     630           0 :                                             break;
     631             : #endif                          /* HAVE_LONG_LONG_INT */
     632             :                                         default:
     633           0 :                                             break;
     634             :                                     }
     635             :                                 }
     636             :                             }
     637             :                             else
     638             :                             {
     639        3840 :                                 strncpy(str, pval, size + 1);
     640             :                             }
     641             :                             /* do the rtrim() */
     642        7752 :                             if (type == ECPGt_string)
     643             :                             {
     644           8 :                                 char       *last = str + size;
     645             : 
     646          60 :                                 while (last > str && (*last == ' ' || *last == '\0'))
     647             :                                 {
     648          44 :                                     *last = '\0';
     649          44 :                                     last--;
     650             :                                 }
     651             :                             }
     652             :                         }
     653             :                         else
     654             :                         {
     655         192 :                             strncpy(str, pval, varcharsize);
     656             : 
     657             :                             /* compatibility mode, null terminate char array */
     658         192 :                             if (ORACLE_MODE(compat) && (varcharsize - 1) < size)
     659             :                             {
     660          12 :                                 if (type == ECPGt_char || type == ECPGt_unsigned_char)
     661          12 :                                     str[varcharsize - 1] = '\0';
     662             :                             }
     663             : 
     664         192 :                             if (varcharsize < size || (ORACLE_MODE(compat) && (varcharsize - 1) < size))
     665             :                             {
     666             :                                 /* truncation */
     667          24 :                                 switch (ind_type)
     668             :                                 {
     669             :                                     case ECPGt_short:
     670             :                                     case ECPGt_unsigned_short:
     671          12 :                                         *((short *) (ind + ind_offset * act_tuple)) = size;
     672          12 :                                         break;
     673             :                                     case ECPGt_int:
     674             :                                     case ECPGt_unsigned_int:
     675           4 :                                         *((int *) (ind + ind_offset * act_tuple)) = size;
     676           4 :                                         break;
     677             :                                     case ECPGt_long:
     678             :                                     case ECPGt_unsigned_long:
     679           0 :                                         *((long *) (ind + ind_offset * act_tuple)) = size;
     680           0 :                                         break;
     681             : #ifdef HAVE_LONG_LONG_INT
     682             :                                     case ECPGt_long_long:
     683             :                                     case ECPGt_unsigned_long_long:
     684           0 :                                         *((long long int *) (ind + ind_offset * act_tuple)) = size;
     685           0 :                                         break;
     686             : #endif                          /* HAVE_LONG_LONG_INT */
     687             :                                     default:
     688           8 :                                         break;
     689             :                                 }
     690          24 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     691             :                             }
     692             :                         }
     693        4068 :                         pval += size;
     694             :                     }
     695        4068 :                     break;
     696             : 
     697             :                 case ECPGt_varchar:
     698             :                     {
     699          88 :                         struct ECPGgeneric_varchar *variable =
     700          88 :                         (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
     701             : 
     702          88 :                         variable->len = size;
     703          88 :                         if (varcharsize == 0)
     704           0 :                             strncpy(variable->arr, pval, variable->len);
     705             :                         else
     706             :                         {
     707          88 :                             strncpy(variable->arr, pval, varcharsize);
     708             : 
     709          88 :                             if (variable->len > varcharsize)
     710             :                             {
     711             :                                 /* truncation */
     712           0 :                                 switch (ind_type)
     713             :                                 {
     714             :                                     case ECPGt_short:
     715             :                                     case ECPGt_unsigned_short:
     716           0 :                                         *((short *) (ind + ind_offset * act_tuple)) = variable->len;
     717           0 :                                         break;
     718             :                                     case ECPGt_int:
     719             :                                     case ECPGt_unsigned_int:
     720           0 :                                         *((int *) (ind + ind_offset * act_tuple)) = variable->len;
     721           0 :                                         break;
     722             :                                     case ECPGt_long:
     723             :                                     case ECPGt_unsigned_long:
     724           0 :                                         *((long *) (ind + ind_offset * act_tuple)) = variable->len;
     725           0 :                                         break;
     726             : #ifdef HAVE_LONG_LONG_INT
     727             :                                     case ECPGt_long_long:
     728             :                                     case ECPGt_unsigned_long_long:
     729           0 :                                         *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
     730           0 :                                         break;
     731             : #endif                          /* HAVE_LONG_LONG_INT */
     732             :                                     default:
     733           0 :                                         break;
     734             :                                 }
     735           0 :                                 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
     736             : 
     737           0 :                                 variable->len = varcharsize;
     738             :                             }
     739             :                         }
     740          88 :                         pval += size;
     741             :                     }
     742          88 :                     break;
     743             : 
     744             :                 case ECPGt_decimal:
     745             :                 case ECPGt_numeric:
     746          92 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
     747          92 :                     endchar = *endptr;
     748          92 :                     *endptr = '\0';
     749          92 :                     nres = PGTYPESnumeric_from_asc(pval, &scan_length);
     750          92 :                     *endptr = endchar;
     751             : 
     752             :                     /* did we get an error? */
     753          92 :                     if (nres == NULL)
     754             :                     {
     755           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     756           0 :                                  lineno, pval, errno);
     757             : 
     758           0 :                         if (INFORMIX_MODE(compat))
     759             :                         {
     760             :                             /*
     761             :                              * Informix wants its own NULL value here instead
     762             :                              * of an error
     763             :                              */
     764           0 :                             nres = PGTYPESnumeric_new();
     765           0 :                             if (nres)
     766           0 :                                 ECPGset_noind_null(ECPGt_numeric, nres);
     767             :                             else
     768             :                             {
     769           0 :                                 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
     770             :                                            ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     771           0 :                                 return false;
     772             :                             }
     773             :                         }
     774             :                         else
     775             :                         {
     776           0 :                             ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
     777             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     778           0 :                             return false;
     779             :                         }
     780             :                     }
     781             :                     else
     782             :                     {
     783          92 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     784             :                         {
     785           0 :                             free(nres);
     786           0 :                             ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
     787             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     788           0 :                             return false;
     789             :                         }
     790             :                     }
     791          92 :                     pval = scan_length;
     792             : 
     793          92 :                     if (type == ECPGt_numeric)
     794          60 :                         PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
     795             :                     else
     796          32 :                         PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
     797             : 
     798          92 :                     PGTYPESnumeric_free(nres);
     799          92 :                     break;
     800             : 
     801             :                 case ECPGt_interval:
     802          40 :                     if (*pval == '"')
     803          40 :                         pval++;
     804             : 
     805          40 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     806          40 :                     endchar = *endptr;
     807          40 :                     *endptr = '\0';
     808          40 :                     ires = PGTYPESinterval_from_asc(pval, &scan_length);
     809          40 :                     *endptr = endchar;
     810             : 
     811             :                     /* did we get an error? */
     812          40 :                     if (ires == NULL)
     813             :                     {
     814           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     815           0 :                                  lineno, pval, errno);
     816             : 
     817           0 :                         if (INFORMIX_MODE(compat))
     818             :                         {
     819             :                             /*
     820             :                              * Informix wants its own NULL value here instead
     821             :                              * of an error
     822             :                              */
     823           0 :                             ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
     824           0 :                             if (!ires)
     825           0 :                                 return false;
     826             : 
     827           0 :                             ECPGset_noind_null(ECPGt_interval, ires);
     828             :                         }
     829             :                         else
     830             :                         {
     831           0 :                             ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
     832             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     833           0 :                             return false;
     834             :                         }
     835             :                     }
     836             :                     else
     837             :                     {
     838          40 :                         if (*scan_length == '"')
     839          40 :                             scan_length++;
     840             : 
     841          40 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     842             :                         {
     843           0 :                             free(ires);
     844           0 :                             ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
     845             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     846           0 :                             return false;
     847             :                         }
     848             :                     }
     849          40 :                     pval = scan_length;
     850             : 
     851          40 :                     PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
     852          40 :                     free(ires);
     853          40 :                     break;
     854             : 
     855             :                 case ECPGt_date:
     856          44 :                     if (*pval == '"')
     857           0 :                         pval++;
     858             : 
     859          44 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     860          44 :                     endchar = *endptr;
     861          44 :                     *endptr = '\0';
     862          44 :                     ddres = PGTYPESdate_from_asc(pval, &scan_length);
     863          44 :                     *endptr = endchar;
     864             : 
     865             :                     /* did we get an error? */
     866          44 :                     if (errno != 0)
     867             :                     {
     868           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     869           0 :                                  lineno, pval, errno);
     870             : 
     871           0 :                         if (INFORMIX_MODE(compat))
     872             :                         {
     873             :                             /*
     874             :                              * Informix wants its own NULL value here instead
     875             :                              * of an error
     876             :                              */
     877           0 :                             ECPGset_noind_null(ECPGt_date, &ddres);
     878             :                         }
     879             :                         else
     880             :                         {
     881           0 :                             ecpg_raise(lineno, ECPG_DATE_FORMAT,
     882             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     883           0 :                             return false;
     884             :                         }
     885             :                     }
     886             :                     else
     887             :                     {
     888          44 :                         if (*scan_length == '"')
     889           0 :                             scan_length++;
     890             : 
     891          44 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     892             :                         {
     893           0 :                             ecpg_raise(lineno, ECPG_DATE_FORMAT,
     894             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     895           0 :                             return false;
     896             :                         }
     897             :                     }
     898             : 
     899          44 :                     *((date *) (var + offset * act_tuple)) = ddres;
     900          44 :                     pval = scan_length;
     901          44 :                     break;
     902             : 
     903             :                 case ECPGt_timestamp:
     904          52 :                     if (*pval == '"')
     905          40 :                         pval++;
     906             : 
     907          52 :                     for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
     908          52 :                     endchar = *endptr;
     909          52 :                     *endptr = '\0';
     910          52 :                     tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
     911          52 :                     *endptr = endchar;
     912             : 
     913             :                     /* did we get an error? */
     914          52 :                     if (errno != 0)
     915             :                     {
     916           0 :                         ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
     917           0 :                                  lineno, pval, errno);
     918             : 
     919           0 :                         if (INFORMIX_MODE(compat))
     920             :                         {
     921             :                             /*
     922             :                              * Informix wants its own NULL value here instead
     923             :                              * of an error
     924             :                              */
     925           0 :                             ECPGset_noind_null(ECPGt_timestamp, &tres);
     926             :                         }
     927             :                         else
     928             :                         {
     929           0 :                             ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
     930             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     931           0 :                             return false;
     932             :                         }
     933             :                     }
     934             :                     else
     935             :                     {
     936          52 :                         if (*scan_length == '"')
     937          40 :                             scan_length++;
     938             : 
     939          52 :                         if (!isarray && garbage_left(isarray, &scan_length, compat))
     940             :                         {
     941           0 :                             ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
     942             :                                        ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
     943           0 :                             return false;
     944             :                         }
     945             :                     }
     946             : 
     947          52 :                     *((timestamp *) (var + offset * act_tuple)) = tres;
     948          52 :                     pval = scan_length;
     949          52 :                     break;
     950             : 
     951             :                 default:
     952           0 :                     ecpg_raise(lineno, ECPG_UNSUPPORTED,
     953             :                                ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
     954             :                                ecpg_type_name(type));
     955           0 :                     return false;
     956             :                     break;
     957             :             }
     958        5584 :             if (ECPG_IS_ARRAY(isarray))
     959             :             {
     960         204 :                 bool        string = false;
     961             : 
     962             :                 /* set array to next entry */
     963         204 :                 ++act_tuple;
     964             : 
     965             :                 /* set pval to the next entry */
     966             : 
     967             :                 /*
     968             :                  * *pval != '\0' should not be needed, but is used as a safety
     969             :                  * guard
     970             :                  */
     971         204 :                 for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
     972           0 :                     if (*pval == '"')
     973           0 :                         string = string ? false : true;
     974             : 
     975         204 :                 if (array_delimiter(isarray, *pval))
     976         180 :                     ++pval;
     977             :             }
     978             :         }
     979        5600 :     } while (*pval != '\0' && !array_boundary(isarray, *pval));
     980             : 
     981        5420 :     return true;
     982             : }

Generated by: LCOV version 1.13