LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - descriptor.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 58.2 % 529 308
Test Date: 2026-07-03 19:57:34 Functions: 90.0 % 20 18
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 48.9 % 233 114

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

Generated by: LCOV version 2.0-1