1
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.38.4.1 2005-03-18 10:01:14 meskes Exp $ */
4
* The aim is to get a simpler inteface to the database routines.
5
* All the tidieous messing around with tuples is supposed to be hidden
9
(actually most if the code is "borrowed" from the distribution and just
13
/* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
16
#define POSTGRES_ECPG_INTERNAL
17
#include "postgres_fe.h"
26
#include "ecpgerrno.h"
29
#include "sql3types.h"
30
#include "pgtypes_numeric.h"
31
#include "pgtypes_date.h"
32
#include "pgtypes_timestamp.h"
33
#include "pgtypes_interval.h"
35
/* This function returns a newly malloced string that has the \
36
in the argument quoted with \ and the ' quoted with ' as SQL92 says.
39
quote_postgres(char *arg, int lineno)
41
char *res = (char *) ECPGalloc(2 * strlen(arg) + 3, lineno);
50
for (i = 0; arg[i]; i++, ri++)
72
#if defined(__GNUC__) && (defined (__powerpc__) || defined(__AMD64__))
79
ECPGget_variable(va_list APREF, enum ECPGttype type, struct variable * var, bool indicator)
82
var->pointer = va_arg(APREF, char *);
84
var->varcharsize = va_arg(APREF, long);
85
var->arrsize = va_arg(APREF, long);
86
var->offset = va_arg(APREF, long);
88
if (var->arrsize == 0 || var->varcharsize == 0)
89
var->value = *((char **) (var->pointer));
91
var->value = var->pointer;
94
* negative values are used to indicate an array without given bounds
96
/* reset to zero for us */
99
if (var->varcharsize < 0)
100
var->varcharsize = 0;
106
var->ind_type = va_arg(APREF, enum ECPGttype);
107
var->ind_pointer = va_arg(APREF, char *);
108
var->ind_varcharsize = va_arg(APREF, long);
109
var->ind_arrsize = va_arg(APREF, long);
110
var->ind_offset = va_arg(APREF, long);
112
if (var->ind_type != ECPGt_NO_INDICATOR
113
&& (var->ind_arrsize == 0 || var->ind_varcharsize == 0))
114
var->ind_value = *((char **) (var->ind_pointer));
116
var->ind_value = var->ind_pointer;
119
* negative values are used to indicate an array without given
122
/* reset to zero for us */
123
if (var->ind_arrsize < 0)
124
var->ind_arrsize = 0;
125
if (var->ind_varcharsize < 0)
126
var->ind_varcharsize = 0;
132
* create a list of variables
133
* The variables are listed with input variables preceding outputvariables
134
* The end of each group is marked by an end marker.
135
* per variable we list:
136
* type - as defined in ecpgtype.h
137
* value - where to store the data
138
* varcharsize - length of string in case we have a stringvariable, else 0
139
* arraysize - 0 for pointer (we don't know the size of the array),
140
* 1 for simple variable, size for arrays
141
* offset - offset between ith and (i+1)th entry in an array,
142
* normally that means sizeof(type)
143
* ind_type - type of indicator variable
144
* ind_value - pointer to indicator variable
145
* ind_varcharsize - empty
146
* ind_arraysize - arraysize of indicator array
147
* ind_offset - indicator offset
150
create_statement(int lineno, int compat, int force_indicator, struct connection * connection, struct statement ** stmt, char *query, va_list ap)
152
struct variable **list = &((*stmt)->inlist);
155
if (!(*stmt = (struct statement *) ECPGalloc(sizeof(struct statement), lineno)))
158
(*stmt)->command = query;
159
(*stmt)->connection = connection;
160
(*stmt)->lineno = lineno;
161
(*stmt)->compat = compat;
162
(*stmt)->force_indicator = force_indicator;
164
list = &((*stmt)->inlist);
166
type = va_arg(ap, enum ECPGttype);
168
while (type != ECPGt_EORT)
170
if (type == ECPGt_EOIT)
171
list = &((*stmt)->outlist);
174
struct variable *var,
177
if (!(var = (struct variable *) ECPGalloc(sizeof(struct variable), lineno)))
180
#if defined(__GNUC__) && (defined (__powerpc__) || defined(__AMD64__))
181
ECPGget_variable(ap, type, var, true);
183
ECPGget_variable(&ap, type, var, true);
186
/* if variable is NULL, the statement hasn't been prepared */
187
if (var->pointer == NULL)
189
ECPGraise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, NULL);
194
for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
202
type = va_arg(ap, enum ECPGttype);
209
free_variable(struct variable * var)
211
struct variable *var_next;
215
var_next = var->next;
221
var_next = var->next;
227
free_statement(struct statement * stmt)
231
free_variable(stmt->inlist);
232
free_variable(stmt->outlist);
237
next_insert(char *text)
242
for (; *ptr != '\0' && (*ptr != '?' || string); ptr++)
244
if (*ptr == '\\') /* escape character */
246
else if (*ptr == '\'')
247
string = string ? false : true;
250
return (*ptr == '\0') ? NULL : ptr;
254
ECPGtypeinfocache_push(struct ECPGtype_information_cache ** cache, int oid, bool isarray, int lineno)
256
struct ECPGtype_information_cache *new_entry
257
= (struct ECPGtype_information_cache *) ECPGalloc(sizeof(struct ECPGtype_information_cache), lineno);
259
new_entry->oid = oid;
260
new_entry->isarray = isarray;
261
new_entry->next = *cache;
265
static enum ARRAY_TYPE
266
ECPGis_type_an_array(int type, const struct statement * stmt, const struct variable * var)
269
enum ARRAY_TYPE isarray = ECPG_ARRAY_NOT_SET;
271
struct ECPGtype_information_cache *cache_entry;
273
if ((stmt->connection->cache_head) == NULL)
276
* Text like types are not an array for ecpg, but postgres counts
277
* them as an array. This define reminds you to not 'correct'
280
#define not_an_array_in_ecpg ECPG_ARRAY_NONE
282
/* populate cache with well known types to speed things up */
283
ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOOLOID, ECPG_ARRAY_NONE, stmt->lineno);
284
ECPGtypeinfocache_push(&(stmt->connection->cache_head), BYTEAOID, ECPG_ARRAY_NONE, stmt->lineno);
285
ECPGtypeinfocache_push(&(stmt->connection->cache_head), CHAROID, ECPG_ARRAY_NONE, stmt->lineno);
286
ECPGtypeinfocache_push(&(stmt->connection->cache_head), NAMEOID, not_an_array_in_ecpg, stmt->lineno);
287
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT8OID, ECPG_ARRAY_NONE, stmt->lineno);
288
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2OID, ECPG_ARRAY_NONE, stmt->lineno);
289
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2VECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno);
290
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT4OID, ECPG_ARRAY_NONE, stmt->lineno);
291
ECPGtypeinfocache_push(&(stmt->connection->cache_head), REGPROCOID, ECPG_ARRAY_NONE, stmt->lineno);
292
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TEXTOID, ECPG_ARRAY_NONE, stmt->lineno);
293
ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDOID, ECPG_ARRAY_NONE, stmt->lineno);
294
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIDOID, ECPG_ARRAY_NONE, stmt->lineno);
295
ECPGtypeinfocache_push(&(stmt->connection->cache_head), XIDOID, ECPG_ARRAY_NONE, stmt->lineno);
296
ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDOID, ECPG_ARRAY_NONE, stmt->lineno);
297
ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDVECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno);
298
ECPGtypeinfocache_push(&(stmt->connection->cache_head), POINTOID, ECPG_ARRAY_VECTOR, stmt->lineno);
299
ECPGtypeinfocache_push(&(stmt->connection->cache_head), LSEGOID, ECPG_ARRAY_VECTOR, stmt->lineno);
300
ECPGtypeinfocache_push(&(stmt->connection->cache_head), PATHOID, ECPG_ARRAY_NONE, stmt->lineno);
301
ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOXOID, ECPG_ARRAY_VECTOR, stmt->lineno);
302
ECPGtypeinfocache_push(&(stmt->connection->cache_head), POLYGONOID, ECPG_ARRAY_NONE, stmt->lineno);
303
ECPGtypeinfocache_push(&(stmt->connection->cache_head), LINEOID, ECPG_ARRAY_VECTOR, stmt->lineno);
304
ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT4OID, ECPG_ARRAY_NONE, stmt->lineno);
305
ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT8OID, ECPG_ARRAY_NONE, stmt->lineno);
306
ECPGtypeinfocache_push(&(stmt->connection->cache_head), ABSTIMEOID, ECPG_ARRAY_NONE, stmt->lineno);
307
ECPGtypeinfocache_push(&(stmt->connection->cache_head), RELTIMEOID, ECPG_ARRAY_NONE, stmt->lineno);
308
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TINTERVALOID, ECPG_ARRAY_NONE, stmt->lineno);
309
ECPGtypeinfocache_push(&(stmt->connection->cache_head), UNKNOWNOID, ECPG_ARRAY_NONE, stmt->lineno);
310
ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIRCLEOID, ECPG_ARRAY_NONE, stmt->lineno);
311
ECPGtypeinfocache_push(&(stmt->connection->cache_head), CASHOID, ECPG_ARRAY_NONE, stmt->lineno);
312
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INETOID, ECPG_ARRAY_NONE, stmt->lineno);
313
ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDROID, ECPG_ARRAY_NONE, stmt->lineno);
314
ECPGtypeinfocache_push(&(stmt->connection->cache_head), BPCHAROID, ECPG_ARRAY_NONE, stmt->lineno);
315
ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARCHAROID, ECPG_ARRAY_NONE, stmt->lineno);
316
ECPGtypeinfocache_push(&(stmt->connection->cache_head), DATEOID, ECPG_ARRAY_NONE, stmt->lineno);
317
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMEOID, ECPG_ARRAY_NONE, stmt->lineno);
318
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, ECPG_ARRAY_NONE, stmt->lineno);
319
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, ECPG_ARRAY_NONE, stmt->lineno);
320
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INTERVALOID, ECPG_ARRAY_NONE, stmt->lineno);
321
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMETZOID, ECPG_ARRAY_NONE, stmt->lineno);
322
ECPGtypeinfocache_push(&(stmt->connection->cache_head), ZPBITOID, ECPG_ARRAY_NONE, stmt->lineno);
323
ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARBITOID, ECPG_ARRAY_NONE, stmt->lineno);
324
ECPGtypeinfocache_push(&(stmt->connection->cache_head), NUMERICOID, ECPG_ARRAY_NONE, stmt->lineno);
327
for (cache_entry = (stmt->connection->cache_head); cache_entry != NULL; cache_entry = cache_entry->next)
329
if (cache_entry->oid == type)
330
return cache_entry->isarray;
333
array_query = (char *) ECPGalloc(strlen("select typlen from pg_type where oid= and typelem<>0") + 11, stmt->lineno);
334
sprintf(array_query, "select typlen from pg_type where oid=%d and typelem<>0", type);
335
query = PQexec(stmt->connection->connection, array_query);
336
ECPGfree(array_query);
337
if (PQresultStatus(query) == PGRES_TUPLES_OK)
339
if (PQntuples(query) == 0)
340
isarray = ECPG_ARRAY_NONE;
343
isarray = (atol((char *) PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR;
344
if (ECPGDynamicType(type) == SQL3_CHARACTER ||
345
ECPGDynamicType(type) == SQL3_CHARACTER_VARYING)
348
* arrays of character strings are not yet implemented
350
isarray = ECPG_ARRAY_NONE;
355
ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
356
ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %s\n", stmt->lineno, type, var->type, isarray ? "Yes" : "No");
362
ECPGstore_result(const PGresult *results, int act_field,
363
const struct statement * stmt, struct variable * var)
365
enum ARRAY_TYPE isarray;
367
ntuples = PQntuples(results);
370
isarray = ECPGis_type_an_array(PQftype(results, act_field), stmt, var);
372
if (isarray == ECPG_ARRAY_NONE)
375
* if we don't have enough space, we cannot read all tuples
377
if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
379
ECPGlog("ECPGstore_result line %d: Incorrect number of matches: %d don't fit into array of %d\n",
380
stmt->lineno, ntuples, var->arrsize);
381
ECPGraise(stmt->lineno, INFORMIX_MODE(stmt->compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
388
* since we read an array, the variable has to be an array too
390
if (var->arrsize == 0)
392
ECPGraise(stmt->lineno, ECPG_NO_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
398
* allocate memory for NULL pointers
400
if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
407
case ECPGt_unsigned_char:
408
if (!var->varcharsize && !var->arrsize)
410
/* special mode for handling char**foo=0 */
411
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
412
len += strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
413
len *= var->offset; /* should be 1, but YMNK */
414
len += (ntuples + 1) * sizeof(char *);
416
ECPGlog("ECPGstore_result: line %d: allocating %d bytes for %d tuples (char**=0)",
417
stmt->lineno, len, ntuples);
421
var->varcharsize = 0;
422
/* check strlen for each tuple */
423
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
425
int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
427
if (len > var->varcharsize)
428
var->varcharsize = len;
430
var->offset *= var->varcharsize;
431
len = var->offset * ntuples;
435
len = ntuples * (var->varcharsize + sizeof(int));
438
len = var->offset * ntuples;
441
var->value = (char *) ECPGalloc(len, stmt->lineno);
442
*((char **) var->pointer) = var->value;
443
ECPGadd_mem(var->value, stmt->lineno);
446
/* allocate indicator variable if needed */
447
if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer != NULL)
449
int len = var->ind_offset * ntuples;
451
var->ind_value = (char *) ECPGalloc(len, stmt->lineno);
452
*((char **) var->ind_pointer) = var->ind_value;
453
ECPGadd_mem(var->ind_value, stmt->lineno);
456
/* fill the variable with the tuple(s) */
457
if (!var->varcharsize && !var->arrsize &&
458
(var->type == ECPGt_char || var->type == ECPGt_unsigned_char))
460
/* special mode for handling char**foo=0 */
462
/* filling the array of (char*)s */
463
char **current_string = (char **) var->value;
465
/* storing the data (after the last array element) */
466
char *current_data_location = (char *) ¤t_string[ntuples + 1];
468
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
470
int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
472
if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
473
var->type, var->ind_type, current_data_location,
474
var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
478
*current_string = current_data_location;
479
current_data_location += len;
484
/* terminate the list */
485
*current_string = NULL;
489
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
491
if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
492
var->type, var->ind_type, var->value,
493
var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
501
ECPGstore_input(const int lineno, const bool force_indicator, const struct variable * var,
502
const char **tobeinserted_p, bool *malloced_p)
504
char *mallocedval = NULL;
505
char *newcopy = NULL;
508
* arrays are not possible unless the attribute is an array too FIXME:
509
* we do not know if the attribute is an array here
512
if (var->arrsize > 1 &&...)
514
ECPGraise(lineno, ECPG_ARRAY_INSERT, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
520
* Some special treatment is needed for records since we want their
521
* contents to arrive in a comma-separated list on insert (I think).
525
*tobeinserted_p = "";
527
/* check for null value and set input buffer accordingly */
528
switch (var->ind_type)
531
case ECPGt_unsigned_short:
532
if (*(short *) var->ind_value < 0)
533
*tobeinserted_p = "null";
536
case ECPGt_unsigned_int:
537
if (*(int *) var->ind_value < 0)
538
*tobeinserted_p = "null";
541
case ECPGt_unsigned_long:
542
if (*(long *) var->ind_value < 0L)
543
*tobeinserted_p = "null";
545
#ifdef HAVE_LONG_LONG_INT_64
546
case ECPGt_long_long:
547
case ECPGt_unsigned_long_long:
548
if (*(long long int *) var->ind_value < (long long) 0)
549
*tobeinserted_p = "null";
551
#endif /* HAVE_LONG_LONG_INT_64 */
552
case ECPGt_NO_INDICATOR:
553
if (force_indicator == false)
555
if (ECPGis_noind_null(var->type, var->value))
556
*tobeinserted_p = "null";
562
if (**tobeinserted_p == '\0')
569
if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
572
if (var->arrsize > 1)
574
strcpy(mallocedval, "array [");
576
for (element = 0; element < var->arrsize; element++)
577
sprintf(mallocedval + strlen(mallocedval), "%hd,", ((short *) var->value)[element]);
579
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
582
sprintf(mallocedval, "%hd", *((short *) var->value));
584
*tobeinserted_p = mallocedval;
589
if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
592
if (var->arrsize > 1)
594
strcpy(mallocedval, "array [");
596
for (element = 0; element < var->arrsize; element++)
597
sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
599
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
602
sprintf(mallocedval, "%d", *((int *) var->value));
604
*tobeinserted_p = mallocedval;
608
case ECPGt_unsigned_short:
609
if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
612
if (var->arrsize > 1)
614
strcpy(mallocedval, "array [");
616
for (element = 0; element < var->arrsize; element++)
617
sprintf(mallocedval + strlen(mallocedval), "%hu,", ((unsigned short *) var->value)[element]);
619
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
622
sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
624
*tobeinserted_p = mallocedval;
628
case ECPGt_unsigned_int:
629
if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
632
if (var->arrsize > 1)
634
strcpy(mallocedval, "array [");
636
for (element = 0; element < var->arrsize; element++)
637
sprintf(mallocedval + strlen(mallocedval), "%u,", ((unsigned int *) var->value)[element]);
639
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
642
sprintf(mallocedval, "%u", *((unsigned int *) var->value));
644
*tobeinserted_p = mallocedval;
649
if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
652
if (var->arrsize > 1)
654
strcpy(mallocedval, "array [");
656
for (element = 0; element < var->arrsize; element++)
657
sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
659
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
662
sprintf(mallocedval, "%ld", *((long *) var->value));
664
*tobeinserted_p = mallocedval;
668
case ECPGt_unsigned_long:
669
if (!(mallocedval = ECPGalloc(var->arrsize * 20, lineno)))
672
if (var->arrsize > 1)
674
strcpy(mallocedval, "array [");
676
for (element = 0; element < var->arrsize; element++)
677
sprintf(mallocedval + strlen(mallocedval), "%lu,", ((unsigned long *) var->value)[element]);
679
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
682
sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
684
*tobeinserted_p = mallocedval;
687
#ifdef HAVE_LONG_LONG_INT_64
688
case ECPGt_long_long:
689
if (!(mallocedval = ECPGalloc(var->arrsize * 30, lineno)))
692
if (var->arrsize > 1)
694
strcpy(mallocedval, "array [");
696
for (element = 0; element < var->arrsize; element++)
697
sprintf(mallocedval + strlen(mallocedval), "%lld,", ((long long *) var->value)[element]);
699
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
702
sprintf(mallocedval, "%lld", *((long long *) var->value));
704
*tobeinserted_p = mallocedval;
708
case ECPGt_unsigned_long_long:
709
if (!(mallocedval = ECPGalloc(var->arrsize * 30, lineno)))
712
if (var->arrsize > 1)
714
strcpy(mallocedval, "array [");
716
for (element = 0; element < var->arrsize; element++)
717
sprintf(mallocedval + strlen(mallocedval), "%llu,", ((unsigned long long *) var->value)[element]);
719
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
722
sprintf(mallocedval, "%llu", *((unsigned long long *) var->value));
724
*tobeinserted_p = mallocedval;
727
#endif /* HAVE_LONG_LONG_INT_64 */
729
if (!(mallocedval = ECPGalloc(var->arrsize * 25, lineno)))
732
if (var->arrsize > 1)
734
strcpy(mallocedval, "array [");
736
for (element = 0; element < var->arrsize; element++)
737
sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((float *) var->value)[element]);
739
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
742
sprintf(mallocedval, "%.14g", *((float *) var->value));
744
*tobeinserted_p = mallocedval;
749
if (!(mallocedval = ECPGalloc(var->arrsize * 25, lineno)))
752
if (var->arrsize > 1)
754
strcpy(mallocedval, "array [");
756
for (element = 0; element < var->arrsize; element++)
757
sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((double *) var->value)[element]);
759
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
762
sprintf(mallocedval, "%.14g", *((double *) var->value));
764
*tobeinserted_p = mallocedval;
769
if (!(mallocedval = ECPGalloc(var->arrsize + sizeof("array []"), lineno)))
772
if (var->arrsize > 1)
774
strcpy(mallocedval, "array [");
776
if (var->offset == sizeof(char))
777
for (element = 0; element < var->arrsize; element++)
778
sprintf(mallocedval + strlen(mallocedval), "%c,", (((char *) var->value)[element]) ? 't' : 'f');
781
* this is necessary since sizeof(C++'s
784
else if (var->offset == sizeof(int))
785
for (element = 0; element < var->arrsize; element++)
786
sprintf(mallocedval + strlen(mallocedval), "%c,", (((int *) var->value)[element]) ? 't' : 'f');
788
ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
790
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
794
if (var->offset == sizeof(char))
795
sprintf(mallocedval, "'%c'", (*((char *) var->value)) ? 't' : 'f');
796
else if (var->offset == sizeof(int))
797
sprintf(mallocedval, "'%c'", (*((int *) var->value)) ? 't' : 'f');
799
ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
802
*tobeinserted_p = mallocedval;
807
case ECPGt_unsigned_char:
809
/* set slen to string length if type is char * */
810
int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
812
if (!(newcopy = ECPGalloc(slen + 1, lineno)))
815
strncpy(newcopy, (char *) var->value, slen);
816
newcopy[slen] = '\0';
818
mallocedval = quote_postgres(newcopy, lineno);
824
*tobeinserted_p = mallocedval;
829
case ECPGt_char_variable:
831
int slen = strlen((char *) var->value);
833
if (!(mallocedval = ECPGalloc(slen + 1, lineno)))
836
strncpy(mallocedval, (char *) var->value, slen);
837
mallocedval[slen] = '\0';
839
*tobeinserted_p = mallocedval;
845
struct ECPGgeneric_varchar *variable =
846
(struct ECPGgeneric_varchar *) (var->value);
848
if (!(newcopy = (char *) ECPGalloc(variable->len + 1, lineno)))
851
strncpy(newcopy, variable->arr, variable->len);
852
newcopy[variable->len] = '\0';
854
mallocedval = quote_postgres(newcopy, lineno);
860
*tobeinserted_p = mallocedval;
870
numeric *nval = PGTYPESnumeric_new();
872
if (var->arrsize > 1)
874
for (element = 0; element < var->arrsize; element++)
876
if (var->type == ECPGt_numeric)
877
PGTYPESnumeric_copy((numeric *) ((var + var->offset * element)->value), nval);
879
PGTYPESnumeric_from_decimal((decimal *) ((var + var->offset * element)->value), nval);
881
str = PGTYPESnumeric_to_asc(nval, nval->dscale);
882
PGTYPESnumeric_free(nval);
885
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [] "), lineno)))
889
strcpy(mallocedval, "array [");
891
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
892
strcpy(mallocedval + strlen(mallocedval), ",");
894
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
898
if (var->type == ECPGt_numeric)
899
PGTYPESnumeric_copy((numeric *) (var->value), nval);
901
PGTYPESnumeric_from_decimal((decimal *) (var->value), nval);
903
str = PGTYPESnumeric_to_asc(nval, nval->dscale);
905
PGTYPESnumeric_free(nval);
908
if (!(mallocedval = ECPGalloc(slen + 1, lineno)))
911
strncpy(mallocedval, str, slen);
912
mallocedval[slen] = '\0';
915
*tobeinserted_p = mallocedval;
926
if (var->arrsize > 1)
928
for (element = 0; element < var->arrsize; element++)
930
str = quote_postgres(PGTYPESinterval_to_asc((interval *) ((var + var->offset * element)->value)), lineno);
933
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],interval "), lineno)))
937
strcpy(mallocedval, "array [");
939
strcpy(mallocedval + strlen(mallocedval), "interval ");
940
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
941
strcpy(mallocedval + strlen(mallocedval), ",");
943
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
947
str = quote_postgres(PGTYPESinterval_to_asc((interval *) (var->value)), lineno);
950
if (!(mallocedval = ECPGalloc(slen + sizeof("interval ") + 1, lineno)))
953
strcpy(mallocedval, "interval ");
954
/* also copy trailing '\0' */
955
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
958
*tobeinserted_p = mallocedval;
969
if (var->arrsize > 1)
971
for (element = 0; element < var->arrsize; element++)
973
str = quote_postgres(PGTYPESdate_to_asc(*(date *) ((var + var->offset * element)->value)), lineno);
976
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],date "), lineno)))
980
strcpy(mallocedval, "array [");
982
strcpy(mallocedval + strlen(mallocedval), "date ");
983
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
984
strcpy(mallocedval + strlen(mallocedval), ",");
986
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
990
str = quote_postgres(PGTYPESdate_to_asc(*(date *) (var->value)), lineno);
993
if (!(mallocedval = ECPGalloc(slen + sizeof("date ") + 1, lineno)))
996
strcpy(mallocedval, "date ");
997
/* also copy trailing '\0' */
998
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
1001
*tobeinserted_p = mallocedval;
1007
case ECPGt_timestamp:
1012
if (var->arrsize > 1)
1014
for (element = 0; element < var->arrsize; element++)
1016
str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) ((var + var->offset * element)->value)), lineno);
1019
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [], timestamp "), lineno)))
1023
strcpy(mallocedval, "array [");
1025
strcpy(mallocedval + strlen(mallocedval), "timestamp ");
1026
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
1027
strcpy(mallocedval + strlen(mallocedval), ",");
1029
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
1033
str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) (var->value)), lineno);
1036
if (!(mallocedval = ECPGalloc(slen + sizeof("timestamp") + 1, lineno)))
1039
strcpy(mallocedval, "timestamp ");
1040
/* also copy trailing '\0' */
1041
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
1044
*tobeinserted_p = mallocedval;
1050
case ECPGt_descriptor:
1054
/* Not implemented yet */
1055
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (char *) ECPGtype_name(var->type));
1064
ECPGexecute(struct statement * stmt)
1066
bool status = false;
1071
struct variable *var;
1072
int desc_counter = 0;
1074
copiedquery = ECPGstrdup(stmt->command, stmt->lineno);
1077
* Now, if the type is one of the fill in types then we take the
1078
* argument and enter that in the string at the first %s position.
1079
* Then if there are any more fill in types we fill in at the next and
1086
char *newcopy = NULL;
1087
const char *tobeinserted;
1089
bool malloced = FALSE;
1092
tobeinserted = NULL;
1095
* A descriptor is a special case since it contains many variables
1096
* but is listed only once.
1098
if (var->type == ECPGt_descriptor)
1101
* We create an additional variable list here, so the same
1104
struct variable desc_inlist;
1105
struct descriptor *desc;
1106
struct descriptor_item *desc_item;
1108
for (desc = all_descriptors; desc; desc = desc->next)
1110
if (strcmp(var->pointer, desc->name) == 0)
1116
ECPGraise(stmt->lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, var->pointer);
1121
if (desc->count < 0 || desc->count >= desc_counter)
1123
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
1125
if (desc_item->num == desc_counter)
1127
desc_inlist.type = ECPGt_char;
1128
desc_inlist.value = desc_item->data;
1129
desc_inlist.pointer = &(desc_item->data);
1130
desc_inlist.varcharsize = strlen(desc_item->data);
1131
desc_inlist.arrsize = 1;
1132
desc_inlist.offset = 0;
1133
if (!desc_item->indicator)
1135
desc_inlist.ind_type = ECPGt_NO_INDICATOR;
1136
desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1137
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1141
desc_inlist.ind_type = ECPGt_int;
1142
desc_inlist.ind_value = &(desc_item->indicator);
1143
desc_inlist.ind_pointer = &(desc_inlist.ind_value);
1144
desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1145
desc_inlist.ind_offset = 0;
1147
if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced))
1154
if (!desc_item) /* no more entries found in descriptor */
1162
if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, &malloced))
1169
* Now tobeinserted points to an area that is to be inserted
1172
if (!(newcopy = (char *) ECPGalloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
1175
strcpy(newcopy, copiedquery);
1176
if ((p = next_insert(newcopy + hostvarl)) == NULL)
1179
* We have an argument but we dont have the matched up
1180
* string in the string
1182
ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
1187
strcpy(p, tobeinserted);
1188
hostvarl = strlen(newcopy);
1191
* The strange thing in the second argument is the rest of
1192
* the string from the old string
1197
+ sizeof("?") - 1 /* don't count the '\0' */ );
1201
* Now everything is safely copied to the newcopy. Lets free
1202
* the oldcopy and let the copiedquery get the var->value from
1207
ECPGfree((char *) tobeinserted);
1208
tobeinserted = NULL;
1211
ECPGfree(copiedquery);
1212
copiedquery = newcopy;
1215
if (desc_counter == 0)
1219
/* Check if there are unmatched things left. */
1220
if (next_insert(copiedquery) != NULL)
1222
ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
1226
/* Now the request is built. */
1228
if (stmt->connection->committed && !stmt->connection->autocommit)
1230
if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
1232
ECPGraise(stmt->lineno, ECPG_TRANS, ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN, NULL);
1236
stmt->connection->committed = false;
1239
ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name);
1240
results = PQexec(stmt->connection->connection, copiedquery);
1241
ECPGfree(copiedquery);
1243
if (results == NULL)
1245
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno, PQerrorMessage(stmt->connection->connection));
1246
ECPGraise_backend(stmt->lineno, NULL, stmt->connection->connection, stmt->compat);
1251
* note: since some of the following code is duplicated in
1252
* descriptor.c it should go into a separate function
1255
bool clear_result = TRUE;
1256
struct sqlca_t *sqlca = ECPGget_sqlca();
1258
var = stmt->outlist;
1259
switch (PQresultStatus(results))
1265
case PGRES_TUPLES_OK:
1266
nfields = PQnfields(results);
1267
sqlca->sqlerrd[2] = ntuples = PQntuples(results);
1268
ECPGlog("ECPGexecute line %d: Correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
1274
ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
1275
stmt->lineno, ntuples);
1276
ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
1281
if (var != NULL && var->type == ECPGt_descriptor)
1283
PGresult **resultpp = ECPGdescriptor_lvalue(stmt->lineno, (const char *) var->pointer);
1285
if (resultpp == NULL)
1291
*resultpp = results;
1292
clear_result = FALSE;
1293
ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
1298
for (act_field = 0; act_field < nfields && status; act_field++)
1302
status = ECPGstore_result(results, act_field, stmt, var);
1305
else if (!INFORMIX_MODE(stmt->compat))
1307
ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
1312
if (status && var != NULL)
1314
ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
1319
case PGRES_EMPTY_QUERY:
1321
ECPGraise(stmt->lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
1323
case PGRES_COMMAND_OK:
1325
cmdstat = PQcmdStatus(results);
1326
sqlca->sqlerrd[1] = PQoidValue(results);
1327
sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
1328
ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
1329
if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
1330
!sqlca->sqlerrd[2] &&
1331
(!strncmp(cmdstat, "UPDATE", 6)
1332
|| !strncmp(cmdstat, "INSERT", 6)
1333
|| !strncmp(cmdstat, "DELETE", 6)))
1334
ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
1336
case PGRES_NONFATAL_ERROR:
1337
case PGRES_FATAL_ERROR:
1338
case PGRES_BAD_RESPONSE:
1339
ECPGlog("ECPGexecute line %d: Error: %s", stmt->lineno, PQresultErrorMessage(results));
1340
ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
1343
case PGRES_COPY_OUT:
1344
ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
1345
PQendcopy(stmt->connection->connection);
1348
ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
1349
PQendcopy(stmt->connection->connection);
1352
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
1354
ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
1362
/* check for asynchronous returns */
1363
notify = PQnotifies(stmt->connection->connection);
1366
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
1367
stmt->lineno, notify->relname, notify->be_pid);
1375
ECPGdo(int lineno, int compat, int force_indicator, const char *connection_name, char *query,...)
1378
struct statement *stmt;
1379
struct connection *con = ECPGget_connection(connection_name);
1383
/* Make sure we do NOT honor the locale for numeric input/output */
1384
/* since the database wants the standard decimal point */
1385
oldlocale = strdup(setlocale(LC_NUMERIC, NULL));
1386
setlocale(LC_NUMERIC, "C");
1388
if (!ECPGinit(con, connection_name, lineno))
1390
setlocale(LC_NUMERIC, oldlocale);
1391
ECPGfree(oldlocale);
1395
/* construct statement in our own structure */
1396
va_start(args, query);
1397
if (create_statement(lineno, compat, force_indicator, con, &stmt, query, args) == false)
1399
setlocale(LC_NUMERIC, oldlocale);
1400
ECPGfree(oldlocale);
1405
/* are we connected? */
1406
if (con == NULL || con->connection == NULL)
1408
free_statement(stmt);
1409
ECPGraise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : "<empty>");
1410
setlocale(LC_NUMERIC, oldlocale);
1411
ECPGfree(oldlocale);
1415
/* initialize auto_mem struct */
1416
ECPGclear_auto_mem();
1418
status = ECPGexecute(stmt);
1419
free_statement(stmt);
1421
/* and reset locale value so our application is not affected */
1422
setlocale(LC_NUMERIC, oldlocale);
1423
ECPGfree(oldlocale);
1428
/* old descriptor interface */
1430
ECPGdo_descriptor(int line, const char *connection,
1431
const char *descriptor, const char *query)
1433
return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, (char *) query, ECPGt_EOIT,
1434
ECPGt_descriptor, descriptor, 0L, 0L, 0L,
1435
ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);