OSDN Git Service

80fa2f5505a02d5fa921619532d55f0599de49d9
[pg-rex/syncrep.git] / src / interfaces / ecpg / ecpglib / execute.c
1 /* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.84 2009/05/20 16:49:23 meskes Exp $ */
2
3 /*
4  * The aim is to get a simpler inteface to the database routines.
5  * All the tidieous 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 <locale.h>
20
21 #include "pg_type.h"
22
23 #include "ecpgtype.h"
24 #include "ecpglib.h"
25 #include "ecpgerrno.h"
26 #include "extern.h"
27 #include "sqlca.h"
28 #include "sql3types.h"
29 #include "pgtypes_numeric.h"
30 #include "pgtypes_date.h"
31 #include "pgtypes_timestamp.h"
32 #include "pgtypes_interval.h"
33
34 /*
35  *      This function returns a newly malloced string that has ' and \
36  *      escaped.
37  */
38 static char *
39 quote_postgres(char *arg, bool quote, int lineno)
40 {
41         char       *res;
42         size_t          length;
43         size_t          escaped_len;
44         size_t          buffer_len;
45
46         /*
47          * if quote is false we just need to store things in a descriptor they
48          * will be quoted once they are inserted in a statement
49          */
50         if (!quote)
51                 return arg;
52         else
53         {
54                 length = strlen(arg);
55                 buffer_len = 2 * length + 1;
56                 res = (char *) ecpg_alloc(buffer_len + 3, lineno);
57                 if (!res)
58                         return (res);
59                 escaped_len = PQescapeString(res + 1, arg, buffer_len);
60                 if (length == escaped_len)
61                 {
62                         res[0] = res[escaped_len + 1] = '\'';
63                         res[escaped_len + 2] = '\0';
64                 }
65                 else
66                 {
67                         /*
68                          * We don't know if the target database is using
69                          * standard_conforming_strings, so we always use E'' strings.
70                          */
71                         memmove(res + 2, res + 1, escaped_len);
72                         res[0] = ESCAPE_STRING_SYNTAX;
73                         res[1] = res[escaped_len + 2] = '\'';
74                         res[escaped_len + 3] = '\0';
75                 }
76                 ecpg_free(arg);
77                 return res;
78         }
79 }
80
81 static void
82 free_variable(struct variable * var)
83 {
84         struct variable *var_next;
85
86         if (var == NULL)
87                 return;
88         var_next = var->next;
89         ecpg_free(var);
90
91         while (var_next)
92         {
93                 var = var_next;
94                 var_next = var->next;
95                 ecpg_free(var);
96         }
97 }
98
99 static void
100 free_statement(struct statement * stmt)
101 {
102         if (stmt == NULL)
103                 return;
104         free_variable(stmt->inlist);
105         free_variable(stmt->outlist);
106         ecpg_free(stmt->command);
107         ecpg_free(stmt->name);
108         ecpg_free(stmt);
109 }
110
111 static int
112 next_insert(char *text, int pos, bool questionmarks)
113 {
114         bool            string = false;
115         int                     p = pos;
116
117         for (; text[p] != '\0'; p++)
118         {
119                 if (text[p] == '\\')    /* escape character */
120                         p++;
121                 else if (text[p] == '\'')
122                         string = string ? false : true;
123                 else if (!string)
124                 {
125                         if (text[p] == '$' && isdigit((unsigned char) text[p + 1]))
126                         {
127                                 /* this can be either a dollar quote or a variable */
128                                 int                     i;
129
130                                 for (i = p + 1; isdigit((unsigned char) text[i]); i++)
131                                         /* empty loop body */ ;
132                                 if (!isalpha((unsigned char) text[i]) &&
133                                         isascii((unsigned char) text[i]) && text[i] != '_')
134                                         /* not dollar delimited quote */
135                                         return p;
136                         }
137                         else if (questionmarks && text[p] == '?')
138                         {
139                                 /* also allow old style placeholders */
140                                 return p;
141                         }
142                 }
143         }
144
145         return -1;
146 }
147
148 static bool
149 ecpg_type_infocache_push(struct ECPGtype_information_cache ** cache, int oid, bool isarray, int lineno)
150 {
151         struct ECPGtype_information_cache *new_entry
152         = (struct ECPGtype_information_cache *) ecpg_alloc(sizeof(struct ECPGtype_information_cache), lineno);
153
154         if (new_entry == NULL)
155                 return (false);
156
157         new_entry->oid = oid;
158         new_entry->isarray = isarray;
159         new_entry->next = *cache;
160         *cache = new_entry;
161         return (true);
162 }
163
164 static enum ARRAY_TYPE
165 ecpg_is_type_an_array(int type, const struct statement * stmt, const struct variable * var)
166 {
167         char       *array_query;
168         enum ARRAY_TYPE isarray = ECPG_ARRAY_NOT_SET;
169         PGresult   *query;
170         struct ECPGtype_information_cache *cache_entry;
171
172         if ((stmt->connection->cache_head) == NULL)
173         {
174                 /*
175                  * Text like types are not an array for ecpg, but postgres counts them
176                  * as an array. This define reminds you to not 'correct' these values.
177                  */
178 #define not_an_array_in_ecpg ECPG_ARRAY_NONE
179
180                 /* populate cache with well known types to speed things up */
181                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BOOLOID, ECPG_ARRAY_NONE, stmt->lineno))
182                         return (ECPG_ARRAY_ERROR);
183                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BYTEAOID, ECPG_ARRAY_NONE, stmt->lineno))
184                         return (ECPG_ARRAY_ERROR);
185                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CHAROID, ECPG_ARRAY_NONE, stmt->lineno))
186                         return (ECPG_ARRAY_ERROR);
187                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NAMEOID, not_an_array_in_ecpg, stmt->lineno))
188                         return (ECPG_ARRAY_ERROR);
189                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT8OID, ECPG_ARRAY_NONE, stmt->lineno))
190                         return (ECPG_ARRAY_ERROR);
191                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT2OID, ECPG_ARRAY_NONE, stmt->lineno))
192                         return (ECPG_ARRAY_ERROR);
193                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT2VECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno))
194                         return (ECPG_ARRAY_ERROR);
195                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT4OID, ECPG_ARRAY_NONE, stmt->lineno))
196                         return (ECPG_ARRAY_ERROR);
197                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), REGPROCOID, ECPG_ARRAY_NONE, stmt->lineno))
198                         return (ECPG_ARRAY_ERROR);
199                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TEXTOID, ECPG_ARRAY_NONE, stmt->lineno))
200                         return (ECPG_ARRAY_ERROR);
201                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), OIDOID, ECPG_ARRAY_NONE, stmt->lineno))
202                         return (ECPG_ARRAY_ERROR);
203                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIDOID, ECPG_ARRAY_NONE, stmt->lineno))
204                         return (ECPG_ARRAY_ERROR);
205                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), XIDOID, ECPG_ARRAY_NONE, stmt->lineno))
206                         return (ECPG_ARRAY_ERROR);
207                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDOID, ECPG_ARRAY_NONE, stmt->lineno))
208                         return (ECPG_ARRAY_ERROR);
209                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), OIDVECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno))
210                         return (ECPG_ARRAY_ERROR);
211                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), POINTOID, ECPG_ARRAY_VECTOR, stmt->lineno))
212                         return (ECPG_ARRAY_ERROR);
213                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), LSEGOID, ECPG_ARRAY_VECTOR, stmt->lineno))
214                         return (ECPG_ARRAY_ERROR);
215                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), PATHOID, ECPG_ARRAY_NONE, stmt->lineno))
216                         return (ECPG_ARRAY_ERROR);
217                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BOXOID, ECPG_ARRAY_VECTOR, stmt->lineno))
218                         return (ECPG_ARRAY_ERROR);
219                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), POLYGONOID, ECPG_ARRAY_NONE, stmt->lineno))
220                         return (ECPG_ARRAY_ERROR);
221                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), LINEOID, ECPG_ARRAY_VECTOR, stmt->lineno))
222                         return (ECPG_ARRAY_ERROR);
223                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), FLOAT4OID, ECPG_ARRAY_NONE, stmt->lineno))
224                         return (ECPG_ARRAY_ERROR);
225                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), FLOAT8OID, ECPG_ARRAY_NONE, stmt->lineno))
226                         return (ECPG_ARRAY_ERROR);
227                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), ABSTIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
228                         return (ECPG_ARRAY_ERROR);
229                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), RELTIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
230                         return (ECPG_ARRAY_ERROR);
231                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TINTERVALOID, ECPG_ARRAY_NONE, stmt->lineno))
232                         return (ECPG_ARRAY_ERROR);
233                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), UNKNOWNOID, ECPG_ARRAY_NONE, stmt->lineno))
234                         return (ECPG_ARRAY_ERROR);
235                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIRCLEOID, ECPG_ARRAY_NONE, stmt->lineno))
236                         return (ECPG_ARRAY_ERROR);
237                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CASHOID, ECPG_ARRAY_NONE, stmt->lineno))
238                         return (ECPG_ARRAY_ERROR);
239                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INETOID, ECPG_ARRAY_NONE, stmt->lineno))
240                         return (ECPG_ARRAY_ERROR);
241                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDROID, ECPG_ARRAY_NONE, stmt->lineno))
242                         return (ECPG_ARRAY_ERROR);
243                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BPCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
244                         return (ECPG_ARRAY_ERROR);
245                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
246                         return (ECPG_ARRAY_ERROR);
247                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), DATEOID, ECPG_ARRAY_NONE, stmt->lineno))
248                         return (ECPG_ARRAY_ERROR);
249                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
250                         return (ECPG_ARRAY_ERROR);
251                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, ECPG_ARRAY_NONE, stmt->lineno))
252                         return (ECPG_ARRAY_ERROR);
253                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, ECPG_ARRAY_NONE, stmt->lineno))
254                         return (ECPG_ARRAY_ERROR);
255                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INTERVALOID, ECPG_ARRAY_NONE, stmt->lineno))
256                         return (ECPG_ARRAY_ERROR);
257                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMETZOID, ECPG_ARRAY_NONE, stmt->lineno))
258                         return (ECPG_ARRAY_ERROR);
259                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), ZPBITOID, ECPG_ARRAY_NONE, stmt->lineno))
260                         return (ECPG_ARRAY_ERROR);
261                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARBITOID, ECPG_ARRAY_NONE, stmt->lineno))
262                         return (ECPG_ARRAY_ERROR);
263                 if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NUMERICOID, ECPG_ARRAY_NONE, stmt->lineno))
264                         return (ECPG_ARRAY_ERROR);
265         }
266
267         for (cache_entry = (stmt->connection->cache_head); cache_entry != NULL; cache_entry = cache_entry->next)
268         {
269                 if (cache_entry->oid == type)
270                         return cache_entry->isarray;
271         }
272
273         array_query = (char *) ecpg_alloc(strlen("select typlen from pg_type where oid= and typelem<>0") + 11, stmt->lineno);
274         if (array_query == NULL)
275                 return (ECPG_ARRAY_ERROR);
276
277         sprintf(array_query, "select typlen from pg_type where oid=%d and typelem<>0", type);
278         query = PQexec(stmt->connection->connection, array_query);
279         ecpg_free(array_query);
280         if (!ecpg_check_PQresult(query, stmt->lineno, stmt->connection->connection, stmt->compat))
281                 return (ECPG_ARRAY_ERROR);
282         else if (PQresultStatus(query) == PGRES_TUPLES_OK)
283         {
284                 if (PQntuples(query) == 0)
285                         isarray = ECPG_ARRAY_NONE;
286                 else
287                 {
288                         isarray = (atol((char *) PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR;
289                         if (ecpg_dynamic_type(type) == SQL3_CHARACTER ||
290                                 ecpg_dynamic_type(type) == SQL3_CHARACTER_VARYING)
291                         {
292                                 /*
293                                  * arrays of character strings are not yet implemented
294                                  */
295                                 isarray = ECPG_ARRAY_NONE;
296                         }
297                 }
298                 PQclear(query);
299         }
300         else
301                 return (ECPG_ARRAY_ERROR);
302
303         ecpg_type_infocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
304         ecpg_log("ecpg_is_type_an_array on line %d: type (%d); C (%d); array (%s)\n", stmt->lineno, type, var->type, isarray ? "yes" : "no");
305         return isarray;
306 }
307
308
309 bool
310 ecpg_store_result(const PGresult *results, int act_field,
311                                   const struct statement * stmt, struct variable * var)
312 {
313         enum ARRAY_TYPE isarray;
314         int                     act_tuple,
315                                 ntuples = PQntuples(results);
316         bool            status = true;
317
318         if ((isarray = ecpg_is_type_an_array(PQftype(results, act_field), stmt, var)) == ECPG_ARRAY_ERROR)
319         {
320                 ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
321                 return false;
322         }
323
324         if (isarray == ECPG_ARRAY_NONE)
325         {
326                 /*
327                  * if we don't have enough space, we cannot read all tuples
328                  */
329                 if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
330                 {
331                         ecpg_log("ecpg_store_result on line %d: incorrect number of matches; %d don't fit into array of %d\n",
332                                          stmt->lineno, ntuples, var->arrsize);
333                         ecpg_raise(stmt->lineno, INFORMIX_MODE(stmt->compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
334                         return false;
335                 }
336         }
337         else
338         {
339                 /*
340                  * since we read an array, the variable has to be an array too
341                  */
342                 if (var->arrsize == 0)
343                 {
344                         ecpg_raise(stmt->lineno, ECPG_NO_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
345                         return false;
346                 }
347         }
348
349         /*
350          * allocate memory for NULL pointers
351          */
352         if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
353         {
354                 int                     len = 0;
355
356                 if (!PQfformat(results, act_field)) 
357                 {
358                         switch (var->type)
359                         {
360                                 case ECPGt_char:
361                                 case ECPGt_unsigned_char:
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_alloc(len, stmt->lineno);
401                 if (!var->value)
402                         return false;
403                 *((char **) var->pointer) = var->value;
404                 ecpg_add_mem(var->value, stmt->lineno);
405         }
406
407         /* allocate indicator variable if needed */
408         if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer != NULL)
409         {
410                 int                     len = var->ind_offset * ntuples;
411
412                 var->ind_value = (char *) ecpg_alloc(len, stmt->lineno);
413                 if (!var->ind_value)
414                         return false;
415                 *((char **) var->ind_pointer) = var->ind_value;
416                 ecpg_add_mem(var->ind_value, stmt->lineno);
417         }
418
419         /* fill the variable with the tuple(s) */
420         if (!var->varcharsize && !var->arrsize &&
421                 (var->type == ECPGt_char || var->type == ECPGt_unsigned_char))
422         {
423                 /* special mode for handling char**foo=0 */
424
425                 /* filling the array of (char*)s */
426                 char      **current_string = (char **) var->value;
427
428                 /* storing the data (after the last array element) */
429                 char       *current_data_location = (char *) &current_string[ntuples + 1];
430
431                 for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
432                 {
433                         int                     len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
434
435                         if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
436                                                          var->type, var->ind_type, current_data_location,
437                                                            var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
438                                 status = false;
439                         else
440                         {
441                                 *current_string = current_data_location;
442                                 current_data_location += len;
443                                 current_string++;
444                         }
445                 }
446
447                 /* terminate the list */
448                 *current_string = NULL;
449         }
450         else
451         {
452                 for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
453                 {
454                         if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
455                                                            var->type, var->ind_type, var->value,
456                                                            var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
457                                 status = false;
458                 }
459         }
460         return status;
461 }
462
463 bool
464 ecpg_store_input(const int lineno, const bool force_indicator, const struct variable * var,
465                                  char **tobeinserted_p, bool quote)
466 {
467         char       *mallocedval = NULL;
468         char       *newcopy = NULL;
469
470         /*
471          * arrays are not possible unless the attribute is an array too FIXME: we
472          * do not know if the attribute is an array here
473          */
474 #if 0
475         if (var->arrsize > 1 &&...)
476         {
477                 ecpg_raise(lineno, ECPG_ARRAY_INSERT, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
478                 return false;
479         }
480 #endif
481
482         /*
483          * Some special treatment is needed for records since we want their
484          * contents to arrive in a comma-separated list on insert (I think).
485          */
486
487         *tobeinserted_p = "";
488
489         /* check for null value and set input buffer accordingly */
490         switch (var->ind_type)
491         {
492                 case ECPGt_short:
493                 case ECPGt_unsigned_short:
494                         if (*(short *) var->ind_value < 0)
495                                 *tobeinserted_p = NULL;
496                         break;
497                 case ECPGt_int:
498                 case ECPGt_unsigned_int:
499                         if (*(int *) var->ind_value < 0)
500                                 *tobeinserted_p = NULL;
501                         break;
502                 case ECPGt_long:
503                 case ECPGt_unsigned_long:
504                         if (*(long *) var->ind_value < 0L)
505                                 *tobeinserted_p = NULL;
506                         break;
507 #ifdef HAVE_LONG_LONG_INT_64
508                 case ECPGt_long_long:
509                 case ECPGt_unsigned_long_long:
510                         if (*(long long int *) var->ind_value < (long long) 0)
511                                 *tobeinserted_p = NULL;
512                         break;
513 #endif   /* HAVE_LONG_LONG_INT_64 */
514                 case ECPGt_NO_INDICATOR:
515                         if (force_indicator == false)
516                         {
517                                 if (ECPGis_noind_null(var->type, var->value))
518                                         *tobeinserted_p = NULL;
519                         }
520                         break;
521                 default:
522                         break;
523         }
524         if (*tobeinserted_p != NULL)
525         {
526                 int                     asize = var->arrsize ? var->arrsize : 1;
527
528                 switch (var->type)
529                 {
530                                 int                     element;
531
532                         case ECPGt_short:
533                                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
534                                         return false;
535
536                                 if (asize > 1)
537                                 {
538                                         strcpy(mallocedval, "array [");
539
540                                         for (element = 0; element < asize; element++)
541                                                 sprintf(mallocedval + strlen(mallocedval), "%hd,", ((short *) var->value)[element]);
542
543                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
544                                 }
545                                 else
546                                         sprintf(mallocedval, "%hd", *((short *) var->value));
547
548                                 *tobeinserted_p = mallocedval;
549                                 break;
550
551                         case ECPGt_int:
552                                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
553                                         return false;
554
555                                 if (asize > 1)
556                                 {
557                                         strcpy(mallocedval, "{");
558
559                                         for (element = 0; element < asize; element++)
560                                                 sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
561
562                                         strcpy(mallocedval + strlen(mallocedval) - 1, "}");
563                                 }
564                                 else
565                                         sprintf(mallocedval, "%d", *((int *) var->value));
566
567                                 *tobeinserted_p = mallocedval;
568                                 break;
569
570                         case ECPGt_unsigned_short:
571                                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
572                                         return false;
573
574                                 if (asize > 1)
575                                 {
576                                         strcpy(mallocedval, "array [");
577
578                                         for (element = 0; element < asize; element++)
579                                                 sprintf(mallocedval + strlen(mallocedval), "%hu,", ((unsigned short *) var->value)[element]);
580
581                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
582                                 }
583                                 else
584                                         sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
585
586                                 *tobeinserted_p = mallocedval;
587                                 break;
588
589                         case ECPGt_unsigned_int:
590                                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
591                                         return false;
592
593                                 if (asize > 1)
594                                 {
595                                         strcpy(mallocedval, "array [");
596
597                                         for (element = 0; element < asize; element++)
598                                                 sprintf(mallocedval + strlen(mallocedval), "%u,", ((unsigned int *) var->value)[element]);
599
600                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
601                                 }
602                                 else
603                                         sprintf(mallocedval, "%u", *((unsigned int *) var->value));
604
605                                 *tobeinserted_p = mallocedval;
606                                 break;
607
608                         case ECPGt_long:
609                                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
610                                         return false;
611
612                                 if (asize > 1)
613                                 {
614                                         strcpy(mallocedval, "array [");
615
616                                         for (element = 0; element < asize; element++)
617                                                 sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
618
619                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
620                                 }
621                                 else
622                                         sprintf(mallocedval, "%ld", *((long *) var->value));
623
624                                 *tobeinserted_p = mallocedval;
625                                 break;
626
627                         case ECPGt_unsigned_long:
628                                 if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
629                                         return false;
630
631                                 if (asize > 1)
632                                 {
633                                         strcpy(mallocedval, "array [");
634
635                                         for (element = 0; element < asize; element++)
636                                                 sprintf(mallocedval + strlen(mallocedval), "%lu,", ((unsigned long *) var->value)[element]);
637
638                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
639                                 }
640                                 else
641                                         sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
642
643                                 *tobeinserted_p = mallocedval;
644                                 break;
645 #ifdef HAVE_LONG_LONG_INT_64
646                         case ECPGt_long_long:
647                                 if (!(mallocedval = ecpg_alloc(asize * 30, lineno)))
648                                         return false;
649
650                                 if (asize > 1)
651                                 {
652                                         strcpy(mallocedval, "array [");
653
654                                         for (element = 0; element < asize; element++)
655                                                 sprintf(mallocedval + strlen(mallocedval), "%lld,", ((long long *) var->value)[element]);
656
657                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
658                                 }
659                                 else
660                                         sprintf(mallocedval, "%lld", *((long long *) var->value));
661
662                                 *tobeinserted_p = mallocedval;
663                                 break;
664
665                         case ECPGt_unsigned_long_long:
666                                 if (!(mallocedval = ecpg_alloc(asize * 30, lineno)))
667                                         return false;
668
669                                 if (asize > 1)
670                                 {
671                                         strcpy(mallocedval, "array [");
672
673                                         for (element = 0; element < asize; element++)
674                                                 sprintf(mallocedval + strlen(mallocedval), "%llu,", ((unsigned long long *) var->value)[element]);
675
676                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
677                                 }
678                                 else
679                                         sprintf(mallocedval, "%llu", *((unsigned long long *) var->value));
680
681                                 *tobeinserted_p = mallocedval;
682                                 break;
683 #endif   /* HAVE_LONG_LONG_INT_64 */
684                         case ECPGt_float:
685                                 if (!(mallocedval = ecpg_alloc(asize * 25, lineno)))
686                                         return false;
687
688                                 if (asize > 1)
689                                 {
690                                         strcpy(mallocedval, "array [");
691
692                                         for (element = 0; element < asize; element++)
693                                                 sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((float *) var->value)[element]);
694
695                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
696                                 }
697                                 else
698                                         sprintf(mallocedval, "%.14g", *((float *) var->value));
699
700                                 *tobeinserted_p = mallocedval;
701                                 break;
702
703                         case ECPGt_double:
704                                 if (!(mallocedval = ecpg_alloc(asize * 25, lineno)))
705                                         return false;
706
707                                 if (asize > 1)
708                                 {
709                                         strcpy(mallocedval, "array [");
710
711                                         for (element = 0; element < asize; element++)
712                                                 sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((double *) var->value)[element]);
713
714                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
715                                 }
716                                 else
717                                         sprintf(mallocedval, "%.14g", *((double *) var->value));
718
719                                 *tobeinserted_p = mallocedval;
720                                 break;
721
722                         case ECPGt_bool:
723                                 if (!(mallocedval = ecpg_alloc(var->arrsize + sizeof("array []"), lineno)))
724                                         return false;
725
726                                 if (var->arrsize > 1)
727                                 {
728                                         strcpy(mallocedval, "array [");
729
730                                         if (var->offset == sizeof(char))
731                                                 for (element = 0; element < var->arrsize; element++)
732                                                         sprintf(mallocedval + strlen(mallocedval), "%c,", (((char *) var->value)[element]) ? 't' : 'f');
733
734                                         /*
735                                          * this is necessary since sizeof(C++'s bool)==sizeof(int)
736                                          */
737                                         else if (var->offset == sizeof(int))
738                                                 for (element = 0; element < var->arrsize; element++)
739                                                         sprintf(mallocedval + strlen(mallocedval), "%c,", (((int *) var->value)[element]) ? 't' : 'f');
740                                         else
741                                                 ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
742
743                                         strcpy(mallocedval + strlen(mallocedval) - 1, "]");
744                                 }
745                                 else
746                                 {
747                                         if (var->offset == sizeof(char))
748                                                 sprintf(mallocedval, "%c", (*((char *) var->value)) ? 't' : 'f');
749                                         else if (var->offset == sizeof(int))
750                                                 sprintf(mallocedval, "%c", (*((int *) var->value)) ? 't' : 'f');
751                                         else
752                                                 ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
753                                 }
754
755                                 *tobeinserted_p = mallocedval;
756                                 break;
757
758                         case ECPGt_char:
759                         case ECPGt_unsigned_char:
760                                 {
761                                         /* set slen to string length if type is char * */
762                                         int                     slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int)var->varcharsize;
763
764                                         if (!(newcopy = ecpg_alloc(slen + 1, lineno)))
765                                                 return false;
766
767                                         strncpy(newcopy, (char *) var->value, slen);
768                                         newcopy[slen] = '\0';
769
770                                         mallocedval = quote_postgres(newcopy, quote, lineno);
771                                         if (!mallocedval)
772                                                 return false;
773
774                                         *tobeinserted_p = mallocedval;
775                                 }
776                                 break;
777                         case ECPGt_const:
778                         case ECPGt_char_variable:
779                                 {
780                                         int                     slen = strlen((char *) var->value);
781
782                                         if (!(mallocedval = ecpg_alloc(slen + 1, lineno)))
783                                                 return false;
784
785                                         strncpy(mallocedval, (char *) var->value, slen);
786                                         mallocedval[slen] = '\0';
787
788                                         *tobeinserted_p = mallocedval;
789                                 }
790                                 break;
791                         case ECPGt_varchar:
792                                 {
793                                         struct ECPGgeneric_varchar *variable =
794                                         (struct ECPGgeneric_varchar *) (var->value);
795
796                                         if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, lineno)))
797                                                 return false;
798
799                                         strncpy(newcopy, variable->arr, variable->len);
800                                         newcopy[variable->len] = '\0';
801
802                                         mallocedval = quote_postgres(newcopy, quote, lineno);
803                                         if (!mallocedval)
804                                                 return false;
805
806                                         *tobeinserted_p = mallocedval;
807                                 }
808                                 break;
809
810                         case ECPGt_decimal:
811                         case ECPGt_numeric:
812                                 {
813                                         char       *str = NULL;
814                                         int                     slen;
815                                         numeric    *nval;
816
817                                         if (var->arrsize > 1)
818                                         {
819                                                 for (element = 0; element < var->arrsize; element++)
820                                                 {
821                                                         nval = PGTYPESnumeric_new();
822                                                         if (!nval)
823                                                                 return false;
824
825                                                         if (var->type == ECPGt_numeric)
826                                                                 PGTYPESnumeric_copy((numeric *) ((var + var->offset * element)->value), nval);
827                                                         else
828                                                                 PGTYPESnumeric_from_decimal((decimal *) ((var + var->offset * element)->value), nval);
829
830                                                         str = PGTYPESnumeric_to_asc(nval, nval->dscale);
831                                                         slen = strlen(str);
832                                                         PGTYPESnumeric_free(nval);
833
834                                                         if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [] "), lineno)))
835                                                         {
836                                                                 ecpg_free(str);
837                                                                 return false;
838                                                         }
839
840                                                         if (!element)
841                                                                 strcpy(mallocedval, "array [");
842
843                                                         strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
844                                                         strcpy(mallocedval + strlen(mallocedval), ",");
845                                                         ecpg_free(str);
846                                                 }
847                                                 strcpy(mallocedval + strlen(mallocedval) - 1, "]");
848                                         }
849                                         else
850                                         {
851                                                 nval = PGTYPESnumeric_new();
852                                                 if (!nval)
853                                                         return false;
854
855                                                 if (var->type == ECPGt_numeric)
856                                                         PGTYPESnumeric_copy((numeric *) (var->value), nval);
857                                                 else
858                                                         PGTYPESnumeric_from_decimal((decimal *) (var->value), nval);
859
860                                                 str = PGTYPESnumeric_to_asc(nval, nval->dscale);
861                                                 slen = strlen(str);
862                                                 PGTYPESnumeric_free(nval);
863
864                                                 if (!(mallocedval = ecpg_alloc(slen + 1, lineno)))
865                                                 {
866                                                         free(str);
867                                                         return false;
868                                                 }
869
870                                                 strncpy(mallocedval, str, slen);
871                                                 mallocedval[slen] = '\0';
872                                                 ecpg_free(str);
873                                         }
874
875                                         *tobeinserted_p = mallocedval;
876                                 }
877                                 break;
878
879                         case ECPGt_interval:
880                                 {
881                                         char       *str = NULL;
882                                         int                     slen;
883
884                                         if (var->arrsize > 1)
885                                         {
886                                                 for (element = 0; element < var->arrsize; element++)
887                                                 {
888                                                         str = quote_postgres(PGTYPESinterval_to_asc((interval *) ((var + var->offset * element)->value)), quote, lineno);
889                                                         if (!str)
890                                                                 return false;
891                                                         slen = strlen(str);
892
893                                                         if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],interval "), lineno)))
894                                                         {
895                                                                 ecpg_free(str);
896                                                                 return false;
897                                                         }
898
899                                                         if (!element)
900                                                                 strcpy(mallocedval, "array [");
901
902                                                         strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
903                                                         strcpy(mallocedval + strlen(mallocedval), ",");
904                                                         ecpg_free(str);
905                                                 }
906                                                 strcpy(mallocedval + strlen(mallocedval) - 1, "]");
907                                         }
908                                         else
909                                         {
910                                                 str = quote_postgres(PGTYPESinterval_to_asc((interval *) (var->value)), quote, lineno);
911                                                 if (!str)
912                                                         return false;
913                                                 slen = strlen(str);
914
915                                                 if (!(mallocedval = ecpg_alloc(slen + sizeof("interval ") + 1, lineno)))
916                                                 {
917                                                         ecpg_free(str);
918                                                         return false;
919                                                 }
920
921                                                 /* also copy trailing '\0' */
922                                                 strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
923                                                 ecpg_free(str);
924                                         }
925
926                                         *tobeinserted_p = mallocedval;
927                                 }
928                                 break;
929
930                         case ECPGt_date:
931                                 {
932                                         char       *str = NULL;
933                                         int                     slen;
934
935                                         if (var->arrsize > 1)
936                                         {
937                                                 for (element = 0; element < var->arrsize; element++)
938                                                 {
939                                                         str = quote_postgres(PGTYPESdate_to_asc(*(date *) ((var + var->offset * element)->value)), quote, lineno);
940                                                         if (!str)
941                                                                 return false;
942                                                         slen = strlen(str);
943
944                                                         if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],date "), lineno)))
945                                                         {
946                                                                 ecpg_free(str);
947                                                                 return false;
948                                                         }
949
950                                                         if (!element)
951                                                                 strcpy(mallocedval, "array [");
952
953                                                         strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
954                                                         strcpy(mallocedval + strlen(mallocedval), ",");
955                                                         ecpg_free(str);
956                                                 }
957                                                 strcpy(mallocedval + strlen(mallocedval) - 1, "]");
958                                         }
959                                         else
960                                         {
961                                                 str = quote_postgres(PGTYPESdate_to_asc(*(date *) (var->value)), quote, lineno);
962                                                 if (!str)
963                                                         return false;
964                                                 slen = strlen(str);
965
966                                                 if (!(mallocedval = ecpg_alloc(slen + sizeof("date ") + 1, lineno)))
967                                                 {
968                                                         ecpg_free(str);
969                                                         return false;
970                                                 }
971
972                                                 /* also copy trailing '\0' */
973                                                 strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
974                                                 ecpg_free(str);
975                                         }
976
977                                         *tobeinserted_p = mallocedval;
978                                 }
979                                 break;
980
981                         case ECPGt_timestamp:
982                                 {
983                                         char       *str = NULL;
984                                         int                     slen;
985
986                                         if (var->arrsize > 1)
987                                         {
988                                                 for (element = 0; element < var->arrsize; element++)
989                                                 {
990                                                         str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) ((var + var->offset * element)->value)), quote, lineno);
991                                                         if (!str)
992                                                                 return false;
993
994                                                         slen = strlen(str);
995
996                                                         if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [], timestamp "), lineno)))
997                                                         {
998                                                                 ecpg_free(str);
999                                                                 return false;
1000                                                         }
1001
1002                                                         if (!element)
1003                                                                 strcpy(mallocedval, "array [");
1004
1005                                                         strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
1006                                                         strcpy(mallocedval + strlen(mallocedval), ",");
1007                                                         ecpg_free(str);
1008                                                 }
1009                                                 strcpy(mallocedval + strlen(mallocedval) - 1, "]");
1010                                         }
1011                                         else
1012                                         {
1013                                                 str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) (var->value)), quote, lineno);
1014                                                 if (!str)
1015                                                         return false;
1016                                                 slen = strlen(str);
1017
1018                                                 if (!(mallocedval = ecpg_alloc(slen + sizeof("timestamp") + 1, lineno)))
1019                                                 {
1020                                                         ecpg_free(str);
1021                                                         return false;
1022                                                 }
1023
1024                                                 /* also copy trailing '\0' */
1025                                                 strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
1026                                                 ecpg_free(str);
1027                                         }
1028
1029                                         *tobeinserted_p = mallocedval;
1030                                 }
1031                                 break;
1032
1033                         case ECPGt_descriptor:
1034                                 break;
1035
1036                         default:
1037                                 /* Not implemented yet */
1038                                 ecpg_raise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (char *) ecpg_type_name(var->type));
1039                                 return false;
1040                                 break;
1041                 }
1042         }
1043         return true;
1044 }
1045
1046 static void
1047 free_params(const char **paramValues, int nParams, bool print, int lineno)
1048 {
1049         int                     n;
1050
1051         for (n = 0; n < nParams; n++)
1052         {
1053                 if (print)
1054                         ecpg_log("free_params on line %d: parameter %d = %s\n", lineno, n + 1, paramValues[n] ? paramValues[n] : "null");
1055                 ecpg_free((void *) (paramValues[n]));
1056         }
1057         ecpg_free(paramValues);
1058 }
1059
1060
1061 static bool
1062 insert_tobeinserted(int position, int ph_len, struct statement * stmt, char *tobeinserted)
1063 {
1064         char    *newcopy;
1065
1066         if (!(newcopy = (char *) ecpg_alloc(strlen(stmt->command)
1067                                                                                 + strlen(tobeinserted)
1068                                                                                 + 1, stmt->lineno)))
1069         {
1070                 ecpg_free(tobeinserted);
1071                 return false;
1072         }
1073
1074         strcpy(newcopy, stmt->command);
1075         strcpy(newcopy + position - 1, tobeinserted);
1076
1077         /*
1078          * The strange thing in the second argument is the rest of the
1079          * string from the old string
1080          */
1081         strcat(newcopy,
1082                    stmt->command
1083                    + position
1084                    + ph_len - 1);
1085
1086         ecpg_free(stmt->command);
1087         stmt->command = newcopy;
1088
1089         ecpg_free((char *) tobeinserted);
1090         return true;
1091 }
1092
1093 static bool
1094 ecpg_execute(struct statement * stmt)
1095 {
1096         bool            status = false;
1097         char       *cmdstat;
1098         PGresult   *results;
1099         PGnotify   *notify;
1100         struct variable *var;
1101         int                     desc_counter = 0;
1102         const char **paramValues = NULL;
1103         int                     nParams = 0;
1104         int                     position = 0;
1105         struct sqlca_t *sqlca = ECPGget_sqlca();
1106         bool            clear_result = true;
1107
1108         /*
1109          * If the type is one of the fill in types then we take the argument and
1110          * enter it to our parameter array at the first position. Then if there
1111          * are any more fill in types we add more parameters.
1112          */
1113         var = stmt->inlist;
1114         while (var)
1115         {
1116                 char *tobeinserted;
1117                 int                     counter = 1;
1118
1119                 tobeinserted = NULL;
1120
1121                 /*
1122                  * A descriptor is a special case since it contains many variables but
1123                  * is listed only once.
1124                  */
1125                 if (var->type == ECPGt_descriptor)
1126                 {
1127                         /*
1128                          * We create an additional variable list here, so the same logic
1129                          * applies.
1130                          */
1131                         struct variable desc_inlist;
1132                         struct descriptor *desc;
1133                         struct descriptor_item *desc_item;
1134
1135                         desc = ecpg_find_desc(stmt->lineno, var->pointer);
1136                         if (desc == NULL)
1137                                 return false;
1138
1139                         desc_counter++;
1140                         for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
1141                         {
1142                                 if (desc_item->num == desc_counter)
1143                                 {
1144                                         desc_inlist.type = ECPGt_char;
1145                                         desc_inlist.value = desc_item->data;
1146                                         desc_inlist.pointer = &(desc_item->data);
1147                                         desc_inlist.varcharsize = strlen(desc_item->data);
1148                                         desc_inlist.arrsize = 1;
1149                                         desc_inlist.offset = 0;
1150                                         if (!desc_item->indicator)
1151                                         {
1152                                                 desc_inlist.ind_type = ECPGt_NO_INDICATOR;
1153                                                 desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1154                                                 desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1155                                         }
1156                                         else
1157                                         {
1158                                                 desc_inlist.ind_type = ECPGt_int;
1159                                                 desc_inlist.ind_value = &(desc_item->indicator);
1160                                                 desc_inlist.ind_pointer = &(desc_inlist.ind_value);
1161                                                 desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1162                                                 desc_inlist.ind_offset = 0;
1163                                         }
1164                                         if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
1165                                                 return false;
1166
1167                                         break;
1168                                 }
1169                         }
1170                         if (desc->count == desc_counter)
1171                                 desc_counter = 0;
1172                 }
1173                 else
1174                 {
1175                         if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
1176                                 return false;
1177                 }
1178
1179                 /*
1180                  * now tobeinserted points to an area that contains the next parameter
1181                  * now find the positin in the string where it belongs
1182                  */
1183                 if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
1184                 {
1185                         /*
1186                          * We have an argument but we dont have the matched up
1187                          * placeholder in the string
1188                          */
1189                         ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
1190                                         ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
1191                                            NULL);
1192                         free_params(paramValues, nParams, false, stmt->lineno);
1193                         return false;
1194                 }
1195
1196                 /* 
1197                  * if var->type=ECPGt_char_variable we have a dynamic cursor we have
1198                  * to simulate a dynamic cursor because there is no backend
1199                  * functionality for it
1200                  */
1201                 if (var->type == ECPGt_char_variable)
1202                 {
1203                         int     ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
1204
1205                         if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
1206                         {
1207                                 free_params(paramValues, nParams, false, stmt->lineno);
1208                                 return false;
1209                         }
1210                         tobeinserted = NULL;
1211                 }
1212                 /*
1213                  * if the placeholder is '$0' we have to replace it on the client side
1214                  * this is for places we want to support variables at that are not supported in the backend
1215                  */
1216                 else if (stmt->command[position] == '0' ) 
1217                 {
1218                         if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
1219                         {
1220                                 free_params(paramValues, nParams, false, stmt->lineno);
1221                                 return false;
1222                         }
1223                         tobeinserted = NULL;
1224                 }
1225                 else
1226                 {
1227                         nParams++;
1228                         if (!(paramValues = (const char **) ecpg_realloc(paramValues, sizeof(const char *) * nParams, stmt->lineno)))
1229                         {
1230                                 ecpg_free(paramValues);
1231                                 return false;
1232                         }
1233
1234                         paramValues[nParams - 1] = tobeinserted;
1235
1236                         /* let's see if this was an old style placeholder */
1237                         if (stmt->command[position] == '?')
1238                         {
1239                                 /* yes, replace with new style */
1240                                 int                     buffersize = sizeof(int) * CHAR_BIT * 10 / 3;           /* a rough guess of the
1241                                                                                                                                                                  * size we need */
1242
1243                                 if (!(tobeinserted = (char *) ecpg_alloc(buffersize, stmt->lineno)))
1244                                 {
1245                                         free_params(paramValues, nParams, false, stmt->lineno);
1246                                         return false;
1247                                 }
1248
1249                                 snprintf(tobeinserted, buffersize, "$%d", counter++);
1250
1251                                 if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
1252                                 {
1253                                         free_params(paramValues, nParams, false, stmt->lineno);
1254                                         return false;
1255                                 }
1256                                 tobeinserted = NULL;
1257                         }
1258                 }
1259
1260                 if (desc_counter == 0)
1261                         var = var->next;
1262         }
1263
1264         /* Check if there are unmatched things left. */
1265         if (next_insert(stmt->command, position, stmt->questionmarks) >= 0)
1266         {
1267                 ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
1268                                  ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
1269                 free_params(paramValues, nParams, false, stmt->lineno);
1270                 return false;
1271         }
1272
1273         /* The request has been build. */
1274
1275         if (stmt->connection->committed && !stmt->connection->autocommit)
1276         {
1277                 results = PQexec(stmt->connection->connection, "begin transaction");
1278                 if (!ecpg_check_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
1279                 {
1280                         free_params(paramValues, nParams, false, stmt->lineno);
1281                         return false;
1282                 }
1283                 PQclear(results);
1284                 stmt->connection->committed = false;
1285         }
1286
1287         ecpg_log("ecpg_execute on line %d: query: %s; with %d parameter(s) on connection %s\n", stmt->lineno, stmt->command, nParams, stmt->connection->name);
1288         if (stmt->statement_type == ECPGst_execute)
1289         {
1290                 results = PQexecPrepared(stmt->connection->connection, stmt->name, nParams, paramValues, NULL, NULL, 0);
1291                 ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
1292         }
1293         else
1294         {
1295                 if (nParams == 0)
1296                 {
1297                         results = PQexec(stmt->connection->connection, stmt->command);
1298                         ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
1299                 }
1300                 else
1301                 {
1302                         results = PQexecParams(stmt->connection->connection, stmt->command, nParams, NULL, paramValues, NULL, NULL, 0);
1303                         ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
1304                 }
1305         }
1306
1307         free_params(paramValues, nParams, true, stmt->lineno);
1308
1309         if (!ecpg_check_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
1310                 return (false);
1311
1312         var = stmt->outlist;
1313         switch (PQresultStatus(results))
1314         {
1315                         int                     nfields,
1316                                                 ntuples,
1317                                                 act_field;
1318
1319                 case PGRES_TUPLES_OK:
1320                         nfields = PQnfields(results);
1321                         sqlca->sqlerrd[2] = ntuples = PQntuples(results);
1322                         ecpg_log("ecpg_execute on line %d: correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
1323                         status = true;
1324
1325                         if (ntuples < 1)
1326                         {
1327                                 if (ntuples)
1328                                         ecpg_log("ecpg_execute on line %d: incorrect number of matches (%d)\n",
1329                                                          stmt->lineno, ntuples);
1330                                 ecpg_raise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
1331                                 status = false;
1332                                 break;
1333                         }
1334
1335                         if (var != NULL && var->type == ECPGt_descriptor)
1336                         {
1337                                 struct descriptor *desc = ecpg_find_desc(stmt->lineno, var->pointer);
1338
1339                                 if (desc == NULL)
1340                                         status = false;
1341                                 else
1342                                 {
1343                                         if (desc->result)
1344                                                 PQclear(desc->result);
1345                                         desc->result = results;
1346                                         clear_result = false;
1347                                         ecpg_log("ecpg_execute on line %d: putting result (%d tuples) into descriptor %s\n",
1348                                                         stmt->lineno, PQntuples(results), (const char *) var->pointer);
1349                                 }
1350                                 var = var->next;
1351                         }
1352                         else
1353                                 for (act_field = 0; act_field < nfields && status; act_field++)
1354                                 {
1355                                         if (var != NULL)
1356                                         {
1357                                                 status = ecpg_store_result(results, act_field, stmt, var);
1358                                                 var = var->next;
1359                                         }
1360                                         else if (!INFORMIX_MODE(stmt->compat))
1361                                         {
1362                                                 ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
1363                                                 return (false);
1364                                         }
1365                                 }
1366
1367                         if (status && var != NULL)
1368                         {
1369                                 ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
1370                                 status = false;
1371                         }
1372
1373                         break;
1374                 case PGRES_COMMAND_OK:
1375                         status = true;
1376                         cmdstat = PQcmdStatus(results);
1377                         sqlca->sqlerrd[1] = PQoidValue(results);
1378                         sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
1379                         ecpg_log("ecpg_execute on line %d: OK: %s\n", stmt->lineno, cmdstat);
1380                         if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
1381                                 !sqlca->sqlerrd[2] &&
1382                                 (!strncmp(cmdstat, "UPDATE", 6)
1383                                  || !strncmp(cmdstat, "INSERT", 6)
1384                                  || !strncmp(cmdstat, "DELETE", 6)))
1385                                 ecpg_raise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
1386                         break;
1387                 case PGRES_COPY_OUT:
1388                         {
1389                                 char       *buffer;
1390                                 int                     res;
1391
1392                                 ecpg_log("ecpg_execute on line %d: COPY OUT data transfer in progress\n", stmt->lineno);
1393                                 while ((res = PQgetCopyData(stmt->connection->connection,
1394                                                                                         &buffer, 0)) > 0)
1395                                 {
1396                                         printf("%s", buffer);
1397                                         PQfreemem(buffer);
1398                                 }
1399                                 if (res == -1)
1400                                 {
1401                                         /* COPY done */
1402                                         PQclear(results);
1403                                         results = PQgetResult(stmt->connection->connection);
1404                                         if (PQresultStatus(results) == PGRES_COMMAND_OK)
1405                                                 ecpg_log("ecpg_execute on line %d: got PGRES_COMMAND_OK after PGRES_COPY_OUT\n", stmt->lineno);
1406                                         else
1407                                                 ecpg_log("ecpg_execute on line %d: got error after PGRES_COPY_OUT: %s", PQresultErrorMessage(results));
1408                                 }
1409                                 break;
1410                         }
1411                 default:
1412
1413                         /*
1414                          * execution should never reach this code because it is already
1415                          * handled in ECPGcheck_PQresult()
1416                          */
1417                         ecpg_log("ecpg_execute on line %d: unknown execution status type\n",
1418                                          stmt->lineno);
1419                         ecpg_raise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
1420                         status = false;
1421                         break;
1422         }
1423         if (clear_result)
1424                 PQclear(results);
1425
1426         /* check for asynchronous returns */
1427         notify = PQnotifies(stmt->connection->connection);
1428         if (notify)
1429         {
1430                 ecpg_log("ecpg_execute on line %d: asynchronous notification of \"%s\" from backend pid %d received\n",
1431                                  stmt->lineno, notify->relname, notify->be_pid);
1432                 PQfreemem(notify);
1433         }
1434
1435         return status;
1436 }
1437
1438 bool
1439 ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query,...)
1440 {
1441         va_list         args;
1442         struct statement *stmt;
1443         struct connection *con;
1444         bool            status;
1445         char       *oldlocale;
1446         enum ECPGttype type;
1447         struct variable **list;
1448         enum ECPG_statement_type statement_type = (enum ECPG_statement_type) st;
1449         char       *prepname;
1450
1451         if (!query)
1452         {
1453                 ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
1454                 return (false);
1455         }
1456
1457         /* Make sure we do NOT honor the locale for numeric input/output */
1458         /* since the database wants the standard decimal point */
1459         oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
1460         setlocale(LC_NUMERIC, "C");
1461
1462 #ifdef ENABLE_THREAD_SAFETY
1463         ecpg_pthreads_init();
1464 #endif
1465
1466         con = ecpg_get_connection(connection_name);
1467
1468         if (!ecpg_init(con, connection_name, lineno))
1469         {
1470                 setlocale(LC_NUMERIC, oldlocale);
1471                 ecpg_free(oldlocale);
1472                 return (false);
1473         }
1474
1475         /* construct statement in our own structure */
1476         va_start(args, query);
1477
1478         /*
1479          * create a list of variables The variables are listed with input
1480          * variables preceding outputvariables The end of each group is marked by
1481          * an end marker. per variable we list: type - as defined in ecpgtype.h
1482          * value - where to store the data varcharsize - length of string in case
1483          * we have a stringvariable, else 0 arraysize - 0 for pointer (we don't
1484          * know the size of the array), 1 for simple variable, size for arrays
1485          * offset - offset between ith and (i+1)th entry in an array, normally
1486          * that means sizeof(type) ind_type - type of indicator variable ind_value
1487          * - pointer to indicator variable ind_varcharsize - empty ind_arraysize -
1488          * arraysize of indicator array ind_offset - indicator offset
1489          */
1490         if (!(stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))
1491         {
1492                 setlocale(LC_NUMERIC, oldlocale);
1493                 ecpg_free(oldlocale);
1494                 va_end(args);
1495                 return false;
1496         }
1497
1498         /*
1499          * If statement type is ECPGst_prepnormal we are supposed to prepare the
1500          * statement before executing them
1501          */
1502         if (statement_type == ECPGst_prepnormal)
1503         {
1504                 if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, query))
1505                         return (false);
1506
1507                 /*
1508                  * statement is now prepared, so instead of the query we have to
1509                  * execute the name
1510                  */
1511                 stmt->command = prepname;
1512                 statement_type = ECPGst_execute;
1513         }
1514         else
1515                 stmt->command = ecpg_strdup(query, lineno);
1516
1517         stmt->name = NULL;
1518
1519         if (statement_type == ECPGst_execute)
1520         {
1521                 /* if we have an EXECUTE command, only the name is send */
1522                 char       *command = ecpg_prepared(stmt->command, con);
1523
1524                 if (command)
1525                 {
1526                         stmt->name = stmt->command;
1527                         stmt->command = ecpg_strdup(command, lineno);
1528                 }
1529                 else
1530                         ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
1531         }
1532
1533         stmt->connection = con;
1534         stmt->lineno = lineno;
1535         stmt->compat = compat;
1536         stmt->force_indicator = force_indicator;
1537         stmt->questionmarks = questionmarks;
1538         stmt->statement_type = statement_type;
1539
1540         list = &(stmt->inlist);
1541
1542         type = va_arg(args, enum ECPGttype);
1543
1544         while (type != ECPGt_EORT)
1545         {
1546                 if (type == ECPGt_EOIT)
1547                         list = &(stmt->outlist);
1548                 else
1549                 {
1550                         struct variable *var,
1551                                            *ptr;
1552
1553                         if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
1554                         {
1555                                 setlocale(LC_NUMERIC, oldlocale);
1556                                 ecpg_free(oldlocale);
1557                                 free_statement(stmt);
1558                                 va_end(args);
1559                                 return false;
1560                         }
1561
1562                         var->type = type;
1563                         var->pointer = va_arg(args, char *);
1564
1565                         var->varcharsize = va_arg(args, long);
1566                         var->arrsize = va_arg(args, long);
1567                         var->offset = va_arg(args, long);
1568
1569                         if (var->arrsize == 0 || var->varcharsize == 0)
1570                                 var->value = *((char **) (var->pointer));
1571                         else
1572                                 var->value = var->pointer;
1573
1574                         /*
1575                          * negative values are used to indicate an array without given
1576                          * bounds
1577                          */
1578                         /* reset to zero for us */
1579                         if (var->arrsize < 0)
1580                                 var->arrsize = 0;
1581                         if (var->varcharsize < 0)
1582                                 var->varcharsize = 0;
1583
1584                         var->next = NULL;
1585
1586                         var->ind_type = va_arg(args, enum ECPGttype);
1587                         var->ind_pointer = va_arg(args, char *);
1588                         var->ind_varcharsize = va_arg(args, long);
1589                         var->ind_arrsize = va_arg(args, long);
1590                         var->ind_offset = va_arg(args, long);
1591
1592                         if (var->ind_type != ECPGt_NO_INDICATOR
1593                                 && (var->ind_arrsize == 0 || var->ind_varcharsize == 0))
1594                                 var->ind_value = *((char **) (var->ind_pointer));
1595                         else
1596                                 var->ind_value = var->ind_pointer;
1597
1598                         /*
1599                          * negative values are used to indicate an array without given
1600                          * bounds
1601                          */
1602                         /* reset to zero for us */
1603                         if (var->ind_arrsize < 0)
1604                                 var->ind_arrsize = 0;
1605                         if (var->ind_varcharsize < 0)
1606                                 var->ind_varcharsize = 0;
1607
1608                         /* if variable is NULL, the statement hasn't been prepared */
1609                         if (var->pointer == NULL)
1610                         {
1611                                 ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, NULL);
1612                                 ecpg_free(var);
1613                                 setlocale(LC_NUMERIC, oldlocale);
1614                                 ecpg_free(oldlocale);
1615                                 free_statement(stmt);
1616                                 va_end(args);
1617                                 return false;
1618                         }
1619
1620                         for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
1621
1622                         if (ptr == NULL)
1623                                 *list = var;
1624                         else
1625                                 ptr->next = var;
1626                 }
1627
1628                 type = va_arg(args, enum ECPGttype);
1629         }
1630
1631         va_end(args);
1632
1633         /* are we connected? */
1634         if (con == NULL || con->connection == NULL)
1635         {
1636                 free_statement(stmt);
1637                 ecpg_raise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : ecpg_gettext("<empty>"));
1638                 setlocale(LC_NUMERIC, oldlocale);
1639                 ecpg_free(oldlocale);
1640                 return false;
1641         }
1642
1643         /* initialize auto_mem struct */
1644         ecpg_clear_auto_mem();
1645
1646         status = ecpg_execute(stmt);
1647         free_statement(stmt);
1648
1649         /* and reset locale value so our application is not affected */
1650         setlocale(LC_NUMERIC, oldlocale);
1651         ecpg_free(oldlocale);
1652
1653         return (status);
1654 }
1655
1656 /* old descriptor interface */
1657 bool
1658 ECPGdo_descriptor(int line, const char *connection,
1659                                   const char *descriptor, const char *query)
1660 {
1661         return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, '\0', 0, (char *) query, ECPGt_EOIT,
1662                                   ECPGt_descriptor, descriptor, 0L, 0L, 0L,
1663                                   ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
1664 }