Header And Logo

PostgreSQL
| The world's most advanced open source database.

descriptor.c

Go to the documentation of this file.
00001 /*
00002  * functions needed for descriptor handling
00003  *
00004  * src/interfaces/ecpg/preproc/descriptor.c
00005  *
00006  * since descriptor might be either a string constant or a string var
00007  * we need to check for a constant if we expect a constant
00008  */
00009 
00010 #include "postgres_fe.h"
00011 
00012 #include "extern.h"
00013 
00014 /*
00015  * assignment handling function (descriptor)
00016  */
00017 
00018 static struct assignment *assignments;
00019 
00020 void
00021 push_assignment(char *var, enum ECPGdtype value)
00022 {
00023     struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
00024 
00025     new->next = assignments;
00026     new->variable = mm_alloc(strlen(var) + 1);
00027     strcpy(new->variable, var);
00028     new->value = value;
00029     assignments = new;
00030 }
00031 
00032 static void
00033 drop_assignments(void)
00034 {
00035     while (assignments)
00036     {
00037         struct assignment *old_head = assignments;
00038 
00039         assignments = old_head->next;
00040         free(old_head->variable);
00041         free(old_head);
00042     }
00043 }
00044 
00045 static void
00046 ECPGnumeric_lvalue(char *name)
00047 {
00048     const struct variable *v = find_variable(name);
00049 
00050     switch (v->type->type)
00051     {
00052         case ECPGt_short:
00053         case ECPGt_int:
00054         case ECPGt_long:
00055         case ECPGt_long_long:
00056         case ECPGt_unsigned_short:
00057         case ECPGt_unsigned_int:
00058         case ECPGt_unsigned_long:
00059         case ECPGt_unsigned_long_long:
00060         case ECPGt_const:
00061             fputs(name, yyout);
00062             break;
00063         default:
00064             mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
00065             break;
00066     }
00067 }
00068 
00069 /*
00070  * descriptor name lookup
00071  */
00072 
00073 static struct descriptor *descriptors;
00074 
00075 void
00076 add_descriptor(char *name, char *connection)
00077 {
00078     struct descriptor *new;
00079 
00080     if (name[0] != '"')
00081         return;
00082 
00083     new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
00084 
00085     new->next = descriptors;
00086     new->name = mm_alloc(strlen(name) + 1);
00087     strcpy(new->name, name);
00088     if (connection)
00089     {
00090         new->connection = mm_alloc(strlen(connection) + 1);
00091         strcpy(new->connection, connection);
00092     }
00093     else
00094         new->connection = connection;
00095     descriptors = new;
00096 }
00097 
00098 void
00099 drop_descriptor(char *name, char *connection)
00100 {
00101     struct descriptor *i;
00102     struct descriptor **lastptr = &descriptors;
00103 
00104     if (name[0] != '"')
00105         return;
00106 
00107     for (i = descriptors; i; lastptr = &i->next, i = i->next)
00108     {
00109         if (strcmp(name, i->name) == 0)
00110         {
00111             if ((!connection && !i->connection)
00112                 || (connection && i->connection
00113                     && strcmp(connection, i->connection) == 0))
00114             {
00115                 *lastptr = i->next;
00116                 if (i->connection)
00117                     free(i->connection);
00118                 free(i->name);
00119                 free(i);
00120                 return;
00121             }
00122         }
00123     }
00124     mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name);
00125 }
00126 
00127 struct descriptor
00128            *
00129 lookup_descriptor(char *name, char *connection)
00130 {
00131     struct descriptor *i;
00132 
00133     if (name[0] != '"')
00134         return NULL;
00135 
00136     for (i = descriptors; i; i = i->next)
00137     {
00138         if (strcmp(name, i->name) == 0)
00139         {
00140             if ((!connection && !i->connection)
00141                 || (connection && i->connection
00142                     && strcmp(connection, i->connection) == 0))
00143                 return i;
00144         }
00145     }
00146     mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name);
00147     return NULL;
00148 }
00149 
00150 void
00151 output_get_descr_header(char *desc_name)
00152 {
00153     struct assignment *results;
00154 
00155     fprintf(yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
00156     for (results = assignments; results != NULL; results = results->next)
00157     {
00158         if (results->value == ECPGd_count)
00159             ECPGnumeric_lvalue(results->variable);
00160         else
00161             mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
00162     }
00163 
00164     drop_assignments();
00165     fprintf(yyout, "));\n");
00166     whenever_action(3);
00167 }
00168 
00169 void
00170 output_get_descr(char *desc_name, char *index)
00171 {
00172     struct assignment *results;
00173 
00174     fprintf(yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
00175     for (results = assignments; results != NULL; results = results->next)
00176     {
00177         const struct variable *v = find_variable(results->variable);
00178 
00179         switch (results->value)
00180         {
00181             case ECPGd_nullable:
00182                 mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
00183                 break;
00184             case ECPGd_key_member:
00185                 mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
00186                 break;
00187             default:
00188                 break;
00189         }
00190         fprintf(yyout, "%s,", get_dtype(results->value));
00191         ECPGdump_a_type(yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, mm_strdup("0"), NULL, NULL);
00192     }
00193     drop_assignments();
00194     fputs("ECPGd_EODT);\n", yyout);
00195 
00196     whenever_action(2 | 1);
00197 }
00198 
00199 void
00200 output_set_descr_header(char *desc_name)
00201 {
00202     struct assignment *results;
00203 
00204     fprintf(yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
00205     for (results = assignments; results != NULL; results = results->next)
00206     {
00207         if (results->value == ECPGd_count)
00208             ECPGnumeric_lvalue(results->variable);
00209         else
00210             mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
00211     }
00212 
00213     drop_assignments();
00214     fprintf(yyout, "));\n");
00215     whenever_action(3);
00216 }
00217 
00218 static const char *
00219 descriptor_item_name(enum ECPGdtype itemcode)
00220 {
00221     switch (itemcode)
00222     {
00223         case ECPGd_cardinality:
00224             return "CARDINALITY";
00225         case ECPGd_count:
00226             return "COUNT";
00227         case ECPGd_data:
00228             return "DATA";
00229         case ECPGd_di_code:
00230             return "DATETIME_INTERVAL_CODE";
00231         case ECPGd_di_precision:
00232             return "DATETIME_INTERVAL_PRECISION";
00233         case ECPGd_indicator:
00234             return "INDICATOR";
00235         case ECPGd_key_member:
00236             return "KEY_MEMBER";
00237         case ECPGd_length:
00238             return "LENGTH";
00239         case ECPGd_name:
00240             return "NAME";
00241         case ECPGd_nullable:
00242             return "NULLABLE";
00243         case ECPGd_octet:
00244             return "OCTET_LENGTH";
00245         case ECPGd_precision:
00246             return "PRECISION";
00247         case ECPGd_ret_length:
00248             return "RETURNED_LENGTH";
00249         case ECPGd_ret_octet:
00250             return "RETURNED_OCTET_LENGTH";
00251         case ECPGd_scale:
00252             return "SCALE";
00253         case ECPGd_type:
00254             return "TYPE";
00255         default:
00256             return NULL;
00257     }
00258 }
00259 
00260 void
00261 output_set_descr(char *desc_name, char *index)
00262 {
00263     struct assignment *results;
00264 
00265     fprintf(yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
00266     for (results = assignments; results != NULL; results = results->next)
00267     {
00268         const struct variable *v = find_variable(results->variable);
00269 
00270         switch (results->value)
00271         {
00272             case ECPGd_cardinality:
00273             case ECPGd_di_code:
00274             case ECPGd_di_precision:
00275             case ECPGd_precision:
00276             case ECPGd_scale:
00277                 mmerror(PARSE_ERROR, ET_FATAL, "descriptor item \"%s\" is not implemented",
00278                         descriptor_item_name(results->value));
00279                 break;
00280 
00281             case ECPGd_key_member:
00282             case ECPGd_name:
00283             case ECPGd_nullable:
00284             case ECPGd_octet:
00285             case ECPGd_ret_length:
00286             case ECPGd_ret_octet:
00287                 mmerror(PARSE_ERROR, ET_FATAL, "descriptor item \"%s\" cannot be set",
00288                         descriptor_item_name(results->value));
00289                 break;
00290 
00291             case ECPGd_data:
00292             case ECPGd_indicator:
00293             case ECPGd_length:
00294             case ECPGd_type:
00295                 fprintf(yyout, "%s,", get_dtype(results->value));
00296                 ECPGdump_a_type(yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, mm_strdup("0"), NULL, NULL);
00297                 break;
00298 
00299             default:
00300                 ;
00301         }
00302     }
00303     drop_assignments();
00304     fputs("ECPGd_EODT);\n", yyout);
00305 
00306     whenever_action(2 | 1);
00307 }
00308 
00309 /* I consider dynamic allocation overkill since at most two descriptor
00310    variables are possible per statement. (input and output descriptor)
00311    And descriptors are no normal variables, so they don't belong into
00312    the variable list.
00313 */
00314 
00315 #define MAX_DESCRIPTOR_NAMELEN 128
00316 struct variable *
00317 descriptor_variable(const char *name, int input)
00318 {
00319     static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN];
00320     static struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0};
00321     static struct variable varspace[2] = {
00322         {descriptor_names[0], &descriptor_type, 0, NULL},
00323         {descriptor_names[1], &descriptor_type, 0, NULL}
00324     };
00325 
00326     strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
00327     return &varspace[input];
00328 }
00329 
00330 struct variable *
00331 sqlda_variable(const char *name)
00332 {
00333     struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
00334 
00335     p->name = mm_strdup(name);
00336     p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
00337     p->type->type = ECPGt_sqlda;
00338     p->type->size = NULL;
00339     p->type->struct_sizeof = NULL;
00340     p->type->u.element = NULL;
00341     p->type->counter = 0;
00342     p->brace_level = 0;
00343     p->next = NULL;
00344 
00345     return p;
00346 }