LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/preproc - descriptor.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 66.5 % 182 121 1 15 45 1 40 1 79 15 39 2
Current Date: 2023-04-08 15:15:32 Functions: 92.3 % 13 12 1 7 1 4 1 7
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

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