LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - descriptor.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 121 182 66.5 %
Date: 2024-03-28 21:11:01 Functions: 12 13 92.3 %
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         156 : push_assignment(char *var, enum ECPGdtype value)
      22             : {
      23         156 :     struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
      24             : 
      25         156 :     new->next = assignments;
      26         156 :     new->variable = mm_alloc(strlen(var) + 1);
      27         156 :     strcpy(new->variable, var);
      28         156 :     new->value = value;
      29         156 :     assignments = new;
      30         156 : }
      31             : 
      32             : static void
      33         108 : drop_assignments(void)
      34             : {
      35         264 :     while (assignments)
      36             :     {
      37         156 :         struct assignment *old_head = assignments;
      38             : 
      39         156 :         assignments = old_head->next;
      40         156 :         free(old_head->variable);
      41         156 :         free(old_head);
      42             :     }
      43         108 : }
      44             : 
      45             : static void
      46          24 : ECPGnumeric_lvalue(char *name)
      47             : {
      48          24 :     const struct variable *v = find_variable(name);
      49             : 
      50          24 :     switch (v->type->type)
      51             :     {
      52          24 :         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          24 :             fputs(name, base_yyout);
      62          24 :             break;
      63           0 :         default:
      64           0 :             mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
      65           0 :             break;
      66             :     }
      67          24 : }
      68             : 
      69             : /*
      70             :  * descriptor name lookup
      71             :  */
      72             : 
      73             : static struct descriptor *descriptors;
      74             : 
      75             : void
      76          36 : add_descriptor(char *name, char *connection)
      77             : {
      78             :     struct descriptor *new;
      79             : 
      80          36 :     if (name[0] != '"')
      81           2 :         return;
      82             : 
      83          34 :     new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
      84             : 
      85          34 :     new->next = descriptors;
      86          34 :     new->name = mm_alloc(strlen(name) + 1);
      87          34 :     strcpy(new->name, name);
      88          34 :     if (connection)
      89             :     {
      90           4 :         new->connection = mm_alloc(strlen(connection) + 1);
      91           4 :         strcpy(new->connection, connection);
      92             :     }
      93             :     else
      94          30 :         new->connection = connection;
      95          34 :     descriptors = new;
      96             : }
      97             : 
      98             : void
      99          32 : drop_descriptor(char *name, char *connection)
     100             : {
     101             :     struct descriptor *i;
     102          32 :     struct descriptor **lastptr = &descriptors;
     103             : 
     104          32 :     if (name[0] != '"')
     105           2 :         return;
     106             : 
     107          38 :     for (i = descriptors; i; lastptr = &i->next, i = i->next)
     108             :     {
     109          38 :         if (strcmp(name, i->name) == 0)
     110             :         {
     111          30 :             if ((!connection && !i->connection)
     112           4 :                 || (connection && i->connection
     113           4 :                     && strcmp(connection, i->connection) == 0))
     114             :             {
     115          30 :                 *lastptr = i->next;
     116          30 :                 free(i->connection);
     117          30 :                 free(i->name);
     118          30 :                 free(i);
     119          30 :                 return;
     120             :             }
     121             :         }
     122             :     }
     123           0 :     if (connection)
     124           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
     125             :     else
     126           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
     127             : }
     128             : 
     129             : struct descriptor
     130             :            *
     131         108 : lookup_descriptor(char *name, char *connection)
     132             : {
     133             :     struct descriptor *i;
     134             : 
     135         108 :     if (name[0] != '"')
     136           2 :         return NULL;
     137             : 
     138         134 :     for (i = descriptors; i; i = i->next)
     139             :     {
     140         134 :         if (strcmp(name, i->name) == 0)
     141             :         {
     142         106 :             if ((!connection && !i->connection)
     143           6 :                 || (connection && i->connection
     144           6 :                     && strcmp(connection, i->connection) == 0))
     145         106 :                 return i;
     146           0 :             if (connection && !i->connection)
     147             :             {
     148             :                 /* overwrite descriptor's connection */
     149           0 :                 i->connection = mm_strdup(connection);
     150           0 :                 return i;
     151             :             }
     152             :         }
     153             :     }
     154           0 :     if (connection)
     155           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
     156             :     else
     157           0 :         mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
     158           0 :     return NULL;
     159             : }
     160             : 
     161             : void
     162          22 : output_get_descr_header(char *desc_name)
     163             : {
     164             :     struct assignment *results;
     165             : 
     166          22 :     fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
     167          44 :     for (results = assignments; results != NULL; results = results->next)
     168             :     {
     169          22 :         if (results->value == ECPGd_count)
     170          22 :             ECPGnumeric_lvalue(results->variable);
     171             :         else
     172           0 :             mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
     173             :     }
     174             : 
     175          22 :     drop_assignments();
     176          22 :     fprintf(base_yyout, "));\n");
     177          22 :     whenever_action(3);
     178          22 : }
     179             : 
     180             : void
     181          62 : output_get_descr(char *desc_name, char *index)
     182             : {
     183             :     struct assignment *results;
     184             : 
     185          62 :     fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
     186         164 :     for (results = assignments; results != NULL; results = results->next)
     187             :     {
     188         102 :         const struct variable *v = find_variable(results->variable);
     189         102 :         char       *str_zero = mm_strdup("0");
     190             : 
     191         102 :         switch (results->value)
     192             :         {
     193           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           0 :                 break;
     199         102 :             default:
     200         102 :                 break;
     201             :         }
     202         102 :         fprintf(base_yyout, "%s,", get_dtype(results->value));
     203         102 :         ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
     204             :                         NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
     205         102 :         free(str_zero);
     206             :     }
     207          62 :     drop_assignments();
     208          62 :     fputs("ECPGd_EODT);\n", base_yyout);
     209             : 
     210          62 :     whenever_action(2 | 1);
     211          62 : }
     212             : 
     213             : void
     214           2 : output_set_descr_header(char *desc_name)
     215             : {
     216             :     struct assignment *results;
     217             : 
     218           2 :     fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
     219           4 :     for (results = assignments; results != NULL; results = results->next)
     220             :     {
     221           2 :         if (results->value == ECPGd_count)
     222           2 :             ECPGnumeric_lvalue(results->variable);
     223             :         else
     224           0 :             mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
     225             :     }
     226             : 
     227           2 :     drop_assignments();
     228           2 :     fprintf(base_yyout, "));\n");
     229           2 :     whenever_action(3);
     230           2 : }
     231             : 
     232             : static const char *
     233           0 : descriptor_item_name(enum ECPGdtype itemcode)
     234             : {
     235           0 :     switch (itemcode)
     236             :     {
     237           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           0 :             return NULL;
     271             :     }
     272             : }
     273             : 
     274             : void
     275          22 : output_set_descr(char *desc_name, char *index)
     276             : {
     277             :     struct assignment *results;
     278             : 
     279          22 :     fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
     280          52 :     for (results = assignments; results != NULL; results = results->next)
     281             :     {
     282          30 :         const struct variable *v = find_variable(results->variable);
     283             : 
     284          30 :         switch (results->value)
     285             :         {
     286           0 :             case ECPGd_cardinality:
     287             :             case ECPGd_di_code:
     288             :             case ECPGd_di_precision:
     289             :             case ECPGd_precision:
     290             :             case ECPGd_scale:
     291           0 :                 mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
     292             :                         descriptor_item_name(results->value));
     293             :                 break;
     294             : 
     295           0 :             case ECPGd_key_member:
     296             :             case ECPGd_name:
     297             :             case ECPGd_nullable:
     298             :             case ECPGd_octet:
     299             :             case ECPGd_ret_length:
     300             :             case ECPGd_ret_octet:
     301           0 :                 mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
     302             :                         descriptor_item_name(results->value));
     303             :                 break;
     304             : 
     305          30 :             case ECPGd_data:
     306             :             case ECPGd_indicator:
     307             :             case ECPGd_length:
     308             :             case ECPGd_type:
     309             :                 {
     310          30 :                     char       *str_zero = mm_strdup("0");
     311             : 
     312          30 :                     fprintf(base_yyout, "%s,", get_dtype(results->value));
     313          30 :                     ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
     314             :                                     NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
     315          30 :                     free(str_zero);
     316             :                 }
     317          30 :                 break;
     318             : 
     319          30 :             default:
     320             :                 ;
     321             :         }
     322             :     }
     323          22 :     drop_assignments();
     324          22 :     fputs("ECPGd_EODT);\n", base_yyout);
     325             : 
     326          22 :     whenever_action(2 | 1);
     327          22 : }
     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             : struct variable *
     337          44 : 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             : 
     346          44 :     strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
     347          44 :     return &varspace[input];
     348             : }
     349             : 
     350             : struct variable *
     351          50 : sqlda_variable(const char *name)
     352             : {
     353          50 :     struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
     354             : 
     355          50 :     p->name = mm_strdup(name);
     356          50 :     p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
     357          50 :     p->type->type = ECPGt_sqlda;
     358          50 :     p->type->size = NULL;
     359          50 :     p->type->struct_sizeof = NULL;
     360          50 :     p->type->u.element = NULL;
     361          50 :     p->type->counter = 0;
     362          50 :     p->brace_level = 0;
     363          50 :     p->next = NULL;
     364             : 
     365          50 :     return p;
     366             : }

Generated by: LCOV version 1.14