1
/* dynamic SQL support routines
6
#define POSTGRES_ECPG_INTERNAL
7
#include "postgres_fe.h"
10
#include "ecpg-pthread-win32.h"
13
#include "ecpgerrno.h"
16
#include "sql3types.h"
18
static void descriptor_free(struct descriptor * desc);
20
/* We manage descriptors separately for each thread. */
21
#ifdef ENABLE_THREAD_SAFETY
22
static pthread_key_t descriptor_key;
23
static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT;
25
static void descriptor_deallocate_all(struct descriptor * list);
28
descriptor_destructor(void *arg)
30
descriptor_deallocate_all(arg);
34
descriptor_key_init(void)
36
pthread_key_create(&descriptor_key, descriptor_destructor);
39
static struct descriptor *
42
pthread_once(&descriptor_once, descriptor_key_init);
43
return (struct descriptor *) pthread_getspecific(descriptor_key);
47
set_descriptors(struct descriptor * value)
49
pthread_setspecific(descriptor_key, value);
52
static struct descriptor *all_descriptors = NULL;
54
#define get_descriptors() (all_descriptors)
55
#define set_descriptors(value) do { all_descriptors = (value); } while(0)
58
/* old internal convenience function that might go away later */
60
ecpg_result_by_descriptor(int line, const char *name)
62
struct descriptor *desc = ecpg_find_desc(line, name);
70
ecpg_dynamic_type_DDT(Oid type)
79
return SQL3_DDT_TIMESTAMP;
81
return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
83
return SQL3_DDT_TIME_WITH_TIME_ZONE;
85
return SQL3_DDT_ILLEGAL;
90
ECPGget_desc_header(int lineno, const char *desc_name, int *count)
93
struct sqlca_t *sqlca = ECPGget_sqlca();
95
ecpg_init_sqlca(sqlca);
96
ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
100
*count = PQnfields(ECPGresult);
101
sqlca->sqlerrd[2] = 1;
102
ecpg_log("ECPGget_desc_header: found %d attributes\n", *count);
107
get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
112
*(short *) var = (short) value;
115
*(int *) var = (int) value;
118
*(long *) var = (long) value;
120
case ECPGt_unsigned_short:
121
*(unsigned short *) var = (unsigned short) value;
123
case ECPGt_unsigned_int:
124
*(unsigned int *) var = (unsigned int) value;
126
case ECPGt_unsigned_long:
127
*(unsigned long *) var = (unsigned long) value;
129
#ifdef HAVE_LONG_LONG_INT_64
130
case ECPGt_long_long:
131
*(long long int *) var = (long long int) value;
133
case ECPGt_unsigned_long_long:
134
*(unsigned long long int *) var = (unsigned long long int) value;
136
#endif /* HAVE_LONG_LONG_INT_64 */
138
*(float *) var = (float) value;
141
*(double *) var = (double) value;
144
ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
152
set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
157
*target = *(short *) var;
160
*target = *(int *) var;
163
*target = *(long *) var;
165
case ECPGt_unsigned_short:
166
*target = *(unsigned short *) var;
168
case ECPGt_unsigned_int:
169
*target = *(unsigned int *) var;
171
case ECPGt_unsigned_long:
172
*target = *(unsigned long *) var;
174
#ifdef HAVE_LONG_LONG_INT_64
175
case ECPGt_long_long:
176
*target = *(long long int *) var;
178
case ECPGt_unsigned_long_long:
179
*target = *(unsigned long long int *) var;
181
#endif /* HAVE_LONG_LONG_INT_64 */
183
*target = *(float *) var;
186
*target = *(double *) var;
189
ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
197
get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
202
case ECPGt_unsigned_char:
203
strncpy((char *) var, value, varcharsize);
207
struct ECPGgeneric_varchar *variable =
208
(struct ECPGgeneric_varchar *) var;
210
if (varcharsize == 0)
211
strncpy(variable->arr, value, strlen(value));
213
strncpy(variable->arr, value, varcharsize);
215
variable->len = strlen(value);
216
if (varcharsize > 0 && variable->len > varcharsize)
217
variable->len = varcharsize;
221
ecpg_raise(lineno, ECPG_VAR_NOT_CHAR, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
229
ECPGget_desc(int lineno, const char *desc_name, int index,...)
232
PGresult *ECPGresult;
236
struct variable data_var;
237
struct sqlca_t *sqlca = ECPGget_sqlca();
239
va_start(args, index);
240
ecpg_init_sqlca(sqlca);
241
ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
245
ntuples = PQntuples(ECPGresult);
248
ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
252
if (index < 1 || index > PQnfields(ECPGresult))
254
ecpg_raise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX, NULL);
258
ecpg_log("ECPGget_desc: reading items for tuple %d\n", index);
261
type = va_arg(args, enum ECPGdtype);
263
memset(&data_var, 0, sizeof data_var);
264
data_var.type = ECPGt_EORT;
265
data_var.ind_type = ECPGt_NO_INDICATOR;
267
while (type != ECPGd_EODT)
273
enum ECPGttype vartype;
276
vartype = va_arg(args, enum ECPGttype);
277
var = va_arg(args, void *);
278
varcharsize = va_arg(args, long);
279
arrsize = va_arg(args, long);
280
offset = va_arg(args, long);
284
case (ECPGd_indicator):
285
data_var.ind_type = vartype;
286
data_var.ind_pointer = var;
287
data_var.ind_varcharsize = varcharsize;
288
data_var.ind_arrsize = arrsize;
289
data_var.ind_offset = offset;
290
if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0)
291
data_var.ind_value = *((void **) (data_var.ind_pointer));
293
data_var.ind_value = data_var.ind_pointer;
297
data_var.type = vartype;
298
data_var.pointer = var;
299
data_var.varcharsize = varcharsize;
300
data_var.arrsize = arrsize;
301
data_var.offset = offset;
302
if (data_var.arrsize == 0 || data_var.varcharsize == 0)
303
data_var.value = *((void **) (data_var.pointer));
305
data_var.value = data_var.pointer;
309
if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
312
ecpg_log("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
316
if (!get_int_item(lineno, var, vartype, 1))
321
case ECPGd_key_member:
322
if (!get_int_item(lineno, var, vartype, 0))
328
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
331
ecpg_log("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
334
case ECPGd_precision:
335
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
338
ecpg_log("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
342
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
345
ecpg_log("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
349
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
352
ecpg_log("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
356
if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type(PQftype(ECPGresult, index))))
359
ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type(PQftype(ECPGresult, index)));
363
if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type_DDT(PQftype(ECPGresult, index))))
366
ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type_DDT(PQftype(ECPGresult, index)));
369
case ECPGd_cardinality:
370
if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
373
ecpg_log("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
376
case ECPGd_ret_length:
377
case ECPGd_ret_octet:
380
* this is like ECPGstore_result
382
if (arrsize > 0 && ntuples > arrsize)
384
ecpg_log("ECPGget_desc on line %d: incorrect number of matches; %d don't fit into array of %d\n",
385
lineno, ntuples, arrsize);
386
ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
389
/* allocate storage if needed */
390
if (arrsize == 0 && *(void **) var == NULL)
392
void *mem = (void *) ecpg_alloc(offset * ntuples, lineno);
396
*(void **) var = mem;
397
ecpg_add_mem(mem, lineno);
401
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
403
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
405
var = (char *) var + offset;
406
ecpg_log("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
411
snprintf(type_str, sizeof(type_str), "%d", type);
412
ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
416
type = va_arg(args, enum ECPGdtype);
419
if (data_var.type != ECPGt_EORT)
421
struct statement stmt;
424
/* Make sure we do NOT honor the locale for numeric input */
425
/* since the database gives the standard decimal point */
426
oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
427
setlocale(LC_NUMERIC, "C");
429
memset(&stmt, 0, sizeof stmt);
430
stmt.lineno = lineno;
432
/* desparate try to guess something sensible */
433
stmt.connection = ecpg_get_connection(NULL);
434
ecpg_store_result(ECPGresult, index, &stmt, &data_var);
436
setlocale(LC_NUMERIC, oldlocale);
437
ecpg_free(oldlocale);
439
else if (data_var.ind_type != ECPGt_NO_INDICATOR && data_var.ind_pointer != NULL)
442
* ind_type != NO_INDICATOR should always have ind_pointer != NULL but
443
* since this might be changed manually in the .c file let's play it
448
* this is like ECPGstore_result but since we don't have a data
449
* variable at hand, we can't call it
451
if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
453
ecpg_log("ECPGget_desc on line %d: incorrect number of matches (indicator); %d don't fit into array of %d\n",
454
lineno, ntuples, data_var.ind_arrsize);
455
ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
459
/* allocate storage if needed */
460
if (data_var.ind_arrsize == 0 && data_var.ind_value == NULL)
462
void *mem = (void *) ecpg_alloc(data_var.ind_offset * ntuples, lineno);
466
*(void **) data_var.ind_pointer = mem;
467
ecpg_add_mem(mem, lineno);
468
data_var.ind_value = mem;
471
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
473
if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
475
data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset;
476
ecpg_log("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
479
sqlca->sqlerrd[2] = ntuples;
484
ECPGset_desc_header(int lineno, const char *desc_name, int count)
486
struct descriptor *desc = ecpg_find_desc(lineno, desc_name);
495
ECPGset_desc(int lineno, const char *desc_name, int index,...)
498
struct descriptor *desc;
499
struct descriptor_item *desc_item;
500
struct variable *var;
502
desc = ecpg_find_desc(lineno, desc_name);
506
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
508
if (desc_item->num == index)
512
if (desc_item == NULL)
514
desc_item = (struct descriptor_item *) ecpg_alloc(sizeof(*desc_item), lineno);
517
desc_item->num = index;
518
if (desc->count < index)
520
desc_item->next = desc->items;
521
desc->items = desc_item;
524
if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
527
va_start(args, index);
531
enum ECPGdtype itemtype;
532
char *tobeinserted = NULL;
534
itemtype = va_arg(args, enum ECPGdtype);
536
if (itemtype == ECPGd_EODT)
539
var->type = va_arg(args, enum ECPGttype);
540
var->pointer = va_arg(args, char *);
542
var->varcharsize = va_arg(args, long);
543
var->arrsize = va_arg(args, long);
544
var->offset = va_arg(args, long);
546
if (var->arrsize == 0 || var->varcharsize == 0)
547
var->value = *((char **) (var->pointer));
549
var->value = var->pointer;
552
* negative values are used to indicate an array without given bounds
554
/* reset to zero for us */
555
if (var->arrsize < 0)
557
if (var->varcharsize < 0)
558
var->varcharsize = 0;
566
if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
572
ecpg_free(desc_item->data); /* free() takes care of a
573
* potential NULL value */
574
desc_item->data = (char *) tobeinserted;
579
case ECPGd_indicator:
580
set_int_item(lineno, &desc_item->indicator, var->pointer, var->type);
584
set_int_item(lineno, &desc_item->length, var->pointer, var->type);
587
case ECPGd_precision:
588
set_int_item(lineno, &desc_item->precision, var->pointer, var->type);
592
set_int_item(lineno, &desc_item->scale, var->pointer, var->type);
596
set_int_item(lineno, &desc_item->type, var->pointer, var->type);
603
snprintf(type_str, sizeof(type_str), "%d", itemtype);
604
ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
615
/* Free the descriptor and items in it. */
617
descriptor_free(struct descriptor * desc)
619
struct descriptor_item *desc_item;
621
for (desc_item = desc->items; desc_item;)
623
struct descriptor_item *di;
625
ecpg_free(desc_item->data);
627
desc_item = desc_item->next;
631
ecpg_free(desc->name);
632
PQclear(desc->result);
637
ECPGdeallocate_desc(int line, const char *name)
639
struct descriptor *desc;
640
struct descriptor *prev;
641
struct sqlca_t *sqlca = ECPGget_sqlca();
643
ecpg_init_sqlca(sqlca);
644
for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
646
if (!strcmp(name, desc->name))
649
prev->next = desc->next;
651
set_descriptors(desc->next);
652
descriptor_free(desc);
656
ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
660
#ifdef ENABLE_THREAD_SAFETY
662
/* Deallocate all descriptors in the list */
664
descriptor_deallocate_all(struct descriptor * list)
668
struct descriptor *next = list->next;
670
descriptor_free(list);
674
#endif /* ENABLE_THREAD_SAFETY */
677
ECPGallocate_desc(int line, const char *name)
679
struct descriptor *new;
680
struct sqlca_t *sqlca = ECPGget_sqlca();
682
ecpg_init_sqlca(sqlca);
683
new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
686
new->next = get_descriptors();
687
new->name = ecpg_alloc(strlen(name) + 1, line);
695
new->result = PQmakeEmptyPGresult(NULL, 0);
698
ecpg_free(new->name);
700
ecpg_raise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
703
strcpy(new->name, name);
704
set_descriptors(new);
708
/* Find descriptor with name in the connection. */
710
ecpg_find_desc(int line, const char *name)
712
struct descriptor *desc;
714
for (desc = get_descriptors(); desc; desc = desc->next)
716
if (strcmp(name, desc->name) == 0)
720
ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
721
return NULL; /* not found */
725
ECPGdescribe(int line, bool input, const char *statement,...)
727
ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line, input ? "input" : "output", statement);