1
/* dynamic SQL support routines
3
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.12 2004-08-29 05:06:59 momjian Exp $
6
#define POSTGRES_ECPG_INTERNAL
7
#include "postgres_fe.h"
12
#include "ecpgerrno.h"
15
#include "sql3types.h"
17
struct descriptor *all_descriptors = NULL;
19
/* old internal convenience function that might go away later */
22
ECPGresultByDescriptor(int line, const char *name)
24
PGresult **resultpp = ECPGdescriptor_lvalue(line, name);
32
ECPGDynamicType_DDT(Oid type)
41
return SQL3_DDT_TIMESTAMP;
43
return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
45
return SQL3_DDT_TIME_WITH_TIME_ZONE;
47
return SQL3_DDT_ILLEGAL;
52
ECPGget_desc_header(int lineno, char *desc_name, int *count)
55
struct sqlca_t *sqlca = ECPGget_sqlca();
57
ECPGinit_sqlca(sqlca);
58
ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
62
*count = PQnfields(ECPGresult);
63
sqlca->sqlerrd[2] = 1;
64
ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
69
get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
74
*(short *) var = (short) value;
77
*(int *) var = (int) value;
80
*(long *) var = (long) value;
82
case ECPGt_unsigned_short:
83
*(unsigned short *) var = (unsigned short) value;
85
case ECPGt_unsigned_int:
86
*(unsigned int *) var = (unsigned int) value;
88
case ECPGt_unsigned_long:
89
*(unsigned long *) var = (unsigned long) value;
91
#ifdef HAVE_LONG_LONG_INT_64
93
*(long long int *) var = (long long int) value;
95
case ECPGt_unsigned_long_long:
96
*(unsigned long long int *) var = (unsigned long long int) value;
98
#endif /* HAVE_LONG_LONG_INT_64 */
100
*(float *) var = (float) value;
103
*(double *) var = (double) value;
106
ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
114
set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
119
*target = *(short *) var;
122
*target = *(int *) var;
125
*target = *(long *) var;
127
case ECPGt_unsigned_short:
128
*target = *(unsigned short *) var;
130
case ECPGt_unsigned_int:
131
*target = *(unsigned int *) var;
133
case ECPGt_unsigned_long:
134
*target = *(unsigned long *) var;
136
#ifdef HAVE_LONG_LONG_INT_64
137
case ECPGt_long_long:
138
*target = *(long long int *) var;
140
case ECPGt_unsigned_long_long:
141
*target = *(unsigned long long int *) var;
143
#endif /* HAVE_LONG_LONG_INT_64 */
145
*target = *(float *) var;
148
*target = *(double *) var;
151
ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
159
get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
164
case ECPGt_unsigned_char:
165
strncpy((char *) var, value, varcharsize);
169
struct ECPGgeneric_varchar *variable =
170
(struct ECPGgeneric_varchar *) var;
172
if (varcharsize == 0)
173
strncpy(variable->arr, value, strlen(value));
175
strncpy(variable->arr, value, varcharsize);
177
variable->len = strlen(value);
178
if (varcharsize > 0 && variable->len > varcharsize)
179
variable->len = varcharsize;
183
ECPGraise(lineno, ECPG_VAR_NOT_CHAR, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
191
ECPGget_desc(int lineno, char *desc_name, int index,...)
194
PGresult *ECPGresult;
198
struct variable data_var;
199
struct sqlca_t *sqlca = ECPGget_sqlca();
201
va_start(args, index);
202
ECPGinit_sqlca(sqlca);
203
ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
207
ntuples = PQntuples(ECPGresult);
210
ECPGraise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
214
if (index < 1 || index > PQnfields(ECPGresult))
216
ECPGraise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX, NULL);
220
ECPGlog("ECPGget_desc: reading items for tuple %d\n", index);
223
type = va_arg(args, enum ECPGdtype);
225
memset(&data_var, 0, sizeof data_var);
226
data_var.type = ECPGt_EORT;
227
data_var.ind_type = ECPGt_NO_INDICATOR;
229
while (type != ECPGd_EODT)
235
enum ECPGttype vartype;
238
vartype = va_arg(args, enum ECPGttype);
239
var = va_arg(args, void *);
240
varcharsize = va_arg(args, long);
241
arrsize = va_arg(args, long);
242
offset = va_arg(args, long);
246
case (ECPGd_indicator):
247
data_var.ind_type = vartype;
248
data_var.ind_pointer = var;
249
data_var.ind_varcharsize = varcharsize;
250
data_var.ind_arrsize = arrsize;
251
data_var.ind_offset = offset;
252
if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0)
253
data_var.ind_value = *((void **) (data_var.ind_pointer));
255
data_var.ind_value = data_var.ind_pointer;
259
data_var.type = vartype;
260
data_var.pointer = var;
261
data_var.varcharsize = varcharsize;
262
data_var.arrsize = arrsize;
263
data_var.offset = offset;
264
if (data_var.arrsize == 0 || data_var.varcharsize == 0)
265
data_var.value = *((void **) (data_var.pointer));
267
data_var.value = data_var.pointer;
271
if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
274
ECPGlog("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
278
if (!get_int_item(lineno, var, vartype, 1))
283
case ECPGd_key_member:
284
if (!get_int_item(lineno, var, vartype, 0))
290
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
293
ECPGlog("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
296
case ECPGd_precision:
297
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
300
ECPGlog("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
304
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
307
ECPGlog("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
311
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
314
ECPGlog("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
318
if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
321
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType(PQftype(ECPGresult, index)));
325
if (!get_int_item(lineno, var, vartype, ECPGDynamicType_DDT(PQftype(ECPGresult, index))))
328
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType_DDT(PQftype(ECPGresult, index)));
331
case ECPGd_cardinality:
332
if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
335
ECPGlog("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
338
case ECPGd_ret_length:
339
case ECPGd_ret_octet:
342
* this is like ECPGstore_result
344
if (arrsize > 0 && ntuples > arrsize)
346
ECPGlog("ECPGget_desc line %d: Incorrect number of matches: %d don't fit into array of %d\n",
347
lineno, ntuples, arrsize);
348
ECPGraise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
351
/* allocate storage if needed */
352
if (arrsize == 0 && var != NULL && *(void **) var == NULL)
354
void *mem = (void *) ECPGalloc(offset * ntuples, lineno);
356
*(void **) var = mem;
357
ECPGadd_mem(mem, lineno);
361
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
363
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
365
var = (char *) var + offset;
366
ECPGlog("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
371
snprintf(type_str, sizeof(type_str), "%d", type);
372
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
376
type = va_arg(args, enum ECPGdtype);
379
if (data_var.type != ECPGt_EORT)
381
struct statement stmt;
384
/* Make sure we do NOT honor the locale for numeric input */
385
/* since the database gives the standard decimal point */
386
oldlocale = strdup(setlocale(LC_NUMERIC, NULL));
387
setlocale(LC_NUMERIC, "C");
389
memset(&stmt, 0, sizeof stmt);
390
stmt.lineno = lineno;
392
/* desparate try to guess something sensible */
393
stmt.connection = ECPGget_connection(NULL);
394
ECPGstore_result(ECPGresult, index, &stmt, &data_var);
396
setlocale(LC_NUMERIC, oldlocale);
399
else if (data_var.ind_type != ECPGt_NO_INDICATOR)
402
* this is like ECPGstore_result but since we don't have a data
403
* variable at hand, we can't call it
405
if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
407
ECPGlog("ECPGget_desc line %d: Incorrect number of matches (indicator): %d don't fit into array of %d\n",
408
lineno, ntuples, data_var.ind_arrsize);
409
ECPGraise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
412
/* allocate storage if needed */
413
if (data_var.ind_arrsize == 0 && data_var.ind_pointer != NULL && data_var.ind_value == NULL)
415
void *mem = (void *) ECPGalloc(data_var.ind_offset * ntuples, lineno);
417
*(void **) data_var.ind_pointer = mem;
418
ECPGadd_mem(mem, lineno);
419
data_var.ind_value = mem;
421
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
423
if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
425
data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset;
426
ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
429
sqlca->sqlerrd[2] = ntuples;
434
ECPGset_desc_header(int lineno, char *desc_name, int count)
436
struct descriptor *desc;
438
for (desc = all_descriptors; desc; desc = desc->next)
440
if (strcmp(desc_name, desc->name) == 0)
446
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
455
ECPGset_desc(int lineno, char *desc_name, int index,...)
458
struct descriptor *desc;
459
struct descriptor_item *desc_item;
460
struct variable *var;
462
for (desc = all_descriptors; desc; desc = desc->next)
464
if (strcmp(desc_name, desc->name) == 0)
470
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
474
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
476
if (desc_item->num == index)
480
if (desc_item == NULL)
482
desc_item = (struct descriptor_item *) ECPGalloc(sizeof(*desc_item), lineno);
483
desc_item->num = index;
484
desc_item->next = desc->items;
485
desc->items = desc_item;
488
if (!(var = (struct variable *) ECPGalloc(sizeof(struct variable), lineno)))
491
va_start(args, index);
495
enum ECPGdtype itemtype;
497
const char *tobeinserted = NULL;
500
itemtype = va_arg(args, enum ECPGdtype);
502
if (itemtype == ECPGd_EODT)
505
type = va_arg(args, enum ECPGttype);
506
ECPGget_variable(&args, type, var, false);
512
if (!ECPGstore_input(lineno, true, var, &tobeinserted, &malloced))
518
desc_item->data = (char *) tobeinserted;
523
case ECPGd_indicator:
524
set_int_item(lineno, &desc_item->indicator, var->pointer, var->type);
528
set_int_item(lineno, &desc_item->length, var->pointer, var->type);
531
case ECPGd_precision:
532
set_int_item(lineno, &desc_item->precision, var->pointer, var->type);
536
set_int_item(lineno, &desc_item->scale, var->pointer, var->type);
540
set_int_item(lineno, &desc_item->type, var->pointer, var->type);
547
snprintf(type_str, sizeof(type_str), "%d", itemtype);
548
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
555
* if (itemtype == ECPGd_data) { free(desc_item->data);
556
* desc_item->data = NULL; }
566
ECPGdeallocate_desc(int line, const char *name)
568
struct descriptor *i;
569
struct descriptor **lastptr = &all_descriptors;
570
struct sqlca_t *sqlca = ECPGget_sqlca();
572
ECPGinit_sqlca(sqlca);
573
for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
575
if (!strcmp(name, i->name))
584
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
589
ECPGallocate_desc(int line, const char *name)
591
struct descriptor *new;
592
struct sqlca_t *sqlca = ECPGget_sqlca();
594
ECPGinit_sqlca(sqlca);
595
new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
598
new->next = all_descriptors;
599
new->name = ECPGalloc(strlen(name) + 1, line);
607
new->result = PQmakeEmptyPGresult(NULL, 0);
612
ECPGraise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
615
strcpy(new->name, name);
616
all_descriptors = new;
621
ECPGdescriptor_lvalue(int line, const char *descriptor)
623
struct descriptor *i;
625
for (i = all_descriptors; i != NULL; i = i->next)
627
if (!strcmp(descriptor, i->name))
631
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, (char *) descriptor);
636
ECPGdescribe(int line, bool input, const char *statement,...)
638
ECPGlog("ECPGdescribe called on line %d for %s in %s\n", line, (input) ? "input" : "output", statement);