LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - descriptor.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 118 179 65.9 %
Date: 2024-11-21 09:14:53 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(const 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_strdup(var);
      27         156 :     new->value = value;
      28         156 :     assignments = new;
      29         156 : }
      30             : 
      31             : static void
      32         108 : drop_assignments(void)
      33             : {
      34         264 :     while (assignments)
      35             :     {
      36         156 :         struct assignment *old_head = assignments;
      37             : 
      38         156 :         assignments = old_head->next;
      39         156 :         free(old_head->variable);
      40         156 :         free(old_head);
      41             :     }
      42         108 : }
      43             : 
      44             : static void
      45          24 : ECPGnumeric_lvalue(char *name)
      46             : {
      47          24 :     const struct variable *v = find_variable(name);
      48             : 
      49          24 :     switch (v->type->type)
      50             :     {
      51          24 :         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          24 :             fputs(name, base_yyout);
      61          24 :             break;
      62           0 :         default:
      63           0 :             mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
      64           0 :             break;
      65             :     }
      66          24 : }
      67             : 
      68             : /*
      69             :  * descriptor name lookup
      70             :  */
      71             : 
      72             : static struct descriptor *descriptors;
      73             : 
      74             : void
      75          36 : add_descriptor(const char *name, const char *connection)
      76             : {
      77             :     struct descriptor *new;
      78             : 
      79          36 :     if (name[0] != '"')
      80           2 :         return;
      81             : 
      82          34 :     new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
      83             : 
      84          34 :     new->next = descriptors;
      85          34 :     new->name = mm_strdup(name);
      86          34 :     if (connection)
      87           4 :         new->connection = mm_strdup(connection);
      88             :     else
      89          30 :         new->connection = NULL;
      90          34 :     descriptors = new;
      91             : }
      92             : 
      93             : void
      94          32 : drop_descriptor(const char *name, const char *connection)
      95             : {
      96             :     struct descriptor *i;
      97          32 :     struct descriptor **lastptr = &descriptors;
      98             : 
      99          32 :     if (name[0] != '"')
     100           2 :         return;
     101             : 
     102          38 :     for (i = descriptors; i; lastptr = &i->next, i = i->next)
     103             :     {
     104          38 :         if (strcmp(name, i->name) == 0)
     105             :         {
     106          30 :             if ((!connection && !i->connection)
     107           4 :                 || (connection && i->connection
     108           4 :                     && strcmp(connection, i->connection) == 0))
     109             :             {
     110          30 :                 *lastptr = i->next;
     111          30 :                 free(i->connection);
     112          30 :                 free(i->name);
     113          30 :                 free(i);
     114          30 :                 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         108 : lookup_descriptor(const char *name, const char *connection)
     126             : {
     127             :     struct descriptor *i;
     128             : 
     129         108 :     if (name[0] != '"')
     130           2 :         return NULL;
     131             : 
     132         134 :     for (i = descriptors; i; i = i->next)
     133             :     {
     134         134 :         if (strcmp(name, i->name) == 0)
     135             :         {
     136         106 :             if ((!connection && !i->connection)
     137           6 :                 || (connection && i->connection
     138           6 :                     && strcmp(connection, i->connection) == 0))
     139         106 :                 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          22 : output_get_descr_header(const char *desc_name)
     157             : {
     158             :     struct assignment *results;
     159             : 
     160          22 :     fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
     161          44 :     for (results = assignments; results != NULL; results = results->next)
     162             :     {
     163          22 :         if (results->value == ECPGd_count)
     164          22 :             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          22 :     drop_assignments();
     170          22 :     fprintf(base_yyout, "));\n");
     171          22 :     whenever_action(3);
     172          22 : }
     173             : 
     174             : void
     175          62 : output_get_descr(const char *desc_name, const char *index)
     176             : {
     177             :     struct assignment *results;
     178             : 
     179          62 :     fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
     180         164 :     for (results = assignments; results != NULL; results = results->next)
     181             :     {
     182         102 :         const struct variable *v = find_variable(results->variable);
     183         102 :         char       *str_zero = mm_strdup("0");
     184             : 
     185         102 :         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         102 :             default:
     194         102 :                 break;
     195             :         }
     196         102 :         fprintf(base_yyout, "%s,", get_dtype(results->value));
     197         102 :         ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
     198             :                         NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
     199         102 :         free(str_zero);
     200             :     }
     201          62 :     drop_assignments();
     202          62 :     fputs("ECPGd_EODT);\n", base_yyout);
     203             : 
     204          62 :     whenever_action(2 | 1);
     205          62 : }
     206             : 
     207             : void
     208           2 : output_set_descr_header(const char *desc_name)
     209             : {
     210             :     struct assignment *results;
     211             : 
     212           2 :     fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
     213           4 :     for (results = assignments; results != NULL; results = results->next)
     214             :     {
     215           2 :         if (results->value == ECPGd_count)
     216           2 :             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           2 :     drop_assignments();
     222           2 :     fprintf(base_yyout, "));\n");
     223           2 :     whenever_action(3);
     224           2 : }
     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          22 : output_set_descr(const char *desc_name, const char *index)
     270             : {
     271             :     struct assignment *results;
     272             : 
     273          22 :     fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
     274          52 :     for (results = assignments; results != NULL; results = results->next)
     275             :     {
     276          30 :         const struct variable *v = find_variable(results->variable);
     277             : 
     278          30 :         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          30 :             case ECPGd_data:
     300             :             case ECPGd_indicator:
     301             :             case ECPGd_length:
     302             :             case ECPGd_type:
     303             :                 {
     304          30 :                     char       *str_zero = mm_strdup("0");
     305             : 
     306          30 :                     fprintf(base_yyout, "%s,", get_dtype(results->value));
     307          30 :                     ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
     308             :                                     NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
     309          30 :                     free(str_zero);
     310             :                 }
     311          30 :                 break;
     312             : 
     313          30 :             default:
     314             :                 ;
     315             :         }
     316             :     }
     317          22 :     drop_assignments();
     318          22 :     fputs("ECPGd_EODT);\n", base_yyout);
     319             : 
     320          22 :     whenever_action(2 | 1);
     321          22 : }
     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          44 : 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          44 :     strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
     341          44 :     return &varspace[input];
     342             : }
     343             : 
     344             : struct variable *
     345          50 : sqlda_variable(const char *name)
     346             : {
     347          50 :     struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
     348             : 
     349          50 :     p->name = mm_strdup(name);
     350          50 :     p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
     351          50 :     p->type->type = ECPGt_sqlda;
     352          50 :     p->type->size = NULL;
     353          50 :     p->type->struct_sizeof = NULL;
     354          50 :     p->type->u.element = NULL;
     355          50 :     p->type->counter = 0;
     356          50 :     p->brace_level = 0;
     357          50 :     p->next = NULL;
     358             : 
     359          50 :     return p;
     360             : }

Generated by: LCOV version 1.14