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