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