~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/interfaces/ecpg/ecpglib/descriptor.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* dynamic SQL support routines
 
2
 *
 
3
 * $PostgreSQL$
 
4
 */
 
5
 
 
6
#define POSTGRES_ECPG_INTERNAL
 
7
#include "postgres_fe.h"
 
8
#include "pg_type.h"
 
9
 
 
10
#include "ecpg-pthread-win32.h"
 
11
#include "ecpgtype.h"
 
12
#include "ecpglib.h"
 
13
#include "ecpgerrno.h"
 
14
#include "extern.h"
 
15
#include "sqlca.h"
 
16
#include "sql3types.h"
 
17
 
 
18
static void descriptor_free(struct descriptor * desc);
 
19
 
 
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;
 
24
 
 
25
static void descriptor_deallocate_all(struct descriptor * list);
 
26
 
 
27
static void
 
28
descriptor_destructor(void *arg)
 
29
{
 
30
        descriptor_deallocate_all(arg);
 
31
}
 
32
 
 
33
static void
 
34
descriptor_key_init(void)
 
35
{
 
36
        pthread_key_create(&descriptor_key, descriptor_destructor);
 
37
}
 
38
 
 
39
static struct descriptor *
 
40
get_descriptors(void)
 
41
{
 
42
        pthread_once(&descriptor_once, descriptor_key_init);
 
43
        return (struct descriptor *) pthread_getspecific(descriptor_key);
 
44
}
 
45
 
 
46
static void
 
47
set_descriptors(struct descriptor * value)
 
48
{
 
49
        pthread_setspecific(descriptor_key, value);
 
50
}
 
51
#else
 
52
static struct descriptor *all_descriptors = NULL;
 
53
 
 
54
#define get_descriptors()               (all_descriptors)
 
55
#define set_descriptors(value)  do { all_descriptors = (value); } while(0)
 
56
#endif
 
57
 
 
58
/* old internal convenience function that might go away later */
 
59
static PGresult *
 
60
ecpg_result_by_descriptor(int line, const char *name)
 
61
{
 
62
        struct descriptor *desc = ecpg_find_desc(line, name);
 
63
 
 
64
        if (desc == NULL)
 
65
                return NULL;
 
66
        return desc->result;
 
67
}
 
68
 
 
69
static unsigned int
 
70
ecpg_dynamic_type_DDT(Oid type)
 
71
{
 
72
        switch (type)
 
73
        {
 
74
                case DATEOID:
 
75
                        return SQL3_DDT_DATE;
 
76
                case TIMEOID:
 
77
                        return SQL3_DDT_TIME;
 
78
                case TIMESTAMPOID:
 
79
                        return SQL3_DDT_TIMESTAMP;
 
80
                case TIMESTAMPTZOID:
 
81
                        return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
 
82
                case TIMETZOID:
 
83
                        return SQL3_DDT_TIME_WITH_TIME_ZONE;
 
84
                default:
 
85
                        return SQL3_DDT_ILLEGAL;
 
86
        }
 
87
}
 
88
 
 
89
bool
 
90
ECPGget_desc_header(int lineno, const char *desc_name, int *count)
 
91
{
 
92
        PGresult   *ECPGresult;
 
93
        struct sqlca_t *sqlca = ECPGget_sqlca();
 
94
 
 
95
        ecpg_init_sqlca(sqlca);
 
96
        ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
 
97
        if (!ECPGresult)
 
98
                return false;
 
99
 
 
100
        *count = PQnfields(ECPGresult);
 
101
        sqlca->sqlerrd[2] = 1;
 
102
        ecpg_log("ECPGget_desc_header: found %d attributes\n", *count);
 
103
        return true;
 
104
}
 
105
 
 
106
static bool
 
107
get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
 
