1 /* dynamic SQL support routines
3 * src/interfaces/ecpg/ecpglib/descriptor.c
6 #define POSTGRES_ECPG_INTERNAL
7 #include "postgres_fe.h"
10 #include "ecpg-pthread-win32.h"
13 #include "ecpgerrno.h"
17 #include "sql3types.h"
19 static void descriptor_free(struct descriptor *desc);
21 /* We manage descriptors separately for each thread. */
22 #ifdef ENABLE_THREAD_SAFETY
23 static pthread_key_t descriptor_key;
24 static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT;
26 static void descriptor_deallocate_all(struct descriptor *list);
29 descriptor_destructor(void *arg)
31 descriptor_deallocate_all(arg);
35 descriptor_key_init(void)
37 pthread_key_create(&descriptor_key, descriptor_destructor);
40 static struct descriptor *
43 pthread_once(&descriptor_once, descriptor_key_init);
44 return (struct descriptor *) pthread_getspecific(descriptor_key);
48 set_descriptors(struct descriptor *value)
50 pthread_setspecific(descriptor_key, value);
53 static struct descriptor *all_descriptors = NULL;
55 #define get_descriptors() (all_descriptors)
56 #define set_descriptors(value) do { all_descriptors = (value); } while(0)
59 /* old internal convenience function that might go away later */
61 ecpg_result_by_descriptor(int line, const char *name)
63 struct descriptor *desc = ecpg_find_desc(line, name);
71 ecpg_dynamic_type_DDT(Oid type)
80 return SQL3_DDT_TIMESTAMP;
82 return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE;
84 return SQL3_DDT_TIME_WITH_TIME_ZONE;
86 return SQL3_DDT_ILLEGAL;
91 ECPGget_desc_header(int lineno, const char *desc_name, int *count)
94 struct sqlca_t *sqlca = ECPGget_sqlca();
98 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
99 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
103 ecpg_init_sqlca(sqlca);
104 ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
108 *count = PQnfields(ECPGresult);
109 sqlca->sqlerrd[2] = 1;
110 ecpg_log("ECPGget_desc_header: found %d attributes\n", *count);
115 get_int_item(int lineno, void *var, enum ECPGttype vartype, int value)
120 *(short *) var = (short) value;
123 *(int *) var = (int) value;
126 *(long *) var = (long) value;
128 case ECPGt_unsigned_short:
129 *(unsigned short *) var = (unsigned short) value;
131 case ECPGt_unsigned_int:
132 *(unsigned int *) var = (unsigned int) value;
134 case ECPGt_unsigned_long:
135 *(unsigned long *) var = (unsigned long) value;
137 #ifdef HAVE_LONG_LONG_INT
138 case ECPGt_long_long:
139 *(long long int *) var = (long long int) value;
141 case ECPGt_unsigned_long_long:
142 *(unsigned long long int *) var = (unsigned long long int) value;
144 #endif /* HAVE_LONG_LONG_INT */
146 *(float *) var = (float) value;
149 *(double *) var = (double) value;
152 ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
160 set_int_item(int lineno, int *target, const void *var, enum ECPGttype vartype)
165 *target = *(const short *) var;
168 *target = *(const int *) var;
171 *target = *(const long *) var;
173 case ECPGt_unsigned_short:
174 *target = *(const unsigned short *) var;
176 case ECPGt_unsigned_int:
177 *target = *(const unsigned int *) var;
179 case ECPGt_unsigned_long:
180 *target = *(const unsigned long *) var;
182 #ifdef HAVE_LONG_LONG_INT
183 case ECPGt_long_long:
184 *target = *(const long long int *) var;
186 case ECPGt_unsigned_long_long:
187 *target = *(const unsigned long long int *) var;
189 #endif /* HAVE_LONG_LONG_INT */
191 *target = *(const float *) var;
194 *target = *(const double *) var;
197 ecpg_raise(lineno, ECPG_VAR_NOT_NUMERIC, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
205 get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int varcharsize)
210 case ECPGt_unsigned_char:
212 strncpy((char *) var, value, varcharsize);
216 struct ECPGgeneric_varchar *variable =
217 (struct ECPGgeneric_varchar *) var;
219 if (varcharsize == 0)
220 strncpy(variable->arr, value, strlen(value));
222 strncpy(variable->arr, value, varcharsize);
224 variable->len = strlen(value);
225 if (varcharsize > 0 && variable->len > varcharsize)
226 variable->len = varcharsize;
230 ecpg_raise(lineno, ECPG_VAR_NOT_CHAR, ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION, NULL);
237 #define RETURN_IF_NO_DATA if (ntuples < 1) \
240 ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); \
245 ECPGget_desc(int lineno, const char *desc_name, int index,...)
248 PGresult *ECPGresult;
252 struct variable data_var;
253 struct sqlca_t *sqlca = ECPGget_sqlca();
257 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
258 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
262 va_start(args, index);
263 ecpg_init_sqlca(sqlca);
264 ECPGresult = ecpg_result_by_descriptor(lineno, desc_name);
271 ntuples = PQntuples(ECPGresult);
273 if (index < 1 || index > PQnfields(ECPGresult))
275 ecpg_raise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX, NULL);
280 ecpg_log("ECPGget_desc: reading items for tuple %d\n", index);
283 type = va_arg(args, enum ECPGdtype);
285 memset(&data_var, 0, sizeof data_var);
286 data_var.type = ECPGt_EORT;
287 data_var.ind_type = ECPGt_NO_INDICATOR;
289 while (type != ECPGd_EODT)
295 enum ECPGttype vartype;
298 vartype = va_arg(args, enum ECPGttype);
299 var = va_arg(args, void *);
300 varcharsize = va_arg(args, long);
301 arrsize = va_arg(args, long);
302 offset = va_arg(args, long);
306 case (ECPGd_indicator):
308 data_var.ind_type = vartype;
309 data_var.ind_pointer = var;
310 data_var.ind_varcharsize = varcharsize;
311 data_var.ind_arrsize = arrsize;
312 data_var.ind_offset = offset;
313 if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0)
314 data_var.ind_value = *((void **) (data_var.ind_pointer));
316 data_var.ind_value = data_var.ind_pointer;
321 data_var.type = vartype;
322 data_var.pointer = var;
323 data_var.varcharsize = varcharsize;
324 data_var.arrsize = arrsize;
325 data_var.offset = offset;
326 if (data_var.arrsize == 0 || data_var.varcharsize == 0)
327 data_var.value = *((void **) (data_var.pointer));
329 data_var.value = data_var.pointer;
333 if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
339 ecpg_log("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
343 if (!get_int_item(lineno, var, vartype, 1))
351 case ECPGd_key_member:
352 if (!get_int_item(lineno, var, vartype, 0))
361 if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
367 ecpg_log("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
370 case ECPGd_precision:
371 if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
377 ecpg_log("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
381 if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
387 ecpg_log("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
391 if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
397 ecpg_log("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
401 if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type(PQftype(ECPGresult, index))))
407 ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type(PQftype(ECPGresult, index)));
411 if (!get_int_item(lineno, var, vartype, ecpg_dynamic_type_DDT(PQftype(ECPGresult, index))))
417 ecpg_log("ECPGget_desc: TYPE = %d\n", ecpg_dynamic_type_DDT(PQftype(ECPGresult, index)));
420 case ECPGd_cardinality:
421 if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
427 ecpg_log("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
430 case ECPGd_ret_length:
431 case ECPGd_ret_octet:
436 * this is like ECPGstore_result
438 if (arrsize > 0 && ntuples > arrsize)
440 ecpg_log("ECPGget_desc on line %d: incorrect number of matches; %d don't fit into array of %ld\n",
441 lineno, ntuples, arrsize);
442 ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
446 /* allocate storage if needed */
447 if (arrsize == 0 && *(void **) var == NULL)
449 void *mem = (void *) ecpg_auto_alloc(offset * ntuples, lineno);
456 *(void **) var = mem;
460 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
462 if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index)))
467 var = (char *) var + offset;
468 ecpg_log("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index));
473 snprintf(type_str, sizeof(type_str), "%d", type);
474 ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
479 type = va_arg(args, enum ECPGdtype);
482 if (data_var.type != ECPGt_EORT)
484 struct statement stmt;
487 /* Make sure we do NOT honor the locale for numeric input */
488 /* since the database gives the standard decimal point */
489 oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
490 setlocale(LC_NUMERIC, "C");
492 memset(&stmt, 0, sizeof stmt);
493 stmt.lineno = lineno;
495 /* desperate try to guess something sensible */
496 stmt.connection = ecpg_get_connection(NULL);
497 ecpg_store_result(ECPGresult, index, &stmt, &data_var);
499 setlocale(LC_NUMERIC, oldlocale);
500 ecpg_free(oldlocale);
502 else if (data_var.ind_type != ECPGt_NO_INDICATOR && data_var.ind_pointer != NULL)
505 * ind_type != NO_INDICATOR should always have ind_pointer != NULL but
506 * since this might be changed manually in the .c file let's play it
511 * this is like ECPGstore_result but since we don't have a data
512 * variable at hand, we can't call it
514 if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize)
516 ecpg_log("ECPGget_desc on line %d: incorrect number of matches (indicator); %d don't fit into array of %ld\n",
517 lineno, ntuples, data_var.ind_arrsize);
518 ecpg_raise(lineno, ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
523 /* allocate storage if needed */
524 if (data_var.ind_arrsize == 0 && data_var.ind_value == NULL)
526 void *mem = (void *) ecpg_auto_alloc(data_var.ind_offset * ntuples, lineno);
533 *(void **) data_var.ind_pointer = mem;
534 data_var.ind_value = mem;
537 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
539 if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index)))
544 data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset;
545 ecpg_log("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
548 sqlca->sqlerrd[2] = ntuples;
553 #undef RETURN_IF_NO_DATA
556 ECPGset_desc_header(int lineno, const char *desc_name, int count)
558 struct descriptor *desc = ecpg_find_desc(lineno, desc_name);
567 ECPGset_desc(int lineno, const char *desc_name, int index,...)
570 struct descriptor *desc;
571 struct descriptor_item *desc_item;
572 struct variable *var;
574 desc = ecpg_find_desc(lineno, desc_name);
578 for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
580 if (desc_item->num == index)
584 if (desc_item == NULL)
586 desc_item = (struct descriptor_item *) ecpg_alloc(sizeof(*desc_item), lineno);
589 desc_item->num = index;
590 if (desc->count < index)
592 desc_item->next = desc->items;
593 desc->items = desc_item;
596 if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
599 va_start(args, index);
603 enum ECPGdtype itemtype;
604 char *tobeinserted = NULL;
606 itemtype = va_arg(args, enum ECPGdtype);
608 if (itemtype == ECPGd_EODT)
611 var->type = va_arg(args, enum ECPGttype);
612 var->pointer = va_arg(args, char *);
614 var->varcharsize = va_arg(args, long);
615 var->arrsize = va_arg(args, long);
616 var->offset = va_arg(args, long);
618 if (var->arrsize == 0 || var->varcharsize == 0)
619 var->value = *((char **) (var->pointer));
621 var->value = var->pointer;
624 * negative values are used to indicate an array without given bounds
626 /* reset to zero for us */
627 if (var->arrsize < 0)
629 if (var->varcharsize < 0)
630 var->varcharsize = 0;
638 if (!ecpg_store_input(lineno, true, var, &tobeinserted, false))
645 ecpg_free(desc_item->data); /* free() takes care of a
646 * potential NULL value */
647 desc_item->data = (char *) tobeinserted;
652 case ECPGd_indicator:
653 set_int_item(lineno, &desc_item->indicator, var->pointer, var->type);
657 set_int_item(lineno, &desc_item->length, var->pointer, var->type);
660 case ECPGd_precision:
661 set_int_item(lineno, &desc_item->precision, var->pointer, var->type);
665 set_int_item(lineno, &desc_item->scale, var->pointer, var->type);
669 set_int_item(lineno, &desc_item->type, var->pointer, var->type);
676 snprintf(type_str, sizeof(type_str), "%d", itemtype);
677 ecpg_raise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, type_str);
690 /* Free the descriptor and items in it. */
692 descriptor_free(struct descriptor *desc)
694 struct descriptor_item *desc_item;
696 for (desc_item = desc->items; desc_item;)
698 struct descriptor_item *di;
700 ecpg_free(desc_item->data);
702 desc_item = desc_item->next;
706 ecpg_free(desc->name);
707 PQclear(desc->result);
712 ECPGdeallocate_desc(int line, const char *name)
714 struct descriptor *desc;
715 struct descriptor *prev;
716 struct sqlca_t *sqlca = ECPGget_sqlca();
720 ecpg_raise(line, ECPG_OUT_OF_MEMORY,
721 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
725 ecpg_init_sqlca(sqlca);
726 for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
728 if (strcmp(name, desc->name) == 0)
731 prev->next = desc->next;
733 set_descriptors(desc->next);
734 descriptor_free(desc);
738 ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
742 #ifdef ENABLE_THREAD_SAFETY
744 /* Deallocate all descriptors in the list */
746 descriptor_deallocate_all(struct descriptor *list)
750 struct descriptor *next = list->next;
752 descriptor_free(list);
756 #endif /* ENABLE_THREAD_SAFETY */
759 ECPGallocate_desc(int line, const char *name)
761 struct descriptor *new;
762 struct sqlca_t *sqlca = ECPGget_sqlca();
766 ecpg_raise(line, ECPG_OUT_OF_MEMORY,
767 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
771 ecpg_init_sqlca(sqlca);
772 new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
775 new->next = get_descriptors();
776 new->name = ecpg_alloc(strlen(name) + 1, line);
784 new->result = PQmakeEmptyPGresult(NULL, 0);
787 ecpg_free(new->name);
789 ecpg_raise(line, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
792 strcpy(new->name, name);
793 set_descriptors(new);
797 /* Find descriptor with name in the connection. */
799 ecpg_find_desc(int line, const char *name)
801 struct descriptor *desc;
803 for (desc = get_descriptors(); desc; desc = desc->next)
805 if (strcmp(name, desc->name) == 0)
809 ecpg_raise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
810 return NULL; /* not found */
814 ECPGdescribe(int line, int compat, bool input, const char *connection_name, const char *stmt_name,...)
817 struct connection *con;
818 struct prepared_statement *prep;
822 /* DESCRIBE INPUT is not yet supported */
825 ecpg_raise(line, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, "DESCRIBE INPUT");
829 con = ecpg_get_connection(connection_name);
832 ecpg_raise(line, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
833 connection_name ? connection_name : ecpg_gettext("NULL"));
836 prep = ecpg_find_prepared_statement(stmt_name, con, NULL);
839 ecpg_raise(line, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt_name);
843 va_start(args, stmt_name);
851 type = va_arg(args, enum ECPGttype);
853 if (type == ECPGt_EORT)
856 /* rest of variable parameters */
857 ptr = va_arg(args, void *);
858 (void) va_arg(args, long); /* skip args */
859 (void) va_arg(args, long);
860 (void) va_arg(args, long);
862 /* variable indicator */
863 (void) va_arg(args, enum ECPGttype);
864 (void) va_arg(args, void *); /* skip args */
865 (void) va_arg(args, long);
866 (void) va_arg(args, long);
867 (void) va_arg(args, long);
871 case ECPGt_descriptor:
874 struct descriptor *desc = ecpg_find_desc(line, name);
879 res = PQdescribePrepared(con->connection, stmt_name);
880 if (!ecpg_check_PQresult(res, line, con->connection, compat))
883 if (desc->result != NULL)
884 PQclear(desc->result);
892 if (INFORMIX_MODE(compat))
894 struct sqlda_compat **_sqlda = ptr;
895 struct sqlda_compat *sqlda;
897 res = PQdescribePrepared(con->connection, stmt_name);
898 if (!ecpg_check_PQresult(res, line, con->connection, compat))
901 sqlda = ecpg_build_compat_sqlda(line, res, -1, compat);
904 struct sqlda_compat *sqlda_old = *_sqlda;
905 struct sqlda_compat *sqlda_old1;
909 sqlda_old1 = sqlda_old->desc_next;
911 sqlda_old = sqlda_old1;
922 struct sqlda_struct **_sqlda = ptr;
923 struct sqlda_struct *sqlda;
925 res = PQdescribePrepared(con->connection, stmt_name);
926 if (!ecpg_check_PQresult(res, line, con->connection, compat))
929 sqlda = ecpg_build_native_sqlda(line, res, -1, compat);
932 struct sqlda_struct *sqlda_old = *_sqlda;
933 struct sqlda_struct *sqlda_old1;
937 sqlda_old1 = sqlda_old->desc_next;
939 sqlda_old = sqlda_old1;
951 /* nothing else may come */