LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - execute.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 67.5 % 1131 763
Test Date: 2026-03-24 02:15:55 Functions: 91.7 % 24 22
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* src/interfaces/ecpg/ecpglib/execute.c */
       2              : 
       3              : /*
       4              :  * The aim is to get a simpler interface to the database routines.
       5              :  * All the tedious messing around with tuples is supposed to be hidden
       6              :  * by this function.
       7              :  */
       8              : /* Author: Linus Tolke
       9              :    (actually most if the code is "borrowed" from the distribution and just
      10              :    slightly modified)
      11              :  */
      12              : 
      13              : /* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
      14              :    on Feb. 5th, 1998 */
      15              : 
      16              : #define POSTGRES_ECPG_INTERNAL
      17              : #include "postgres_fe.h"
      18              : 
      19              : #include <math.h>
      20              : 
      21              : #include "catalog/pg_type_d.h"
      22              : #include "ecpgerrno.h"
      23              : #include "ecpglib.h"
      24              : #include "ecpglib_extern.h"
      25              : #include "ecpgtype.h"
      26              : #include "pgtypes_date.h"
      27              : #include "pgtypes_interval.h"
      28              : #include "pgtypes_numeric.h"
      29              : #include "pgtypes_timestamp.h"
      30              : #include "sql3types.h"
      31              : #include "sqlca.h"
      32              : #include "sqlda-compat.h"
      33              : #include "sqlda-native.h"
      34              : 
      35              : /*
      36              :  *  This function returns a newly malloced string that has ' and \
      37              :  *  escaped.
      38              :  */
      39              : static char *
      40         1134 : quote_postgres(char *arg, bool quote, int lineno)
      41              : {
      42              :     char       *res;
      43              :     size_t      length;
      44              :     size_t      escaped_len;
      45              :     size_t      buffer_len;
      46              : 
      47              :     /*
      48              :      * if quote is false we just need to store things in a descriptor they
      49              :      * will be quoted once they are inserted in a statement
      50              :      */
      51         1134 :     if (!quote)
      52         1134 :         return arg;
      53              :     else
      54              :     {
      55            0 :         length = strlen(arg);
      56            0 :         buffer_len = 2 * length + 1;
      57            0 :         res = ecpg_alloc(buffer_len + 3, lineno);
      58            0 :         if (!res)
      59            0 :             return res;
      60            0 :         escaped_len = PQescapeString(res + 1, arg, buffer_len);
      61            0 :         if (length == escaped_len)
      62              :         {
      63            0 :             res[0] = res[escaped_len + 1] = '\'';
      64            0 :             res[escaped_len + 2] = '\0';
      65              :         }
      66              :         else
      67              :         {
      68              :             /*
      69              :              * We don't know if the target database is using
      70              :              * standard_conforming_strings, so we always use E'' strings.
      71              :              */
      72            0 :             memmove(res + 2, res + 1, escaped_len);
      73            0 :             res[0] = ESCAPE_STRING_SYNTAX;
      74            0 :             res[1] = res[escaped_len + 2] = '\'';
      75            0 :             res[escaped_len + 3] = '\0';
      76              :         }
      77            0 :         ecpg_free(arg);
      78            0 :         return res;
      79              :     }
      80              : }
      81              : 
      82              : static void
      83        10690 : free_variable(struct variable *var)
      84              : {
      85              :     struct variable *var_next;
      86              : 
      87        17000 :     while (var)
      88              :     {
      89         6310 :         var_next = var->next;
      90         6310 :         ecpg_free(var);
      91         6310 :         var = var_next;
      92              :     }
      93        10690 : }
      94              : 
      95              : static void
      96         5345 : free_statement(struct statement *stmt)
      97              : {
      98         5345 :     if (stmt == NULL)
      99            0 :         return;
     100         5345 :     free_variable(stmt->inlist);
     101         5345 :     free_variable(stmt->outlist);
     102         5345 :     ecpg_free(stmt->command);
     103         5345 :     ecpg_free(stmt->name);
     104              : #ifndef HAVE_USELOCALE
     105              :     ecpg_free(stmt->oldlocale);
     106              : #endif
     107         5345 :     ecpg_free(stmt);
     108              : }
     109              : 
     110              : static int
     111         9013 : next_insert(char *text, int pos, bool questionmarks, bool std_strings)
     112              : {
     113         9013 :     bool        string = false;
     114         9013 :     int         p = pos;
     115              : 
     116       243201 :     for (; text[p] != '\0'; p++)
     117              :     {
     118       237866 :         if (string && !std_strings && text[p] == '\\')  /* escape character */
     119            0 :             p++;
     120       237866 :         else if (text[p] == '\'')
     121         3942 :             string = string ? false : true;
     122       233924 :         else if (!string)
     123              :         {
     124       218871 :             if (text[p] == '$' && isdigit((unsigned char) text[p + 1]))
     125            0 :             {
     126              :                 /* this can be either a dollar quote or a variable */
     127              :                 int         i;
     128              : 
     129         7358 :                 for (i = p + 1; isdigit((unsigned char) text[i]); i++)
     130              :                      /* empty loop body */ ;
     131         3678 :                 if (!isalpha((unsigned char) text[i]) &&
     132         3678 :                     isascii((unsigned char) text[i]) && text[i] != '_')
     133              :                     /* not dollar delimited quote */
     134         3678 :                     return p;
     135              :             }
     136       215193 :             else if (questionmarks && text[p] == '?')
     137              :             {
     138              :                 /* also allow old style placeholders */
     139            0 :                 return p;
     140              :             }
     141              :         }
     142              :     }
     143              : 
     144         5335 :     return -1;
     145              : }
     146              : 
     147              : static bool
     148         5162 : ecpg_type_infocache_push(struct ECPGtype_information_cache **cache, Oid oid, enum ARRAY_TYPE isarray, int lineno)
     149              : {
     150              :     struct ECPGtype_information_cache *new_entry
     151         5162 :     = (struct ECPGtype_information_cache *) ecpg_alloc(sizeof(struct ECPGtype_information_cache), lineno);
     152              : 
     153         5162 :     if (new_entry == NULL)
     154            0 :         return false;
     155              : 
     156         5162 :     new_entry->oid = oid;
     157         5162 :     new_entry->isarray = isarray;
     158         5162 :     new_entry->next = *cache;
     159         5162 :     *cache = new_entry;
     160         5162 :     return true;
     161              : }
     162              : 
     163              : static enum ARRAY_TYPE
     164         2522 : ecpg_is_type_an_array(Oid type, const struct statement *stmt, const struct variable *var)
     165              : {
     166              :     char       *array_query;
     167         2522 :     enum ARRAY_TYPE isarray = ECPG_ARRAY_NOT_SET;
     168              :     PGresult   *query;
     169              :     struct ECPGtype_information_cache *cache_entry;
     170              : 
     171         2522 :     if ((stmt->connection->cache_head) == NULL)
     172              :     {
     173              :         /*
     174              :          * Text like types are not an array for ecpg, but postgres counts them
     175              :          * as an array. This define reminds you to not 'correct' these values.
     176              :          */
     177              : #define not_an_array_in_ecpg ECPG_ARRAY_NONE
     178              : 
     179              :         /* populate cache with well known types to speed things up */
     180          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BOOLOID, ECPG_ARRAY_NONE, stmt->lineno))
     181            0 :             return ECPG_ARRAY_ERROR;
     182          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BYTEAOID, ECPG_ARRAY_NONE, stmt->lineno))
     183            0 :             return ECPG_ARRAY_ERROR;
     184          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CHAROID, ECPG_ARRAY_NONE, stmt->lineno))
     185            0 :             return ECPG_ARRAY_ERROR;
     186          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NAMEOID, not_an_array_in_ecpg, stmt->lineno))
     187            0 :             return ECPG_ARRAY_ERROR;
     188          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT8OID, ECPG_ARRAY_NONE, stmt->lineno))
     189            0 :             return ECPG_ARRAY_ERROR;
     190          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT2OID, ECPG_ARRAY_NONE, stmt->lineno))
     191            0 :             return ECPG_ARRAY_ERROR;
     192          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT2VECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno))
     193            0 :             return ECPG_ARRAY_ERROR;
     194          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT4OID, ECPG_ARRAY_NONE, stmt->lineno))
     195            0 :             return ECPG_ARRAY_ERROR;
     196          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), REGPROCOID, ECPG_ARRAY_NONE, stmt->lineno))
     197            0 :             return ECPG_ARRAY_ERROR;
     198          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TEXTOID, ECPG_ARRAY_NONE, stmt->lineno))
     199            0 :             return ECPG_ARRAY_ERROR;
     200          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), OIDOID, ECPG_ARRAY_NONE, stmt->lineno))
     201            0 :             return ECPG_ARRAY_ERROR;
     202          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIDOID, ECPG_ARRAY_NONE, stmt->lineno))
     203            0 :             return ECPG_ARRAY_ERROR;
     204          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), XIDOID, ECPG_ARRAY_NONE, stmt->lineno))
     205            0 :             return ECPG_ARRAY_ERROR;
     206          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDOID, ECPG_ARRAY_NONE, stmt->lineno))
     207            0 :             return ECPG_ARRAY_ERROR;
     208          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), OIDVECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno))
     209            0 :             return ECPG_ARRAY_ERROR;
     210          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), POINTOID, ECPG_ARRAY_VECTOR, stmt->lineno))
     211            0 :             return ECPG_ARRAY_ERROR;
     212          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), LSEGOID, ECPG_ARRAY_VECTOR, stmt->lineno))
     213            0 :             return ECPG_ARRAY_ERROR;
     214          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), PATHOID, ECPG_ARRAY_NONE, stmt->lineno))
     215            0 :             return ECPG_ARRAY_ERROR;
     216          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BOXOID, ECPG_ARRAY_VECTOR, stmt->lineno))
     217            0 :             return ECPG_ARRAY_ERROR;
     218          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), POLYGONOID, ECPG_ARRAY_NONE, stmt->lineno))
     219            0 :             return ECPG_ARRAY_ERROR;
     220          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), LINEOID, ECPG_ARRAY_VECTOR, stmt->lineno))
     221            0 :             return ECPG_ARRAY_ERROR;
     222          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), FLOAT4OID, ECPG_ARRAY_NONE, stmt->lineno))
     223            0 :             return ECPG_ARRAY_ERROR;
     224          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), FLOAT8OID, ECPG_ARRAY_NONE, stmt->lineno))
     225            0 :             return ECPG_ARRAY_ERROR;
     226          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), UNKNOWNOID, ECPG_ARRAY_NONE, stmt->lineno))
     227            0 :             return ECPG_ARRAY_ERROR;
     228          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIRCLEOID, ECPG_ARRAY_NONE, stmt->lineno))
     229            0 :             return ECPG_ARRAY_ERROR;
     230          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), MONEYOID, ECPG_ARRAY_NONE, stmt->lineno))
     231            0 :             return ECPG_ARRAY_ERROR;
     232          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INETOID, ECPG_ARRAY_NONE, stmt->lineno))
     233            0 :             return ECPG_ARRAY_ERROR;
     234          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDROID, ECPG_ARRAY_NONE, stmt->lineno))
     235            0 :             return ECPG_ARRAY_ERROR;
     236          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BPCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
     237            0 :             return ECPG_ARRAY_ERROR;
     238          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
     239            0 :             return ECPG_ARRAY_ERROR;
     240          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), DATEOID, ECPG_ARRAY_NONE, stmt->lineno))
     241            0 :             return ECPG_ARRAY_ERROR;
     242          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
     243            0 :             return ECPG_ARRAY_ERROR;
     244          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, ECPG_ARRAY_NONE, stmt->lineno))
     245            0 :             return ECPG_ARRAY_ERROR;
     246          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, ECPG_ARRAY_NONE, stmt->lineno))
     247            0 :             return ECPG_ARRAY_ERROR;
     248          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INTERVALOID, ECPG_ARRAY_NONE, stmt->lineno))
     249            0 :             return ECPG_ARRAY_ERROR;
     250          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMETZOID, ECPG_ARRAY_NONE, stmt->lineno))
     251            0 :             return ECPG_ARRAY_ERROR;
     252          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BITOID, ECPG_ARRAY_NONE, stmt->lineno))
     253            0 :             return ECPG_ARRAY_ERROR;
     254          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARBITOID, ECPG_ARRAY_NONE, stmt->lineno))
     255            0 :             return ECPG_ARRAY_ERROR;
     256          132 :         if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NUMERICOID, ECPG_ARRAY_NONE, stmt->lineno))
     257            0 :             return ECPG_ARRAY_ERROR;
     258              :     }
     259              : 
     260        80122 :     for (cache_entry = (stmt->connection->cache_head); cache_entry != NULL; cache_entry = cache_entry->next)
     261              :     {
     262        80108 :         if (cache_entry->oid == type)
     263         2508 :             return cache_entry->isarray;
     264              :     }
     265              : 
     266           14 :     array_query = ecpg_alloc(strlen("select typlen from pg_type where oid= and typelem<>0") + 11, stmt->lineno);
     267           14 :     if (array_query == NULL)
     268            0 :         return ECPG_ARRAY_ERROR;
     269              : 
     270           14 :     sprintf(array_query, "select typlen from pg_type where oid=%u and typelem<>0", type);
     271           14 :     query = PQexec(stmt->connection->connection, array_query);
     272           14 :     ecpg_free(array_query);
     273           14 :     if (!ecpg_check_PQresult(query, stmt->lineno, stmt->connection->connection, stmt->compat))
     274            0 :         return ECPG_ARRAY_ERROR;
     275           14 :     else if (PQresultStatus(query) == PGRES_TUPLES_OK)
     276              :     {
     277           14 :         if (PQntuples(query) == 0)
     278            4 :             isarray = ECPG_ARRAY_NONE;
     279              :         else
     280              :         {
     281           10 :             isarray = (atoi(PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR;
     282           20 :             if (ecpg_dynamic_type(type) == SQL3_CHARACTER ||
     283           10 :                 ecpg_dynamic_type(type) == SQL3_CHARACTER_VARYING)
     284              :             {
     285              :                 /*
     286              :                  * arrays of character strings are not yet implemented
     287              :                  */
     288            0 :                 isarray = ECPG_ARRAY_NONE;
     289              :             }
     290              :         }
     291           14 :         PQclear(query);
     292              :     }
     293              :     else
     294            0 :         return ECPG_ARRAY_ERROR;
     295              : 
     296           14 :     ecpg_type_infocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
     297           18 :     ecpg_log("ecpg_is_type_an_array on line %d: type (%u); C (%d); array (%s)\n",
     298           18 :              stmt->lineno, type, var->type, ECPG_IS_ARRAY(isarray) ? "yes" : "no");
     299           14 :     return isarray;
     300              : }
     301              : 
     302              : 
     303              : bool
     304         2522 : ecpg_store_result(const PGresult *results, int act_field,
     305              :                   const struct statement *stmt, struct variable *var)
     306              : {
     307              :     enum ARRAY_TYPE isarray;
     308              :     int         act_tuple,
     309         2522 :                 ntuples = PQntuples(results);
     310         2522 :     bool        status = true;
     311              : 
     312         2522 :     if ((isarray = ecpg_is_type_an_array(PQftype(results, act_field), stmt, var)) == ECPG_ARRAY_ERROR)
     313              :     {
     314            0 :         ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
     315            0 :         return false;
     316              :     }
     317              : 
     318         2522 :     if (isarray == ECPG_ARRAY_NONE)
     319              :     {
     320              :         /*
     321              :          * if we don't have enough space, we cannot read all tuples
     322              :          */
     323         2510 :         if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
     324              :         {
     325            0 :             ecpg_log("ecpg_store_result on line %d: incorrect number of matches; %d don't fit into array of %ld\n",
     326            0 :                      stmt->lineno, ntuples, var->arrsize);
     327            0 :             ecpg_raise(stmt->lineno, INFORMIX_MODE(stmt->compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
     328            0 :             return false;
     329              :         }
     330              :     }
     331              :     else
     332              :     {
     333              :         /*
     334              :          * since we read an array, the variable has to be an array too
     335              :          */
     336           12 :         if (var->arrsize == 0)
     337              :         {
     338            0 :             ecpg_raise(stmt->lineno, ECPG_NO_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
     339            0 :             return false;
     340              :         }
     341              :     }
     342              : 
     343              :     /*
     344              :      * allocate memory for NULL pointers
     345              :      */
     346         2522 :     if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
     347              :     {
     348         1652 :         int         len = 0;
     349              : 
     350         1652 :         if (!PQfformat(results, act_field))
     351              :         {
     352         1650 :             switch (var->type)
     353              :             {
     354         1642 :                 case ECPGt_char:
     355              :                 case ECPGt_unsigned_char:
     356              :                 case ECPGt_string:
     357         1642 :                     if (!var->varcharsize && !var->arrsize)
     358              :                     {
     359              :                         /* special mode for handling char**foo=0 */
     360         3250 :                         for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
     361         1636 :                             len += strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
     362         1614 :                         len *= var->offset; /* should be 1, but YMNK */
     363         1614 :                         len += (ntuples + 1) * sizeof(char *);
     364              :                     }
     365              :                     else
     366              :                     {
     367           28 :                         var->varcharsize = 0;
     368              :                         /* check strlen for each tuple */
     369           56 :                         for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
     370              :                         {
     371           28 :                             int         slen = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
     372              : 
     373           28 :                             if (slen > var->varcharsize)
     374           28 :                                 var->varcharsize = slen;
     375              :                         }
     376           28 :                         var->offset *= var->varcharsize;
     377           28 :                         len = var->offset * ntuples;
     378              :                     }
     379         1642 :                     break;
     380            0 :                 case ECPGt_varchar:
     381            0 :                     len = ntuples * (var->varcharsize + sizeof(int));
     382            0 :                     break;
     383            8 :                 default:
     384            8 :                     len = var->offset * ntuples;
     385            8 :                     break;
     386              :             }
     387              :         }
     388              :         else
     389              :         {
     390            4 :             for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
     391            2 :                 len += PQgetlength(results, act_tuple, act_field);
     392              :         }
     393              : 
     394         1652 :         ecpg_log("ecpg_store_result on line %d: allocating memory for %d tuples\n", stmt->lineno, ntuples);
     395         1652 :         var->value = ecpg_auto_alloc(len, stmt->lineno);
     396         1652 :         if (!var->value)
     397            0 :             return false;
     398         1652 :         *((char **) var->pointer) = var->value;
     399              :     }
     400              : 
     401              :     /* allocate indicator variable if needed */
     402         2522 :     if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer != NULL)
     403              :     {
     404           20 :         int         len = var->ind_offset * ntuples;
     405              : 
     406           20 :         var->ind_value = ecpg_auto_alloc(len, stmt->lineno);
     407           20 :         if (!var->ind_value)
     408            0 :             return false;
     409           20 :         *((char **) var->ind_pointer) = var->ind_value;
     410              :     }
     411              : 
     412              :     /* fill the variable with the tuple(s) */
     413         2522 :     if (!var->varcharsize && !var->arrsize &&
     414         1614 :         (var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string))
     415         1614 :     {
     416              :         /* special mode for handling char**foo=0 */
     417              : 
     418              :         /* filling the array of (char*)s */
     419         1614 :         char      **current_string = (char **) var->value;
     420              : 
     421              :         /* storing the data (after the last array element) */
     422         1614 :         char       *current_data_location = (char *) &current_string[ntuples + 1];
     423              : 
     424         3250 :         for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
     425              :         {
     426         1636 :             int         len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
     427              : 
     428         1636 :             if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
     429              :                                var->type, var->ind_type, current_data_location,
     430         1636 :                                var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
     431            0 :                 status = false;
     432              :             else
     433              :             {
     434         1636 :                 *current_string = current_data_location;
     435         1636 :                 current_data_location += len;
     436         1636 :                 current_string++;
     437              :             }
     438              :         }
     439              : 
     440              :         /* terminate the list */
     441         1614 :         *current_string = NULL;
     442              :     }
     443              :     else
     444              :     {
     445         1984 :         for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
     446              :         {
     447         1076 :             if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
     448         1076 :                                var->type, var->ind_type, var->value,
     449         1076 :                                var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
     450           12 :                 status = false;
     451              :         }
     452              :     }
     453         2522 :     return status;
     454              : }
     455              : 
     456              : static void
     457           12 : sprintf_double_value(char *ptr, double value, const char *delim)
     458              : {
     459           12 :     if (isnan(value))
     460            2 :         sprintf(ptr, "%s%s", "NaN", delim);
     461           10 :     else if (isinf(value))
     462              :     {
     463            4 :         if (value < 0)
     464            2 :             sprintf(ptr, "%s%s", "-Infinity", delim);
     465              :         else
     466            2 :             sprintf(ptr, "%s%s", "Infinity", delim);
     467              :     }
     468              :     else
     469            6 :         sprintf(ptr, "%.15g%s", value, delim);
     470           12 : }
     471              : 
     472              : static void
     473            2 : sprintf_float_value(char *ptr, float value, const char *delim)
     474              : {
     475            2 :     if (isnan(value))
     476            0 :         sprintf(ptr, "%s%s", "NaN", delim);
     477            2 :     else if (isinf(value))
     478              :     {
     479            0 :         if (value < 0)
     480            0 :             sprintf(ptr, "%s%s", "-Infinity", delim);
     481              :         else
     482            0 :             sprintf(ptr, "%s%s", "Infinity", delim);
     483              :     }
     484              :     else
     485            2 :         sprintf(ptr, "%.15g%s", value, delim);
     486            2 : }
     487              : 
     488              : static char *
     489            0 : convert_bytea_to_string(char *from_data, int from_len, int lineno)
     490              : {
     491              :     char       *to_data;
     492            0 :     int         to_len = ecpg_hex_enc_len(from_len) + 4 + 1;    /* backslash + 'x' +
     493              :                                                                  * quote + quote */
     494              : 
     495            0 :     to_data = ecpg_alloc(to_len, lineno);
     496            0 :     if (!to_data)
     497            0 :         return NULL;
     498              : 
     499            0 :     strcpy(to_data, "'\\x");
     500            0 :     ecpg_hex_encode(from_data, from_len, to_data + 3);
     501            0 :     strcpy(to_data + 3 + ecpg_hex_enc_len(from_len), "\'");
     502              : 
     503            0 :     return to_data;
     504              : }
     505              : 
     506              : bool
     507         3696 : ecpg_store_input(const int lineno, const bool force_indicator, const struct variable *var,
     508              :                  char **tobeinserted_p, bool quote)
     509              : {
     510         3696 :     char       *mallocedval = NULL;
     511         3696 :     char       *newcopy = NULL;
     512              : 
     513              :     /*
     514              :      * arrays are not possible unless the column is an array, too FIXME: we do
     515              :      * not know if the column is an array here array input to singleton column
     516              :      * will result in a runtime error
     517              :      */
     518              : 
     519              :     /*
     520              :      * Some special treatment is needed for records since we want their
     521              :      * contents to arrive in a comma-separated list on insert (I think).
     522              :      */
     523              : 
     524         3696 :     *tobeinserted_p = "";
     525              : 
     526              :     /* check for null value and set input buffer accordingly */
     527         3696 :     switch (var->ind_type)
     528              :     {
     529            0 :         case ECPGt_short:
     530              :         case ECPGt_unsigned_short:
     531            0 :             if (*(short *) var->ind_value < 0)
     532            0 :                 *tobeinserted_p = NULL;
     533            0 :             break;
     534           10 :         case ECPGt_int:
     535              :         case ECPGt_unsigned_int:
     536           10 :             if (*(int *) var->ind_value < 0)
     537            6 :                 *tobeinserted_p = NULL;
     538           10 :             break;
     539            0 :         case ECPGt_long:
     540              :         case ECPGt_unsigned_long:
     541            0 :             if (*(long *) var->ind_value < 0L)
     542            0 :                 *tobeinserted_p = NULL;
     543            0 :             break;
     544            0 :         case ECPGt_long_long:
     545              :         case ECPGt_unsigned_long_long:
     546            0 :             if (*(long long int *) var->ind_value < (long long) 0)
     547            0 :                 *tobeinserted_p = NULL;
     548            0 :             break;
     549         3664 :         case ECPGt_NO_INDICATOR:
     550         3664 :             if (force_indicator == false)
     551              :             {
     552           34 :                 if (ECPGis_noind_null(var->type, var->value))
     553           18 :                     *tobeinserted_p = NULL;
     554              :             }
     555         3664 :             break;
     556           22 :         default:
     557           22 :             break;
     558              :     }
     559         3696 :     if (*tobeinserted_p != NULL)
     560              :     {
     561         3672 :         int         asize = var->arrsize ? var->arrsize : 1;
     562              : 
     563         3672 :         switch (var->type)
     564              :         {
     565              :                 int         element;
     566              : 
     567            8 :             case ECPGt_short:
     568            8 :                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
     569            0 :                     return false;
     570              : 
     571            8 :                 if (asize > 1)
     572              :                 {
     573            4 :                     strcpy(mallocedval, "{");
     574              : 
     575           44 :                     for (element = 0; element < asize; element++)
     576           40 :                         sprintf(mallocedval + strlen(mallocedval), "%hd,", ((short *) var->value)[element]);
     577              : 
     578            4 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     579              :                 }
     580              :                 else
     581            4 :                     sprintf(mallocedval, "%hd", *((short *) var->value));
     582              : 
     583            8 :                 *tobeinserted_p = mallocedval;
     584            8 :                 break;
     585              : 
     586         2550 :             case ECPGt_int:
     587         2550 :                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
     588            0 :                     return false;
     589              : 
     590         2550 :                 if (asize > 1)
     591              :                 {
     592            0 :                     strcpy(mallocedval, "{");
     593              : 
     594            0 :                     for (element = 0; element < asize; element++)
     595            0 :                         sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
     596              : 
     597            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     598              :                 }
     599              :                 else
     600         2550 :                     sprintf(mallocedval, "%d", *((int *) var->value));
     601              : 
     602         2550 :                 *tobeinserted_p = mallocedval;
     603         2550 :                 break;
     604              : 
     605            0 :             case ECPGt_unsigned_short:
     606            0 :                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
     607            0 :                     return false;
     608              : 
     609            0 :                 if (asize > 1)
     610              :                 {
     611            0 :                     strcpy(mallocedval, "{");
     612              : 
     613            0 :                     for (element = 0; element < asize; element++)
     614            0 :                         sprintf(mallocedval + strlen(mallocedval), "%hu,", ((unsigned short *) var->value)[element]);
     615              : 
     616            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     617              :                 }
     618              :                 else
     619            0 :                     sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
     620              : 
     621            0 :                 *tobeinserted_p = mallocedval;
     622            0 :                 break;
     623              : 
     624            0 :             case ECPGt_unsigned_int:
     625            0 :                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
     626            0 :                     return false;
     627              : 
     628            0 :                 if (asize > 1)
     629              :                 {
     630            0 :                     strcpy(mallocedval, "{");
     631              : 
     632            0 :                     for (element = 0; element < asize; element++)
     633            0 :                         sprintf(mallocedval + strlen(mallocedval), "%u,", ((unsigned int *) var->value)[element]);
     634              : 
     635            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     636              :                 }
     637              :                 else
     638            0 :                     sprintf(mallocedval, "%u", *((unsigned int *) var->value));
     639              : 
     640            0 :                 *tobeinserted_p = mallocedval;
     641            0 :                 break;
     642              : 
     643           10 :             case ECPGt_long:
     644           10 :                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
     645            0 :                     return false;
     646              : 
     647           10 :                 if (asize > 1)
     648              :                 {
     649            0 :                     strcpy(mallocedval, "{");
     650              : 
     651            0 :                     for (element = 0; element < asize; element++)
     652            0 :                         sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
     653              : 
     654            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     655              :                 }
     656              :                 else
     657           10 :                     sprintf(mallocedval, "%ld", *((long *) var->value));
     658              : 
     659           10 :                 *tobeinserted_p = mallocedval;
     660           10 :                 break;
     661              : 
     662            0 :             case ECPGt_unsigned_long:
     663            0 :                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
     664            0 :                     return false;
     665              : 
     666            0 :                 if (asize > 1)
     667              :                 {
     668            0 :                     strcpy(mallocedval, "{");
     669              : 
     670            0 :                     for (element = 0; element < asize; element++)
     671            0 :                         sprintf(mallocedval + strlen(mallocedval), "%lu,", ((unsigned long *) var->value)[element]);
     672              : 
     673            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     674              :                 }
     675              :                 else
     676            0 :                     sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
     677              : 
     678            0 :                 *tobeinserted_p = mallocedval;
     679            0 :                 break;
     680              : 
     681            0 :             case ECPGt_long_long:
     682            0 :                 if (!(mallocedval = ecpg_alloc(asize * 30, lineno)))
     683            0 :                     return false;
     684              : 
     685            0 :                 if (asize > 1)
     686              :                 {
     687            0 :                     strcpy(mallocedval, "{");
     688              : 
     689            0 :                     for (element = 0; element < asize; element++)
     690            0 :                         sprintf(mallocedval + strlen(mallocedval), "%lld,", ((long long int *) var->value)[element]);
     691              : 
     692            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     693              :                 }
     694              :                 else
     695            0 :                     sprintf(mallocedval, "%lld", *((long long int *) var->value));
     696              : 
     697            0 :                 *tobeinserted_p = mallocedval;
     698            0 :                 break;
     699              : 
     700            0 :             case ECPGt_unsigned_long_long:
     701            0 :                 if (!(mallocedval = ecpg_alloc(asize * 30, lineno)))
     702            0 :                     return false;
     703              : 
     704            0 :                 if (asize > 1)
     705              :                 {
     706            0 :                     strcpy(mallocedval, "{");
     707              : 
     708            0 :                     for (element = 0; element < asize; element++)
     709            0 :                         sprintf(mallocedval + strlen(mallocedval), "%llu,", ((unsigned long long int *) var->value)[element]);
     710              : 
     711            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     712              :                 }
     713              :                 else
     714            0 :                     sprintf(mallocedval, "%llu", *((unsigned long long int *) var->value));
     715              : 
     716            0 :                 *tobeinserted_p = mallocedval;
     717            0 :                 break;
     718              : 
     719            2 :             case ECPGt_float:
     720            2 :                 if (!(mallocedval = ecpg_alloc(asize * 25, lineno)))
     721            0 :                     return false;
     722              : 
     723            2 :                 if (asize > 1)
     724              :                 {
     725            0 :                     strcpy(mallocedval, "{");
     726              : 
     727            0 :                     for (element = 0; element < asize; element++)
     728            0 :                         sprintf_float_value(mallocedval + strlen(mallocedval), ((float *) var->value)[element], ",");
     729              : 
     730            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     731              :                 }
     732              :                 else
     733            2 :                     sprintf_float_value(mallocedval, *((float *) var->value), "");
     734              : 
     735            2 :                 *tobeinserted_p = mallocedval;
     736            2 :                 break;
     737              : 
     738           12 :             case ECPGt_double:
     739           12 :                 if (!(mallocedval = ecpg_alloc(asize * 25, lineno)))
     740            0 :                     return false;
     741              : 
     742           12 :                 if (asize > 1)
     743              :                 {
     744            0 :                     strcpy(mallocedval, "{");
     745              : 
     746            0 :                     for (element = 0; element < asize; element++)
     747            0 :                         sprintf_double_value(mallocedval + strlen(mallocedval), ((double *) var->value)[element], ",");
     748              : 
     749            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     750              :                 }
     751              :                 else
     752           12 :                     sprintf_double_value(mallocedval, *((double *) var->value), "");
     753              : 
     754           12 :                 *tobeinserted_p = mallocedval;
     755           12 :                 break;
     756              : 
     757            4 :             case ECPGt_bool:
     758            4 :                 if (!(mallocedval = ecpg_alloc(var->arrsize + sizeof("{}"), lineno)))
     759            0 :                     return false;
     760              : 
     761            4 :                 if (var->arrsize > 1)
     762              :                 {
     763            0 :                     strcpy(mallocedval, "{");
     764              : 
     765            0 :                     for (element = 0; element < asize; element++)
     766            0 :                         sprintf(mallocedval + strlen(mallocedval), "%c,", (((bool *) var->value)[element]) ? 't' : 'f');
     767              : 
     768            0 :                     strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     769              :                 }
     770              :                 else
     771              :                 {
     772            4 :                     if (var->offset == sizeof(char))
     773            4 :                         sprintf(mallocedval, "%c", (*((char *) var->value)) ? 't' : 'f');
     774            0 :                     else if (var->offset == sizeof(int))
     775            0 :                         sprintf(mallocedval, "%c", (*((int *) var->value)) ? 't' : 'f');
     776              :                     else
     777            0 :                         ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
     778              :                 }
     779              : 
     780            4 :                 *tobeinserted_p = mallocedval;
     781            4 :                 break;
     782              : 
     783          918 :             case ECPGt_char:
     784              :             case ECPGt_unsigned_char:
     785              :             case ECPGt_string:
     786              :                 {
     787              :                     /* set slen to string length if type is char * */
     788          918 :                     int         slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int) var->varcharsize;
     789              : 
     790          918 :                     if (!(newcopy = ecpg_alloc(slen + 1, lineno)))
     791            0 :                         return false;
     792              : 
     793          918 :                     strncpy(newcopy, (char *) var->value, slen);
     794          918 :                     newcopy[slen] = '\0';
     795              : 
     796          918 :                     mallocedval = quote_postgres(newcopy, quote, lineno);
     797          918 :                     if (!mallocedval)
     798              :                     {
     799            0 :                         ecpg_free(newcopy);
     800            0 :                         return false;
     801              :                     }
     802              : 
     803          918 :                     *tobeinserted_p = mallocedval;
     804              :                 }
     805          918 :                 break;
     806           74 :             case ECPGt_const:
     807              :             case ECPGt_char_variable:
     808              :                 {
     809           74 :                     int         slen = strlen((char *) var->value);
     810              : 
     811           74 :                     if (!(mallocedval = ecpg_alloc(slen + 1, lineno)))
     812            0 :                         return false;
     813              : 
     814           74 :                     strncpy(mallocedval, (char *) var->value, slen);
     815           74 :                     mallocedval[slen] = '\0';
     816              : 
     817           74 :                     *tobeinserted_p = mallocedval;
     818              :                 }
     819           74 :                 break;
     820              : 
     821           26 :             case ECPGt_bytea:
     822              :                 {
     823           26 :                     struct ECPGgeneric_bytea *variable =
     824              :                         (struct ECPGgeneric_bytea *) (var->value);
     825              : 
     826           26 :                     if (!(mallocedval = ecpg_alloc(variable->len, lineno)))
     827            0 :                         return false;
     828              : 
     829           26 :                     memcpy(mallocedval, variable->arr, variable->len);
     830           26 :                     *tobeinserted_p = mallocedval;
     831              :                 }
     832           26 :                 break;
     833              : 
     834           26 :             case ECPGt_varchar:
     835              :                 {
     836           26 :                     struct ECPGgeneric_varchar *variable =
     837              :                         (struct ECPGgeneric_varchar *) (var->value);
     838              : 
     839           26 :                     if (!(newcopy = ecpg_alloc(variable->len + 1, lineno)))
     840            0 :                         return false;
     841              : 
     842           26 :                     strncpy(newcopy, variable->arr, variable->len);
     843           26 :                     newcopy[variable->len] = '\0';
     844              : 
     845           26 :                     mallocedval = quote_postgres(newcopy, quote, lineno);
     846           26 :                     if (!mallocedval)
     847              :                     {
     848            0 :                         ecpg_free(newcopy);
     849            0 :                         return false;
     850              :                     }
     851              : 
     852           26 :                     *tobeinserted_p = mallocedval;
     853              :                 }
     854           26 :                 break;
     855              : 
     856           14 :             case ECPGt_decimal:
     857              :             case ECPGt_numeric:
     858              :                 {
     859           14 :                     char       *str = NULL;
     860              :                     int         slen;
     861              :                     numeric    *nval;
     862              : 
     863           14 :                     if (var->arrsize > 1)
     864            6 :                         mallocedval = ecpg_strdup("{", lineno, NULL);
     865              :                     else
     866            8 :                         mallocedval = ecpg_strdup("", lineno, NULL);
     867              : 
     868           14 :                     if (!mallocedval)
     869            0 :                         return false;
     870              : 
     871           82 :                     for (element = 0; element < asize; element++)
     872              :                     {
     873              :                         int         result;
     874              : 
     875           68 :                         nval = PGTYPESnumeric_new();
     876           68 :                         if (!nval)
     877              :                         {
     878            0 :                             ecpg_free(mallocedval);
     879            0 :                             return false;
     880              :                         }
     881              : 
     882           68 :                         if (var->type == ECPGt_numeric)
     883           64 :                             result = PGTYPESnumeric_copy(&(((numeric *) (var->value))[element]), nval);
     884              :                         else
     885            4 :                             result = PGTYPESnumeric_from_decimal(&(((decimal *) (var->value))[element]), nval);
     886              : 
     887           68 :                         if (result != 0)
     888              :                         {
     889            0 :                             PGTYPESnumeric_free(nval);
     890            0 :                             ecpg_free(mallocedval);
     891            0 :                             return false;
     892              :                         }
     893              : 
     894           68 :                         str = PGTYPESnumeric_to_asc(nval, nval->dscale);
     895           68 :                         slen = strlen(str);
     896           68 :                         PGTYPESnumeric_free(nval);
     897              : 
     898           68 :                         if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
     899              :                         {
     900            0 :                             ecpg_free(mallocedval);
     901            0 :                             ecpg_free(str);
     902            0 :                             return false;
     903              :                         }
     904           68 :                         mallocedval = newcopy;
     905              : 
     906              :                         /* also copy trailing '\0' */
     907           68 :                         memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
     908           68 :                         if (var->arrsize > 1)
     909           60 :                             strcpy(mallocedval + strlen(mallocedval), ",");
     910              : 
     911           68 :                         ecpg_free(str);
     912              :                     }
     913              : 
     914           14 :                     if (var->arrsize > 1)
     915            6 :                         strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     916              : 
     917           14 :                     *tobeinserted_p = mallocedval;
     918              :                 }
     919           14 :                 break;
     920              : 
     921            6 :             case ECPGt_interval:
     922              :                 {
     923            6 :                     char       *str = NULL;
     924              :                     int         slen;
     925              : 
     926            6 :                     if (var->arrsize > 1)
     927            6 :                         mallocedval = ecpg_strdup("{", lineno, NULL);
     928              :                     else
     929            0 :                         mallocedval = ecpg_strdup("", lineno, NULL);
     930              : 
     931            6 :                     if (!mallocedval)
     932            0 :                         return false;
     933              : 
     934           66 :                     for (element = 0; element < asize; element++)
     935              :                     {
     936           60 :                         str = quote_postgres(PGTYPESinterval_to_asc(&(((interval *) (var->value))[element])), quote, lineno);
     937           60 :                         if (!str)
     938              :                         {
     939            0 :                             ecpg_free(mallocedval);
     940            0 :                             return false;
     941              :                         }
     942              : 
     943           60 :                         slen = strlen(str);
     944              : 
     945           60 :                         if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
     946              :                         {
     947            0 :                             ecpg_free(mallocedval);
     948            0 :                             ecpg_free(str);
     949            0 :                             return false;
     950              :                         }
     951           60 :                         mallocedval = newcopy;
     952              : 
     953              :                         /* also copy trailing '\0' */
     954           60 :                         memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
     955           60 :                         if (var->arrsize > 1)
     956           60 :                             strcpy(mallocedval + strlen(mallocedval), ",");
     957              : 
     958           60 :                         ecpg_free(str);
     959              :                     }
     960              : 
     961            6 :                     if (var->arrsize > 1)
     962            6 :                         strcpy(mallocedval + strlen(mallocedval) - 1, "}");
     963              : 
     964            6 :                     *tobeinserted_p = mallocedval;
     965              :                 }
     966            6 :                 break;
     967              : 
     968           10 :             case ECPGt_date:
     969              :                 {
     970           10 :                     char       *str = NULL;
     971              :                     int         slen;
     972              : 
     973           10 :                     if (var->arrsize > 1)
     974            6 :                         mallocedval = ecpg_strdup("{", lineno, NULL);
     975              :                     else
     976            4 :                         mallocedval = ecpg_strdup("", lineno, NULL);
     977              : 
     978           10 :                     if (!mallocedval)
     979            0 :                         return false;
     980              : 
     981           74 :                     for (element = 0; element < asize; element++)
     982              :                     {
     983           64 :                         str = quote_postgres(PGTYPESdate_to_asc(((date *) (var->value))[element]), quote, lineno);
     984           64 :                         if (!str)
     985              :                         {
     986            0 :                             ecpg_free(mallocedval);
     987            0 :                             return false;
     988              :                         }
     989              : 
     990           64 :                         slen = strlen(str);
     991              : 
     992           64 :                         if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
     993              :                         {
     994            0 :                             ecpg_free(mallocedval);
     995            0 :                             ecpg_free(str);
     996            0 :                             return false;
     997              :                         }
     998           64 :                         mallocedval = newcopy;
     999              : 
    1000              :                         /* also copy trailing '\0' */
    1001           64 :                         memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
    1002           64 :                         if (var->arrsize > 1)
    1003           60 :                             strcpy(mallocedval + strlen(mallocedval), ",");
    1004              : 
    1005           64 :                         ecpg_free(str);
    1006              :                     }
    1007              : 
    1008           10 :                     if (var->arrsize > 1)
    1009            6 :                         strcpy(mallocedval + strlen(mallocedval) - 1, "}");
    1010              : 
    1011           10 :                     *tobeinserted_p = mallocedval;
    1012              :                 }
    1013           10 :                 break;
    1014              : 
    1015           12 :             case ECPGt_timestamp:
    1016              :                 {
    1017           12 :                     char       *str = NULL;
    1018              :                     int         slen;
    1019              : 
    1020           12 :                     if (var->arrsize > 1)
    1021            6 :                         mallocedval = ecpg_strdup("{", lineno, NULL);
    1022              :                     else
    1023            6 :                         mallocedval = ecpg_strdup("", lineno, NULL);
    1024              : 
    1025           12 :                     if (!mallocedval)
    1026            0 :                         return false;
    1027              : 
    1028           78 :                     for (element = 0; element < asize; element++)
    1029              :                     {
    1030           66 :                         str = quote_postgres(PGTYPEStimestamp_to_asc(((timestamp *) (var->value))[element]), quote, lineno);
    1031           66 :                         if (!str)
    1032              :                         {
    1033            0 :                             ecpg_free(mallocedval);
    1034            0 :                             return false;
    1035              :                         }
    1036              : 
    1037           66 :                         slen = strlen(str);
    1038              : 
    1039           66 :                         if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
    1040              :                         {
    1041            0 :                             ecpg_free(mallocedval);
    1042            0 :                             ecpg_free(str);
    1043            0 :                             return false;
    1044              :                         }
    1045           66 :                         mallocedval = newcopy;
    1046              : 
    1047              :                         /* also copy trailing '\0' */
    1048           66 :                         memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
    1049           66 :                         if (var->arrsize > 1)
    1050           60 :                             strcpy(mallocedval + strlen(mallocedval), ",");
    1051              : 
    1052           66 :                         ecpg_free(str);
    1053              :                     }
    1054              : 
    1055           12 :                     if (var->arrsize > 1)
    1056            6 :                         strcpy(mallocedval + strlen(mallocedval) - 1, "}");
    1057              : 
    1058           12 :                     *tobeinserted_p = mallocedval;
    1059              :                 }
    1060           12 :                 break;
    1061              : 
    1062            0 :             case ECPGt_descriptor:
    1063              :             case ECPGt_sqlda:
    1064            0 :                 break;
    1065              : 
    1066            0 :             default:
    1067              :                 /* Not implemented yet */
    1068            0 :                 ecpg_raise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ecpg_type_name(var->type));
    1069            0 :                 return false;
    1070              :                 break;
    1071              :         }
    1072              :     }
    1073         3696 :     return true;
    1074              : }
    1075              : 
    1076              : static void
    1077         3484 : print_param_value(char *value, int len, int is_binary, int lineno, int nth)
    1078              : {
    1079              :     char       *value_s;
    1080         3484 :     bool        malloced = false;
    1081              : 
    1082         3484 :     if (value == NULL)
    1083           24 :         value_s = "null";
    1084         3460 :     else if (!is_binary)
    1085         3434 :         value_s = value;
    1086              :     else
    1087              :     {
    1088           26 :         value_s = ecpg_alloc(ecpg_hex_enc_len(len) + 1, lineno);
    1089           26 :         if (value_s != NULL)
    1090              :         {
    1091           26 :             ecpg_hex_encode(value, len, value_s);
    1092           26 :             value_s[ecpg_hex_enc_len(len)] = '\0';
    1093           26 :             malloced = true;
    1094              :         }
    1095              :         else
    1096            0 :             value_s = "no memory for logging of parameter";
    1097              :     }
    1098              : 
    1099         3484 :     ecpg_log("ecpg_free_params on line %d: parameter %d = %s\n",
    1100              :              lineno, nth, value_s);
    1101              : 
    1102         3484 :     if (malloced)
    1103           26 :         ecpg_free(value_s);
    1104         3484 : }
    1105              : 
    1106              : void
    1107         5345 : ecpg_free_params(struct statement *stmt, bool print)
    1108              : {
    1109              :     int         n;
    1110              : 
    1111         8829 :     for (n = 0; n < stmt->nparams; n++)
    1112              :     {
    1113         3484 :         if (print)
    1114         3484 :             print_param_value(stmt->paramvalues[n], stmt->paramlengths[n],
    1115         3484 :                               stmt->paramformats[n], stmt->lineno, n + 1);
    1116         3484 :         ecpg_free(stmt->paramvalues[n]);
    1117              :     }
    1118         5345 :     ecpg_free(stmt->paramvalues);
    1119         5345 :     ecpg_free(stmt->paramlengths);
    1120         5345 :     ecpg_free(stmt->paramformats);
    1121         5345 :     stmt->paramvalues = NULL;
    1122         5345 :     stmt->paramlengths = NULL;
    1123         5345 :     stmt->paramformats = NULL;
    1124         5345 :     stmt->nparams = 0;
    1125         5345 : }
    1126              : 
    1127              : static bool
    1128          194 : insert_tobeinserted(int position, int ph_len, struct statement *stmt, char *tobeinserted)
    1129              : {
    1130              :     char       *newcopy;
    1131              : 
    1132          194 :     if (!(newcopy = ecpg_alloc(strlen(stmt->command) + strlen(tobeinserted) + 1, stmt->lineno)))
    1133              :     {
    1134            0 :         ecpg_free(tobeinserted);
    1135            0 :         return false;
    1136              :     }
    1137              : 
    1138          194 :     strcpy(newcopy, stmt->command);
    1139          194 :     strcpy(newcopy + position - 1, tobeinserted);
    1140              : 
    1141              :     /*
    1142              :      * The strange thing in the second argument is the rest of the string from
    1143              :      * the old string
    1144              :      */
    1145          194 :     strcat(newcopy,
    1146          194 :            stmt->command
    1147              :            + position
    1148          194 :            + ph_len - 1);
    1149              : 
    1150          194 :     ecpg_free(stmt->command);
    1151          194 :     stmt->command = newcopy;
    1152              : 
    1153          194 :     ecpg_free(tobeinserted);
    1154          194 :     return true;
    1155              : }
    1156              : 
    1157              : static bool
    1158           26 : store_input_from_desc(struct statement *stmt, struct descriptor_item *desc_item,
    1159              :                       char **tobeinserted)
    1160              : {
    1161              :     struct variable var;
    1162              : 
    1163              :     /*
    1164              :      * In case of binary data, only allocate memory and memcpy because binary
    1165              :      * data have been already stored into desc_item->data with
    1166              :      * ecpg_store_input() at ECPGset_desc().
    1167              :      */
    1168           26 :     if (desc_item->is_binary)
    1169              :     {
    1170            4 :         if (!(*tobeinserted = ecpg_alloc(desc_item->data_len, stmt->lineno)))
    1171            0 :             return false;
    1172            4 :         memcpy(*tobeinserted, desc_item->data, desc_item->data_len);
    1173            4 :         return true;
    1174              :     }
    1175              : 
    1176           22 :     var.type = ECPGt_char;
    1177           22 :     var.varcharsize = strlen(desc_item->data);
    1178           22 :     var.value = desc_item->data;
    1179           22 :     var.pointer = &(desc_item->data);
    1180           22 :     var.arrsize = 1;
    1181           22 :     var.offset = 0;
    1182              : 
    1183           22 :     if (!desc_item->indicator)
    1184              :     {
    1185           18 :         var.ind_type = ECPGt_NO_INDICATOR;
    1186           18 :         var.ind_value = var.ind_pointer = NULL;
    1187           18 :         var.ind_varcharsize = var.ind_arrsize = var.ind_offset = 0;
    1188              :     }
    1189              :     else
    1190              :     {
    1191            4 :         var.ind_type = ECPGt_int;
    1192            4 :         var.ind_value = &(desc_item->indicator);
    1193            4 :         var.ind_pointer = &(var.ind_value);
    1194            4 :         var.ind_varcharsize = var.ind_arrsize = 1;
    1195            4 :         var.ind_offset = 0;
    1196              :     }
    1197              : 
    1198           22 :     if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &var, tobeinserted, false))
    1199            0 :         return false;
    1200              : 
    1201           22 :     return true;
    1202              : }
    1203              : 
    1204              : /*
    1205              :  * ecpg_build_params
    1206              :  *      Build statement parameters
    1207              :  *
    1208              :  * The input values are taken from user variables, and the results are stored
    1209              :  * in arrays which can be used by PQexecParams().
    1210              :  */
    1211              : bool
    1212         5345 : ecpg_build_params(struct statement *stmt)
    1213              : {
    1214              :     struct variable *var;
    1215         5345 :     int         desc_counter = 0;
    1216         5345 :     int         position = 0;
    1217              :     const char *value;
    1218         5345 :     bool        std_strings = false;
    1219              : 
    1220              :     /* Get standard_conforming_strings setting. */
    1221         5345 :     value = PQparameterStatus(stmt->connection->connection, "standard_conforming_strings");
    1222         5345 :     if (value && strcmp(value, "on") == 0)
    1223         5345 :         std_strings = true;
    1224              : 
    1225              :     /*
    1226              :      * If the type is one of the fill in types then we take the argument and
    1227              :      * enter it to our parameter array at the first position. Then if there
    1228              :      * are any more fill in types we add more parameters.
    1229              :      */
    1230         5345 :     var = stmt->inlist;
    1231         9023 :     while (var)
    1232              :     {
    1233              :         char       *tobeinserted;
    1234         3678 :         int         counter = 1;
    1235              :         bool        binary_format;
    1236              :         int         binary_length;
    1237              : 
    1238              : 
    1239         3678 :         tobeinserted = NULL;
    1240         3678 :         binary_length = 0;
    1241         3678 :         binary_format = false;
    1242              : 
    1243              :         /*
    1244              :          * A descriptor is a special case since it contains many variables but
    1245              :          * is listed only once.
    1246              :          */
    1247         3678 :         if (var->type == ECPGt_descriptor)
    1248              :         {
    1249              :             /*
    1250              :              * We create an additional variable list here, so the same logic
    1251              :              * applies.
    1252              :              */
    1253              :             struct descriptor *desc;
    1254              :             struct descriptor_item *desc_item;
    1255              : 
    1256           26 :             desc = ecpg_find_desc(stmt->lineno, var->pointer);
    1257           26 :             if (desc == NULL)
    1258            0 :                 return false;
    1259              : 
    1260           26 :             desc_counter++;
    1261           40 :             for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
    1262              :             {
    1263           40 :                 if (desc_item->num != desc_counter)
    1264           14 :                     continue;
    1265              : 
    1266           26 :                 if (!store_input_from_desc(stmt, desc_item, &tobeinserted))
    1267            0 :                     return false;
    1268              : 
    1269           26 :                 if (desc_item->is_binary)
    1270              :                 {
    1271            4 :                     binary_length = desc_item->data_len;
    1272            4 :                     binary_format = true;
    1273              :                 }
    1274           26 :                 break;
    1275              :             }
    1276           26 :             if (desc->count == desc_counter)
    1277           14 :                 desc_counter = 0;
    1278              :         }
    1279         3652 :         else if (var->type == ECPGt_sqlda)
    1280              :         {
    1281            8 :             if (INFORMIX_MODE(stmt->compat))
    1282            4 :             {
    1283            4 :                 struct sqlda_compat *sqlda = *(struct sqlda_compat **) var->pointer;
    1284              :                 struct variable desc_inlist;
    1285              :                 int         i;
    1286              : 
    1287            4 :                 if (sqlda == NULL)
    1288            0 :                     return false;
    1289              : 
    1290            4 :                 desc_counter++;
    1291            4 :                 for (i = 0; i < sqlda->sqld; i++)
    1292              :                 {
    1293            4 :                     if (i + 1 == desc_counter)
    1294              :                     {
    1295            4 :                         desc_inlist.type = sqlda->sqlvar[i].sqltype;
    1296            4 :                         desc_inlist.value = sqlda->sqlvar[i].sqldata;
    1297            4 :                         desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
    1298            4 :                         switch (desc_inlist.type)
    1299              :                         {
    1300            0 :                             case ECPGt_char:
    1301              :                             case ECPGt_varchar:
    1302            0 :                                 desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
    1303            0 :                                 break;
    1304            4 :                             default:
    1305            4 :                                 desc_inlist.varcharsize = 0;
    1306            4 :                                 break;
    1307              :                         }
    1308            4 :                         desc_inlist.arrsize = 1;
    1309            4 :                         desc_inlist.offset = 0;
    1310            4 :                         if (sqlda->sqlvar[i].sqlind)
    1311              :                         {
    1312            0 :                             desc_inlist.ind_type = ECPGt_short;
    1313              :                             /* ECPG expects indicator value < 0 */
    1314            0 :                             if (*(sqlda->sqlvar[i].sqlind))
    1315            0 :                                 *(sqlda->sqlvar[i].sqlind) = -1;
    1316            0 :                             desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
    1317            0 :                             desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
    1318            0 :                             desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
    1319            0 :                             desc_inlist.ind_offset = 0;
    1320              :                         }
    1321              :                         else
    1322              :                         {
    1323            4 :                             desc_inlist.ind_type = ECPGt_NO_INDICATOR;
    1324            4 :                             desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
    1325            4 :                             desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
    1326              :                         }
    1327            4 :                         if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
    1328            0 :                             return false;
    1329              : 
    1330            4 :                         break;
    1331              :                     }
    1332              :                 }
    1333            4 :                 if (sqlda->sqld == desc_counter)
    1334            4 :                     desc_counter = 0;
    1335              :             }
    1336              :             else
    1337              :             {
    1338            4 :                 struct sqlda_struct *sqlda = *(struct sqlda_struct **) var->pointer;
    1339              :                 struct variable desc_inlist;
    1340              :                 int         i;
    1341              : 
    1342            4 :                 if (sqlda == NULL)
    1343            0 :                     return false;
    1344              : 
    1345            4 :                 desc_counter++;
    1346            4 :                 for (i = 0; i < sqlda->sqln; i++)
    1347              :                 {
    1348            4 :                     if (i + 1 == desc_counter)
    1349              :                     {
    1350            4 :                         desc_inlist.type = sqlda->sqlvar[i].sqltype;
    1351            4 :                         desc_inlist.value = sqlda->sqlvar[i].sqldata;
    1352            4 :                         desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
    1353            4 :                         switch (desc_inlist.type)
    1354              :                         {
    1355            0 :                             case ECPGt_char:
    1356              :                             case ECPGt_varchar:
    1357            0 :                                 desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
    1358            0 :                                 break;
    1359            4 :                             default:
    1360            4 :                                 desc_inlist.varcharsize = 0;
    1361            4 :                                 break;
    1362              :                         }
    1363            4 :                         desc_inlist.arrsize = 1;
    1364            4 :                         desc_inlist.offset = 0;
    1365            4 :                         if (sqlda->sqlvar[i].sqlind)
    1366              :                         {
    1367            0 :                             desc_inlist.ind_type = ECPGt_short;
    1368              :                             /* ECPG expects indicator value < 0 */
    1369            0 :                             if (*(sqlda->sqlvar[i].sqlind))
    1370            0 :                                 *(sqlda->sqlvar[i].sqlind) = -1;
    1371            0 :                             desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
    1372            0 :                             desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
    1373            0 :                             desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
    1374            0 :                             desc_inlist.ind_offset = 0;
    1375              :                         }
    1376              :                         else
    1377              :                         {
    1378            4 :                             desc_inlist.ind_type = ECPGt_NO_INDICATOR;
    1379            4 :                             desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
    1380            4 :                             desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
    1381              :                         }
    1382            4 :                         if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
    1383            0 :                             return false;
    1384              : 
    1385            4 :                         break;
    1386              :                     }
    1387              :                 }
    1388            4 :                 if (sqlda->sqln == desc_counter)
    1389            4 :                     desc_counter = 0;
    1390              :             }
    1391              :         }
    1392              :         else
    1393              :         {
    1394         3644 :             if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
    1395            0 :                 return false;
    1396              : 
    1397         3644 :             if (var->type == ECPGt_bytea)
    1398              :             {
    1399           22 :                 binary_length = ((struct ECPGgeneric_bytea *) (var->value))->len;
    1400           22 :                 binary_format = true;
    1401              :             }
    1402              :         }
    1403              : 
    1404              :         /*
    1405              :          * now tobeinserted points to an area that contains the next
    1406              :          * parameter; now find the position in the string where it belongs
    1407              :          */
    1408         3678 :         if ((position = next_insert(stmt->command, position, stmt->questionmarks, std_strings) + 1) == 0)
    1409              :         {
    1410              :             /*
    1411              :              * We have an argument but we don't have the matched up
    1412              :              * placeholder in the string
    1413              :              */
    1414            0 :             ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
    1415              :                        ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
    1416              :                        NULL);
    1417            0 :             ecpg_free_params(stmt, false);
    1418            0 :             ecpg_free(tobeinserted);
    1419            0 :             return false;
    1420              :         }
    1421              : 
    1422              :         /*
    1423              :          * if var->type=ECPGt_char_variable we have a dynamic cursor we have
    1424              :          * to simulate a dynamic cursor because there is no backend
    1425              :          * functionality for it
    1426              :          */
    1427         3678 :         if (var->type == ECPGt_char_variable)
    1428              :         {
    1429           42 :             int         ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
    1430              : 
    1431           42 :             if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
    1432              :             {
    1433            0 :                 ecpg_free_params(stmt, false);
    1434            0 :                 return false;
    1435              :             }
    1436           42 :             tobeinserted = NULL;
    1437              :         }
    1438              : 
    1439              :         /*
    1440              :          * if the placeholder is '$0' we have to replace it on the client side
    1441              :          * this is for places we want to support variables at that are not
    1442              :          * supported in the backend
    1443              :          */
    1444         3636 :         else if (stmt->command[position] == '0')
    1445              :         {
    1446          124 :             if (stmt->statement_type == ECPGst_prepare ||
    1447          114 :                 stmt->statement_type == ECPGst_exec_with_exprlist)
    1448              :             {
    1449              :                 /* Need to double-quote the inserted statement name. */
    1450           28 :                 char       *str = ecpg_alloc(strlen(tobeinserted) + 2 + 1,
    1451              :                                              stmt->lineno);
    1452              : 
    1453           28 :                 if (!str)
    1454              :                 {
    1455            0 :                     ecpg_free(tobeinserted);
    1456            0 :                     ecpg_free_params(stmt, false);
    1457            0 :                     return false;
    1458              :                 }
    1459           28 :                 sprintf(str, "\"%s\"", tobeinserted);
    1460           28 :                 ecpg_free(tobeinserted);
    1461           28 :                 tobeinserted = str;
    1462              :             }
    1463              : 
    1464          124 :             if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
    1465              :             {
    1466            0 :                 ecpg_free_params(stmt, false);
    1467            0 :                 return false;
    1468              :             }
    1469          124 :             tobeinserted = NULL;
    1470              :         }
    1471         3512 :         else if (stmt->statement_type == ECPGst_exec_with_exprlist)
    1472              :         {
    1473           28 :             if (binary_format)
    1474              :             {
    1475            0 :                 char       *p = convert_bytea_to_string(tobeinserted,
    1476              :                                                         binary_length,
    1477              :                                                         stmt->lineno);
    1478              : 
    1479            0 :                 ecpg_free(tobeinserted);
    1480            0 :                 if (!p)
    1481              :                 {
    1482            0 :                     ecpg_free_params(stmt, false);
    1483            0 :                     return false;
    1484              :                 }
    1485            0 :                 tobeinserted = p;
    1486              :             }
    1487              : 
    1488           28 :             if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
    1489              :             {
    1490            0 :                 ecpg_free_params(stmt, false);
    1491            0 :                 return false;
    1492              :             }
    1493           28 :             tobeinserted = NULL;
    1494              :         }
    1495              :         else
    1496              :         {
    1497         3484 :             bool        realloc_failed = false;
    1498              :             char      **newparamvalues;
    1499              :             int        *newparamlengths;
    1500              :             int        *newparamformats;
    1501              : 
    1502              :             /* enlarge all the param arrays */
    1503         3484 :             if ((newparamvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
    1504         3484 :                 stmt->paramvalues = newparamvalues;
    1505              :             else
    1506            0 :                 realloc_failed = true;
    1507              : 
    1508         3484 :             if ((newparamlengths = (int *) ecpg_realloc(stmt->paramlengths, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
    1509         3484 :                 stmt->paramlengths = newparamlengths;
    1510              :             else
    1511            0 :                 realloc_failed = true;
    1512              : 
    1513         3484 :             if ((newparamformats = (int *) ecpg_realloc(stmt->paramformats, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
    1514         3484 :                 stmt->paramformats = newparamformats;
    1515              :             else
    1516            0 :                 realloc_failed = true;
    1517              : 
    1518         3484 :             if (realloc_failed)
    1519              :             {
    1520            0 :                 ecpg_free_params(stmt, false);
    1521            0 :                 ecpg_free(tobeinserted);
    1522            0 :                 return false;
    1523              :             }
    1524              : 
    1525              :             /* only now can we assign ownership of "tobeinserted" to stmt */
    1526         3484 :             stmt->paramvalues[stmt->nparams] = tobeinserted;
    1527         3484 :             stmt->paramlengths[stmt->nparams] = binary_length;
    1528         3484 :             stmt->paramformats[stmt->nparams] = (binary_format ? 1 : 0);
    1529         3484 :             stmt->nparams++;
    1530              : 
    1531              :             /* let's see if this was an old style placeholder */
    1532         3484 :             if (stmt->command[position] == '?')
    1533              :             {
    1534              :                 /* yes, replace with new style */
    1535            0 :                 int         buffersize = sizeof(int) * CHAR_BIT * 10 / 3;   /* a rough guess of the
    1536              :                                                                              * size we need */
    1537              : 
    1538            0 :                 if (!(tobeinserted = ecpg_alloc(buffersize, stmt->lineno)))
    1539              :                 {
    1540            0 :                     ecpg_free_params(stmt, false);
    1541            0 :                     return false;
    1542              :                 }
    1543              : 
    1544            0 :                 snprintf(tobeinserted, buffersize, "$%d", counter++);
    1545              : 
    1546            0 :                 if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
    1547              :                 {
    1548            0 :                     ecpg_free_params(stmt, false);
    1549            0 :                     return false;
    1550              :                 }
    1551            0 :                 tobeinserted = NULL;
    1552              :             }
    1553              :         }
    1554              : 
    1555         3678 :         if (desc_counter == 0)
    1556         3666 :             var = var->next;
    1557              :     }
    1558              : 
    1559              :     /*
    1560              :      * Check if there are unmatched things left. PREPARE AS has no parameter.
    1561              :      * Check other statement.
    1562              :      */
    1563        10680 :     if (stmt->statement_type != ECPGst_prepare &&
    1564         5335 :         next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
    1565              :     {
    1566            0 :         ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
    1567              :                    ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
    1568            0 :         ecpg_free_params(stmt, false);
    1569            0 :         return false;
    1570              :     }
    1571              : 
    1572         5345 :     return true;
    1573              : }
    1574              : 
    1575              : /*
    1576              :  * ecpg_autostart_transaction
    1577              :  *      If we are in non-autocommit mode, automatically start a transaction.
    1578              :  */
    1579              : bool
    1580         5345 : ecpg_autostart_transaction(struct statement *stmt)
    1581              : {
    1582         5345 :     if (PQtransactionStatus(stmt->connection->connection) == PQTRANS_IDLE && !stmt->connection->autocommit)
    1583              :     {
    1584          189 :         stmt->results = PQexec(stmt->connection->connection, "begin transaction");
    1585          189 :         if (!ecpg_check_PQresult(stmt->results, stmt->lineno, stmt->connection->connection, stmt->compat))
    1586              :         {
    1587            0 :             ecpg_free_params(stmt, false);
    1588            0 :             return false;
    1589              :         }
    1590          189 :         PQclear(stmt->results);
    1591          189 :         stmt->results = NULL;
    1592              :     }
    1593         5345 :     return true;
    1594              : }
    1595              : 
    1596              : /*
    1597              :  * ecpg_execute
    1598              :  *      Execute the SQL statement.
    1599              :  */
    1600              : bool
    1601         5345 : ecpg_execute(struct statement *stmt)
    1602              : {
    1603         5345 :     ecpg_log("ecpg_execute on line %d: query: %s; with %d parameter(s) on connection %s\n", stmt->lineno, stmt->command, stmt->nparams, stmt->connection->name);
    1604         5345 :     if (stmt->statement_type == ECPGst_execute)
    1605              :     {
    1606         3332 :         stmt->results = PQexecPrepared(stmt->connection->connection,
    1607         1666 :                                        stmt->name,
    1608              :                                        stmt->nparams,
    1609         1666 :                                        (const char *const *) stmt->paramvalues,
    1610         1666 :                                        (const int *) stmt->paramlengths,
    1611         1666 :                                        (const int *) stmt->paramformats,
    1612              :                                        0);
    1613         1666 :         ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
    1614              :     }
    1615              :     else
    1616              :     {
    1617         3679 :         if (stmt->nparams == 0)
    1618              :         {
    1619         2761 :             stmt->results = PQexec(stmt->connection->connection, stmt->command);
    1620         2761 :             ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
    1621              :         }
    1622              :         else
    1623              :         {
    1624         1836 :             stmt->results = PQexecParams(stmt->connection->connection,
    1625          918 :                                          stmt->command, stmt->nparams, NULL,
    1626          918 :                                          (const char *const *) stmt->paramvalues,
    1627          918 :                                          (const int *) stmt->paramlengths,
    1628          918 :                                          (const int *) stmt->paramformats,
    1629              :                                          0);
    1630              : 
    1631          918 :             ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
    1632              :         }
    1633              : 
    1634         3679 :         if (stmt->statement_type == ECPGst_prepare)
    1635              :         {
    1636           10 :             if (!ecpg_register_prepared_stmt(stmt))
    1637              :             {
    1638            0 :                 ecpg_free_params(stmt, true);
    1639            0 :                 return false;
    1640              :             }
    1641              :         }
    1642              :     }
    1643              : 
    1644         5345 :     ecpg_free_params(stmt, true);
    1645              : 
    1646         5345 :     if (!ecpg_check_PQresult(stmt->results, stmt->lineno, stmt->connection->connection, stmt->compat))
    1647           26 :         return false;
    1648              : 
    1649         5319 :     return true;
    1650              : }
    1651              : 
    1652              : /*-------
    1653              :  * ecpg_process_output
    1654              :  *
    1655              :  *  Process the statement result and store it into application variables.  This
    1656              :  *  function can be called repeatedly during the same statement in case cursor
    1657              :  *  readahead is used and the application does FETCH N which overflows the
    1658              :  *  readahead window.
    1659              :  *
    1660              :  * Parameters
    1661              :  *  stmt    statement structure holding the PGresult and
    1662              :  *          the list of output variables
    1663              :  *  clear_result
    1664              :  *          PQclear() the result upon returning from this function
    1665              :  *
    1666              :  * Returns success as boolean. Also an SQL error is raised in case of failure.
    1667              :  *-------
    1668              :  */
    1669              : bool
    1670         5319 : ecpg_process_output(struct statement *stmt, bool clear_result)
    1671              : {
    1672              :     struct variable *var;
    1673         5319 :     bool        status = false;
    1674              :     char       *cmdstat;
    1675              :     PGnotify   *notify;
    1676         5319 :     struct sqlca_t *sqlca = ECPGget_sqlca();
    1677              :     int         nfields,
    1678              :                 ntuples,
    1679              :                 act_field;
    1680              : 
    1681         5319 :     if (sqlca == NULL)
    1682              :     {
    1683            0 :         ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY,
    1684              :                    ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
    1685            0 :         return false;
    1686              :     }
    1687              : 
    1688         5319 :     var = stmt->outlist;
    1689         5319 :     switch (PQresultStatus(stmt->results))
    1690              :     {
    1691         2106 :         case PGRES_TUPLES_OK:
    1692         2106 :             nfields = PQnfields(stmt->results);
    1693         2106 :             sqlca->sqlerrd[2] = ntuples = PQntuples(stmt->results);
    1694              : 
    1695         2106 :             ecpg_log("ecpg_process_output on line %d: correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
    1696         2106 :             status = true;
    1697              : 
    1698         2106 :             if (ntuples < 1)
    1699              :             {
    1700           42 :                 if (ntuples)
    1701            0 :                     ecpg_log("ecpg_process_output on line %d: incorrect number of matches (%d)\n",
    1702              :                              stmt->lineno, ntuples);
    1703           42 :                 ecpg_raise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
    1704           42 :                 status = false;
    1705           42 :                 break;
    1706              :             }
    1707              : 
    1708         2064 :             if (var != NULL && var->type == ECPGt_descriptor)
    1709           14 :             {
    1710           14 :                 struct descriptor *desc = ecpg_find_desc(stmt->lineno, var->pointer);
    1711              : 
    1712           14 :                 if (desc == NULL)
    1713            0 :                     status = false;
    1714              :                 else
    1715              :                 {
    1716           14 :                     PQclear(desc->result);
    1717           14 :                     desc->result = stmt->results;
    1718           14 :                     clear_result = false;
    1719           14 :                     ecpg_log("ecpg_process_output on line %d: putting result (%d tuples) into descriptor %s\n",
    1720           14 :                              stmt->lineno, PQntuples(stmt->results), (const char *) var->pointer);
    1721              :                 }
    1722           14 :                 var = var->next;
    1723              :             }
    1724         2050 :             else if (var != NULL && var->type == ECPGt_sqlda)
    1725              :             {
    1726           34 :                 if (INFORMIX_MODE(stmt->compat))
    1727           16 :                 {
    1728           16 :                     struct sqlda_compat **_sqlda = (struct sqlda_compat **) var->pointer;
    1729           16 :                     struct sqlda_compat *sqlda = *_sqlda;
    1730              :                     struct sqlda_compat *sqlda_new;
    1731              :                     int         i;
    1732              : 
    1733              :                     /*
    1734              :                      * If we are passed in a previously existing sqlda (chain)
    1735              :                      * then free it.
    1736              :                      */
    1737           24 :                     while (sqlda)
    1738              :                     {
    1739            8 :                         sqlda_new = sqlda->desc_next;
    1740            8 :                         free(sqlda);
    1741            8 :                         sqlda = sqlda_new;
    1742              :                     }
    1743           16 :                     *_sqlda = sqlda = sqlda_new = NULL;
    1744           32 :                     for (i = ntuples - 1; i >= 0; i--)
    1745              :                     {
    1746              :                         /*
    1747              :                          * Build a new sqlda structure. Note that only
    1748              :                          * fetching 1 record is supported
    1749              :                          */
    1750           16 :                         sqlda_new = ecpg_build_compat_sqlda(stmt->lineno, stmt->results, i, stmt->compat);
    1751              : 
    1752           16 :                         if (!sqlda_new)
    1753              :                         {
    1754              :                             /* cleanup all SQLDAs we created up */
    1755            0 :                             while (sqlda)
    1756              :                             {
    1757            0 :                                 sqlda_new = sqlda->desc_next;
    1758            0 :                                 free(sqlda);
    1759            0 :                                 sqlda = sqlda_new;
    1760              :                             }
    1761            0 :                             *_sqlda = NULL;
    1762              : 
    1763            0 :                             ecpg_log("ecpg_process_output on line %d: out of memory allocating a new sqlda\n", stmt->lineno);
    1764            0 :                             status = false;
    1765            0 :                             break;
    1766              :                         }
    1767              :                         else
    1768              :                         {
    1769           16 :                             ecpg_log("ecpg_process_output on line %d: new sqlda was built\n", stmt->lineno);
    1770              : 
    1771           16 :                             *_sqlda = sqlda_new;
    1772              : 
    1773           16 :                             ecpg_set_compat_sqlda(stmt->lineno, _sqlda, stmt->results, i, stmt->compat);
    1774           16 :                             ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
    1775           16 :                                      stmt->lineno, PQnfields(stmt->results));
    1776              : 
    1777           16 :                             sqlda_new->desc_next = sqlda;
    1778           16 :                             sqlda = sqlda_new;
    1779              :                         }
    1780              :                     }
    1781              :                 }
    1782              :                 else
    1783              :                 {
    1784           18 :                     struct sqlda_struct **_sqlda = (struct sqlda_struct **) var->pointer;
    1785           18 :                     struct sqlda_struct *sqlda = *_sqlda;
    1786              :                     struct sqlda_struct *sqlda_new;
    1787              :                     int         i;
    1788              : 
    1789              :                     /*
    1790              :                      * If we are passed in a previously existing sqlda (chain)
    1791              :                      * then free it.
    1792              :                      */
    1793           26 :                     while (sqlda)
    1794              :                     {
    1795            8 :                         sqlda_new = sqlda->desc_next;
    1796            8 :                         free(sqlda);
    1797            8 :                         sqlda = sqlda_new;
    1798              :                     }
    1799           18 :                     *_sqlda = sqlda = sqlda_new = NULL;
    1800           44 :                     for (i = ntuples - 1; i >= 0; i--)
    1801              :                     {
    1802              :                         /*
    1803              :                          * Build a new sqlda structure. Note that only
    1804              :                          * fetching 1 record is supported
    1805              :                          */
    1806           26 :                         sqlda_new = ecpg_build_native_sqlda(stmt->lineno, stmt->results, i, stmt->compat);
    1807              : 
    1808           26 :                         if (!sqlda_new)
    1809              :                         {
    1810              :                             /* cleanup all SQLDAs we created up */
    1811            0 :                             while (sqlda)
    1812              :                             {
    1813            0 :                                 sqlda_new = sqlda->desc_next;
    1814            0 :                                 free(sqlda);
    1815            0 :                                 sqlda = sqlda_new;
    1816              :                             }
    1817            0 :                             *_sqlda = NULL;
    1818              : 
    1819            0 :                             ecpg_log("ecpg_process_output on line %d: out of memory allocating a new sqlda\n", stmt->lineno);
    1820            0 :                             status = false;
    1821            0 :                             break;
    1822              :                         }
    1823              :                         else
    1824              :                         {
    1825           26 :                             ecpg_log("ecpg_process_output on line %d: new sqlda was built\n", stmt->lineno);
    1826              : 
    1827           26 :                             *_sqlda = sqlda_new;
    1828              : 
    1829           26 :                             ecpg_set_native_sqlda(stmt->lineno, _sqlda, stmt->results, i, stmt->compat);
    1830           26 :                             ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
    1831           26 :                                      stmt->lineno, PQnfields(stmt->results));
    1832              : 
    1833           26 :                             sqlda_new->desc_next = sqlda;
    1834           26 :                             sqlda = sqlda_new;
    1835              :                         }
    1836              :                     }
    1837              :                 }
    1838              : 
    1839           34 :                 var = var->next;
    1840              :             }
    1841              :             else
    1842         4486 :                 for (act_field = 0; act_field < nfields && status; act_field++)
    1843              :                 {
    1844         2470 :                     if (var != NULL)
    1845              :                     {
    1846         2466 :                         status = ecpg_store_result(stmt->results, act_field, stmt, var);
    1847         2466 :                         var = var->next;
    1848              :                     }
    1849            4 :                     else if (!INFORMIX_MODE(stmt->compat))
    1850              :                     {
    1851            0 :                         ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
    1852            0 :                         return false;
    1853              :                     }
    1854              :                 }
    1855              : 
    1856         2064 :             if (status && var != NULL)
    1857              :             {
    1858            0 :                 ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
    1859            0 :                 status = false;
    1860              :             }
    1861              : 
    1862         2064 :             break;
    1863         3211 :         case PGRES_COMMAND_OK:
    1864         3211 :             status = true;
    1865         3211 :             cmdstat = PQcmdStatus(stmt->results);
    1866         3211 :             sqlca->sqlerrd[1] = PQoidValue(stmt->results);
    1867         3211 :             sqlca->sqlerrd[2] = atol(PQcmdTuples(stmt->results));
    1868         3211 :             ecpg_log("ecpg_process_output on line %d: OK: %s\n", stmt->lineno, cmdstat);
    1869         3211 :             if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
    1870         3211 :                 !sqlca->sqlerrd[2] &&
    1871          491 :                 (strncmp(cmdstat, "UPDATE", 6) == 0
    1872          489 :                  || strncmp(cmdstat, "INSERT", 6) == 0
    1873          487 :                  || strncmp(cmdstat, "DELETE", 6) == 0))
    1874            8 :                 ecpg_raise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
    1875         3211 :             break;
    1876            2 :         case PGRES_COPY_OUT:
    1877              :             {
    1878              :                 char       *buffer;
    1879              :                 int         res;
    1880              : 
    1881            2 :                 ecpg_log("ecpg_process_output on line %d: COPY OUT data transfer in progress\n", stmt->lineno);
    1882            8 :                 while ((res = PQgetCopyData(stmt->connection->connection,
    1883            8 :                                             &buffer, 0)) > 0)
    1884              :                 {
    1885            6 :                     printf("%s", buffer);
    1886            6 :                     PQfreemem(buffer);
    1887              :                 }
    1888            2 :                 if (res == -1)
    1889              :                 {
    1890              :                     /* COPY done */
    1891            2 :                     PQclear(stmt->results);
    1892            2 :                     stmt->results = PQgetResult(stmt->connection->connection);
    1893            2 :                     if (PQresultStatus(stmt->results) == PGRES_COMMAND_OK)
    1894            2 :                         ecpg_log("ecpg_process_output on line %d: got PGRES_COMMAND_OK after PGRES_COPY_OUT\n", stmt->lineno);
    1895              :                     else
    1896            0 :                         ecpg_log("ecpg_process_output on line %d: got error after PGRES_COPY_OUT: %s", stmt->lineno, PQresultErrorMessage(stmt->results));
    1897              :                 }
    1898            2 :                 break;
    1899              :             }
    1900            0 :         default:
    1901              : 
    1902              :             /*
    1903              :              * execution should never reach this code because it is already
    1904              :              * handled in ecpg_check_PQresult()
    1905              :              */
    1906            0 :             ecpg_log("ecpg_process_output on line %d: unknown execution status type\n",
    1907              :                      stmt->lineno);
    1908            0 :             ecpg_raise_backend(stmt->lineno, stmt->results, stmt->connection->connection, stmt->compat);
    1909            0 :             status = false;
    1910            0 :             break;
    1911              :     }
    1912              : 
    1913         5319 :     if (clear_result)
    1914              :     {
    1915         5305 :         PQclear(stmt->results);
    1916         5305 :         stmt->results = NULL;
    1917              :     }
    1918              : 
    1919              :     /* check for asynchronous returns */
    1920         5319 :     PQconsumeInput(stmt->connection->connection);
    1921         5319 :     while ((notify = PQnotifies(stmt->connection->connection)) != NULL)
    1922              :     {
    1923            0 :         ecpg_log("ecpg_process_output on line %d: asynchronous notification of \"%s\" from backend PID %d received\n",
    1924              :                  stmt->lineno, notify->relname, notify->be_pid);
    1925            0 :         PQfreemem(notify);
    1926            0 :         PQconsumeInput(stmt->connection->connection);
    1927              :     }
    1928              : 
    1929         5319 :     return status;
    1930              : }
    1931              : 
    1932              : /*
    1933              :  * ecpg_do_prologue
    1934              :  *
    1935              :  * Initialize various infrastructure elements for executing the statement:
    1936              :  *
    1937              :  *  - create the statement structure
    1938              :  *  - set the C numeric locale for communicating with the backend
    1939              :  *  - preprocess the variable list of input/output parameters into
    1940              :  *    linked lists
    1941              :  */
    1942              : bool
    1943         5357 : ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
    1944              :                  const char *connection_name, const bool questionmarks,
    1945              :                  enum ECPG_statement_type statement_type, const char *query,
    1946              :                  va_list args, struct statement **stmt_out)
    1947              : {
    1948         5357 :     struct statement *stmt = NULL;
    1949              :     struct connection *con;
    1950              :     enum ECPGttype type;
    1951              :     struct variable **list;
    1952              :     char       *prepname;
    1953              :     bool        is_prepared_name_set;
    1954              : 
    1955         5357 :     *stmt_out = NULL;
    1956              : 
    1957         5357 :     if (!query)
    1958              :     {
    1959            0 :         ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
    1960            0 :         return false;
    1961              :     }
    1962              : 
    1963         5357 :     ecpg_pthreads_init();
    1964              : 
    1965         5357 :     con = ecpg_get_connection(connection_name);
    1966              : 
    1967         5357 :     if (!ecpg_init(con, connection_name, lineno))
    1968           12 :         return false;
    1969              : 
    1970         5345 :     stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
    1971              : 
    1972         5345 :     if (stmt == NULL)
    1973            0 :         return false;
    1974              : 
    1975              :     /*
    1976              :      * Make sure we do NOT honor the locale for numeric input/output since the
    1977              :      * database wants the standard decimal point.  If available, use
    1978              :      * uselocale() for this because it's thread-safe.  Windows doesn't have
    1979              :      * that, but it does have _configthreadlocale().
    1980              :      */
    1981              : #ifdef HAVE_USELOCALE
    1982              : 
    1983              :     /*
    1984              :      * Since ecpg_init() succeeded, we have a connection.  Any successful
    1985              :      * connection initializes ecpg_clocale.
    1986              :      */
    1987              :     Assert(ecpg_clocale);
    1988         5345 :     stmt->oldlocale = uselocale(ecpg_clocale);
    1989         5345 :     if (stmt->oldlocale == (locale_t) 0)
    1990              :     {
    1991            0 :         ecpg_do_epilogue(stmt);
    1992            0 :         return false;
    1993              :     }
    1994              : #else
    1995              : #ifdef WIN32
    1996              :     stmt->oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
    1997              :     if (stmt->oldthreadlocale == -1)
    1998              :     {
    1999              :         ecpg_do_epilogue(stmt);
    2000              :         return false;
    2001              :     }
    2002              : #endif
    2003              :     stmt->oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno,
    2004              :                                   NULL);
    2005              :     if (stmt->oldlocale == NULL)
    2006              :     {
    2007              :         ecpg_do_epilogue(stmt);
    2008              :         return false;
    2009              :     }
    2010              :     setlocale(LC_NUMERIC, "C");
    2011              : #endif
    2012              : 
    2013              :     /*
    2014              :      * If statement type is ECPGst_prepnormal we are supposed to prepare the
    2015              :      * statement before executing them
    2016              :      */
    2017         5345 :     if (statement_type == ECPGst_prepnormal)
    2018              :     {
    2019           16 :         if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, query))
    2020              :         {
    2021            0 :             ecpg_do_epilogue(stmt);
    2022            0 :             return false;
    2023              :         }
    2024              : 
    2025              :         /*
    2026              :          * statement is now prepared, so instead of the query we have to
    2027              :          * execute the name
    2028              :          */
    2029           16 :         stmt->command = prepname;
    2030           16 :         statement_type = ECPGst_execute;
    2031              :     }
    2032              :     else
    2033              :     {
    2034         5329 :         stmt->command = ecpg_strdup(query, lineno, NULL);
    2035         5329 :         if (!stmt->command)
    2036              :         {
    2037            0 :             ecpg_do_epilogue(stmt);
    2038            0 :             return false;
    2039              :         }
    2040              :     }
    2041              : 
    2042         5345 :     stmt->name = NULL;
    2043              : 
    2044         5345 :     if (statement_type == ECPGst_execute)
    2045              :     {
    2046              :         /* if we have an EXECUTE command, only the name is send */
    2047         1666 :         char       *command = ecpg_prepared(stmt->command, con);
    2048              : 
    2049         1666 :         if (command)
    2050              :         {
    2051         1666 :             stmt->name = stmt->command;
    2052         1666 :             stmt->command = ecpg_strdup(command, lineno, NULL);
    2053         1666 :             if (!stmt->command)
    2054              :             {
    2055            0 :                 ecpg_do_epilogue(stmt);
    2056            0 :                 return false;
    2057              :             }
    2058              :         }
    2059              :         else
    2060              :         {
    2061            0 :             ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
    2062            0 :             ecpg_do_epilogue(stmt);
    2063            0 :             return false;
    2064              :         }
    2065              :     }
    2066              :     /* name of PREPARE AS will be set in loop of inlist */
    2067              : 
    2068         5345 :     stmt->connection = con;
    2069         5345 :     stmt->lineno = lineno;
    2070         5345 :     stmt->compat = compat;
    2071         5345 :     stmt->force_indicator = force_indicator;
    2072         5345 :     stmt->questionmarks = questionmarks;
    2073         5345 :     stmt->statement_type = statement_type;
    2074              : 
    2075              :     /*------
    2076              :      * create a list of variables
    2077              :      *
    2078              :      * The variables are listed with input variables preceding output
    2079              :      * variables.  The end of each group is marked by an end marker.
    2080              :      * Per variable we list:
    2081              :      *
    2082              :      * type - as defined in ecpgtype.h
    2083              :      * value - where to store the data
    2084              :      * varcharsize - length of string in case we have a stringvariable, else 0
    2085              :      * arraysize - 0 for pointer (we don't know the size of the array), 1 for
    2086              :      * simple variable, size for arrays
    2087              :      * offset - offset between ith and (i+1)th entry in an array, normally
    2088              :      * that means sizeof(type)
    2089              :      * ind_type - type of indicator variable
    2090              :      * ind_pointer - pointer to indicator variable
    2091              :      * ind_varcharsize - empty
    2092              :      * ind_arrsize - arraysize of indicator array
    2093              :      * ind_offset - indicator offset
    2094              :      *------
    2095              :      */
    2096              : 
    2097         5345 :     is_prepared_name_set = false;
    2098              : 
    2099         5345 :     list = &(stmt->inlist);
    2100              : 
    2101         5345 :     type = va_arg(args, enum ECPGttype);
    2102              : 
    2103        17000 :     while (type != ECPGt_EORT)
    2104              :     {
    2105        11655 :         if (type == ECPGt_EOIT)
    2106         5345 :             list = &(stmt->outlist);
    2107              :         else
    2108              :         {
    2109              :             struct variable *var,
    2110              :                        *ptr;
    2111              : 
    2112         6310 :             if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
    2113              :             {
    2114            0 :                 ecpg_do_epilogue(stmt);
    2115            0 :                 return false;
    2116              :             }
    2117              : 
    2118         6310 :             var->type = type;
    2119         6310 :             var->pointer = va_arg(args, char *);
    2120              : 
    2121         6310 :             var->varcharsize = va_arg(args, long);
    2122         6310 :             var->arrsize = va_arg(args, long);
    2123         6310 :             var->offset = va_arg(args, long);
    2124              : 
    2125              :             /*
    2126              :              * Unknown array size means pointer to an array. Unknown
    2127              :              * varcharsize usually also means pointer. But if the type is
    2128              :              * character and the array size is known, it is an array of
    2129              :              * pointers to char, so use var->pointer as it is.
    2130              :              */
    2131         6310 :             if (var->arrsize == 0 ||
    2132         4642 :                 (var->varcharsize == 0 && ((var->type != ECPGt_char && var->type != ECPGt_unsigned_char) || (var->arrsize <= 1))))
    2133         1764 :                 var->value = *((char **) (var->pointer));
    2134              :             else
    2135         4546 :                 var->value = var->pointer;
    2136              : 
    2137              :             /*
    2138              :              * negative values are used to indicate an array without given
    2139              :              * bounds
    2140              :              */
    2141              :             /* reset to zero for us */
    2142         6310 :             if (var->arrsize < 0)
    2143           28 :                 var->arrsize = 0;
    2144         6310 :             if (var->varcharsize < 0)
    2145            0 :                 var->varcharsize = 0;
    2146              : 
    2147         6310 :             var->next = NULL;
    2148              : 
    2149         6310 :             var->ind_type = va_arg(args, enum ECPGttype);
    2150         6310 :             var->ind_pointer = va_arg(args, char *);
    2151         6310 :             var->ind_varcharsize = va_arg(args, long);
    2152         6310 :             var->ind_arrsize = va_arg(args, long);
    2153         6310 :             var->ind_offset = va_arg(args, long);
    2154              : 
    2155         6310 :             if (var->ind_type != ECPGt_NO_INDICATOR
    2156          224 :                 && (var->ind_arrsize == 0 || var->ind_varcharsize == 0))
    2157            0 :                 var->ind_value = *((char **) (var->ind_pointer));
    2158              :             else
    2159         6310 :                 var->ind_value = var->ind_pointer;
    2160              : 
    2161              :             /*
    2162              :              * negative values are used to indicate an array without given
    2163              :              * bounds
    2164              :              */
    2165              :             /* reset to zero for us */
    2166         6310 :             if (var->ind_arrsize < 0)
    2167           28 :                 var->ind_arrsize = 0;
    2168         6310 :             if (var->ind_varcharsize < 0)
    2169            0 :                 var->ind_varcharsize = 0;
    2170              : 
    2171              :             /* if variable is NULL, the statement hasn't been prepared */
    2172         6310 :             if (var->pointer == NULL)
    2173              :             {
    2174            0 :                 ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, NULL);
    2175            0 :                 ecpg_free(var);
    2176            0 :                 ecpg_do_epilogue(stmt);
    2177            0 :                 return false;
    2178              :             }
    2179              : 
    2180         6950 :             for (ptr = *list; ptr && ptr->next; ptr = ptr->next)
    2181              :                 ;
    2182              : 
    2183         6310 :             if (ptr == NULL)
    2184         4824 :                 *list = var;
    2185              :             else
    2186         1486 :                 ptr->next = var;
    2187              : 
    2188         6310 :             if (!is_prepared_name_set && stmt->statement_type == ECPGst_prepare)
    2189              :             {
    2190           10 :                 stmt->name = ecpg_strdup(var->value, lineno, NULL);
    2191           10 :                 if (!stmt->name)
    2192              :                 {
    2193            0 :                     ecpg_do_epilogue(stmt);
    2194            0 :                     return false;
    2195              :                 }
    2196           10 :                 is_prepared_name_set = true;
    2197              :             }
    2198              :         }
    2199              : 
    2200        11655 :         type = va_arg(args, enum ECPGttype);
    2201              :     }
    2202              : 
    2203              :     /* are we connected? */
    2204         5345 :     if (con == NULL || con->connection == NULL)
    2205              :     {
    2206            0 :         ecpg_raise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : ecpg_gettext("<empty>"));
    2207            0 :         ecpg_do_epilogue(stmt);
    2208            0 :         return false;
    2209              :     }
    2210              : 
    2211         5345 :     if (!is_prepared_name_set && stmt->statement_type == ECPGst_prepare)
    2212              :     {
    2213            0 :         ecpg_raise(lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : ecpg_gettext("<empty>"));
    2214            0 :         ecpg_do_epilogue(stmt);
    2215            0 :         return false;
    2216              :     }
    2217              : 
    2218              :     /* initialize auto_mem struct */
    2219         5345 :     ecpg_clear_auto_mem();
    2220              : 
    2221         5345 :     *stmt_out = stmt;
    2222              : 
    2223         5345 :     return true;
    2224              : }
    2225              : 
    2226              : /*
    2227              :  * ecpg_do_epilogue
    2228              :  *    Restore the application locale and free the statement structure.
    2229              :  */
    2230              : void
    2231         5357 : ecpg_do_epilogue(struct statement *stmt)
    2232              : {
    2233         5357 :     if (stmt == NULL)
    2234           12 :         return;
    2235              : 
    2236              : #ifdef HAVE_USELOCALE
    2237         5345 :     if (stmt->oldlocale != (locale_t) 0)
    2238         5345 :         uselocale(stmt->oldlocale);
    2239              : #else
    2240              :     if (stmt->oldlocale)
    2241              :     {
    2242              :         setlocale(LC_NUMERIC, stmt->oldlocale);
    2243              : #ifdef WIN32
    2244              :         _configthreadlocale(stmt->oldthreadlocale);
    2245              : #endif
    2246              :     }
    2247              : #endif
    2248              : 
    2249         5345 :     free_statement(stmt);
    2250              : }
    2251              : 
    2252              : /*
    2253              :  * Execute SQL statements in the backend.
    2254              :  * The input/output parameters (variable argument list) are passed
    2255              :  * in a va_list, so other functions can use this interface.
    2256              :  */
    2257              : bool
    2258         5357 : ecpg_do(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query, va_list args)
    2259              : {
    2260         5357 :     struct statement *stmt = NULL;
    2261              : 
    2262         5357 :     if (!ecpg_do_prologue(lineno, compat, force_indicator, connection_name,
    2263              :                           questionmarks, (enum ECPG_statement_type) st,
    2264              :                           query, args, &stmt))
    2265           12 :         goto fail;
    2266              : 
    2267         5345 :     if (!ecpg_build_params(stmt))
    2268            0 :         goto fail;
    2269              : 
    2270         5345 :     if (!ecpg_autostart_transaction(stmt))
    2271            0 :         goto fail;
    2272              : 
    2273         5345 :     if (!ecpg_execute(stmt))
    2274           26 :         goto fail;
    2275              : 
    2276         5319 :     if (!ecpg_process_output(stmt, true))
    2277           56 :         goto fail;
    2278              : 
    2279         5263 :     ecpg_do_epilogue(stmt);
    2280         5263 :     return true;
    2281              : 
    2282           94 : fail:
    2283           94 :     ecpg_do_epilogue(stmt);
    2284           94 :     return false;
    2285              : }
    2286              : 
    2287              : /*
    2288              :  * Execute SQL statements in the backend.
    2289              :  * The input/output parameters are passed as variable-length argument list.
    2290              :  */
    2291              : bool
    2292         5357 : ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query,...)
    2293              : {
    2294              :     va_list     args;
    2295              :     bool        ret;
    2296              : 
    2297         5357 :     va_start(args, query);
    2298         5357 :     ret = ecpg_do(lineno, compat, force_indicator, connection_name,
    2299              :                   questionmarks, st, query, args);
    2300         5357 :     va_end(args);
    2301              : 
    2302         5357 :     return ret;
    2303              : }
    2304              : 
    2305              : /* old descriptor interface */
    2306              : bool
    2307            0 : ECPGdo_descriptor(int line, const char *connection,
    2308              :                   const char *descriptor, const char *query)
    2309              : {
    2310            0 :     return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, '\0', 0, query, ECPGt_EOIT,
    2311              :                   ECPGt_descriptor, descriptor, 0L, 0L, 0L,
    2312              :                   ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
    2313              : }
        

Generated by: LCOV version 2.0-1