108
{
 
109
        switch (vartype)
 
110
        {
 
111
                case ECPGt_short:
 
112
                        *(short *) var = (short) value;
 
113
                        break;
 
114
                case ECPGt_int:
 
115
                        *(int *) var = (int) value;
 
116
                        break;
 
117
                case ECPGt_long:
 
118
                        *(long *) var = (long) value;
 
119
                        break;
 
120
                case ECPGt_unsigned_short:
 
121
                        *(unsigned short *) var = (unsigned short) value;
 
122
                        break;
 
123
                case ECPGt_unsigned_int:
 
124
                        *(unsigned int *) var = (unsigned int) value;
 
125
                        break;
 
126
                case ECPGt_unsigned_long:
 
127
                        *(unsigned long *) var = (unsigned long) value;
 
128
                        break;
 
129
#ifdef HAVE_LONG_LONG_INT_64
 
130
                case ECPGt_long_long:
 
131
                        *(long long int *) var = (long long int) value;
 
132
                        break;
 
133
                case ECPGt_unsigned_long_long:
 
134
                        *(unsigned long long int *) var = (unsigned long long int) value;
 
135
                        break;
 
136
#endif   /* HAVE_LONG_LONG_INT_64 */
 
137
                case ECPGt_float:
 
138
                        *(float *) var = (float) value;
 
139
                        break;
 
140
                case ECPGt_double:
 
141
                        *(double *) var = (double) value;
 
142
                        break;
 
143
                default:
 
144
                        ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
 
145
                        return (false);
 
146
        }
 
147
 
 
148
        return (true);
 
149
}
 
150
 
 
151
static bool
 
152
set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
 
153
{
 
154
        switch (vartype)
 
155
        {
 
156
                case ECPGt_short:
 
157
                        *target = *(short *) var;
 
158
                        break;
 
159
                case ECPGt_int:
 
160
                        *target = *(int *) var;
 
161
                        break;
 
162
                case ECPGt_long:
 
163
                        *target = *(long *) var;
 
164
                        break;
 
165
                case ECPGt_unsigned_short:
 
166
                        *target = *(unsigned short *) var;
 
167
                        break;
 
168
                case ECPGt_unsigned_int:
 
169
                        *target = *(unsigned int *) var;
 
170
                        break;
 
171
                case ECPGt_unsigned_long:
 
172
                        *target = *(unsigned long *) var;
 
173
                        break;
 
174
#ifdef HAVE_LONG_LONG_INT_64
 
175
                case ECPGt_long_long:
 
176
                        *target = *(long long int *) var;
 
177
                        break;
 
178
                case ECPGt_unsigned_long_long:
 
179
                        *target = *(unsigned long long int *) var;
 
180
                        break;
 
181
#endif   /* HAVE_LONG_LONG_INT_64 */
 
182
                case ECPGt_float:
 
183
                        *target = *(float *) var;
 
184
                        break;
 
185
                case ECPGt_double:
 
186
                        *target = *(double *) var;
 
187
                        break;
 
188
                default:
 
189
                        ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
 
190
                        return (false);
 
191
        }
 
192
 
 
193
        return true;
 
194
}
 
195
 
 
196
static bool
 
197
get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
 
