LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - descriptor.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 66.1 % 180 119
Test Date: 2026-07-12 22:15:32 Functions: 92.3 % 13 12
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 48.8 % 84 41

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * functions needed for descriptor handling
       3                 :             :  *
       4                 :             :  * src/interfaces/ecpg/preproc/descriptor.c
       5                 :             :  *
       6                 :             :  * since descriptor might be either a string constant or a string var
       7                 :             :  * we need to check for a constant if we expect a constant
       8                 :             :  */
       9                 :             : 
      10                 :             : #include "postgres_fe.h"
      11                 :             : 
      12                 :             : #include "preproc_extern.h"
      13                 :             : 
      14                 :             : /*
      15                 :             :  * assignment handling function (descriptor)
      16                 :             :  */
      17                 :             : 
      18                 :             : static struct assignment *assignments;
      19                 :             : 
      20                 :             : void
      21                 :          81 : push_assignment(const char *var, enum ECPGdtype value)
      22                 :             : {
      23                 :          81 :     struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
      24                 :             : 
      25                 :          81 :     new->next = assignments;
      26                 :          81 :     new->variable = mm_strdup(var);
      27                 :          81 :     new->value = value;
      28                 :          81 :     assignments = new;
      29                 :          81 : }
      30                 :             : 
      31                 :             : static void
      32                 :          57 : drop_assignments(void)
      33                 :             : {
      34         [ +  + ]:         138 :     while (assignments)
      35                 :             :     {
      36                 :          81 :         struct assignment *old_head = assignments;
      37                 :             : 
      38                 :          81 :         assignments = old_head->next;
      39                 :          81 :         free(old_head->variable);
      40                 :          81 :         free(old_head);
      41                 :             :     }
      42                 :          57 : }
      43                 :             : 
      44                 :             : static void
      45                 :          12 : ECPGnumeric_lvalue(char *name)
      46                 :             : {
      47                 :          12 :     const struct variable *v = find_variable(name);
      48                 :             : 
      49         [ +  - ]:          12 :     switch (v->type->type)
      50                 :             :     {
      51                 :          12 :         case ECPGt_short:
      52                 :             :         case ECPGt_int:
      53                 :             :         case ECPGt_long:
      54                 :             :         case ECPGt_long_long:
      55                 :             :         case ECPGt_unsigned_short:
      56                 :             :         case ECPGt_unsigned_int:
      57                 :             :         case ECPGt_unsigned_long:
      58                 :             :         case ECPGt_unsigned_long_long:
      59                 :             :         case ECPGt_const:
      60                 :          12 :             fputs(name, base_yyout);
      61                 :          12 :             break;
      62                 :           0 :         default:
      63                 :           0 :             mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
      64                 :           0 :             break;
      65                 :             :     }
      66                 :          12 : }
      67                 :             : 
      68                 :             : /*
      69                 :             :  * descriptor name lookup
      70                 :             :  */
      71                 :             : 
      72                 :             : static struct descriptor *descriptors;
      73                 :             : 
      74                 :             : void
      75                 :          20 : add_descriptor(const char *name, const char *connection)
      76                 :             : {
      77                 :             :     struct descriptor *new;
      78                 :             : 
      79         [ +  + ]:          20 :     if (name[0] != '"')
      80                 :           1 :         return;
      81                 :             : 
      82                 :          19 :     new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
      83                 :             : 
      84                 :          19 :     new->next = descriptors;
      85                 :          19 :     new->name = mm_strdup(name);
      86         [ +  + ]:          19 :     if (connection)
      87                 :           2 :         new->connection = mm_strdup(connection);
      88                 :             :     else
      89                 :          17 :         new->connection = NULL;
      90                 :          19 :     descriptors = new;
      91                 :             : }
      92                 :             : 
      93                 :             : void
      94                 :          16 : drop_descriptor(const char *name, const char *connection)
      95                 :             : {
      96                 :             :     struct descriptor *i;
      97                 :          16 :     struct descriptor **lastptr = &descriptors;
      98                 :             : 
      99         [ +  + ]:          16 :     if (name[0] != '"')
     100                 :           1 :         return;
     101                 :             : 
     102         [ +  - ]:          19 :     for (i = descriptors; i; lastptr = &i->next, i = i->next)
     103                 :             :     {
     104         [ +  + ]:          19 :         if (strcmp(name, i->name) == 0)
     105                 :             :         {
     106   [ +  +  -  + ]:          15 :             if ((!connection && !i->connection)
     107   [ +  -  +  - ]:           2 :                 || (connection && i->connection
     108         [ +  - ]:           2 :                     && strcmp(connection, i->connection) == 0))
     109                 :             :             {
     110                 :          15 :                 *lastptr = i->next;
     111                 :          15 :                 free(i->connection);
     112                 :          15 :                 free(i->name);
     113                 :          15 :                 free(i);
     114                 :          15 :                 return;
     115                 :             :             }
     116                 :             :         }
     117                 :             :     }
     118         [ #  # ]:           0 :     if (connection)
     119                 :           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
     120                 :             :     else
     121                 :           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
     122                 :             : }
     123                 :             : 
     124                 :             : struct descriptor *
     125                 :          57 : lookup_descriptor(const char *name, const char *connection)
     126                 :             : {
     127                 :             :     struct descriptor *i;
     128                 :             : 
     129         [ +  + ]:          57 :     if (name[0] != '"')
     130                 :           1 :         return NULL;
     131                 :             : 
     132         [ +  - ]:          72 :     for (i = descriptors; i; i = i->next)
     133                 :             :     {
     134         [ +  + ]:          72 :         if (strcmp(name, i->name) == 0)
     135                 :             :         {
     136   [ +  +  -  + ]:          56 :             if ((!connection && !i->connection)
     137   [ +  -  +  - ]:           3 :                 || (connection && i->connection
     138         [ +  - ]:           3 :                     && strcmp(connection, i->connection) == 0))
     139                 :          56 :                 return i;
     140   [ #  #  #  # ]:           0 :             if (connection && !i->connection)
     141                 :             :             {
     142                 :             :                 /* overwrite descriptor's connection */
     143                 :           0 :                 i->connection = mm_strdup(connection);
     144                 :           0 :                 return i;
     145                 :             :             }
     146                 :             :         }
     147                 :             :     }
     148         [ #  # ]:           0 :     if (connection)
     149                 :           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
     150                 :             :     else
     151                 :           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
     152                 :           0 :     return NULL;
     153                 :             : }
     154                 :             : 
     155                 :             : void
     156                 :          11 : output_get_descr_header(const char *desc_name)
     157                 :             : {
     158                 :             :     struct assignment *results;
     159                 :             : 
     160                 :          11 :     fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
     161         [ +  + ]:          22 :     for (results = assignments; results != NULL; results = results->next)
     162                 :             :     {
     163         [ +  - ]:          11 :         if (results->value == ECPGd_count)
     164                 :          11 :             ECPGnumeric_lvalue(results->variable);
     165                 :             :         else
     166                 :           0 :             mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
     167                 :             :     }
     168                 :             : 
     169                 :          11 :     drop_assignments();
     170                 :          11 :     fprintf(base_yyout, "));\n");
     171                 :          11 :     whenever_action(3);
     172                 :          11 : }
     173                 :             : 
     174                 :             : void
     175                 :          32 : output_get_descr(const char *desc_name, const char *index)
     176                 :             : {
     177                 :             :     struct assignment *results;
     178                 :             : 
     179                 :          32 :     fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
     180         [ +  + ]:          84 :     for (results = assignments; results != NULL; results = results->next)
     181                 :             :     {
     182                 :          52 :         const struct variable *v = find_variable(results->variable);
     183                 :          52 :         char       *str_zero = mm_strdup("0");
     184                 :             : 
     185      [ -  -  + ]:          52 :         switch (results->value)
     186                 :             :         {
     187                 :           0 :             case ECPGd_nullable:
     188                 :           0 :                 mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
     189                 :           0 :                 break;
     190                 :           0 :             case ECPGd_key_member:
     191                 :           0 :                 mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
     192                 :           0 :                 break;
     193                 :          52 :             default:
     194                 :          52 :                 break;
     195                 :             :         }
     196                 :          52 :         fprintf(base_yyout, "%s,", get_dtype(results->value));
     197                 :          52 :         ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
     198                 :             :                         NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
     199                 :          52 :         free(str_zero);
     200                 :             :     }
     201                 :          32 :     drop_assignments();
     202                 :          32 :     fputs("ECPGd_EODT);\n", base_yyout);
     203                 :             : 
     204                 :          32 :     whenever_action(2 | 1);
     205                 :          32 : }
     206                 :             : 
     207                 :             : void
     208                 :           1 : output_set_descr_header(const char *desc_name)
     209                 :             : {
     210                 :             :     struct assignment *results;
     211                 :             : 
     212                 :           1 :     fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
     213         [ +  + ]:           2 :     for (results = assignments; results != NULL; results = results->next)
     214                 :             :     {
     215         [ +  - ]:           1 :         if (results->value == ECPGd_count)
     216                 :           1 :             ECPGnumeric_lvalue(results->variable);
     217                 :             :         else
     218                 :           0 :             mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
     219                 :             :     }
     220                 :             : 
     221                 :           1 :     drop_assignments();
     222                 :           1 :     fprintf(base_yyout, "));\n");
     223                 :           1 :     whenever_action(3);
     224                 :           1 : }
     225                 :             : 
     226                 :             : static const char *
     227                 :           0 : descriptor_item_name(enum ECPGdtype itemcode)
     228                 :             : {
     229   [ #  #  #  #  :           0 :     switch (itemcode)
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     230                 :             :     {
     231                 :           0 :         case ECPGd_cardinality:
     232                 :           0 :             return "CARDINALITY";
     233                 :           0 :         case ECPGd_count:
     234                 :           0 :             return "COUNT";
     235                 :           0 :         case ECPGd_data:
     236                 :           0 :             return "DATA";
     237                 :           0 :         case ECPGd_di_code:
     238                 :           0 :             return "DATETIME_INTERVAL_CODE";
     239                 :           0 :         case ECPGd_di_precision:
     240                 :           0 :             return "DATETIME_INTERVAL_PRECISION";
     241                 :           0 :         case ECPGd_indicator:
     242                 :           0 :             return "INDICATOR";
     243                 :           0 :         case ECPGd_key_member:
     244                 :           0 :             return "KEY_MEMBER";
     245                 :           0 :         case ECPGd_length:
     246                 :           0 :             return "LENGTH";
     247                 :           0 :         case ECPGd_name:
     248                 :           0 :             return "NAME";
     249                 :           0 :         case ECPGd_nullable:
     250                 :           0 :             return "NULLABLE";
     251                 :           0 :         case ECPGd_octet:
     252                 :           0 :             return "OCTET_LENGTH";
     253                 :           0 :         case ECPGd_precision:
     254                 :           0 :             return "PRECISION";
     255                 :           0 :         case ECPGd_ret_length:
     256                 :           0 :             return "RETURNED_LENGTH";
     257                 :           0 :         case ECPGd_ret_octet:
     258                 :           0 :             return "RETURNED_OCTET_LENGTH";
     259                 :           0 :         case ECPGd_scale:
     260                 :           0 :             return "SCALE";
     261                 :           0 :         case ECPGd_type:
     262                 :           0 :             return "TYPE";
     263                 :           0 :         default:
     264                 :           0 :             return NULL;
     265                 :             :     }
     266                 :             : }
     267                 :             : 
     268                 :             : void
     269                 :          13 : output_set_descr(const char *desc_name, const char *index)
     270                 :             : {
     271                 :             :     struct assignment *results;
     272                 :             : 
     273                 :          13 :     fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
     274         [ +  + ]:          30 :     for (results = assignments; results != NULL; results = results->next)
     275                 :             :     {
     276                 :          17 :         const struct variable *v = find_variable(results->variable);
     277                 :             : 
     278   [ -  -  +  - ]:          17 :         switch (results->value)
     279                 :             :         {
     280                 :           0 :             case ECPGd_cardinality:
     281                 :             :             case ECPGd_di_code:
     282                 :             :             case ECPGd_di_precision:
     283                 :             :             case ECPGd_precision:
     284                 :             :             case ECPGd_scale:
     285                 :           0 :                 mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
     286                 :             :                         descriptor_item_name(results->value));
     287                 :             :                 break;
     288                 :             : 
     289                 :           0 :             case ECPGd_key_member:
     290                 :             :             case ECPGd_name:
     291                 :             :             case ECPGd_nullable:
     292                 :             :             case ECPGd_octet:
     293                 :             :             case ECPGd_ret_length:
     294                 :             :             case ECPGd_ret_octet:
     295                 :           0 :                 mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
     296                 :             :                         descriptor_item_name(results->value));
     297                 :             :                 break;
     298                 :             : 
     299                 :          17 :             case ECPGd_data:
     300                 :             :             case ECPGd_indicator:
     301                 :             :             case ECPGd_length:
     302                 :             :             case ECPGd_type:
     303                 :             :                 {
     304                 :          17 :                     char       *str_zero = mm_strdup("0");
     305                 :             : 
     306                 :          17 :                     fprintf(base_yyout, "%s,", get_dtype(results->value));
     307                 :          17 :                     ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
     308                 :             :                                     NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
     309                 :          17 :                     free(str_zero);
     310                 :             :                 }
     311                 :          17 :                 break;
     312                 :             : 
     313                 :          17 :             default:
     314                 :             :                 ;
     315                 :             :         }
     316                 :             :     }
     317                 :          13 :     drop_assignments();
     318                 :          13 :     fputs("ECPGd_EODT);\n", base_yyout);
     319                 :             : 
     320                 :          13 :     whenever_action(2 | 1);
     321                 :          13 : }
     322                 :             : 
     323                 :             : /*
     324                 :             :  * I consider dynamic allocation overkill since at most two descriptor
     325                 :             :  * variables are possible per statement. (input and output descriptor)
     326                 :             :  * And descriptors are no normal variables, so they don't belong into
     327                 :             :  * the variable list.
     328                 :             :  */
     329                 :             : 
     330                 :             : #define MAX_DESCRIPTOR_NAMELEN 128
     331                 :             : struct variable *
     332                 :          24 : descriptor_variable(const char *name, int input)
     333                 :             : {
     334                 :             :     static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN];
     335                 :             :     static struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0};
     336                 :             :     static struct variable varspace[2] = {
     337                 :             :         {descriptor_names[0], &descriptor_type, 0, NULL},
     338                 :             :         {descriptor_names[1], &descriptor_type, 0, NULL}
     339                 :             :     };
     340                 :             : 
     341                 :          24 :     strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
     342                 :          24 :     return &varspace[input];
     343                 :             : }
     344                 :             : 
     345                 :             : struct variable *
     346                 :          25 : sqlda_variable(const char *name)
     347                 :             : {
     348                 :             :     /*
     349                 :             :      * Presently, sqlda variables are only needed for the duration of the
     350                 :             :      * current statement.  Rather than add infrastructure to manage them,
     351                 :             :      * let's just loc_alloc them.
     352                 :             :      */
     353                 :          25 :     struct variable *p = (struct variable *) loc_alloc(sizeof(struct variable));
     354                 :             : 
     355                 :          25 :     p->name = loc_strdup(name);
     356                 :          25 :     p->type = (struct ECPGtype *) loc_alloc(sizeof(struct ECPGtype));
     357                 :          25 :     p->type->type = ECPGt_sqlda;
     358                 :          25 :     p->type->type_name = NULL;
     359                 :          25 :     p->type->size = NULL;
     360                 :          25 :     p->type->struct_sizeof = NULL;
     361                 :          25 :     p->type->u.element = NULL;
     362                 :          25 :     p->type->counter = 0;
     363                 :          25 :     p->brace_level = 0;
     364                 :          25 :     p->next = NULL;
     365                 :             : 
     366                 :          25 :     return p;
     367                 :             : }
        

Generated by: LCOV version 2.0-1