2 * functions needed for descriptor handling
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
10 #include "postgres_fe.h"
15 * assignment handling function (descriptor)
18 static struct assignment
*assignments
;
21 push_assignment(char *var
, enum ECPGdtype value
)
23 struct assignment
*new = (struct assignment
*) mm_alloc(sizeof(struct assignment
));
25 new->next
= assignments
;
26 new->variable
= mm_alloc(strlen(var
) + 1);
27 strcpy(new->variable
, var
);
33 drop_assignments(void)
37 struct assignment
*old_head
= assignments
;
39 assignments
= old_head
->next
;
40 free(old_head
->variable
);
46 ECPGnumeric_lvalue(char *name
)
48 const struct variable
*v
= find_variable(name
);
50 switch (v
->type
->type
)
56 case ECPGt_unsigned_short
:
57 case ECPGt_unsigned_int
:
58 case ECPGt_unsigned_long
:
59 case ECPGt_unsigned_long_long
:
64 mmerror(PARSE_ERROR
, ET_ERROR
, "variable \"%s\" must have a numeric type", name
);
70 * descriptor name lookup
73 static struct descriptor
*descriptors
;
76 add_descriptor(char *name
, char *connection
)
78 struct descriptor
*new;
83 new = (struct descriptor
*) mm_alloc(sizeof(struct descriptor
));
85 new->next
= descriptors
;
86 new->name
= mm_alloc(strlen(name
) + 1);
87 strcpy(new->name
, name
);
90 new->connection
= mm_alloc(strlen(connection
) + 1);
91 strcpy(new->connection
, connection
);
94 new->connection
= connection
;
99 drop_descriptor(char *name
, char *connection
)
101 struct descriptor
*i
;
102 struct descriptor
**lastptr
= &descriptors
;
107 for (i
= descriptors
; i
; lastptr
= &i
->next
, i
= i
->next
)
109 if (!strcmp(name
, i
->name
))
111 if ((!connection
&& !i
->connection
)
112 || (connection
&& i
->connection
113 && !strcmp(connection
, i
->connection
)))
124 mmerror(PARSE_ERROR
, ET_WARNING
, "descriptor \"%s\" does not exist", name
);
129 lookup_descriptor(char *name
, char *connection
)
131 struct descriptor
*i
;
136 for (i
= descriptors
; i
; i
= i
->next
)
138 if (!strcmp(name
, i
->name
))
140 if ((!connection
&& !i
->connection
)
141 || (connection
&& i
->connection
142 && !strcmp(connection
, i
->connection
)))
146 mmerror(PARSE_ERROR
, ET_WARNING
, "descriptor \"%s\" does not exist", name
);
151 output_get_descr_header(char *desc_name
)
153 struct assignment
*results
;
155 fprintf(yyout
, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name
);
156 for (results
= assignments
; results
!= NULL
; results
= results
->next
)
158 if (results
->value
== ECPGd_count
)
159 ECPGnumeric_lvalue(results
->variable
);
161 mmerror(PARSE_ERROR
, ET_WARNING
, "descriptor header item \"%d\" does not exist", results
->value
);
165 fprintf(yyout
, "));\n");
170 output_get_descr(char *desc_name
, char *index
)
172 struct assignment
*results
;
174 fprintf(yyout
, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name
, index
);
175 for (results
= assignments
; results
!= NULL
; results
= results
->next
)
177 const struct variable
*v
= find_variable(results
->variable
);
179 switch (results
->value
)
182 mmerror(PARSE_ERROR
, ET_WARNING
, "nullable is always 1");
184 case ECPGd_key_member
:
185 mmerror(PARSE_ERROR
, ET_WARNING
, "key_member is always 0");
190 fprintf(yyout
, "%s,", get_dtype(results
->value
));
191 ECPGdump_a_type(yyout
, v
->name
, v
->type
, NULL
, NULL
, NULL
, NULL
, make_str("0"), NULL
, NULL
);
194 fputs("ECPGd_EODT);\n", yyout
);
196 whenever_action(2 | 1);
200 output_set_descr_header(char *desc_name
)
202 struct assignment
*results
;
204 fprintf(yyout
, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name
);
205 for (results
= assignments
; results
!= NULL
; results
= results
->next
)
207 if (results
->value
== ECPGd_count
)
208 ECPGnumeric_lvalue(results
->variable
);
210 mmerror(PARSE_ERROR
, ET_WARNING
, "descriptor header item \"%d\" does not exist", results
->value
);
214 fprintf(yyout
, "));\n");
219 descriptor_item_name(enum ECPGdtype itemcode
)
223 case ECPGd_cardinality
:
224 return "CARDINALITY";
230 return "DATETIME_INTERVAL_CODE";
231 case ECPGd_di_precision
:
232 return "DATETIME_INTERVAL_PRECISION";
233 case ECPGd_indicator
:
235 case ECPGd_key_member
:
244 return "OCTET_LENGTH";
245 case ECPGd_precision
:
247 case ECPGd_ret_length
:
248 return "RETURNED_LENGTH";
249 case ECPGd_ret_octet
:
250 return "RETURNED_OCTET_LENGTH";
261 output_set_descr(char *desc_name
, char *index
)
263 struct assignment
*results
;
265 fprintf(yyout
, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name
, index
);
266 for (results
= assignments
; results
!= NULL
; results
= results
->next
)
268 const struct variable
*v
= find_variable(results
->variable
);
270 switch (results
->value
)
272 case ECPGd_cardinality
:
274 case ECPGd_di_precision
:
275 case ECPGd_precision
:
277 mmerror(PARSE_ERROR
, ET_FATAL
, "descriptor item \"%s\" is not implemented",
278 descriptor_item_name(results
->value
));
281 case ECPGd_key_member
:
285 case ECPGd_ret_length
:
286 case ECPGd_ret_octet
:
287 mmerror(PARSE_ERROR
, ET_FATAL
, "descriptor item \"%s\" cannot be set",
288 descriptor_item_name(results
->value
));
292 case ECPGd_indicator
:
295 fprintf(yyout
, "%s,", get_dtype(results
->value
));
296 ECPGdump_a_type(yyout
, v
->name
, v
->type
, NULL
, NULL
, NULL
, NULL
, make_str("0"), NULL
, NULL
);
304 fputs("ECPGd_EODT);\n", yyout
);
306 whenever_action(2 | 1);
309 /* I consider dynamic allocation overkill since at most two descriptor
310 variables are possible per statement. (input and output descriptor)
311 And descriptors are no normal variables, so they don't belong into
315 #define MAX_DESCRIPTOR_NAMELEN 128
317 descriptor_variable(const char *name
, int input
)
319 static char descriptor_names
[2][MAX_DESCRIPTOR_NAMELEN
];
320 static const struct ECPGtype descriptor_type
= {ECPGt_descriptor
, NULL
, NULL
, {NULL
}, 0};
321 static const struct variable varspace
[2] = {
322 {descriptor_names
[0], (struct ECPGtype
*) & descriptor_type
, 0, NULL
},
323 {descriptor_names
[1], (struct ECPGtype
*) & descriptor_type
, 0, NULL
}
326 strlcpy(descriptor_names
[input
], name
, sizeof(descriptor_names
[input
]));
327 return (struct variable
*) & varspace
[input
];