LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - descriptor.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 545 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 20 0
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.3.2-1