198
{
 
199
        switch (vartype)
 
200
        {
 
201
                case ECPGt_char:
 
202
                case ECPGt_unsigned_char:
 
203
                        strncpy((char *) var, value, varcharsize);
 
204
                        break;
 
205
                case ECPGt_varchar:
 
206
                        {
 
207
                                struct ECPGgeneric_varchar *variable =
 
208
                                (struct ECPGgeneric_varchar *) var;
 
209
 
 
210
                                if (varcharsize == 0)
 
211
                                        strncpy(variable->arr, value, strlen(value));
 
212
                                else
 
213
                                        strncpy(variable->arr, value, varcharsize);
 
214
 
 
215
                                variable->len = strlen(value);
 
216
                                if (varcharsize > 0 && variable->len > varcharsize)
 
217
                                        variable->len = varcharsize;
 
218
                        }
 
219
                        break;
 
220
                default:
 
221
                        ecpg_raise(lineno, ECPG_VAR_NOT_CHAR, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
 
222
                        return (false);
 
223
        }
 
224
 
 
225
        return (true);
 
226
}
 
227
 
 
228
bool
 
229
ECPGget_desc(int lineno, const char *desc_name, int index,...)
 
230
{
 
231
        va_list         args;
 
232
        PGresult   *ECPGresult;
 
233
        enum ECPGdtype type;
 
234
        int                     ntuples,
 
235
                                act_tuple;
 
236
        struct variable data_var;
 
237
        struct sqlca_t *sqlca = ECPGget_sqlca();
 
238
 
 
239
        va_start(args, index);
 
240
        ecpg_init_sqlca(sqlca);
 
241
        ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
 
242
        if (!ECPGresult)
 
243
                return (false);
 
244
 
 
245
        ntuples = PQntuples(ECPGresult);
 
246
        if (ntuples < 1)
 
247
        {
 
248
                ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
 
249
                return (false);
 
250
        }
 
251
 
 
252
        if (index < 1 || index > PQnfields(ECPGresult))
 
253
        {
 
254
                ecpg_raise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX, NULL);
 
255
                return (false);
 
256
        }
 
257
 
 
258
        ecpg_log("ECPGget_desc: reading items for tuple %d\n", index);
 
259
        --index;
 
260
 
 
261
        type = va_arg(args, enum ECPGdtype);
 
262
 
 
263
        memset(&data_var, 0, sizeof data_var);
 
264
        data_var.type = ECPGt_EORT;
 
265
        data_var.ind_type = ECPGt_NO_INDICATOR;
 
266
 
 
267
        while (type != ECPGd_EODT)
 
268
        {
 
269
                char            type_str[20];
 
270
                long            varcharsize;
 
271
                long            offset;
 
272
                long            arrsize;
 
273
                enum ECPGttype vartype;
 
274
                void       *var;
 
275
 
 
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);
 
281
 
 
282
                switch (type)
 
283
                {
 
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));
 
292
                                else
 
293
                                        data_var.ind_value = data_var.ind_pointer;
 
294
                                break;
 
295
 
 
296
                        case ECPGd_data:
 
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));
 
304
                                else
 
305
                                        data_var.value = data_var.pointer;
 
306
                                break;
 
307
 
 
308
                        case ECPGd_name:
 
309
                                if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
 
310
                                        return (false);
 
311
 
 
312
                                ecpg_log("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
 
313
                                break;
 
314
 
 
315
                        case ECPGd_nullable:
 
316
                                if (!get_int_item(lineno, var, vartype, 1))
 
317
                                        return (false);
 
318
 
 
319
                                break;
 
320
 
 
321
                        case ECPGd_key_member:
 
322
                                if (!get_int_item(lineno, var, vartype, 0))
 
323
                                        return (false);
 
324
 
 
325
                                break;
 
326
 
 
327
                        case ECPGd_scale:
 
328
                                if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
 
329
                                        return (false);
 
330
 
 
331
                                ecpg_log("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
 
332
                                break;
 
333
 
 
334
                        case ECPGd_precision:
 
335
                                if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
 
336
                                        return (false);
 
337
 
 
338
                                ecpg_log("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
 
339
                                break;
 
340
 
 
341
                        case ECPGd_octet:
 
342
                                if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
 
343
                                        return (false);
 
344
 
 
345
                                ecpg_log("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
 
346
                                break;
 
347
 
 
348
                        case ECPGd_length:
 
349
                                if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
 
350
                                        return (false);
 
351
 
 
352
                                ecpg_log("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
 
353
                                break;
 
354
 
 
355
                        case ECPGd_type:
 
356
                                if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type(PQftype(ECPGresult, index))))
 
357
                                        return (false);
 
358
 
 
359
                                ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type(PQftype(ECPGresult, index)));
 
360
                                break;
 
361
 
 
362
                        case ECPGd_di_code:
 
363
                                if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type_DDT(PQftype(ECPGresult, index))))
 
364
                                        return (false);
 
365
 
 
366
                                ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type_DDT(PQftype(ECPGresult, index)));
 
