1 /* dynamic SQL support routines
6 #define POSTGRES_ECPG_INTERNAL
7 #include "postgres_fe.h"
10 #include "ecpg-pthread-win32.h"
13 #include "ecpgerrno.h"
16 #include "sql3types.h"
18 static void descriptor_free(struct descriptor
* desc
);
20 /* We manage descriptors separately for each thread. */
21 #ifdef ENABLE_THREAD_SAFETY
22 static pthread_key_t descriptor_key
;
23 static pthread_once_t descriptor_once
= PTHREAD_ONCE_INIT
;
25 static void descriptor_deallocate_all(struct descriptor
* list
);
28 descriptor_destructor(void *arg
)
30 descriptor_deallocate_all(arg
);
34 descriptor_key_init(void)
36 pthread_key_create(&descriptor_key
, descriptor_destructor
);
39 static struct descriptor
*
42 pthread_once(&descriptor_once
, descriptor_key_init
);
43 return (struct descriptor
*) pthread_getspecific(descriptor_key
);
47 set_descriptors(struct descriptor
* value
)
49 pthread_setspecific(descriptor_key
, value
);
52 static struct descriptor
*all_descriptors
= NULL
;
54 #define get_descriptors() (all_descriptors)
55 #define set_descriptors(value) do { all_descriptors = (value); } while(0)
58 /* old internal convenience function that might go away later */
60 ecpg_result_by_descriptor(int line
, const char *name
)
62 struct descriptor
*desc
= ecpg_find_desc(line
, name
);
70 ecpg_dynamic_type_DDT(Oid type
)
79 return SQL3_DDT_TIMESTAMP
;
81 return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE
;
83 return SQL3_DDT_TIME_WITH_TIME_ZONE
;
85 return SQL3_DDT_ILLEGAL
;
90 ECPGget_desc_header(int lineno
, const char *desc_name
, int *count
)
93 struct sqlca_t
*sqlca
= ECPGget_sqlca();
95 ecpg_init_sqlca(sqlca
);
96 ECPGresult
= ecpg_result_by_descriptor(lineno
, desc_name
);
100 *count
= PQnfields(ECPGresult
);
101 sqlca
->sqlerrd
[2] = 1;
102 ecpg_log("ECPGget_desc_header: found %d attributes\n", *count
);
107 get_int_item(int lineno
, void *var
, enum ECPGttype vartype
, int value
)
112 *(short *) var
= (short) value
;
115 *(int *) var
= (int) value
;
118 *(long *) var
= (long) value
;
120 case ECPGt_unsigned_short
:
121 *(unsigned short *) var
= (unsigned short) value
;
123 case ECPGt_unsigned_int
:
124 *(unsigned int *) var
= (unsigned int) value
;
126 case ECPGt_unsigned_long
:
127 *(unsigned long *) var
= (unsigned long) value
;
129 #ifdef HAVE_LONG_LONG_INT_64
130 case ECPGt_long_long
:
131 *(long long int *) var
= (long long int) value
;
133 case ECPGt_unsigned_long_long
:
134 *(unsigned long long int *) var
= (unsigned long long int) value
;
136 #endif /* HAVE_LONG_LONG_INT_64 */
138 *(float *) var
= (float) value
;
141 *(double *) var
= (double) value
;
144 ecpg_raise(lineno
, ECPG_VAR_NOT_NUMERIC
, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION
, NULL
);
152 set_int_item(int lineno
, int *target
, const void *var
, enum ECPGttype vartype
)
157 *target
= *(short *) var
;
160 *target
= *(int *) var
;
163 *target
= *(long *) var
;
165 case ECPGt_unsigned_short
:
166 *target
= *(unsigned short *) var
;
168 case ECPGt_unsigned_int
:
169 *target
= *(unsigned int *) var
;
171 case ECPGt_unsigned_long
:
172 *target
= *(unsigned long *) var
;
174 #ifdef HAVE_LONG_LONG_INT_64
175 case ECPGt_long_long
:
176 *target
= *(long long int *) var
;
178 case ECPGt_unsigned_long_long
:
179 *target
= *(unsigned long long int *) var
;
181 #endif /* HAVE_LONG_LONG_INT_64 */
183 *target
= *(float *) var
;
186 *target
= *(double *) var
;
189 ecpg_raise(lineno
, ECPG_VAR_NOT_NUMERIC
, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION
, NULL
);
197 get_char_item(int lineno
, void *var
, enum ECPGttype vartype
, char *value
, int varcharsize
)
202 case ECPGt_unsigned_char
:
203 strncpy((char *) var
, value
, varcharsize
);
207 struct ECPGgeneric_varchar
*variable
=
208 (struct ECPGgeneric_varchar
*) var
;
210 if (varcharsize
== 0)
211 strncpy(variable
->arr
, value
, strlen(value
));
213 strncpy(variable
->arr
, value
, varcharsize
);
215 variable
->len
= strlen(value
);
216 if (varcharsize
> 0 && variable
->len
> varcharsize
)
217 variable
->len
= varcharsize
;
221 ecpg_raise(lineno
, ECPG_VAR_NOT_CHAR
, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION
, NULL
);
229 ECPGget_desc(int lineno
, const char *desc_name
, int index
,...)
232 PGresult
*ECPGresult
;
236 struct variable data_var
;
237 struct sqlca_t
*sqlca
= ECPGget_sqlca();
239 va_start(args
, index
);
240 ecpg_init_sqlca(sqlca
);
241 ECPGresult
= ecpg_result_by_descriptor(lineno
, desc_name
);
245 ntuples
= PQntuples(ECPGresult
);
248 ecpg_raise(lineno
, ECPG_NOT_FOUND
, ECPG_SQLSTATE_NO_DATA
, NULL
);
252 if (index
< 1 || index
> PQnfields(ECPGresult
))
254 ecpg_raise(lineno
, ECPG_INVALID_DESCRIPTOR_INDEX
, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX
, NULL
);
258 ecpg_log("ECPGget_desc: reading items for tuple %d\n", index
);
261 type
= va_arg(args
, enum ECPGdtype
);
263 memset(&data_var
, 0, sizeof data_var
);
264 data_var
.type
= ECPGt_EORT
;
265 data_var
.ind_type
= ECPGt_NO_INDICATOR
;
267 while (type
!= ECPGd_EODT
)
273 enum ECPGttype vartype
;
276 vartype
= va_arg(args
, enum ECPGttype
);
277 var
= va_arg(args
, void *);
278 varcharsize
= va_arg(args
, long);
279 arrsize
= va_arg(args
, long);
280 offset
= va_arg(args
, long);
284 case (ECPGd_indicator
):
285 data_var
.ind_type
= vartype
;
286 data_var
.ind_pointer
= var
;
287 data_var
.ind_varcharsize
= varcharsize
;
288 data_var
.ind_arrsize
= arrsize
;
289 data_var
.ind_offset
= offset
;
290 if (data_var
.ind_arrsize
== 0 || data_var
.ind_varcharsize
== 0)
291 data_var
.ind_value
= *((void **) (data_var
.ind_pointer
));
293 data_var
.ind_value
= data_var
.ind_pointer
;
297 data_var
.type
= vartype
;
298 data_var
.pointer
= var
;
299 data_var
.varcharsize
= varcharsize
;
300 data_var
.arrsize
= arrsize
;
301 data_var
.offset
= offset
;
302 if (data_var
.arrsize
== 0 || data_var
.varcharsize
== 0)
303 data_var
.value
= *((void **) (data_var
.pointer
));
305 data_var
.value
= data_var
.pointer
;
309 if (!get_char_item(lineno
, var
, vartype
, PQfname(ECPGresult
, index
), varcharsize
))
312 ecpg_log("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult
, index
));
316 if (!get_int_item(lineno
, var
, vartype
, 1))
321 case ECPGd_key_member
:
322 if (!get_int_item(lineno
, var
, vartype
, 0))
328 if (!get_int_item(lineno
, var
, vartype
, (PQfmod(ECPGresult
, index
) - VARHDRSZ
) & 0xffff))
331 ecpg_log("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult
, index
) - VARHDRSZ
) & 0xffff);
334 case ECPGd_precision
:
335 if (!get_int_item(lineno
, var
, vartype
, PQfmod(ECPGresult
, index
) >> 16))
338 ecpg_log("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult
, index
) >> 16);
342 if (!get_int_item(lineno
, var
, vartype
, PQfsize(ECPGresult
, index
)))
345 ecpg_log("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult
, index
));
349 if (!get_int_item(lineno
, var
, vartype
, PQfmod(ECPGresult
, index
) - VARHDRSZ
))
352 ecpg_log("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult
, index
) - VARHDRSZ
);
356 if (!get_int_item(lineno
, var
, vartype
, ecpg_dynamic_type(PQftype(ECPGresult
, index
))))
359 ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type(PQftype(ECPGresult
, index
)));
363 if (!get_int_item(lineno
, var
, vartype
, ecpg_dynamic_type_DDT(PQftype(ECPGresult
, index
))))
366 ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type_DDT(PQftype(ECPGresult
, index
)));
369 case ECPGd_cardinality
:
370 if (!get_int_item(lineno
, var
, vartype
, PQntuples(ECPGresult
)))
373 ecpg_log("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult
));
376 case ECPGd_ret_length
:
377 case ECPGd_ret_octet
:
380 * this is like ECPGstore_result
382 if (arrsize
> 0 && ntuples
> arrsize
)
384 ecpg_log("ECPGget_desc on line %d: incorrect number of matches; %d don't fit into array of %d\n",
385 lineno
, ntuples
, arrsize
);
386 ecpg_raise(lineno
, ECPG_TOO_MANY_MATCHES
, ECPG_SQLSTATE_CARDINALITY_VIOLATION
, NULL
);
389 /* allocate storage if needed */
390 if (arrsize
== 0 && *(void **) var
== NULL
)
392 void *mem
= (void *) ecpg_alloc(offset
* ntuples
, lineno
);
396 *(void **) var
= mem
;
397 ecpg_add_mem(mem
, lineno
);
401 for (act_tuple
= 0; act_tuple
< ntuples
; act_tuple
++)
403 if (!get_int_item(lineno
, var
, vartype
, PQgetlength(ECPGresult
, act_tuple
, index
)))
405 var
= (char *) var
+ offset
;
406 ecpg_log("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple
, PQgetlength(ECPGresult
, act_tuple
, index
));
411 snprintf(type_str
, sizeof(type_str
), "%d", type
);
412 ecpg_raise(lineno
, ECPG_UNKNOWN_DESCRIPTOR_ITEM
, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
, type_str
);
416 type
= va_arg(args
, enum ECPGdtype
);
419 if (data_var
.type
!= ECPGt_EORT
)
421 struct statement stmt
;
424 /* Make sure we do NOT honor the locale for numeric input */
425 /* since the database gives the standard decimal point */
426 oldlocale
= ecpg_strdup(setlocale(LC_NUMERIC
, NULL
), lineno
);
427 setlocale(LC_NUMERIC
, "C");
429 memset(&stmt
, 0, sizeof stmt
);
430 stmt
.lineno
= lineno
;
432 /* desparate try to guess something sensible */
433 stmt
.connection
= ecpg_get_connection(NULL
);
434 ecpg_store_result(ECPGresult
, index
, &stmt
, &data_var
);
436 setlocale(LC_NUMERIC
, oldlocale
);
437 ecpg_free(oldlocale
);
439 else if (data_var
.ind_type
!= ECPGt_NO_INDICATOR
&& data_var
.ind_pointer
!= NULL
)
442 * ind_type != NO_INDICATOR should always have ind_pointer != NULL but
443 * since this might be changed manually in the .c file let's play it
448 * this is like ECPGstore_result but since we don't have a data
449 * variable at hand, we can't call it
451 if (data_var
.ind_arrsize
> 0 && ntuples
> data_var
.ind_arrsize
)
453 ecpg_log("ECPGget_desc on line %d: incorrect number of matches (indicator); %d don't fit into array of %d\n",
454 lineno
, ntuples
, data_var
.ind_arrsize
);
455 ecpg_raise(lineno
, ECPG_TOO_MANY_MATCHES
, ECPG_SQLSTATE_CARDINALITY_VIOLATION
, NULL
);
459 /* allocate storage if needed */
460 if (data_var
.ind_arrsize
== 0 && data_var
.ind_value
== NULL
)
462 void *mem
= (void *) ecpg_alloc(data_var
.ind_offset
* ntuples
, lineno
);
466 *(void **) data_var
.ind_pointer
= mem
;
467 ecpg_add_mem(mem
, lineno
);
468 data_var
.ind_value
= mem
;
471 for (act_tuple
= 0; act_tuple
< ntuples
; act_tuple
++)
473 if (!get_int_item(lineno
, data_var
.ind_value
, data_var
.ind_type
, -PQgetisnull(ECPGresult
, act_tuple
, index
)))
475 data_var
.ind_value
= (char *) data_var
.ind_value
+ data_var
.ind_offset
;
476 ecpg_log("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple
, -PQgetisnull(ECPGresult
, act_tuple
, index
));
479 sqlca
->sqlerrd
[2] = ntuples
;
484 ECPGset_desc_header(int lineno
, const char *desc_name
, int count
)
486 struct descriptor
*desc
= ecpg_find_desc(lineno
, desc_name
);
495 ECPGset_desc(int lineno
, const char *desc_name
, int index
,...)
498 struct descriptor
*desc
;
499 struct descriptor_item
*desc_item
;
500 struct variable
*var
;
502 desc
= ecpg_find_desc(lineno
, desc_name
);
506 for (desc_item
= desc
->items
; desc_item
; desc_item
= desc_item
->next
)
508 if (desc_item
->num
== index
)
512 if (desc_item
== NULL
)
514 desc_item
= (struct descriptor_item
*) ecpg_alloc(sizeof(*desc_item
), lineno
);
517 desc_item
->num
= index
;
518 if (desc
->count
< index
)
520 desc_item
->next
= desc
->items
;
521 desc
->items
= desc_item
;
524 if (!(var
= (struct variable
*) ecpg_alloc(sizeof(struct variable
), lineno
)))
527 va_start(args
, index
);
531 enum ECPGdtype itemtype
;
532 char *tobeinserted
= NULL
;
534 itemtype
= va_arg(args
, enum ECPGdtype
);
536 if (itemtype
== ECPGd_EODT
)
539 var
->type
= va_arg(args
, enum ECPGttype
);
540 var
->pointer
= va_arg(args
, char *);
542 var
->varcharsize
= va_arg(args
, long);
543 var
->arrsize
= va_arg(args
, long);
544 var
->offset
= va_arg(args
, long);
546 if (var
->arrsize
== 0 || var
->varcharsize
== 0)
547 var
->value
= *((char **) (var
->pointer
));
549 var
->value
= var
->pointer
;
552 * negative values are used to indicate an array without given bounds
554 /* reset to zero for us */
555 if (var
->arrsize
< 0)
557 if (var
->varcharsize
< 0)
558 var
->varcharsize
= 0;
566 if (!ecpg_store_input(lineno
, true, var
, &tobeinserted
, false))
572 ecpg_free(desc_item
->data
); /* free() takes care of a
573 * potential NULL value */
574 desc_item
->data
= (char *) tobeinserted
;
579 case ECPGd_indicator
:
580 set_int_item(lineno
, &desc_item
->indicator
, var
->pointer
, var
->type
);
584 set_int_item(lineno
, &desc_item
->length
, var
->pointer
, var
->type
);
587 case ECPGd_precision
:
588 set_int_item(lineno
, &desc_item
->precision
, var
->pointer
, var
->type
);
592 set_int_item(lineno
, &desc_item
->scale
, var
->pointer
, var
->type
);
596 set_int_item(lineno
, &desc_item
->type
, var
->pointer
, var
->type
);
603 snprintf(type_str
, sizeof(type_str
), "%d", itemtype
);
604 ecpg_raise(lineno
, ECPG_UNKNOWN_DESCRIPTOR_ITEM
, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
, type_str
);
615 /* Free the descriptor and items in it. */
617 descriptor_free(struct descriptor
* desc
)
619 struct descriptor_item
*desc_item
;
621 for (desc_item
= desc
->items
; desc_item
;)
623 struct descriptor_item
*di
;
625 ecpg_free(desc_item
->data
);
627 desc_item
= desc_item
->next
;
631 ecpg_free(desc
->name
);
632 PQclear(desc
->result
);
637 ECPGdeallocate_desc(int line
, const char *name
)
639 struct descriptor
*desc
;
640 struct descriptor
*prev
;
641 struct sqlca_t
*sqlca
= ECPGget_sqlca();
643 ecpg_init_sqlca(sqlca
);
644 for (desc
= get_descriptors(), prev
= NULL
; desc
; prev
= desc
, desc
= desc
->next
)
646 if (!strcmp(name
, desc
->name
))
649 prev
->next
= desc
->next
;
651 set_descriptors(desc
->next
);
652 descriptor_free(desc
);
656 ecpg_raise(line
, ECPG_UNKNOWN_DESCRIPTOR
, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME
, name
);
660 #ifdef ENABLE_THREAD_SAFETY
662 /* Deallocate all descriptors in the list */
664 descriptor_deallocate_all(struct descriptor
* list
)
668 struct descriptor
*next
= list
->next
;
670 descriptor_free(list
);
674 #endif /* ENABLE_THREAD_SAFETY */
677 ECPGallocate_desc(int line
, const char *name
)
679 struct descriptor
*new;
680 struct sqlca_t
*sqlca
= ECPGget_sqlca();
682 ecpg_init_sqlca(sqlca
);
683 new = (struct descriptor
*) ecpg_alloc(sizeof(struct descriptor
), line
);
686 new->next
= get_descriptors();
687 new->name
= ecpg_alloc(strlen(name
) + 1, line
);
695 new->result
= PQmakeEmptyPGresult(NULL
, 0);
698 ecpg_free(new->name
);
700 ecpg_raise(line
, ECPG_OUT_OF_MEMORY
, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY
, NULL
);
703 strcpy(new->name
, name
);
704 set_descriptors(new);
708 /* Find descriptor with name in the connection. */
710 ecpg_find_desc(int line
, const char *name
)
712 struct descriptor
*desc
;
714 for (desc
= get_descriptors(); desc
; desc
= desc
->next
)
716 if (strcmp(name
, desc
->name
) == 0)
720 ecpg_raise(line
, ECPG_UNKNOWN_DESCRIPTOR
, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME
, name
);
721 return NULL
; /* not found */
725 ECPGdescribe(int line
, bool input
, const char *statement
,...)
727 ecpg_log("ECPGdescribe called on line %d for %s: %s\n", line
, (input
) ? _("input") : _("output"), statement
);