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