367
                                break;
 
368
 
 
369
                        case ECPGd_cardinality:
 
370
                                if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
 
371
                                        return (false);
 
372
 
 
373
                                ecpg_log("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
 
374
                                break;
 
375
 
 
376
                        case ECPGd_ret_length:
 
377
                        case ECPGd_ret_octet:
 
378
 
 
379
                                /*
 
380
                                 * this is like ECPGstore_result
 
381
                                 */
 
382
                                if (arrsize > 0 && ntuples > arrsize)
 
383
                                {
 
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);
 
387
                                        return false;
 
388
                                }
 
389
                                /* allocate storage if needed */
 
390
                                if (arrsize == 0 && *(void **) var == NULL)
 
391
                                {
 
392
                                        void       *mem = (void *) ecpg_alloc(offset * ntuples, lineno);
 
393
 
 
394
                                        if (!mem)
 
395
                                                return false;
 
396
                                        *(void **) var = mem;
 
397
                                        ecpg_add_mem(mem, lineno);
 
398
                                        var = mem;
 
399
                                }
 
400
 
 
401
                                for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
 
402
                                {
 
403
                                        if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
 
404
                                                return (false);
 
405
                                        var = (char *) var + offset;
 
406
                                        ecpg_log("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
 
407
                                }
 
408
                                break;
 
409
 
 
410
                        default:
 
411
                                snprintf(type_str, sizeof(type_str), "%d", type);
 
412
                                ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
 
413
                                return (false);
 
414
                }
 
415
 
 
416
                type = va_arg(args, enum ECPGdtype);
 
417
        }
 
418
 
 
419
        if (data_var.type != ECPGt_EORT)
 
420
        {
 
421
                struct statement stmt;
 
422
                char       *oldlocale;
 
423
 
 
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");
 
428
 
 
429
                memset(&stmt, 0, sizeof stmt);
 
430
                stmt.lineno = lineno;
 
431
 
 
432
                /* desparate try to guess something sensible */
 
433
                stmt.connection = ecpg_get_connection(NULL);
 
434
                ecpg_store_result(ECPGresult, index, &stmt, &data_var);
 
435
 
 
436
                setlocale(LC_NUMERIC, oldlocale);
 
437
                ecpg_free(oldlocale);
 
438
        }
 
439
        else if (data_var.ind_type != ECPGt_NO_INDICATOR && data_var.ind_pointer != NULL)
 
440
 
 
441
                /*
 
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
 
444
                 * safe
 
445
                 */
 
446
        {
 
447
                /*
 
448
                 * this is like ECPGstore_result but since we don't have a data
 
449
                 * variable at hand, we can't call it
 
450
                 */
 
451
                if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
 
452
                {
 
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);
 
456
                        return false;
 
457
                }
 
458
 
 
459
                /* allocate storage if needed */
 
460
                if (data_var.ind_arrsize == 0 && data_var.ind_value == NULL)
 
461
                {
 
462
                        void       *mem = (void *) ecpg_alloc(data_var.ind_offset * ntuples, lineno);
 
463
 
 
464
                        if (!mem)
 
465
                                return false;
 
466
                        *(void **) data_var.ind_pointer = mem;
 
467
                        ecpg_add_mem(mem, lineno);
 
468
                        data_var.ind_value = mem;
 
469
                }
 
470
 
 
471
                for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
 
472
                {
 
473
                        if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
 
474
                                return (false);
 
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));
 
477
                }
 
478
        }
 
479
        sqlca->sqlerrd[2] = ntuples;
 
480
        return (true);
 
481
}
 
482
 
 
483
bool
 
484
ECPGset_desc_header(int lineno, const char *desc_name, int count)
 
485
{
 
486
        struct descriptor *desc = ecpg_find_desc(lineno, desc_name);
 
487
 
 
488
        if (desc == NULL)
 
489
                return false;
 
490
        desc->count = count;
 
491
        return true;
 
492
}
 
493
 
 
494
bool
 
