/
githubmirror
/
postgres
Обзор
Документация
Войти
/
githubmirror
/
postgres
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/interfaces/ecpg/preproc/descriptor.c
367 строк
9 KB
Tom Lane
Pre-beta mechanical code beautification, step 1: run pgindent.
13 май 2026, 17:34
13 май 2026, 17:34
020794e
Код
Авторство
О чём код?
/* * functions needed for descriptor handling * * src/interfaces/ecpg/preproc/descriptor.c * * since descriptor might be either a string constant or a string var * we need to check for a constant if we expect a constant */ #include "postgres_fe.h" #include "preproc_extern.h" /* * assignment handling function (descriptor) */ static struct assignment *assignments; void push_assignment(const char *var, enum ECPGdtype value) { struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment)); new->next = assignments; new->variable = mm_strdup(var); new->value = value; assignments = new; } static void drop_assignments(void) { while (assignments) { struct assignment *old_head = assignments; assignments = old_head->next; free(old_head->variable); free(old_head); } } static void ECPGnumeric_lvalue(char *name) { const struct variable *v = find_variable(name); switch (v->type->type) { case ECPGt_short: case ECPGt_int: case ECPGt_long: case ECPGt_long_long: case ECPGt_unsigned_short: case ECPGt_unsigned_int: case ECPGt_unsigned_long: case ECPGt_unsigned_long_long: case ECPGt_const: fputs(name, base_yyout); break; default: mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name); break; } } /* * descriptor name lookup */ static struct descriptor *descriptors; void add_descriptor(const char *name, const char *connection) { struct descriptor *new; if (name[0] != '"') return; new = (struct descriptor *) mm_alloc(sizeof(struct descriptor)); new->next = descriptors; new->name = mm_strdup(name); if (connection) new->connection = mm_strdup(connection); else new->connection = NULL; descriptors = new; } void drop_descriptor(const char *name, const char *connection) { struct descriptor *i; struct descriptor **lastptr = &descriptors; if (name[0] != '"') return; for (i = descriptors; i; lastptr = &i->next, i = i->next) { if (strcmp(name, i->name) == 0) { if ((!connection && !i->connection) || (connection && i->connection && strcmp(connection, i->connection) == 0)) { *lastptr = i->next; free(i->connection); free(i->name); free(i); return; } } } if (connection) mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection); else mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name); } struct descriptor * lookup_descriptor(const char *name, const char *connection) { struct descriptor *i; if (name[0] != '"') return NULL; for (i = descriptors; i; i = i->next) { if (strcmp(name, i->name) == 0) { if ((!connection && !i->connection) || (connection && i->connection && strcmp(connection, i->connection) == 0)) return i; if (connection && !i->connection) { /* overwrite descriptor's connection */ i->connection = mm_strdup(connection); return i; } } } if (connection) mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection); else mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name); return NULL; } void output_get_descr_header(const char *desc_name) { struct assignment *results; fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name); for (results = assignments; results != NULL; results = results->next) { if (results->value == ECPGd_count) ECPGnumeric_lvalue(results->variable); else mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value); } drop_assignments(); fprintf(base_yyout, "));\n"); whenever_action(3); } void output_get_descr(const char *desc_name, const char *index) { struct assignment *results; fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index); for (results = assignments; results != NULL; results = results->next) { const struct variable *v = find_variable(results->variable); char *str_zero = mm_strdup("0"); switch (results->value) { case ECPGd_nullable: mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1"); break; case ECPGd_key_member: mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0"); break; default: break; } fprintf(base_yyout, "%s,", get_dtype(results->value)); ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL); free(str_zero); } drop_assignments(); fputs("ECPGd_EODT);\n", base_yyout); whenever_action(2 | 1); } void output_set_descr_header(const char *desc_name) { struct assignment *results; fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name); for (results = assignments; results != NULL; results = results->next) { if (results->value == ECPGd_count) ECPGnumeric_lvalue(results->variable); else mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value); } drop_assignments(); fprintf(base_yyout, "));\n"); whenever_action(3); } static const char * descriptor_item_name(enum ECPGdtype itemcode) { switch (itemcode) { case ECPGd_cardinality: return "CARDINALITY"; case ECPGd_count: return "COUNT"; case ECPGd_data: return "DATA"; case ECPGd_di_code: return "DATETIME_INTERVAL_CODE"; case ECPGd_di_precision: return "DATETIME_INTERVAL_PRECISION"; case ECPGd_indicator: return "INDICATOR"; case ECPGd_key_member: return "KEY_MEMBER"; case ECPGd_length: return "LENGTH"; case ECPGd_name: return "NAME"; case ECPGd_nullable: return "NULLABLE"; case ECPGd_octet: return "OCTET_LENGTH"; case ECPGd_precision: return "PRECISION"; case ECPGd_ret_length: return "RETURNED_LENGTH"; case ECPGd_ret_octet: return "RETURNED_OCTET_LENGTH"; case ECPGd_scale: return "SCALE"; case ECPGd_type: return "TYPE"; default: return NULL; } } void output_set_descr(const char *desc_name, const char *index) { struct assignment *results; fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index); for (results = assignments; results != NULL; results = results->next) { const struct variable *v = find_variable(results->variable); switch (results->value) { case ECPGd_cardinality: case ECPGd_di_code: case ECPGd_di_precision: case ECPGd_precision: case ECPGd_scale: mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented", descriptor_item_name(results->value)); break; case ECPGd_key_member: case ECPGd_name: case ECPGd_nullable: case ECPGd_octet: case ECPGd_ret_length: case ECPGd_ret_octet: mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set", descriptor_item_name(results->value)); break; case ECPGd_data: case ECPGd_indicator: case ECPGd_length: case ECPGd_type: { char *str_zero = mm_strdup("0"); fprintf(base_yyout, "%s,", get_dtype(results->value)); ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL); free(str_zero); } break; default: ; } } drop_assignments(); fputs("ECPGd_EODT);\n", base_yyout); whenever_action(2 | 1); } /* * I consider dynamic allocation overkill since at most two descriptor * variables are possible per statement. (input and output descriptor) * And descriptors are no normal variables, so they don't belong into * the variable list. */ #define MAX_DESCRIPTOR_NAMELEN 128 struct variable * descriptor_variable(const char *name, int input) { static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN]; static struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0}; static struct variable varspace[2] = { {descriptor_names[0], &descriptor_type, 0, NULL}, {descriptor_names[1], &descriptor_type, 0, NULL} }; strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input])); return &varspace[input]; } struct variable * sqlda_variable(const char *name) { /* * Presently, sqlda variables are only needed for the duration of the * current statement. Rather than add infrastructure to manage them, * let's just loc_alloc them. */ struct variable *p = (struct variable *) loc_alloc(sizeof(struct variable)); p->name = loc_strdup(name); p->type = (struct ECPGtype *) loc_alloc(sizeof(struct ECPGtype)); p->type->type = ECPGt_sqlda; p->type->type_name = NULL; p->type->size = NULL; p->type->struct_sizeof = NULL; p->type->u.element = NULL; p->type->counter = 0; p->brace_level = 0; p->next = NULL; return p; }