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

Generated by: LCOV version 1.13