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