495
ECPGset_desc(int lineno, const char *desc_name, int index,...)
 
496
{
 
497
        va_list         args;
 
498
        struct descriptor *desc;
 
499
        struct descriptor_item *desc_item;
 
500
        struct variable *var;
 
501
 
 
502
        desc = ecpg_find_desc(lineno, desc_name);
 
503
        if (desc == NULL)
 
504
                return false;
 
505
 
 
506
        for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
 
507
        {
 
508
                if (desc_item->num == index)
 
509
                        break;
 
510
        }
 
511
 
 
512
        if (desc_item == NULL)
 
513
        {
 
514
                desc_item = (struct descriptor_item *) ecpg_alloc(sizeof(*desc_item), lineno);
 
515
                if (!desc_item)
 
516
                        return false;
 
517
                desc_item->num = index;
 
518
                if (desc->count < index)
 
519
                        desc->count = index;
 
520
                desc_item->next = desc->items;
 
521
                desc->items = desc_item;
 
522
        }
 
523
 
 
524
        if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
 
525
                return false;
 
526
 
 
527
        va_start(args, index);
 
528
 
 
529
        for (;;)
 
530
        {
 
531
                enum ECPGdtype itemtype;
 
532
                char *tobeinserted = NULL;
 
533
 
 
534
                itemtype = va_arg(args, enum ECPGdtype);
 
535
 
 
536
                if (itemtype == ECPGd_EODT)
 
537
                        break;
 
538
 
 
539
                var->type = va_arg(args, enum ECPGttype);
 
540
                var->pointer = va_arg(args, char *);
 
541
 
 
542
                var->varcharsize = va_arg(args, long);
 
543
                var->arrsize = va_arg(args, long);
 
544
                var->offset = va_arg(args, long);
 
545
 
 
546
                if (var->arrsize == 0 || var->varcharsize == 0)
 
547
                        var->value = *((char **) (var->pointer));
 
548
                else
 
549
                        var->value = var->pointer;
 
550
 
 
551
                /*
 
552
                 * negative values are used to indicate an array without given bounds
 
553
                 */
 
554
                /* reset to zero for us */
 
555
                if (var->arrsize < 0)
 
556
                        var->arrsize = 0;
 
557
                if (var->varcharsize < 0)
 
558
                        var->varcharsize = 0;
 
559
 
 
560
                var->next = NULL;
 
561
 
 
562
                switch (itemtype)
 
563
                {
 
564
                        case ECPGd_data:
 
565
                                {
 
566
                                        if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
 
567
                                        {
 
568
                                                ecpg_free(var);
 
569
                                                return false;
 
570
                                        }
 
571
 
 
572
                                        ecpg_free(desc_item->data); /* free() takes care of a
 
573
                                                                                                 * potential NULL value */
 
574
                                        desc_item->data = (char *) tobeinserted;
 
575
                                        tobeinserted = NULL;
 
576
                                        break;
 
577
                                }
 
578
 
 
579
                        case ECPGd_indicator:
 
580
                                set_int_item(lineno, &desc_item->indicator, var->pointer, var->type);
 
581
                                break;
 
582
 
 
583
                        case ECPGd_length:
 
584
                                set_int_item(lineno, &desc_item->length, var->pointer, var->type);
 
585
                                break;
 
586
 
 
587
                        case ECPGd_precision:
 
588
                                set_int_item(lineno, &desc_item->precision, var->pointer, var->type);
 
589
                                break;
 
590
 
 
591
                        case ECPGd_scale:
 
592
                                set_int_item(lineno, &desc_item->scale, var->pointer, var->type);
 
593
                                break;
 
594
 
 
595
                        case ECPGd_type:
 
596
                                set_int_item(lineno, &desc_item->type, var->pointer, var->type);
 
597
                                break;
 
598
 
 
599
                        default:
 
600
                                {
 
601
                                        char            type_str[20];
 
602
 
 
603
                                        snprintf(type_str, sizeof(type_str), "%d", itemtype);
 
604
                                        ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
 
605
                                        ecpg_free(var);
 
606
                                        return false;
 
607
                                }
 
608
                }
 
609
        }
 
610
        ecpg_free(var);
 
611
 
 
612
        return true;
 
613
}
 
