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 0 : push_assignment(const char *var, enum ECPGdtype value)
22 : {
23 0 : struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
24 :
25 0 : new->next = assignments;
26 0 : new->variable = mm_strdup(var);
27 0 : new->value = value;
28 0 : assignments = new;
29 0 : }
30 :
31 : static void
32 0 : drop_assignments(void)
33 : {
34 0 : while (assignments)
35 : {
36 0 : struct assignment *old_head = assignments;
37 :
38 0 : assignments = old_head->next;
39 0 : free(old_head->variable);
40 0 : free(old_head);
41 0 : }
42 0 : }
43 :
44 : static void
45 0 : ECPGnumeric_lvalue(char *name)
46 : {
47 0 : const struct variable *v = find_variable(name);
48 :
49 0 : switch (v->type->type)
50 : {
51 : 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 0 : fputs(name, base_yyout);
61 0 : break;
62 : default:
63 0 : mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
64 0 : break;
65 : }
66 0 : }
67 :
68 : /*
69 : * descriptor name lookup
70 : */
71 :
72 : static struct descriptor *descriptors;
73 :
74 : void
75 0 : add_descriptor(const char *name, const char *connection)
76 : {
77 0 : struct descriptor *new;
78 :
79 0 : if (name[0] != '"')
80 0 : return;
81 :
82 0 : new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
83 :
84 0 : new->next = descriptors;
85 0 : new->name = mm_strdup(name);
86 0 : if (connection)
87 0 : new->connection = mm_strdup(connection);
88 : else
89 0 : new->connection = NULL;
90 0 : descriptors = new;
91 0 : }
92 :
93 : void
94 0 : drop_descriptor(const char *name, const char *connection)
95 : {
96 0 : struct descriptor *i;
97 0 : struct descriptor **lastptr = &descriptors;
98 :
99 0 : if (name[0] != '"')
100 0 : return;
101 :
102 0 : for (i = descriptors; i; lastptr = &i->next, i = i->next)
103 : {
104 0 : if (strcmp(name, i->name) == 0)
105 : {
106 0 : if ((!connection && !i->connection)
107 0 : || (connection && i->connection
108 0 : && strcmp(connection, i->connection) == 0))
109 : {
110 0 : *lastptr = i->next;
111 0 : free(i->connection);
112 0 : free(i->name);
113 0 : free(i);
114 0 : return;
115 : }
116 0 : }
117 0 : }
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 0 : }
123 :
124 : struct descriptor *
125 0 : lookup_descriptor(const char *name, const char *connection)
126 : {
127 0 : struct descriptor *i;
128 :
129 0 : if (name[0] != '"')
130 0 : return NULL;
131 :
132 0 : for (i = descriptors; i; i = i->next)
133 : {
134 0 : if (strcmp(name, i->name) == 0)
135 : {
136 0 : if ((!connection && !i->connection)
137 0 : || (connection && i->connection
138 0 : && strcmp(connection, i->connection) == 0))
139 0 : 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 0 : }
147 0 : }
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 0 : }
154 :
155 : void
156 0 : output_get_descr_header(const char *desc_name)
157 : {
158 0 : struct assignment *results;
159 :
160 0 : fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
161 0 : for (results = assignments; results != NULL; results = results->next)
162 : {
163 0 : if (results->value == ECPGd_count)
164 0 : ECPGnumeric_lvalue(results->variable);
165 : else
166 0 : mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
167 0 : }
168 :
169 0 : drop_assignments();
170 0 : fprintf(base_yyout, "));\n");
171 0 : whenever_action(3);
172 0 : }
173 :
174 : void
175 0 : output_get_descr(const char *desc_name, const char *index)
176 : {
177 0 : struct assignment *results;
178 :
179 0 : fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
180 0 : for (results = assignments; results != NULL; results = results->next)
181 : {
182 0 : const struct variable *v = find_variable(results->variable);
183 0 : char *str_zero = mm_strdup("0");
184 :
185 0 : switch (results->value)
186 : {
187 : case ECPGd_nullable:
188 0 : mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
189 0 : break;
190 : case ECPGd_key_member:
191 0 : mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
192 0 : break;
193 : default:
194 0 : break;
195 : }
196 0 : fprintf(base_yyout, "%s,", get_dtype(results->value));
197 0 : ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
198 0 : NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
199 0 : free(str_zero);
200 0 : }
201 0 : drop_assignments();
202 0 : fputs("ECPGd_EODT);\n", base_yyout);
203 :
204 0 : whenever_action(2 | 1);
205 0 : }
206 :
207 : void
208 0 : output_set_descr_header(const char *desc_name)
209 : {
210 0 : struct assignment *results;
211 :
212 0 : fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
213 0 : for (results = assignments; results != NULL; results = results->next)
214 : {
215 0 : if (results->value == ECPGd_count)
216 0 : ECPGnumeric_lvalue(results->variable);
217 : else
218 0 : mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
219 0 : }
220 :
221 0 : drop_assignments();
222 0 : fprintf(base_yyout, "));\n");
223 0 : whenever_action(3);
224 0 : }
225 :
226 : static const char *
227 0 : descriptor_item_name(enum ECPGdtype itemcode)
228 : {
229 0 : switch (itemcode)
230 : {
231 : case ECPGd_cardinality:
232 0 : return "CARDINALITY";
233 : case ECPGd_count:
234 0 : return "COUNT";
235 : case ECPGd_data:
236 0 : return "DATA";
237 : case ECPGd_di_code:
238 0 : return "DATETIME_INTERVAL_CODE";
239 : case ECPGd_di_precision:
240 0 : return "DATETIME_INTERVAL_PRECISION";
241 : case ECPGd_indicator:
242 0 : return "INDICATOR";
243 : case ECPGd_key_member:
244 0 : return "KEY_MEMBER";
245 : case ECPGd_length:
246 0 : return "LENGTH";
247 : case ECPGd_name:
248 0 : return "NAME";
249 : case ECPGd_nullable:
250 0 : return "NULLABLE";
251 : case ECPGd_octet:
252 0 : return "OCTET_LENGTH";
253 : case ECPGd_precision:
254 0 : return "PRECISION";
255 : case ECPGd_ret_length:
256 0 : return "RETURNED_LENGTH";
257 : case ECPGd_ret_octet:
258 0 : return "RETURNED_OCTET_LENGTH";
259 : case ECPGd_scale:
260 0 : return "SCALE";
261 : case ECPGd_type:
262 0 : return "TYPE";
263 : default:
264 0 : return NULL;
265 : }
266 0 : }
267 :
268 : void
269 0 : output_set_descr(const char *desc_name, const char *index)
270 : {
271 0 : struct assignment *results;
272 :
273 0 : fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
274 0 : for (results = assignments; results != NULL; results = results->next)
275 : {
276 0 : const struct variable *v = find_variable(results->variable);
277 :
278 0 : switch (results->value)
279 : {
280 : 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 0 : descriptor_item_name(results->value));
287 : break;
288 :
289 : 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 0 : descriptor_item_name(results->value));
297 : break;
298 :
299 : case ECPGd_data:
300 : case ECPGd_indicator:
301 : case ECPGd_length:
302 : case ECPGd_type:
303 : {
304 0 : char *str_zero = mm_strdup("0");
305 :
306 0 : fprintf(base_yyout, "%s,", get_dtype(results->value));
307 0 : ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
308 0 : NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
309 0 : free(str_zero);
310 0 : }
311 0 : break;
312 :
313 : default:
314 : ;
315 0 : }
316 0 : }
317 0 : drop_assignments();
318 0 : fputs("ECPGd_EODT);\n", base_yyout);
319 :
320 0 : whenever_action(2 | 1);
321 0 : }
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 0 : 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 0 : strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
341 0 : return &varspace[input];
342 : }
343 :
344 : struct variable *
345 0 : 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 0 : struct variable *p = (struct variable *) loc_alloc(sizeof(struct variable));
353 :
354 0 : p->name = loc_strdup(name);
355 0 : p->type = (struct ECPGtype *) loc_alloc(sizeof(struct ECPGtype));
356 0 : p->type->type = ECPGt_sqlda;
357 0 : p->type->type_name = NULL;
358 0 : p->type->size = NULL;
359 0 : p->type->struct_sizeof = NULL;
360 0 : p->type->u.element = NULL;
361 0 : p->type->counter = 0;
362 0 : p->brace_level = 0;
363 0 : p->next = NULL;
364 :
365 0 : return p;
366 0 : }
|