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

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

Generated by: LCOV version 2.3.2-1