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