Age Owner Branch data TLA Line data Source code
1 : : /* dynamic SQL support routines
2 : : *
3 : : * src/interfaces/ecpg/ecpglib/descriptor.c
4 : : */
5 : :
6 : : #define POSTGRES_ECPG_INTERNAL
7 : : #include "postgres_fe.h"
8 : :
9 : : #include "catalog/pg_type_d.h"
10 : : #include "ecpg-pthread-win32.h"
11 : : #include "ecpgerrno.h"
12 : : #include "ecpglib.h"
13 : : #include "ecpglib_extern.h"
14 : : #include "ecpgtype.h"
15 : : #include "sql3types.h"
16 : : #include "sqlca.h"
17 : : #include "sqlda.h"
18 : :
19 : : static void descriptor_free(struct descriptor *desc);
20 : :
21 : : /* We manage descriptors separately for each thread. */
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
6039 meskes@postgresql.or 28 :UBC 0 : descriptor_destructor(void *arg)
29 : : {
30 : 0 : descriptor_deallocate_all(arg);
31 : 0 : }
32 : :
33 : : static void
6039 meskes@postgresql.or 34 :CBC 9 : descriptor_key_init(void)
35 : : {
36 : 9 : pthread_key_create(&descriptor_key, descriptor_destructor);
37 : 9 : }
38 : :
39 : : static struct descriptor *
40 : 1600146 : get_descriptors(void)
41 : : {
42 : 1600146 : pthread_once(&descriptor_once, descriptor_key_init);
43 : 1600146 : return (struct descriptor *) pthread_getspecific(descriptor_key);
44 : : }
45 : :
46 : : static void
2489 tgl@sss.pgh.pa.us 47 : 1600027 : set_descriptors(struct descriptor *value)
48 : : {
6039 meskes@postgresql.or 49 : 1600027 : pthread_setspecific(descriptor_key, value);
50 : 1600027 : }
51 : :
52 : : /* old internal convenience function that might go away later */
53 : : static PGresult *
6038 54 : 73 : ecpg_result_by_descriptor(int line, const char *name)
55 : : {
56 : 73 : struct descriptor *desc = ecpg_find_desc(line, name);
57 : :
6039 58 [ - + ]: 73 : if (desc == NULL)
6039 meskes@postgresql.or 59 :UBC 0 : return NULL;
6039 meskes@postgresql.or 60 :CBC 73 : return desc->result;
61 : : }
62 : :
63 : : static unsigned int
6038 64 : 8 : ecpg_dynamic_type_DDT(Oid type)
65 : : {
7700 66 [ + - - - : 8 : switch (type)
- - ]
67 : : {
68 : 8 : case DATEOID:
69 : 8 : return SQL3_DDT_DATE;
7700 meskes@postgresql.or 70 :UBC 0 : case TIMEOID:
71 : 0 : return SQL3_DDT_TIME;
72 : 0 : case TIMESTAMPOID:
73 : 0 : return SQL3_DDT_TIMESTAMP;
74 : 0 : case TIMESTAMPTZOID:
75 : 0 : return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
76 : 0 : case TIMETZOID:
77 : 0 : return SQL3_DDT_TIME_WITH_TIME_ZONE;
78 : 0 : default:
79 : 0 : return SQL3_DDT_ILLEGAL;
80 : : }
81 : : }
82 : :
83 : : bool
6710 meskes@postgresql.or 84 :CBC 12 : ECPGget_desc_header(int lineno, const char *desc_name, int *count)
85 : : {
86 : : PGresult *ECPGresult;
7609 bruce@momjian.us 87 : 12 : struct sqlca_t *sqlca = ECPGget_sqlca();
88 : :
3226 meskes@postgresql.or 89 [ - + ]: 12 : if (sqlca == NULL)
90 : : {
3226 meskes@postgresql.or 91 :UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
92 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
93 : 0 : return false;
94 : : }
95 : :
6038 meskes@postgresql.or 96 :CBC 12 : ecpg_init_sqlca(sqlca);
97 : 12 : ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
7700 98 [ - + ]: 12 : if (!ECPGresult)
7700 meskes@postgresql.or 99 :UBC 0 : return false;
100 : :
7700 meskes@postgresql.or 101 :CBC 12 : *count = PQnfields(ECPGresult);
7609 bruce@momjian.us 102 : 12 : sqlca->sqlerrd[2] = 1;
5812 peter_e@gmx.net 103 : 12 : ecpg_log("ECPGget_desc_header: found %d attributes\n", *count);
7700 meskes@postgresql.or 104 : 12 : return true;
105 : : }
106 : :
107 : : static bool
108 : 103 : get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
109 : : {
110 [ - + - - : 103 : switch (vartype)
- - - - -
- - ]
111 : : {
7700 meskes@postgresql.or 112 :UBC 0 : case ECPGt_short:
113 : 0 : *(short *) var = (short) value;
114 : 0 : break;
7700 meskes@postgresql.or 115 :CBC 103 : case ECPGt_int:
116 : 103 : *(int *) var = (int) value;
117 : 103 : break;
7700 meskes@postgresql.or 118 :UBC 0 : case ECPGt_long:
119 : 0 : *(long *) var = (long) value;
120 : 0 : break;
121 : 0 : case ECPGt_unsigned_short:
122 : 0 : *(unsigned short *) var = (unsigned short) value;
123 : 0 : break;
124 : 0 : case ECPGt_unsigned_int:
125 : 0 : *(unsigned int *) var = (unsigned int) value;
126 : 0 : break;
127 : 0 : case ECPGt_unsigned_long:
128 : 0 : *(unsigned long *) var = (unsigned long) value;
129 : 0 : break;
130 : 0 : case ECPGt_long_long:
131 : 0 : *(long long int *) var = (long long int) value;
132 : 0 : break;
133 : 0 : case ECPGt_unsigned_long_long:
134 : 0 : *(unsigned long long int *) var = (unsigned long long int) value;
135 : 0 : break;
136 : 0 : case ECPGt_float:
137 : 0 : *(float *) var = (float) value;
138 : 0 : break;
139 : 0 : case ECPGt_double:
140 : 0 : *(double *) var = (double) value;
141 : 0 : break;
142 : 0 : default:
6038 143 : 0 : ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
2432 peter_e@gmx.net 144 : 0 : return false;
145 : : }
146 : :
2432 peter_e@gmx.net 147 :CBC 103 : return true;
148 : : }
149 : :
150 : : static bool
7228 meskes@postgresql.or 151 : 4 : set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
152 : : {
153 [ - + - - : 4 : switch (vartype)
- - - - -
- - ]
154 : : {
7228 meskes@postgresql.or 155 :UBC 0 : case ECPGt_short:
4599 peter_e@gmx.net 156 : 0 : *target = *(const short *) var;
7228 meskes@postgresql.or 157 : 0 : break;
7228 meskes@postgresql.or 158 :CBC 4 : case ECPGt_int:
4599 peter_e@gmx.net 159 : 4 : *target = *(const int *) var;
7228 meskes@postgresql.or 160 : 4 : break;
7228 meskes@postgresql.or 161 :UBC 0 : case ECPGt_long:
4599 peter_e@gmx.net 162 : 0 : *target = *(const long *) var;
7228 meskes@postgresql.or 163 : 0 : break;
164 : 0 : case ECPGt_unsigned_short:
4599 peter_e@gmx.net 165 : 0 : *target = *(const unsigned short *) var;
7228 meskes@postgresql.or 166 : 0 : break;
167 : 0 : case ECPGt_unsigned_int:
4599 peter_e@gmx.net 168 : 0 : *target = *(const unsigned int *) var;
7228 meskes@postgresql.or 169 : 0 : break;
170 : 0 : case ECPGt_unsigned_long:
4599 peter_e@gmx.net 171 : 0 : *target = *(const unsigned long *) var;
7228 meskes@postgresql.or 172 : 0 : break;
173 : 0 : case ECPGt_long_long:
4599 peter_e@gmx.net 174 : 0 : *target = *(const long long int *) var;
7228 meskes@postgresql.or 175 : 0 : break;
176 : 0 : case ECPGt_unsigned_long_long:
4599 peter_e@gmx.net 177 : 0 : *target = *(const unsigned long long int *) var;
7228 meskes@postgresql.or 178 : 0 : break;
179 : 0 : case ECPGt_float:
4599 peter_e@gmx.net 180 : 0 : *target = *(const float *) var;
7228 meskes@postgresql.or 181 : 0 : break;
182 : 0 : case ECPGt_double:
4599 peter_e@gmx.net 183 : 0 : *target = *(const double *) var;
7228 meskes@postgresql.or 184 : 0 : break;
185 : 0 : default:
6038 186 : 0 : ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
2432 peter_e@gmx.net 187 : 0 : return false;
188 : : }
189 : :
7228 meskes@postgresql.or 190 :CBC 4 : return true;
191 : : }
192 : :
193 : : static bool
7700 194 : 30 : get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
195 : : {
196 [ + - - ]: 30 : switch (vartype)
197 : : {
198 : 30 : case ECPGt_char:
199 : : case ECPGt_unsigned_char:
200 : : case ECPGt_string:
201 : 30 : strncpy((char *) var, value, varcharsize);
202 : 30 : break;
7700 meskes@postgresql.or 203 :UBC 0 : case ECPGt_varchar:
204 : : {
205 : 0 : struct ECPGgeneric_varchar *variable =
206 : : (struct ECPGgeneric_varchar *) var;
207 : :
208 [ # # ]: 0 : if (varcharsize == 0)
2129 tgl@sss.pgh.pa.us 209 : 0 : memcpy(variable->arr, value, strlen(value));
210 : : else
7700 meskes@postgresql.or 211 : 0 : strncpy(variable->arr, value, varcharsize);
212 : :
213 : 0 : variable->len = strlen(value);
214 [ # # # # ]: 0 : if (varcharsize > 0 && variable->len > varcharsize)
215 : 0 : variable->len = varcharsize;
216 : : }
217 : 0 : break;
218 : 0 : default:
6038 219 : 0 : ecpg_raise(lineno, ECPG_VAR_NOT_CHAR, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
2432 peter_e@gmx.net 220 : 0 : return false;
221 : : }
222 : :
2432 peter_e@gmx.net 223 :CBC 30 : return true;
224 : : }
225 : :
226 : : #define RETURN_IF_NO_DATA if (ntuples < 1) \
227 : : { \
228 : : va_end(args); \
229 : : ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); \
230 : : return false; \
231 : : }
232 : :
233 : : bool
6710 meskes@postgresql.or 234 : 61 : ECPGget_desc(int lineno, const char *desc_name, int index,...)
235 : : {
236 : : va_list args;
237 : : PGresult *ECPGresult;
238 : : enum ECPGdtype type;
239 : : int ntuples,
240 : : act_tuple;
241 : : struct variable data_var;
7609 bruce@momjian.us 242 : 61 : struct sqlca_t *sqlca = ECPGget_sqlca();
243 : :
3226 meskes@postgresql.or 244 [ - + ]: 61 : if (sqlca == NULL)
245 : : {
3226 meskes@postgresql.or 246 :UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
247 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
248 : 0 : return false;
249 : : }
250 : :
7700 meskes@postgresql.or 251 :CBC 61 : va_start(args, index);
6038 252 : 61 : ecpg_init_sqlca(sqlca);
253 : 61 : ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
7700 254 [ - + ]: 61 : if (!ECPGresult)
255 : : {
4414 peter_e@gmx.net 256 :UBC 0 : va_end(args);
2432 257 : 0 : return false;
258 : : }
259 : :
7700 meskes@postgresql.or 260 :CBC 61 : ntuples = PQntuples(ECPGresult);
261 : :
262 [ + - - + ]: 61 : if (index < 1 || index > PQnfields(ECPGresult))
263 : : {
6038 meskes@postgresql.or 264 :UBC 0 : ecpg_raise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX, NULL);
4414 peter_e@gmx.net 265 : 0 : va_end(args);
2432 266 : 0 : return false;
267 : : }
268 : :
6038 meskes@postgresql.or 269 :CBC 61 : ecpg_log("ECPGget_desc: reading items for tuple %d\n", index);
7700 270 : 61 : --index;
271 : :
272 : 61 : type = va_arg(args, enum ECPGdtype);
273 : :
274 : 61 : memset(&data_var, 0, sizeof data_var);
275 : 61 : data_var.type = ECPGt_EORT;
276 : 61 : data_var.ind_type = ECPGt_NO_INDICATOR;
277 : :
278 [ + + ]: 234 : while (type != ECPGd_EODT)
279 : : {
280 : : char type_str[20];
281 : : long varcharsize;
282 : : long offset;
283 : : long arrsize;
284 : : enum ECPGttype vartype;
285 : : void *var;
286 : :
287 : 173 : vartype = va_arg(args, enum ECPGttype);
288 : 173 : var = va_arg(args, void *);
289 : 173 : varcharsize = va_arg(args, long);
290 : 173 : arrsize = va_arg(args, long);
291 : 173 : offset = va_arg(args, long);
292 : :
293 [ + + + - : 173 : switch (type)
- + + + +
+ + - +
- ]
294 : : {
295 : 26 : case (ECPGd_indicator):
5203 296 [ - + ]: 26 : RETURN_IF_NO_DATA;
7700 297 : 26 : data_var.ind_type = vartype;
298 : 26 : data_var.ind_pointer = var;
299 : 26 : data_var.ind_varcharsize = varcharsize;
300 : 26 : data_var.ind_arrsize = arrsize;
301 : 26 : data_var.ind_offset = offset;
6463 302 [ + + - + ]: 26 : if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0)
7700 303 : 10 : data_var.ind_value = *((void **) (data_var.ind_pointer));
304 : : else
305 : 16 : data_var.ind_value = data_var.ind_pointer;
306 : 26 : break;
307 : :
308 : 28 : case ECPGd_data:
5203 309 [ - + ]: 28 : RETURN_IF_NO_DATA;
7700 310 : 28 : data_var.type = vartype;
311 : 28 : data_var.pointer = var;
312 : 28 : data_var.varcharsize = varcharsize;
313 : 28 : data_var.arrsize = arrsize;
314 : 28 : data_var.offset = offset;
315 [ + + - + ]: 28 : if (data_var.arrsize == 0 || data_var.varcharsize == 0)
316 : 10 : data_var.value = *((void **) (data_var.pointer));
317 : : else
318 : 18 : data_var.value = data_var.pointer;
319 : 28 : break;
320 : :
321 : 30 : case ECPGd_name:
322 [ - + ]: 30 : if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
323 : : {
4414 peter_e@gmx.net 324 :UBC 0 : va_end(args);
2432 325 : 0 : return false;
326 : : }
327 : :
6038 meskes@postgresql.or 328 :CBC 30 : ecpg_log("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
7700 329 : 30 : break;
330 : :
7700 meskes@postgresql.or 331 :UBC 0 : case ECPGd_nullable:
332 [ # # ]: 0 : if (!get_int_item(lineno, var, vartype, 1))
333 : : {
4414 peter_e@gmx.net 334 : 0 : va_end(args);
2432 335 : 0 : return false;
336 : : }
337 : :
7700 meskes@postgresql.or 338 : 0 : break;
339 : :
340 : 0 : case ECPGd_key_member:
341 [ # # ]: 0 : if (!get_int_item(lineno, var, vartype, 0))
342 : : {
4414 peter_e@gmx.net 343 : 0 : va_end(args);
2432 344 : 0 : return false;
345 : : }
346 : :
7700 meskes@postgresql.or 347 : 0 : break;
348 : :
7700 meskes@postgresql.or 349 :CBC 14 : case ECPGd_scale:
350 [ - + ]: 14 : if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
351 : : {
4414 peter_e@gmx.net 352 :UBC 0 : va_end(args);
2432 353 : 0 : return false;
354 : : }
355 : :
6038 meskes@postgresql.or 356 :CBC 14 : ecpg_log("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
7700 357 : 14 : break;
358 : :
359 : 14 : case ECPGd_precision:
360 [ - + ]: 14 : if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
361 : : {
4414 peter_e@gmx.net 362 :UBC 0 : va_end(args);
2432 363 : 0 : return false;
364 : : }
365 : :
6038 meskes@postgresql.or 366 :CBC 14 : ecpg_log("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
7700 367 : 14 : break;
368 : :
369 : 14 : case ECPGd_octet:
370 [ - + ]: 14 : if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
371 : : {
4414 peter_e@gmx.net 372 :UBC 0 : va_end(args);
2432 373 : 0 : return false;
374 : : }
375 : :
6038 meskes@postgresql.or 376 :CBC 14 : ecpg_log("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
7700 377 : 14 : break;
378 : :
379 : 15 : case ECPGd_length:
380 [ - + ]: 15 : if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
381 : : {
4414 peter_e@gmx.net 382 :UBC 0 : va_end(args);
2432 383 : 0 : return false;
384 : : }
385 : :
6038 meskes@postgresql.or 386 :CBC 15 : ecpg_log("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
7700 387 : 15 : break;
388 : :
389 : 14 : case ECPGd_type:
6038 390 [ - + ]: 14 : if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type(PQftype(ECPGresult, index))))
391 : : {
4414 peter_e@gmx.net 392 :UBC 0 : va_end(args);
2432 393 : 0 : return false;
394 : : }
395 : :
6038 meskes@postgresql.or 396 :CBC 14 : ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type(PQftype(ECPGresult, index)));
7700 397 : 14 : break;
398 : :
399 : 4 : case ECPGd_di_code:
6038 400 [ - + ]: 4 : if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type_DDT(PQftype(ECPGresult, index))))
401 : : {
4414 peter_e@gmx.net 402 :UBC 0 : va_end(args);
2432 403 : 0 : return false;
404 : : }
405 : :
6038 meskes@postgresql.or 406 :CBC 4 : ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type_DDT(PQftype(ECPGresult, index)));
7700 407 : 4 : break;
408 : :
7700 meskes@postgresql.or 409 :UBC 0 : case ECPGd_cardinality:
410 [ # # ]: 0 : if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
411 : : {
4414 peter_e@gmx.net 412 : 0 : va_end(args);
2432 413 : 0 : return false;
414 : : }
415 : :
6038 meskes@postgresql.or 416 : 0 : ecpg_log("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
7700 417 : 0 : break;
418 : :
7700 meskes@postgresql.or 419 :CBC 14 : case ECPGd_ret_length:
420 : : case ECPGd_ret_octet:
421 : :
5203 422 [ - + ]: 14 : RETURN_IF_NO_DATA;
423 : :
424 : : /*
425 : : * this is like ECPGstore_result
426 : : */
7700 427 [ + - - + ]: 14 : if (arrsize > 0 && ntuples > arrsize)
428 : : {
4600 peter_e@gmx.net 429 :UBC 0 : ecpg_log("ECPGget_desc on line %d: incorrect number of matches; %d don't fit into array of %ld\n",
430 : : lineno, ntuples, arrsize);
6038 meskes@postgresql.or 431 : 0 : ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
4414 peter_e@gmx.net 432 : 0 : va_end(args);
7700 meskes@postgresql.or 433 : 0 : return false;
434 : : }
435 : : /* allocate storage if needed */
6503 meskes@postgresql.or 436 [ - + - - ]:CBC 14 : if (arrsize == 0 && *(void **) var == NULL)
437 : : {
3356 meskes@postgresql.or 438 :UBC 0 : void *mem = (void *) ecpg_auto_alloc(offset * ntuples, lineno);
439 : :
6507 440 [ # # ]: 0 : if (!mem)
441 : : {
4414 peter_e@gmx.net 442 : 0 : va_end(args);
6507 meskes@postgresql.or 443 : 0 : return false;
444 : : }
7700 445 : 0 : *(void **) var = mem;
446 : 0 : var = mem;
447 : : }
448 : :
7700 meskes@postgresql.or 449 [ + + ]:CBC 28 : for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
450 : : {
451 [ - + ]: 14 : if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
452 : : {
4414 peter_e@gmx.net 453 :UBC 0 : va_end(args);
2432 454 : 0 : return false;
455 : : }
7700 meskes@postgresql.or 456 :CBC 14 : var = (char *) var + offset;
6038 457 : 14 : ecpg_log("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
458 : : }
7700 459 : 14 : break;
460 : :
7700 meskes@postgresql.or 461 :UBC 0 : default:
462 : 0 : snprintf(type_str, sizeof(type_str), "%d", type);
6038 463 : 0 : ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
4414 peter_e@gmx.net 464 : 0 : va_end(args);
2432 465 : 0 : return false;
466 : : }
467 : :
7700 meskes@postgresql.or 468 :CBC 173 : type = va_arg(args, enum ECPGdtype);
469 : : }
470 : :
471 [ + + ]: 61 : if (data_var.type != ECPGt_EORT)
472 : : {
473 : : struct statement stmt;
474 : :
1910 tgl@sss.pgh.pa.us 475 : 28 : memset(&stmt, 0, sizeof stmt);
476 : 28 : stmt.lineno = lineno;
477 : :
478 : : /* Make sure we do NOT honor the locale for numeric input */
479 : : /* since the database gives the standard decimal point */
480 : : /* (see comments in execute.c) */
481 : : #ifdef HAVE_USELOCALE
482 : :
483 : : /*
484 : : * To get here, the above PQnfields() test must have found nonzero
485 : : * fields. One needs a connection to create such a descriptor. (EXEC
486 : : * SQL SET DESCRIPTOR can populate the descriptor's "items", but it
487 : : * can't change the descriptor's PQnfields().) Any successful
488 : : * connection initializes ecpg_clocale.
489 : : */
652 noah@leadboat.com 490 [ - + ]: 28 : Assert(ecpg_clocale);
491 : 28 : stmt.oldlocale = uselocale(ecpg_clocale);
492 : : #else
493 : : #ifdef HAVE__CONFIGTHREADLOCALE
494 : : stmt.oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
495 : : #endif
496 : : stmt.oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
497 : : setlocale(LC_NUMERIC, "C");
498 : : #endif
499 : :
500 : : /* desperate try to guess something sensible */
6038 meskes@postgresql.or 501 : 28 : stmt.connection = ecpg_get_connection(NULL);
502 : 28 : ecpg_store_result(ECPGresult, index, &stmt, &data_var);
503 : :
504 : : #ifdef HAVE_USELOCALE
1910 tgl@sss.pgh.pa.us 505 [ + - ]: 28 : if (stmt.oldlocale != (locale_t) 0)
506 : 28 : uselocale(stmt.oldlocale);
507 : : #else
508 : : if (stmt.oldlocale)
509 : : {
510 : : setlocale(LC_NUMERIC, stmt.oldlocale);
511 : : ecpg_free(stmt.oldlocale);
512 : : }
513 : : #ifdef HAVE__CONFIGTHREADLOCALE
514 : : if (stmt.oldthreadlocale != -1)
515 : : (void) _configthreadlocale(stmt.oldthreadlocale);
516 : : #endif
517 : : #endif
518 : : }
6493 meskes@postgresql.or 519 [ + + + - ]: 33 : else if (data_var.ind_type != ECPGt_NO_INDICATOR && data_var.ind_pointer != NULL)
520 : :
521 : : /*
522 : : * ind_type != NO_INDICATOR should always have ind_pointer != NULL but
523 : : * since this might be changed manually in the .c file let's play it
524 : : * safe
525 : : */
526 : : {
527 : : /*
528 : : * this is like ECPGstore_result but since we don't have a data
529 : : * variable at hand, we can't call it
530 : : */
7700 531 [ + - - + ]: 14 : if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
532 : : {
4600 peter_e@gmx.net 533 :UBC 0 : ecpg_log("ECPGget_desc on line %d: incorrect number of matches (indicator); %d don't fit into array of %ld\n",
534 : : lineno, ntuples, data_var.ind_arrsize);
6038 meskes@postgresql.or 535 : 0 : ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
4414 peter_e@gmx.net 536 : 0 : va_end(args);
7700 meskes@postgresql.or 537 : 0 : return false;
538 : : }
539 : :
540 : : /* allocate storage if needed */
6493 meskes@postgresql.or 541 [ - + - - ]:CBC 14 : if (data_var.ind_arrsize == 0 && data_var.ind_value == NULL)
542 : : {
3356 meskes@postgresql.or 543 :UBC 0 : void *mem = (void *) ecpg_auto_alloc(data_var.ind_offset * ntuples, lineno);
544 : :
6507 545 [ # # ]: 0 : if (!mem)
546 : : {
4414 peter_e@gmx.net 547 : 0 : va_end(args);
6507 meskes@postgresql.or 548 : 0 : return false;
549 : : }
7700 550 : 0 : *(void **) data_var.ind_pointer = mem;
551 : 0 : data_var.ind_value = mem;
552 : : }
553 : :
7700 meskes@postgresql.or 554 [ + + ]:CBC 28 : for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
555 : : {
556 [ - + ]: 14 : if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
557 : : {
4414 peter_e@gmx.net 558 :UBC 0 : va_end(args);
2432 559 : 0 : return false;
560 : : }
7700 meskes@postgresql.or 561 :CBC 14 : data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset;
6038 562 : 14 : ecpg_log("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
563 : : }
564 : : }
7609 bruce@momjian.us 565 : 61 : sqlca->sqlerrd[2] = ntuples;
4414 peter_e@gmx.net 566 : 61 : va_end(args);
2432 567 : 61 : return true;
568 : : }
569 : :
570 : : #undef RETURN_IF_NO_DATA
571 : :
572 : : bool
6710 meskes@postgresql.or 573 : 1 : ECPGset_desc_header(int lineno, const char *desc_name, int count)
574 : : {
6038 575 : 1 : struct descriptor *desc = ecpg_find_desc(lineno, desc_name);
576 : :
7223 577 [ - + ]: 1 : if (desc == NULL)
7223 meskes@postgresql.or 578 :UBC 0 : return false;
7223 meskes@postgresql.or 579 :CBC 1 : desc->count = count;
580 : 1 : return true;
581 : : }
582 : :
583 : : static void
1882 584 : 11 : set_desc_attr(struct descriptor_item *desc_item, struct variable *var,
585 : : char *tobeinserted)
586 : : {
587 [ + + ]: 11 : if (var->type != ECPGt_bytea)
588 : 9 : desc_item->is_binary = false;
589 : :
590 : : else
591 : : {
1357 michael@paquier.xyz 592 : 2 : struct ECPGgeneric_bytea *variable =
593 : : (struct ECPGgeneric_bytea *) (var->value);
594 : :
1882 meskes@postgresql.or 595 : 2 : desc_item->is_binary = true;
596 : 2 : desc_item->data_len = variable->len;
597 : : }
598 : :
1789 tgl@sss.pgh.pa.us 599 : 11 : ecpg_free(desc_item->data); /* free() takes care of a potential NULL value */
1882 meskes@postgresql.or 600 : 11 : desc_item->data = (char *) tobeinserted;
601 : 11 : }
602 : :
603 : :
604 : : bool
6710 605 : 11 : ECPGset_desc(int lineno, const char *desc_name, int index,...)
606 : : {
607 : : va_list args;
608 : : struct descriptor *desc;
609 : : struct descriptor_item *desc_item;
610 : : struct variable *var;
611 : :
6038 612 : 11 : desc = ecpg_find_desc(lineno, desc_name);
7228 613 [ - + ]: 11 : if (desc == NULL)
7228 meskes@postgresql.or 614 :UBC 0 : return false;
615 : :
7228 meskes@postgresql.or 616 [ + + ]:CBC 17 : for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
617 : : {
618 [ + + ]: 13 : if (desc_item->num == index)
619 : 7 : break;
620 : : }
621 : :
622 [ + + ]: 11 : if (desc_item == NULL)
623 : : {
6038 624 : 4 : desc_item = (struct descriptor_item *) ecpg_alloc(sizeof(*desc_item), lineno);
6507 625 [ - + ]: 4 : if (!desc_item)
6507 meskes@postgresql.or 626 :UBC 0 : return false;
7228 meskes@postgresql.or 627 :CBC 4 : desc_item->num = index;
6088 628 [ + - ]: 4 : if (desc->count < index)
629 : 4 : desc->count = index;
7228 630 : 4 : desc_item->next = desc->items;
631 : 4 : desc->items = desc_item;
632 : : }
633 : :
6038 634 [ - + ]: 11 : if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
7168 bruce@momjian.us 635 :UBC 0 : return false;
636 : :
7228 meskes@postgresql.or 637 :CBC 11 : va_start(args, index);
638 : :
639 : : for (;;)
640 : 15 : {
641 : : enum ECPGdtype itemtype;
5421 bruce@momjian.us 642 : 26 : char *tobeinserted = NULL;
643 : :
7228 meskes@postgresql.or 644 : 26 : itemtype = va_arg(args, enum ECPGdtype);
645 : :
646 [ + + ]: 26 : if (itemtype == ECPGd_EODT)
647 : 11 : break;
648 : :
6197 649 : 15 : var->type = va_arg(args, enum ECPGttype);
650 : 15 : var->pointer = va_arg(args, char *);
651 : :
652 : 15 : var->varcharsize = va_arg(args, long);
653 : 15 : var->arrsize = va_arg(args, long);
654 : 15 : var->offset = va_arg(args, long);
655 : :
656 [ + - - + ]: 15 : if (var->arrsize == 0 || var->varcharsize == 0)
6197 meskes@postgresql.or 657 :UBC 0 : var->value = *((char **) (var->pointer));
658 : : else
6197 meskes@postgresql.or 659 :CBC 15 : var->value = var->pointer;
660 : :
661 : : /*
662 : : * negative values are used to indicate an array without given bounds
663 : : */
664 : : /* reset to zero for us */
665 [ - + ]: 15 : if (var->arrsize < 0)
6197 meskes@postgresql.or 666 :UBC 0 : var->arrsize = 0;
6197 meskes@postgresql.or 667 [ - + ]:CBC 15 : if (var->varcharsize < 0)
6197 meskes@postgresql.or 668 :UBC 0 : var->varcharsize = 0;
669 : :
6197 meskes@postgresql.or 670 :CBC 15 : var->next = NULL;
671 : :
7228 672 [ + + - - : 15 : switch (itemtype)
- - - ]
673 : : {
674 : 11 : case ECPGd_data:
675 : : {
6038 676 [ - + ]: 11 : if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
677 : : {
6038 meskes@postgresql.or 678 :UBC 0 : ecpg_free(var);
4414 peter_e@gmx.net 679 : 0 : va_end(args);
7168 bruce@momjian.us 680 : 0 : return false;
681 : : }
682 : :
1882 meskes@postgresql.or 683 :CBC 11 : set_desc_attr(desc_item, var, tobeinserted);
7168 bruce@momjian.us 684 : 11 : tobeinserted = NULL;
685 : 11 : break;
686 : : }
687 : :
7228 meskes@postgresql.or 688 : 4 : case ECPGd_indicator:
7224 689 : 4 : set_int_item(lineno, &desc_item->indicator, var->pointer, var->type);
7228 690 : 4 : break;
691 : :
7228 meskes@postgresql.or 692 :UBC 0 : case ECPGd_length:
7224 693 : 0 : set_int_item(lineno, &desc_item->length, var->pointer, var->type);
7228 694 : 0 : break;
695 : :
696 : 0 : case ECPGd_precision:
7224 697 : 0 : set_int_item(lineno, &desc_item->precision, var->pointer, var->type);
7228 698 : 0 : break;
699 : :
700 : 0 : case ECPGd_scale:
7224 701 : 0 : set_int_item(lineno, &desc_item->scale, var->pointer, var->type);
7228 702 : 0 : break;
703 : :
704 : 0 : case ECPGd_type:
7224 705 : 0 : set_int_item(lineno, &desc_item->type, var->pointer, var->type);
7228 706 : 0 : break;
707 : :
708 : 0 : default:
709 : : {
710 : : char type_str[20];
711 : :
7168 bruce@momjian.us 712 : 0 : snprintf(type_str, sizeof(type_str), "%d", itemtype);
6038 meskes@postgresql.or 713 : 0 : ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
714 : 0 : ecpg_free(var);
4414 peter_e@gmx.net 715 : 0 : va_end(args);
7168 bruce@momjian.us 716 : 0 : return false;
717 : : }
718 : : }
719 : : }
6038 meskes@postgresql.or 720 :CBC 11 : ecpg_free(var);
4414 peter_e@gmx.net 721 : 11 : va_end(args);
722 : :
7228 meskes@postgresql.or 723 : 11 : return true;
724 : : }
725 : :
726 : : /* Free the descriptor and items in it. */
727 : : static void
2489 tgl@sss.pgh.pa.us 728 : 800015 : descriptor_free(struct descriptor *desc)
729 : : {
730 : : struct descriptor_item *desc_item;
731 : :
6039 meskes@postgresql.or 732 [ + + ]: 800017 : for (desc_item = desc->items; desc_item;)
733 : : {
734 : : struct descriptor_item *di;
735 : :
6038 736 : 2 : ecpg_free(desc_item->data);
6039 737 : 2 : di = desc_item;
738 : 2 : desc_item = desc_item->next;
6038 739 : 2 : ecpg_free(di);
740 : : }
741 : :
742 : 800015 : ecpg_free(desc->name);
6039 743 : 800015 : PQclear(desc->result);
6038 744 : 800015 : ecpg_free(desc);
6039 745 : 800015 : }
746 : :
747 : : bool
7700 748 : 800015 : ECPGdeallocate_desc(int line, const char *name)
749 : : {
750 : : struct descriptor *desc;
751 : : struct descriptor *prev;
7609 bruce@momjian.us 752 : 800015 : struct sqlca_t *sqlca = ECPGget_sqlca();
753 : :
3226 meskes@postgresql.or 754 [ - + ]: 800015 : if (sqlca == NULL)
755 : : {
3226 meskes@postgresql.or 756 :UBC 0 : ecpg_raise(line, ECPG_OUT_OF_MEMORY,
757 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
758 : 0 : return false;
759 : : }
760 : :
6038 meskes@postgresql.or 761 :CBC 800015 : ecpg_init_sqlca(sqlca);
6039 762 [ + - ]: 800020 : for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
763 : : {
4492 peter_e@gmx.net 764 [ + + ]: 800020 : if (strcmp(name, desc->name) == 0)
765 : : {
6039 meskes@postgresql.or 766 [ + + ]: 800015 : if (prev)
767 : 5 : prev->next = desc->next;
768 : : else
769 : 800010 : set_descriptors(desc->next);
770 : 800015 : descriptor_free(desc);
7700 771 : 800015 : return true;
772 : : }
773 : : }
6038 meskes@postgresql.or 774 :UBC 0 : ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
7700 775 : 0 : return false;
776 : : }
777 : :
778 : : /* Deallocate all descriptors in the list */
779 : : static void
2489 tgl@sss.pgh.pa.us 780 : 0 : descriptor_deallocate_all(struct descriptor *list)
781 : : {
6039 meskes@postgresql.or 782 [ # # ]: 0 : while (list)
783 : : {
784 : 0 : struct descriptor *next = list->next;
785 : :
786 : 0 : descriptor_free(list);
787 : 0 : list = next;
788 : : }
789 : 0 : }
790 : :
791 : : bool
7700 meskes@postgresql.or 792 :CBC 800017 : ECPGallocate_desc(int line, const char *name)
793 : : {
794 : : struct descriptor *new;
7609 bruce@momjian.us 795 : 800017 : struct sqlca_t *sqlca = ECPGget_sqlca();
796 : :
3226 meskes@postgresql.or 797 [ - + ]: 800017 : if (sqlca == NULL)
798 : : {
3226 meskes@postgresql.or 799 :UBC 0 : ecpg_raise(line, ECPG_OUT_OF_MEMORY,
800 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
801 : 0 : return false;
802 : : }
803 : :
6038 meskes@postgresql.or 804 :CBC 800017 : ecpg_init_sqlca(sqlca);
805 : 800017 : new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
7700 806 [ - + ]: 800017 : if (!new)
7700 meskes@postgresql.or 807 :UBC 0 : return false;
6039 meskes@postgresql.or 808 :CBC 800017 : new->next = get_descriptors();
6038 809 : 800017 : new->name = ecpg_alloc(strlen(name) + 1, line);
7700 810 [ - + ]: 800017 : if (!new->name)
811 : : {
6038 meskes@postgresql.or 812 :UBC 0 : ecpg_free(new);
7700 813 : 0 : return false;
814 : : }
7223 meskes@postgresql.or 815 :CBC 800017 : new->count = -1;
7228 816 : 800017 : new->items = NULL;
7700 817 : 800017 : new->result = PQmakeEmptyPGresult(NULL, 0);
818 [ - + ]: 800017 : if (!new->result)
819 : : {
6038 meskes@postgresql.or 820 :UBC 0 : ecpg_free(new->name);
821 : 0 : ecpg_free(new);
822 : 0 : ecpg_raise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
7700 823 : 0 : return false;
824 : : }
7700 meskes@postgresql.or 825 :CBC 800017 : strcpy(new->name, name);
6039 826 : 800017 : set_descriptors(new);
7700 827 : 800017 : return true;
828 : : }
829 : :
830 : : /* Find descriptor with name in the connection. */
831 : : struct descriptor *
6038 832 : 114 : ecpg_find_desc(int line, const char *name)
833 : : {
834 : : struct descriptor *desc;
835 : :
6039 836 [ + - ]: 159 : for (desc = get_descriptors(); desc; desc = desc->next)
837 : : {
838 [ + + ]: 159 : if (strcmp(name, desc->name) == 0)
839 : 114 : return desc;
840 : : }
841 : :
6038 meskes@postgresql.or 842 :UBC 0 : ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
5995 bruce@momjian.us 843 : 0 : return NULL; /* not found */
844 : : }
845 : :
846 : : bool
5161 bruce@momjian.us 847 :CBC 21 : ECPGdescribe(int line, int compat, bool input, const char *connection_name, const char *stmt_name,...)
848 : : {
5203 meskes@postgresql.or 849 : 21 : bool ret = false;
850 : : struct connection *con;
851 : : struct prepared_statement *prep;
852 : : PGresult *res;
853 : : va_list args;
854 : :
855 : : /* DESCRIBE INPUT is not yet supported */
856 [ - + ]: 21 : if (input)
857 : : {
5203 meskes@postgresql.or 858 :UBC 0 : ecpg_raise(line, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, "DESCRIBE INPUT");
859 : 0 : return ret;
860 : : }
861 : :
1668 tgl@sss.pgh.pa.us 862 :CBC 21 : con = ecpg_get_connection(connection_name);
5203 meskes@postgresql.or 863 [ - + ]: 21 : if (!con)
864 : : {
5203 meskes@postgresql.or 865 [ # # ]:UBC 0 : ecpg_raise(line, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
1668 tgl@sss.pgh.pa.us 866 : 0 : connection_name ? connection_name : ecpg_gettext("NULL"));
5203 meskes@postgresql.or 867 : 0 : return ret;
868 : : }
5203 meskes@postgresql.or 869 :CBC 21 : prep = ecpg_find_prepared_statement(stmt_name, con, NULL);
870 [ - + ]: 21 : if (!prep)
871 : : {
5203 meskes@postgresql.or 872 :UBC 0 : ecpg_raise(line, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt_name);
873 : 0 : return ret;
874 : : }
875 : :
5203 meskes@postgresql.or 876 :CBC 21 : va_start(args, stmt_name);
877 : :
878 : : for (;;)
879 : 21 : {
880 : : enum ECPGttype type;
881 : : void *ptr;
882 : :
883 : : /* variable type */
884 : 42 : type = va_arg(args, enum ECPGttype);
885 : :
886 [ + + ]: 42 : if (type == ECPGt_EORT)
887 : 21 : break;
888 : :
889 : : /* rest of variable parameters */
890 : 21 : ptr = va_arg(args, void *);
2489 tgl@sss.pgh.pa.us 891 : 21 : (void) va_arg(args, long); /* skip args */
4751 892 : 21 : (void) va_arg(args, long);
893 : 21 : (void) va_arg(args, long);
894 : :
895 : : /* variable indicator */
896 : 21 : (void) va_arg(args, enum ECPGttype);
897 : 21 : (void) va_arg(args, void *); /* skip args */
898 : 21 : (void) va_arg(args, long);
899 : 21 : (void) va_arg(args, long);
900 : 21 : (void) va_arg(args, long);
901 : :
5203 meskes@postgresql.or 902 [ + + - ]: 21 : switch (type)
903 : : {
904 : 9 : case ECPGt_descriptor:
905 : : {
5161 bruce@momjian.us 906 : 9 : char *name = ptr;
907 : 9 : struct descriptor *desc = ecpg_find_desc(line, name);
908 : :
909 [ - + ]: 9 : if (desc == NULL)
5161 bruce@momjian.us 910 :UBC 0 : break;
911 : :
5203 meskes@postgresql.or 912 :CBC 9 : res = PQdescribePrepared(con->connection, stmt_name);
913 [ - + ]: 9 : if (!ecpg_check_PQresult(res, line, con->connection, compat))
5203 meskes@postgresql.or 914 :UBC 0 : break;
915 : :
651 peter@eisentraut.org 916 :CBC 9 : PQclear(desc->result);
917 : :
5161 bruce@momjian.us 918 : 9 : desc->result = res;
919 : 9 : ret = true;
920 : 9 : break;
921 : : }
922 : 12 : case ECPGt_sqlda:
923 : : {
924 [ + + - + ]: 12 : if (INFORMIX_MODE(compat))
5203 meskes@postgresql.or 925 : 6 : {
5161 bruce@momjian.us 926 : 6 : struct sqlda_compat **_sqlda = ptr;
927 : : struct sqlda_compat *sqlda;
928 : :
929 : 6 : res = PQdescribePrepared(con->connection, stmt_name);
930 [ - + ]: 6 : if (!ecpg_check_PQresult(res, line, con->connection, compat))
5161 bruce@momjian.us 931 :UBC 0 : break;
932 : :
5161 bruce@momjian.us 933 :CBC 6 : sqlda = ecpg_build_compat_sqlda(line, res, -1, compat);
934 [ + - ]: 6 : if (sqlda)
935 : : {
936 : 6 : struct sqlda_compat *sqlda_old = *_sqlda;
937 : : struct sqlda_compat *sqlda_old1;
938 : :
939 [ - + ]: 6 : while (sqlda_old)
940 : : {
5161 bruce@momjian.us 941 :UBC 0 : sqlda_old1 = sqlda_old->desc_next;
942 : 0 : free(sqlda_old);
943 : 0 : sqlda_old = sqlda_old1;
944 : : }
945 : :
5161 bruce@momjian.us 946 :CBC 6 : *_sqlda = sqlda;
947 : 6 : ret = true;
948 : : }
949 : :
950 : 6 : PQclear(res);
951 : : }
952 : : else
953 : : {
954 : 6 : struct sqlda_struct **_sqlda = ptr;
955 : : struct sqlda_struct *sqlda;
956 : :
957 : 6 : res = PQdescribePrepared(con->connection, stmt_name);
958 [ - + ]: 6 : if (!ecpg_check_PQresult(res, line, con->connection, compat))
5161 bruce@momjian.us 959 :UBC 0 : break;
960 : :
5161 bruce@momjian.us 961 :CBC 6 : sqlda = ecpg_build_native_sqlda(line, res, -1, compat);
962 [ + - ]: 6 : if (sqlda)
963 : : {
964 : 6 : struct sqlda_struct *sqlda_old = *_sqlda;
965 : : struct sqlda_struct *sqlda_old1;
966 : :
967 [ - + ]: 6 : while (sqlda_old)
968 : : {
5161 bruce@momjian.us 969 :UBC 0 : sqlda_old1 = sqlda_old->desc_next;
970 : 0 : free(sqlda_old);
971 : 0 : sqlda_old = sqlda_old1;
972 : : }
973 : :
5161 bruce@momjian.us 974 :CBC 6 : *_sqlda = sqlda;
975 : 6 : ret = true;
976 : : }
977 : :
978 : 6 : PQclear(res);
979 : : }
980 : 12 : break;
981 : : }
5203 meskes@postgresql.or 982 : 21 : default:
983 : : /* nothing else may come */
984 : : ;
985 : : }
986 : : }
987 : :
988 : 21 : va_end(args);
989 : :
990 : 21 : return ret;
991 : : }
|