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