PostgreSQL Source Code  git master
descriptor.c
Go to the documentation of this file.
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 push_assignment(const char *var, enum ECPGdtype value)
22 {
23  struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
24 
25  new->next = assignments;
26  new->variable = mm_strdup(var);
27  new->value = value;
28  assignments = new;
29 }
30 
31 static void
33 {
34  while (assignments)
35  {
36  struct assignment *old_head = assignments;
37 
38  assignments = old_head->next;
39  free(old_head->variable);
40  free(old_head);
41  }
42 }
43 
44 static void
46 {
47  const struct variable *v = find_variable(name);
48 
49  switch (v->type->type)
50  {
51  case ECPGt_short:
52  case ECPGt_int:
53  case ECPGt_long:
54  case ECPGt_long_long:
56  case ECPGt_unsigned_int:
59  case ECPGt_const:
60  fputs(name, base_yyout);
61  break;
62  default:
63  mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
64  break;
65  }
66 }
67 
68 /*
69  * descriptor name lookup
70  */
71 
72 static struct descriptor *descriptors;
73 
74 void
75 add_descriptor(const char *name, const char *connection)
76 {
77  struct descriptor *new;
78 
79  if (name[0] != '"')
80  return;
81 
82  new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
83 
84  new->next = descriptors;
85  new->name = mm_strdup(name);
86  if (connection)
87  new->connection = mm_strdup(connection);
88  else
89  new->connection = NULL;
90  descriptors = new;
91 }
92 
93 void
94 drop_descriptor(const char *name, const char *connection)
95 {
96  struct descriptor *i;
97  struct descriptor **lastptr = &descriptors;
98 
99  if (name[0] != '"')
100  return;
101 
102  for (i = descriptors; i; lastptr = &i->next, i = i->next)
103  {
104  if (strcmp(name, i->name) == 0)
105  {
106  if ((!connection && !i->connection)
107  || (connection && i->connection
108  && strcmp(connection, i->connection) == 0))
109  {
110  *lastptr = i->next;
111  free(i->connection);
112  free(i->name);
113  free(i);
114  return;
115  }
116  }
117  }
118  if (connection)
119  mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
120  else
121  mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
122 }
123 
124 struct descriptor *
125 lookup_descriptor(const char *name, const char *connection)
126 {
127  struct descriptor *i;
128 
129  if (name[0] != '"')
130  return NULL;
131 
132  for (i = descriptors; i; i = i->next)
133  {
134  if (strcmp(name, i->name) == 0)
135  {
136  if ((!connection && !i->connection)
137  || (connection && i->connection
138  && strcmp(connection, i->connection) == 0))
139  return i;
140  if (connection && !i->connection)
141  {
142  /* overwrite descriptor's connection */
143  i->connection = mm_strdup(connection);
144  return i;
145  }
146  }
147  }
148  if (connection)
149  mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
150  else
151  mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
152  return NULL;
153 }
154 
155 void
156 output_get_descr_header(const char *desc_name)
157 {
158  struct assignment *results;
159 
160  fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
161  for (results = assignments; results != NULL; results = results->next)
162  {
163  if (results->value == ECPGd_count)
164  ECPGnumeric_lvalue(results->variable);
165  else
166  mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
167  }
168 
170  fprintf(base_yyout, "));\n");
171  whenever_action(3);
172 }
173 
174 void
175 output_get_descr(const char *desc_name, const char *index)
176 {
177  struct assignment *results;
178 
179  fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
180  for (results = assignments; results != NULL; results = results->next)
181  {
182  const struct variable *v = find_variable(results->variable);
183  char *str_zero = mm_strdup("0");
184 
185  switch (results->value)
186  {
187  case ECPGd_nullable:
188  mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
189  break;
190  case ECPGd_key_member:
191  mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
192  break;
193  default:
194  break;
195  }
196  fprintf(base_yyout, "%s,", get_dtype(results->value));
198  NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
199  free(str_zero);
200  }
202  fputs("ECPGd_EODT);\n", base_yyout);
203 
204  whenever_action(2 | 1);
205 }
206 
207 void
208 output_set_descr_header(const char *desc_name)
209 {
210  struct assignment *results;
211 
212  fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
213  for (results = assignments; results != NULL; results = results->next)
214  {
215  if (results->value == ECPGd_count)
216  ECPGnumeric_lvalue(results->variable);
217  else
218  mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
219  }
220 
222  fprintf(base_yyout, "));\n");
223  whenever_action(3);
224 }
225 
226 static const char *
228 {
229  switch (itemcode)
230  {
231  case ECPGd_cardinality:
232  return "CARDINALITY";
233  case ECPGd_count:
234  return "COUNT";
235  case ECPGd_data:
236  return "DATA";
237  case ECPGd_di_code:
238  return "DATETIME_INTERVAL_CODE";
239  case ECPGd_di_precision:
240  return "DATETIME_INTERVAL_PRECISION";
241  case ECPGd_indicator:
242  return "INDICATOR";
243  case ECPGd_key_member:
244  return "KEY_MEMBER";
245  case ECPGd_length:
246  return "LENGTH";
247  case ECPGd_name:
248  return "NAME";
249  case ECPGd_nullable:
250  return "NULLABLE";
251  case ECPGd_octet:
252  return "OCTET_LENGTH";
253  case ECPGd_precision:
254  return "PRECISION";
255  case ECPGd_ret_length:
256  return "RETURNED_LENGTH";
257  case ECPGd_ret_octet:
258  return "RETURNED_OCTET_LENGTH";
259  case ECPGd_scale:
260  return "SCALE";
261  case ECPGd_type:
262  return "TYPE";
263  default:
264  return NULL;
265  }
266 }
267 
268 void
269 output_set_descr(const char *desc_name, const char *index)
270 {
271  struct assignment *results;
272 
273  fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
274  for (results = assignments; results != NULL; results = results->next)
275  {
276  const struct variable *v = find_variable(results->variable);
277 
278  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  mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
286  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  mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
296  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  char *str_zero = mm_strdup("0");
305 
306  fprintf(base_yyout, "%s,", get_dtype(results->value));
308  NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
309  free(str_zero);
310  }
311  break;
312 
313  default:
314  ;
315  }
316  }
318  fputs("ECPGd_EODT);\n", base_yyout);
319 
320  whenever_action(2 | 1);
321 }
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 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  strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
341  return &varspace[input];
342 }
343 
344 struct variable *
345 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  struct variable *p = (struct variable *) loc_alloc(sizeof(struct variable));
353 
354  p->name = loc_strdup(name);
355  p->type = (struct ECPGtype *) loc_alloc(sizeof(struct ECPGtype));
356  p->type->type = ECPGt_sqlda;
357  p->type->type_name = NULL;
358  p->type->size = NULL;
359  p->type->struct_sizeof = NULL;
360  p->type->u.element = NULL;
361  p->type->counter = 0;
362  p->brace_level = 0;
363  p->next = NULL;
364 
365  return p;
366 }
@ ECPGt_long_long
Definition: ecpgtype.h:45
@ ECPGt_sqlda
Definition: ecpgtype.h:66
@ ECPGt_short
Definition: ecpgtype.h:43
@ ECPGt_unsigned_short
Definition: ecpgtype.h:43
@ ECPGt_int
Definition: ecpgtype.h:44
@ ECPGt_long
Definition: ecpgtype.h:44
@ ECPGt_unsigned_long
Definition: ecpgtype.h:44
@ ECPGt_const
Definition: ecpgtype.h:61
@ ECPGt_unsigned_long_long
Definition: ecpgtype.h:45
@ ECPGt_unsigned_int
Definition: ecpgtype.h:44
@ ECPGt_descriptor
Definition: ecpgtype.h:59
ECPGdtype
Definition: ecpgtype.h:72
@ ECPGd_scale
Definition: ecpgtype.h:86
@ ECPGd_precision
Definition: ecpgtype.h:83
@ ECPGd_length
Definition: ecpgtype.h:79
@ ECPGd_nullable
Definition: ecpgtype.h:81
@ ECPGd_di_precision
Definition: ecpgtype.h:76
@ ECPGd_type
Definition: ecpgtype.h:87
@ ECPGd_cardinality
Definition: ecpgtype.h:89
@ ECPGd_indicator
Definition: ecpgtype.h:77
@ ECPGd_ret_length
Definition: ecpgtype.h:84
@ ECPGd_di_code
Definition: ecpgtype.h:75
@ ECPGd_count
Definition: ecpgtype.h:73
@ ECPGd_name
Definition: ecpgtype.h:80
@ ECPGd_key_member
Definition: ecpgtype.h:78
@ ECPGd_octet
Definition: ecpgtype.h:82
@ ECPGd_ret_octet
Definition: ecpgtype.h:85
@ ECPGd_data
Definition: ecpgtype.h:74
#define free(a)
Definition: header.h:65
FILE * input
static struct @160 value
int i
Definition: isn.c:72
void whenever_action(int mode)
Definition: output.c:64
#define fprintf
Definition: port.h:242
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void output_set_descr(const char *desc_name, const char *index)
Definition: descriptor.c:269
struct variable * descriptor_variable(const char *name, int input)
Definition: descriptor.c:331
void add_descriptor(const char *name, const char *connection)
Definition: descriptor.c:75
static struct descriptor * descriptors
Definition: descriptor.c:72
static struct assignment * assignments
Definition: descriptor.c:18
void push_assignment(const char *var, enum ECPGdtype value)
Definition: descriptor.c:21
void output_get_descr_header(const char *desc_name)
Definition: descriptor.c:156
struct descriptor * lookup_descriptor(const char *name, const char *connection)
Definition: descriptor.c:125
static void ECPGnumeric_lvalue(char *name)
Definition: descriptor.c:45
void drop_descriptor(const char *name, const char *connection)
Definition: descriptor.c:94
void output_get_descr(const char *desc_name, const char *index)
Definition: descriptor.c:175
static const char * descriptor_item_name(enum ECPGdtype itemcode)
Definition: descriptor.c:227
void output_set_descr_header(const char *desc_name)
Definition: descriptor.c:208
static void drop_assignments(void)
Definition: descriptor.c:32
struct variable * sqlda_variable(const char *name)
Definition: descriptor.c:345
#define MAX_DESCRIPTOR_NAMELEN
Definition: descriptor.c:329
void mmerror(int error_code, enum errortype type, const char *error,...) pg_attribute_printf(3
char * loc_strdup(const char *string)
Definition: util.c:170
char * mm_strdup(const char *string)
Definition: util.c:97
void void mmfatal(int error_code, const char *error,...) pg_attribute_printf(2
const char * get_dtype(enum ECPGdtype)
Definition: type.c:672
#define PARSE_ERROR
struct variable * find_variable(const char *name)
Definition: variable.c:193
void * loc_alloc(size_t size)
Definition: util.c:138
FILE * base_yyout
void * mm_alloc(size_t size)
Definition: util.c:85
Definition: type.h:18
char * variable
Definition: type.h:213
enum ECPGdtype value
Definition: type.h:214
struct assignment * next
Definition: type.h:215
Definition: type.h:96
char * name
Definition: type.h:191
struct variable * next
enum ECPGttype type
int brace_level
Definition: type.h:193
void ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype *type, const int brace_level, const char *ind_name, struct ECPGtype *ind_type, const int ind_brace_level, const char *prefix, const char *ind_prefix, char *arr_str_size, const char *struct_sizeof, const char *ind_struct_sizeof)
Definition: type.c:218
@ ET_WARNING
Definition: type.h:220
@ ET_ERROR
Definition: type.h:220
const char * name