LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - descriptor.c (source / functions) Coverage Total Hit UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 57.8 % 524 303 4 217 2 18 1 282 2 20 1
Current Date: 2023-04-08 15:15:32 Functions: 90.0 % 20 18 2 1 17
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a