Age Owner Branch data TLA 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
8768 bruce@momjian.us 21 :CBC 78 : push_assignment(char *var, enum ECPGdtype value)
22 : : {
23 : 78 : struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
24 : :
8822 meskes@postgresql.or 25 : 78 : new->next = assignments;
8818 26 : 78 : new->variable = mm_alloc(strlen(var) + 1);
27 : 78 : strcpy(new->variable, var);
28 : 78 : new->value = value;
8822 29 : 78 : assignments = new;
8823 30 : 78 : }
31 : :
32 : : static void
33 : 54 : drop_assignments(void)
34 : : {
8822 35 [ + + ]: 132 : while (assignments)
36 : : {
37 : 78 : struct assignment *old_head = assignments;
38 : :
39 : 78 : assignments = old_head->next;
8823 40 : 78 : free(old_head->variable);
41 : 78 : free(old_head);
42 : : }
43 : 54 : }
44 : :
45 : : static void
5959 46 : 12 : ECPGnumeric_lvalue(char *name)
47 : : {
8768 bruce@momjian.us 48 : 12 : const struct variable *v = find_variable(name);
49 : :
8148 meskes@postgresql.or 50 [ + - ]: 12 : switch (v->type->type)
51 : : {
8823 52 : 12 : 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:
2681 tgl@sss.pgh.pa.us 61 : 12 : fputs(name, base_yyout);
8823 meskes@postgresql.or 62 : 12 : break;
8823 meskes@postgresql.or 63 :UBC 0 : default:
5560 peter_e@gmx.net 64 : 0 : mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
8823 meskes@postgresql.or 65 : 0 : break;
66 : : }
8823 meskes@postgresql.or 67 :CBC 12 : }
68 : :
69 : : /*
70 : : * descriptor name lookup
71 : : */
72 : :
73 : : static struct descriptor *descriptors;
74 : :
75 : : void
8768 bruce@momjian.us 76 : 18 : add_descriptor(char *name, char *connection)
77 : : {
78 : : struct descriptor *new;
79 : :
8207 80 [ + + ]: 18 : if (name[0] != '"')
81 : 1 : return;
82 : :
8274 meskes@postgresql.or 83 : 17 : new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
84 : :
8818 85 : 17 : new->next = descriptors;
86 : 17 : new->name = mm_alloc(strlen(name) + 1);
8768 bruce@momjian.us 87 : 17 : strcpy(new->name, name);
88 [ + + ]: 17 : if (connection)
89 : : {
8818 meskes@postgresql.or 90 : 2 : new->connection = mm_alloc(strlen(connection) + 1);
91 : 2 : strcpy(new->connection, connection);
92 : : }
93 : : else
8768 bruce@momjian.us 94 : 15 : new->connection = connection;
8818 meskes@postgresql.or 95 : 17 : descriptors = new;
96 : : }
97 : :
98 : : void
8768 bruce@momjian.us 99 : 16 : drop_descriptor(char *name, char *connection)
100 : : {
101 : : struct descriptor *i;
102 : 16 : struct descriptor **lastptr = &descriptors;
103 : :
8207 104 [ + + ]: 16 : if (name[0] != '"')
105 : 1 : return;
106 : :
8768 107 [ + - ]: 19 : for (i = descriptors; i; lastptr = &i->next, i = i->next)
108 : : {
4492 peter_e@gmx.net 109 [ + + ]: 19 : if (strcmp(name, i->name) == 0)
110 : : {
8768 bruce@momjian.us 111 [ + + - + ]: 15 : if ((!connection && !i->connection)
112 [ + - + - ]: 2 : || (connection && i->connection
4492 peter_e@gmx.net 113 [ + - ]: 2 : && strcmp(connection, i->connection) == 0))
114 : : {
8768 bruce@momjian.us 115 : 15 : *lastptr = i->next;
668 peter@eisentraut.org 116 : 15 : free(i->connection);
8822 meskes@postgresql.or 117 : 15 : free(i->name);
118 : 15 : free(i);
119 : 15 : return;
120 : : }
121 : : }
122 : : }
975 meskes@postgresql.or 123 [ # # ]:UBC 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 : : *
8424 bruce@momjian.us 131 :CBC 54 : lookup_descriptor(char *name, char *connection)
132 : : {
133 : : struct descriptor *i;
134 : :
8207 135 [ + + ]: 54 : if (name[0] != '"')
136 : 1 : return NULL;
137 : :
8818 meskes@postgresql.or 138 [ + - ]: 67 : for (i = descriptors; i; i = i->next)
139 : : {
4492 peter_e@gmx.net 140 [ + + ]: 67 : if (strcmp(name, i->name) == 0)
141 : : {
8768 bruce@momjian.us 142 [ + + - + ]: 53 : if ((!connection && !i->connection)
143 [ + - + - ]: 3 : || (connection && i->connection
4492 peter_e@gmx.net 144 [ + - ]: 3 : && strcmp(connection, i->connection) == 0))
8822 meskes@postgresql.or 145 : 53 : return i;
975 meskes@postgresql.or 146 [ # # # # ]:UBC 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);
8822 158 : 0 : return NULL;
159 : : }
160 : :
161 : : void
8823 meskes@postgresql.or 162 :CBC 11 : output_get_descr_header(char *desc_name)
163 : : {
164 : : struct assignment *results;
165 : :
2681 tgl@sss.pgh.pa.us 166 : 11 : fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
8822 meskes@postgresql.or 167 [ + + ]: 22 : for (results = assignments; results != NULL; results = results->next)
168 : : {
8818 169 [ + - ]: 11 : if (results->value == ECPGd_count)
5959 170 : 11 : ECPGnumeric_lvalue(results->variable);
171 : : else
5560 peter_e@gmx.net 172 :UBC 0 : mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
173 : : }
174 : :
8822 meskes@postgresql.or 175 :CBC 11 : drop_assignments();
2681 tgl@sss.pgh.pa.us 176 : 11 : fprintf(base_yyout, "));\n");
8822 meskes@postgresql.or 177 : 11 : whenever_action(3);
8823 178 : 11 : }
179 : :
180 : : void
8818 181 : 31 : output_get_descr(char *desc_name, char *index)
182 : : {
183 : : struct assignment *results;
184 : :
2681 tgl@sss.pgh.pa.us 185 : 31 : fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
8818 meskes@postgresql.or 186 [ + + ]: 82 : for (results = assignments; results != NULL; results = results->next)
187 : : {
188 : 51 : const struct variable *v = find_variable(results->variable);
2866 rhaas@postgresql.org 189 : 51 : char *str_zero = mm_strdup("0");
190 : :
8818 meskes@postgresql.or 191 [ - - + ]: 51 : switch (results->value)
192 : : {
8818 meskes@postgresql.or 193 :UBC 0 : case ECPGd_nullable:
8075 bruce@momjian.us 194 : 0 : mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
8818 meskes@postgresql.or 195 : 0 : break;
196 : 0 : case ECPGd_key_member:
8075 bruce@momjian.us 197 : 0 : mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
8818 meskes@postgresql.or 198 : 0 : break;
8818 meskes@postgresql.or 199 :CBC 51 : default:
8768 bruce@momjian.us 200 : 51 : break;
201 : : }
2681 tgl@sss.pgh.pa.us 202 : 51 : fprintf(base_yyout, "%s,", get_dtype(results->value));
203 : 51 : ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
204 : : NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
3229 meskes@postgresql.or 205 : 51 : free(str_zero);
206 : : }
8823 207 : 31 : drop_assignments();
2681 tgl@sss.pgh.pa.us 208 : 31 : fputs("ECPGd_EODT);\n", base_yyout);
209 : :
8768 bruce@momjian.us 210 : 31 : whenever_action(2 | 1);
8823 meskes@postgresql.or 211 : 31 : }
212 : :
213 : : void
7228 214 : 1 : output_set_descr_header(char *desc_name)
215 : : {
216 : : struct assignment *results;
217 : :
2681 tgl@sss.pgh.pa.us 218 : 1 : fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
7228 meskes@postgresql.or 219 [ + + ]: 2 : for (results = assignments; results != NULL; results = results->next)
220 : : {
221 [ + - ]: 1 : if (results->value == ECPGd_count)
5959 222 : 1 : ECPGnumeric_lvalue(results->variable);
223 : : else
5560 peter_e@gmx.net 224 :UBC 0 : mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
225 : : }
226 : :
7228 meskes@postgresql.or 227 :CBC 1 : drop_assignments();
2681 tgl@sss.pgh.pa.us 228 : 1 : fprintf(base_yyout, "));\n");
7228 meskes@postgresql.or 229 : 1 : whenever_action(3);
230 : 1 : }
231 : :
232 : : static const char *
7228 meskes@postgresql.or 233 :UBC 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
7228 meskes@postgresql.or 275 :CBC 11 : output_set_descr(char *desc_name, char *index)
276 : : {
277 : : struct assignment *results;
278 : :
2681 tgl@sss.pgh.pa.us 279 : 11 : fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
7228 meskes@postgresql.or 280 [ + + ]: 26 : for (results = assignments; results != NULL; results = results->next)
281 : : {
282 : 15 : const struct variable *v = find_variable(results->variable);
283 : :
284 [ - - + - ]: 15 : switch (results->value)
285 : : {
7228 meskes@postgresql.or 286 :UBC 0 : case ECPGd_cardinality:
287 : : case ECPGd_di_code:
288 : : case ECPGd_di_precision:
289 : : case ECPGd_precision:
290 : : case ECPGd_scale:
3806 peter_e@gmx.net 291 : 0 : mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
292 : : descriptor_item_name(results->value));
293 : : break;
294 : :
7228 meskes@postgresql.or 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:
3806 peter_e@gmx.net 301 : 0 : mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
302 : : descriptor_item_name(results->value));
303 : : break;
304 : :
7228 meskes@postgresql.or 305 :CBC 15 : case ECPGd_data:
306 : : case ECPGd_indicator:
307 : : case ECPGd_length:
308 : : case ECPGd_type:
309 : : {
2866 rhaas@postgresql.org 310 : 15 : char *str_zero = mm_strdup("0");
311 : :
2681 tgl@sss.pgh.pa.us 312 : 15 : fprintf(base_yyout, "%s,", get_dtype(results->value));
313 : 15 : ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
314 : : NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
3229 meskes@postgresql.or 315 : 15 : free(str_zero);
316 : : }
7228 317 : 15 : break;
318 : :
319 : 15 : default:
320 : : ;
321 : : }
322 : : }
323 : 11 : drop_assignments();
2681 tgl@sss.pgh.pa.us 324 : 11 : fputs("ECPGd_EODT);\n", base_yyout);
325 : :
7228 meskes@postgresql.or 326 : 11 : whenever_action(2 | 1);
327 : 11 : }
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 *
8207 bruce@momjian.us 337 : 22 : 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 : :
6276 peter_e@gmx.net 346 : 22 : strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
4426 347 : 22 : return &varspace[input];
348 : : }
349 : :
350 : : struct variable *
5213 meskes@postgresql.or 351 : 25 : sqlda_variable(const char *name)
352 : : {
353 : 25 : struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
354 : :
355 : 25 : p->name = mm_strdup(name);
356 : 25 : p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
357 : 25 : p->type->type = ECPGt_sqlda;
358 : 25 : p->type->size = NULL;
359 : 25 : p->type->struct_sizeof = NULL;
360 : 25 : p->type->u.element = NULL;
5150 361 : 25 : p->type->counter = 0;
5213 362 : 25 : p->brace_level = 0;
363 : 25 : p->next = NULL;
364 : :
365 : 25 : return p;
366 : : }
|