614
 
 
615
/* Free the descriptor and items in it. */
 
616
static void
 
617
descriptor_free(struct descriptor * desc)
 
618
{
 
619
        struct descriptor_item *desc_item;
 
620
 
 
621
        for (desc_item = desc->items; desc_item;)
 
622
        {
 
623
                struct descriptor_item *di;
 
624
 
 
625
                ecpg_free(desc_item->data);
 
626
                di = desc_item;
 
627
                desc_item = desc_item->next;
 
628
                ecpg_free(di);
 
629
        }
 
630
 
 
631
        ecpg_free(desc->name);
 
632
        PQclear(desc->result);
 
633
        ecpg_free(desc);
 
634
}
 
635
 
 
636
bool
 
637
ECPGdeallocate_desc(int line, const char *name)
 
638
{
 
639
        struct descriptor *desc;
 
640
        struct descriptor *prev;
 
641
        struct sqlca_t *sqlca = ECPGget_sqlca();
 
642
 
 
643
        ecpg_init_sqlca(sqlca);
 
644
        for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
 
645
        {
 
646
                if (!strcmp(name, desc->name))
 
647
                {
 
648
                        if (prev)
 
649
                                prev->next = desc->next;
 
650
                        else
 
651
                                set_descriptors(desc->next);
 
652
                        descriptor_free(desc);
 
653
                        return true;
 
654
                }
 
655
        }
 
656
        ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
 
657
        return false;
 
658
}
 
659
 
 
660
#ifdef ENABLE_THREAD_SAFETY
 
661
 
 
662
/* Deallocate all descriptors in the list */
 
663
static void
 
664
descriptor_deallocate_all(struct descriptor * list)
 
665
{
 
666
        while (list)
 
667
        {
 
668
                struct descriptor *next = list->next;
 
669
 
 
670
                descriptor_free(list);
 
671
                list = next;
 
672
        }
 
673
}
 
674
#endif   /* ENABLE_THREAD_SAFETY */
 
675
 
 
676
bool
 
677
ECPGallocate_desc(int line, const char *name)
 
678
{
 
679
        struct descriptor *new;
 
680
        struct sqlca_t *sqlca = ECPGget_sqlca();
 
681
 
 
682
        ecpg_init_sqlca(sqlca);
 
683
        new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
 
684
        if (!new)
 
685
                return false;
 
686
        new->next = get_descriptors();
 
687
        new->name = ecpg_alloc(strlen(name) + 1, line);
 
688
        if (!new->name)
 
689
        {
 
690
                ecpg_free(new);
 
691
                return false;
 
692
        }
 
693
        new->count = -1;
 
694
        new->items = NULL;
 
695
        new->result = PQmakeEmptyPGresult(NULL, 0);
 
696
        if (!new->result)
 
697
        {
 
698
                ecpg_free(new->name);
 
699
                ecpg_free(new);
 
700
                ecpg_raise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
 
701
                return false;
 
702
        }
 
703
        strcpy(new->name, name);
 
704
        set_descriptors(new);
 
705
        return true;
 
706
}
 
707
 
 
708
/* Find descriptor with name in the connection. */
 
709
struct descriptor *
 
710
ecpg_find_desc(int line, const char *name)
 
711
{
 
712
        struct descriptor *desc;
 
713
 
 
714
        for (desc = get_descriptors(); desc; desc = desc->next)
 
715
        {
 
716
                if (strcmp(name, desc->name) == 0)
 
717
                        return desc;
 
718
        }
 
719
 
 
720
        ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
 
721
        return NULL;                            /* not found */
 
722
}
 
723
 
 
724
bool
 
725
ECPGdescribe(int line, bool input, const char *statement,...)
 
726
{
 
727
        ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line, input ? "input" : "output", statement);
 
728
        return false;
 
729
}