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
327 tgl@sss.pgh.pa.us 21 :GIC 78 : push_assignment(const char *var, enum ECPGdtype value)
22 : : {
9278 bruce@momjian.us 23 : 78 : struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
24 : :
9332 meskes@postgresql.or 25 : 78 : new->next = assignments;
327 tgl@sss.pgh.pa.us 26 : 78 : new->variable = mm_strdup(var);
9328 meskes@postgresql.or 27 : 78 : new->value = value;
9332 28 : 78 : assignments = new;
9333 29 : 78 : }
30 : :
31 : : static void
32 : 54 : drop_assignments(void)
33 : : {
9332 34 [ + + ]: 132 : while (assignments)
35 : : {
36 : 78 : struct assignment *old_head = assignments;
37 : :
38 : 78 : assignments = old_head->next;
9333 39 : 78 : free(old_head->variable);
40 : 78 : free(old_head);
41 : : }
42 : 54 : }
43 : :
44 : : static void
6469 45 : 12 : ECPGnumeric_lvalue(char *name)
46 : : {
9278 bruce@momjian.us 47 : 12 : const struct variable *v = find_variable(name);
48 : :
8658 meskes@postgresql.or 49 [ + - ]: 12 : switch (v->type->type)
50 : : {
9333 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:
3191 tgl@sss.pgh.pa.us 60 : 12 : fputs(name, base_yyout);
9333 meskes@postgresql.or 61 : 12 : break;
9333 meskes@postgresql.or 62 :UIC 0 : default:
6070 peter_e@gmx.net 63 : 0 : mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
9333 meskes@postgresql.or 64 : 0 : break;
65 : : }
9333 meskes@postgresql.or 66 :GIC 12 : }
67 : :
68 : : /*
69 : : * descriptor name lookup
70 : : */
71 : :
72 : : static struct descriptor *descriptors;
73 : :
74 : : void
327 tgl@sss.pgh.pa.us 75 : 18 : add_descriptor(const char *name, const char *connection)
76 : : {
77 : : struct descriptor *new;
78 : :
8717 bruce@momjian.us 79 [ + + ]: 18 : if (name[0] != '"')
80 : 1 : return;
81 : :
8784 meskes@postgresql.or 82 : 17 : new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
83 : :
9328 84 : 17 : new->next = descriptors;
327 tgl@sss.pgh.pa.us 85 : 17 : new->name = mm_strdup(name);
9278 bruce@momjian.us 86 [ + + ]: 17 : if (connection)
327 tgl@sss.pgh.pa.us 87 : 2 : new->connection = mm_strdup(connection);
88 : : else
89 : 15 : new->connection = NULL;
9328 meskes@postgresql.or 90 : 17 : descriptors = new;
91 : : }
92 : :
93 : : void
327 tgl@sss.pgh.pa.us 94 : 16 : drop_descriptor(const char *name, const char *connection)
95 : : {
96 : : struct descriptor *i;
9278 bruce@momjian.us 97 : 16 : struct descriptor **lastptr = &descriptors;
98 : :
8717 99 [ + + ]: 16 : if (name[0] != '"')
100 : 1 : return;
101 : :
9278 102 [ + - ]: 19 : for (i = descriptors; i; lastptr = &i->next, i = i->next)
103 : : {
5002 peter_e@gmx.net 104 [ + + ]: 19 : if (strcmp(name, i->name) == 0)
105 : : {
9278 bruce@momjian.us 106 [ + + - + ]: 15 : if ((!connection && !i->connection)
107 [ + - + - ]: 2 : || (connection && i->connection
5002 peter_e@gmx.net 108 [ + - ]: 2 : && strcmp(connection, i->connection) == 0))
109 : : {
9278 bruce@momjian.us 110 : 15 : *lastptr = i->next;
1178 peter@eisentraut.org 111 : 15 : free(i->connection);
9332 meskes@postgresql.or 112 : 15 : free(i->name);
113 : 15 : free(i);
114 : 15 : return;
115 : : }
116 : : }
117 : : }
1485 meskes@postgresql.or 118 [ # # ]:UIC 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 *
327 tgl@sss.pgh.pa.us 125 :GIC 54 : lookup_descriptor(const char *name, const char *connection)
126 : : {
127 : : struct descriptor *i;
128 : :
8717 bruce@momjian.us 129 [ + + ]: 54 : if (name[0] != '"')
130 : 1 : return NULL;
131 : :
9328 meskes@postgresql.or 132 [ + - ]: 67 : for (i = descriptors; i; i = i->next)
133 : : {
5002 peter_e@gmx.net 134 [ + + ]: 67 : if (strcmp(name, i->name) == 0)
135 : : {
9278 bruce@momjian.us 136 [ + + - + ]: 53 : if ((!connection && !i->connection)
137 [ + - + - ]: 3 : || (connection && i->connection
5002 peter_e@gmx.net 138 [ + - ]: 3 : && strcmp(connection, i->connection) == 0))
9332 meskes@postgresql.or 139 : 53 : return i;
1485 meskes@postgresql.or 140 [ # # # # ]:UIC 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);
9332 152 : 0 : return NULL;
153 : : }
154 : :
155 : : void
327 tgl@sss.pgh.pa.us 156 :GIC 11 : output_get_descr_header(const char *desc_name)
157 : : {
158 : : struct assignment *results;
159 : :
3191 160 : 11 : fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
9332 meskes@postgresql.or 161 [ + + ]: 22 : for (results = assignments; results != NULL; results = results->next)
162 : : {
9328 163 [ + - ]: 11 : if (results->value == ECPGd_count)
6469 164 : 11 : ECPGnumeric_lvalue(results->variable);
165 : : else
6070 peter_e@gmx.net 166 :UIC 0 : mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
167 : : }
168 : :
9332 meskes@postgresql.or 169 :GIC 11 : drop_assignments();
3191 tgl@sss.pgh.pa.us 170 : 11 : fprintf(base_yyout, "));\n");
9332 meskes@postgresql.or 171 : 11 : whenever_action(3);
9333 172 : 11 : }
173 : :
174 : : void
327 tgl@sss.pgh.pa.us 175 : 31 : output_get_descr(const char *desc_name, const char *index)
176 : : {
177 : : struct assignment *results;
178 : :
3191 179 : 31 : fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
9328 meskes@postgresql.or 180 [ + + ]: 82 : for (results = assignments; results != NULL; results = results->next)
181 : : {
182 : 51 : const struct variable *v = find_variable(results->variable);
3376 rhaas@postgresql.org 183 : 51 : char *str_zero = mm_strdup("0");
184 : :
9328 meskes@postgresql.or 185 [ - - + ]: 51 : switch (results->value)
186 : : {
9328 meskes@postgresql.or 187 :UIC 0 : case ECPGd_nullable:
8585 bruce@momjian.us 188 : 0 : mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
9328 meskes@postgresql.or 189 : 0 : break;
190 : 0 : case ECPGd_key_member:
8585 bruce@momjian.us 191 : 0 : mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
9328 meskes@postgresql.or 192 : 0 : break;
9328 meskes@postgresql.or 193 :GIC 51 : default:
9278 bruce@momjian.us 194 : 51 : break;
195 : : }
3191 tgl@sss.pgh.pa.us 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);
3739 meskes@postgresql.or 199 : 51 : free(str_zero);
200 : : }
9333 201 : 31 : drop_assignments();
3191 tgl@sss.pgh.pa.us 202 : 31 : fputs("ECPGd_EODT);\n", base_yyout);
203 : :
9278 bruce@momjian.us 204 : 31 : whenever_action(2 | 1);
9333 meskes@postgresql.or 205 : 31 : }
206 : :
207 : : void
327 tgl@sss.pgh.pa.us 208 : 1 : output_set_descr_header(const char *desc_name)
209 : : {
210 : : struct assignment *results;
211 : :
3191 212 : 1 : fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
7738 meskes@postgresql.or 213 [ + + ]: 2 : for (results = assignments; results != NULL; results = results->next)
214 : : {
215 [ + - ]: 1 : if (results->value == ECPGd_count)
6469 216 : 1 : ECPGnumeric_lvalue(results->variable);
217 : : else
6070 peter_e@gmx.net 218 :UIC 0 : mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
219 : : }
220 : :
7738 meskes@postgresql.or 221 :GIC 1 : drop_assignments();
3191 tgl@sss.pgh.pa.us 222 : 1 : fprintf(base_yyout, "));\n");
7738 meskes@postgresql.or 223 : 1 : whenever_action(3);
224 : 1 : }
225 : :
226 : : static const char *
7738 meskes@postgresql.or 227 :UIC 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
327 tgl@sss.pgh.pa.us 269 :GIC 11 : output_set_descr(const char *desc_name, const char *index)
270 : : {
271 : : struct assignment *results;
272 : :
3191 273 : 11 : fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
7738 meskes@postgresql.or 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 : : {
7738 meskes@postgresql.or 280 :UIC 0 : case ECPGd_cardinality:
281 : : case ECPGd_di_code:
282 : : case ECPGd_di_precision:
283 : : case ECPGd_precision:
284 : : case ECPGd_scale:
4316 peter_e@gmx.net 285 : 0 : mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
286 : : descriptor_item_name(results->value));
287 : : break;
288 : :
7738 meskes@postgresql.or 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:
4316 peter_e@gmx.net 295 : 0 : mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
296 : : descriptor_item_name(results->value));
297 : : break;
298 : :
7738 meskes@postgresql.or 299 :GIC 15 : case ECPGd_data:
300 : : case ECPGd_indicator:
301 : : case ECPGd_length:
302 : : case ECPGd_type:
303 : : {
3376 rhaas@postgresql.org 304 : 15 : char *str_zero = mm_strdup("0");
305 : :
3191 tgl@sss.pgh.pa.us 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);
3739 meskes@postgresql.or 309 : 15 : free(str_zero);
310 : : }
7738 311 : 15 : break;
312 : :
313 : 15 : default:
314 : : ;
315 : : }
316 : : }
317 : 11 : drop_assignments();
3191 tgl@sss.pgh.pa.us 318 : 11 : fputs("ECPGd_EODT);\n", base_yyout);
319 : :
7738 meskes@postgresql.or 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 *
8717 bruce@momjian.us 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 : :
6786 peter_e@gmx.net 340 : 22 : strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
4936 341 : 22 : return &varspace[input];
342 : : }
343 : :
344 : : struct variable *
5723 meskes@postgresql.or 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 : : */
283 tgl@sss.pgh.pa.us 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));
5723 meskes@postgresql.or 356 : 25 : p->type->type = ECPGt_sqlda;
283 tgl@sss.pgh.pa.us 357 : 25 : p->type->type_name = NULL;
5723 meskes@postgresql.or 358 : 25 : p->type->size = NULL;
359 : 25 : p->type->struct_sizeof = NULL;
360 : 25 : p->type->u.element = NULL;
5660 361 : 25 : p->type->counter = 0;
5723 362 : 25 : p->brace_level = 0;
363 : 25 : p->next = NULL;
364 : :
365 : 25 : return p;
366 : : }
|