Thu May 29 13:58:25 CEST 2003
- ecpg should now be able to parse forward struct definition.
+
+Thu May 29 15:45:57 CEST 2003
+
+ - Changed parsing of variables to be able to reference one attribute
+ of the n-th entry in an array of structs.
- Set ecpg version to 2.12.0.
- Set ecpg library to 3.4.2.
- Set pgtypes library to 1.0.0
break;
}
fprintf(yyout, "%s,", get_dtype(results->value));
- ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL);
+ ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL);
}
drop_assignments();
fputs("ECPGd_EODT);\n", yyout);
extern void drop_descriptor(char *, char *);
extern struct descriptor *lookup_descriptor(char *, char *);
extern struct variable *descriptor_variable(const char *name, int input);
-extern void add_variable(struct arguments **, struct variable *, char *i, struct variable *, char *);
-extern void append_variable(struct arguments **, struct variable *, char *, struct variable *, char *);
+extern void add_variable(struct arguments **, struct variable *, struct variable *);
+extern void append_variable(struct arguments **, struct variable *, struct variable *);
extern void dump_variables(struct arguments *, int);
extern struct typedefs *get_typedef(char *);
extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.112 2003/05/29 12:00:21 meskes Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.113 2003/05/29 13:59:26 meskes Exp $
*
*-------------------------------------------------------------------------
*/
yylval.str = mm_strdup(yytext);
return FCONST;
}
-<SQL>:{identifier}(("->"|\.){identifier})* {
+<SQL>:{identifier}((("->"|\.){identifier})|(\[{array}\]))* {
yylval.str = mm_strdup(yytext+1);
return(CVARIABLE);
}
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.224 2003/05/29 12:00:21 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.225 2003/05/29 13:59:26 meskes Exp $ */
/* Copyright comment */
%{
{
/* merge variables given in prepare statement with those given here */
for (p = ptr->argsinsert; p; p = p->next)
- append_variable(&argsinsert, p->variable, p->var_array_element, p->indicator, p->ind_array_element);
+ append_variable(&argsinsert, p->variable, p->indicator);
for (p = ptr->argsresult; p; p = p->next)
- add_variable(&argsresult, p->variable, p->var_array_element, p->indicator, p->ind_array_element);
+ add_variable(&argsresult, p->variable, p->indicator);
output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL);
}
sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $7);
this->argsinsert = NULL;
- add_variable(&(this->argsinsert), thisquery, NULL, &no_indicator, NULL);
+ add_variable(&(this->argsinsert), thisquery, &no_indicator);
cur = this;
thisquery->next = NULL;
thisquery->name = $3;
- add_variable(&argsinsert, thisquery, NULL, &no_indicator, NULL);
+ add_variable(&argsinsert, thisquery, &no_indicator);
$$ = make_str("?");
}
thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($2));
sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $2);
- add_variable(&argsinsert, thisquery, NULL, &no_indicator, NULL);
+ add_variable(&argsinsert, thisquery, &no_indicator);
}
opt_ecpg_using opt_ecpg_into
{
}
| INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
- add_variable(&argsresult, descriptor_variable($4,0), NULL, &no_indicator, NULL);
+ add_variable(&argsresult, descriptor_variable($4,0), &no_indicator);
$$ = EMPTY;
}
;
| c_list { $$ = $1; }
;
-coutputvariable: CVARIABLE '[' Iresult ']' indicator '[' Iresult ']'
- { add_variable(&argsresult, find_variable($1), $3, find_variable($5), $7); }
- | CVARIABLE indicator '[' Iresult ']'
- { add_variable(&argsresult, find_variable($1), NULL, find_variable($2), $4); }
- | CVARIABLE '[' Iresult ']' indicator
- { add_variable(&argsresult, find_variable($1), $3, find_variable($5), NULL); }
- | CVARIABLE indicator
- { add_variable(&argsresult, find_variable($1), NULL, find_variable($2), NULL); }
- | CVARIABLE '[' Iresult ']'
- { add_variable(&argsresult, find_variable($1), $3, &no_indicator, NULL); }
+coutputvariable: CVARIABLE indicator
+ { add_variable(&argsresult, find_variable($1), find_variable($2)); }
| CVARIABLE
- { add_variable(&argsresult, find_variable($1), NULL, &no_indicator, NULL); }
+ { add_variable(&argsresult, find_variable($1), &no_indicator); }
;
-civarind: CVARIABLE '[' Iresult ']' indicator '[' Iresult ']'
- {
- add_variable(&argsinsert, find_variable($1), $3, find_variable($5), $7);
- $$ = create_questionmarks($1, true);
- }
- | CVARIABLE indicator '[' Iresult ']'
- {
- add_variable(&argsinsert, find_variable($1), NULL, find_variable($2), $4);
- $$ = create_questionmarks($1, false);
- }
- | CVARIABLE '[' Iresult ']' indicator
- {
- if (find_variable($5)->type->type == ECPGt_array)
- mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
-
- add_variable(&argsinsert, find_variable($1), $3, find_variable($5), NULL);
- $$ = create_questionmarks($1, true);
- }
- | CVARIABLE indicator
+civarind: CVARIABLE indicator
{
if (find_variable($2)->type->type == ECPGt_array)
mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
- add_variable(&argsinsert, find_variable($1), NULL, find_variable($2), NULL);
+ add_variable(&argsinsert, find_variable($1), find_variable($2));
$$ = create_questionmarks($1, false);
}
;
-civar: CVARIABLE '[' Iresult ']'
- {
- add_variable(&argsinsert, find_variable($1), mm_strdup($3), &no_indicator, NULL);
- $$ = create_questionmarks($1, true);
- }
- | CVARIABLE
+civar: CVARIABLE
{
- add_variable(&argsinsert, find_variable($1), NULL, &no_indicator, NULL);
+ add_variable(&argsinsert, find_variable($1), &no_indicator);
$$ = create_questionmarks($1, false);
}
;
void
ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
- const char *var_array_element, const char *ind_name,
- struct ECPGtype * ind_type, const char *ind_array_element,
+ const char *ind_name, struct ECPGtype * ind_type,
const char *prefix, const char *ind_prefix,
char *arr_str_siz, const char *struct_sizeof,
const char *ind_struct_sizeof)
break;
case ECPGt_struct:
case ECPGt_union:
- /* If var_array_element is not equal
- * NULL, we have to use the
- * <var_array_element>th entry and
- * not the whole array */
- if (var_array_element == NULL)
- ECPGdump_a_struct(o, name,
- ind_name,
- type->size,
- type->u.element,
- (ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
- NULL, prefix, ind_prefix);
- else
- {
- char *array_element = (char *)mm_alloc(strlen(name) + strlen(var_array_element) + sizeof("[]\0")), *ind_array_element;
-
- sprintf(array_element, "%s[%s]", name, var_array_element);
-
- if (ind_type->type != ECPGt_NO_INDICATOR)
- {
- ind_array_element = (char *)mm_alloc(strlen(ind_name) + strlen(ind_array_element) + sizeof("+\0"));
- sprintf(ind_array_element, "%s[%s]", ind_name, ind_array_element);
-
- ECPGdump_a_struct(o, array_element, ind_array_element, make_str("1"),
- type->u.element, ind_type->u.element,
- NULL, prefix, ind_prefix);
- free(ind_array_element);
- }
- else
- ECPGdump_a_struct(o, array_element, ind_name, make_str("1"),
- type->u.element, ind_type,
- NULL, prefix, ind_prefix);
-
- free (array_element);
- }
+ ECPGdump_a_struct(o, name,
+ ind_name,
+ type->size,
+ type->u.element,
+ (ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
+ NULL, prefix, ind_prefix);
break;
default:
if (!IS_SIMPLE_TYPE(type->u.element->type))
yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org");
- /* If var_array_element is not equal
- * NULL, we have to use the
- * <var_array_element>th entry and not
- * the whole array */
- if (var_array_element == NULL)
- ECPGdump_a_simple(o, name,
- type->u.element->type,
+ ECPGdump_a_simple(o, name,
+ type->u.element->type,
type->u.element->size, type->size, NULL, prefix);
- else
- {
- char *array_element = (char *)mm_alloc(strlen(name) + strlen(var_array_element) + sizeof("+\0"));
-
- sprintf(array_element, "%s+%s", name, var_array_element);
- ECPGdump_a_simple(o, array_element,
- type->u.element->type,
- type->u.element->size, make_str("1"), NULL, prefix);
- free(array_element);
-
-
- }
if (ind_type != NULL)
{
ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, make_str("-1"), NULL, ind_prefix);
else
{
- if (ind_array_element == NULL)
- ECPGdump_a_simple(o, ind_name, ind_type->u.element->type,
- ind_type->u.element->size, ind_type->size, NULL, prefix);
- else
- {
- char *array_element = (char *)mm_alloc(strlen(ind_name) + strlen(ind_array_element) + sizeof("+\0"));
-
- sprintf(array_element, "%s+%s", ind_name, ind_array_element);
- ECPGdump_a_simple(o, array_element,
- ind_type->u.element->type,
- ind_type->u.element->size,
- make_str("1"), NULL, prefix);
- free(array_element);
- }
+ ECPGdump_a_simple(o, ind_name, ind_type->u.element->type,
+ ind_type->u.element->size, ind_type->size, NULL, prefix);
}
}
}
for (p = type->u.members; p; p = p->next)
{
- ECPGdump_a_type(o, p->name, p->type, NULL,
+ ECPGdump_a_type(o, p->name, p->type,
(ind_p != NULL) ? ind_p->name : NULL,
- (ind_p != NULL) ? ind_p->type : NULL, NULL,
+ (ind_p != NULL) ? ind_p->type : NULL,
prefix, ind_prefix, arrsiz, type->struct_sizeof,
(ind_p != NULL) ? ind_type->struct_sizeof : NULL);
if (ind_p != NULL && ind_p != &struct_no_indicator)
size is the maxsize in case it is a varchar. Otherwise it is the size of
the variable (required to do array fetches of structs).
*/
-void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *,
- const char *, struct ECPGtype *, const char *, const char *,
+void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *,
+ const char *, struct ECPGtype *, const char *,
const char *, char *, const char *, const char *);
/* A simple struct to keep a variable and its type. */
struct arguments
{
struct variable *variable;
- char *var_array_element;
struct variable *indicator;
- char *ind_array_element;
struct arguments *next;
};
static struct variable *
find_struct_member(char *name, char *str, struct ECPGstruct_member * members, int brace_level)
{
- char *next = strchr(++str, '.'),
- c = '\0';
+ char *next = strpbrk(++str, ".-["),
+ *end, c = '\0';
if (next != NULL)
{
{
if (strcmp(members->name, str) == 0)
{
- if (c == '\0')
+ if (next == NULL)
{
/* found the end */
switch (members->type->type)
else
{
*next = c;
- if (c == '-')
+ if (c == '[')
{
- next++;
- return (find_struct_member(name, next, members->type->u.element->u.members, brace_level));
+ int count;
+
+ /* We don't care about what's inside the array braces
+ * so just eat up the character */
+ for (count=1, end=next+1; count; end++)
+ {
+ switch (*end)
+ {
+ case '[': count++;
+ break;
+ case ']': count--;
+ break;
+ default : break;
+ }
+ }
+ }
+ else end = next;
+
+ switch (*end)
+ {
+ case '\0': /* found the end, but this time it has to be an array element */
+ if (members->type->type != ECPGt_array)
+ {
+ snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);
+ mmerror(PARSE_ERROR, ET_FATAL, errortext);
+ }
+
+ switch (members->type->u.element->type)
+ {
+ case ECPGt_array:
+ return (new_variable(name, ECPGmake_array_type(members->type->u.element->u.element, members->type->u.element->size), brace_level));
+ case ECPGt_struct:
+ case ECPGt_union:
+ return (new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->struct_sizeof), brace_level));
+ default:
+ return (new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size), brace_level));
+ }
+ break;
+ case '-': return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
+ break;
+ case '.': if (members->type->type != ECPGt_array)
+ return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
+ else
+ return (find_struct_member(name, next, members->type->u.members, brace_level));
+ break;
+ default : snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);
+ mmerror(PARSE_ERROR, ET_FATAL, errortext);
+ break;
}
- else
- return (find_struct_member(name, next, members->type->u.members, brace_level));
}
}
}
struct variable *p;
int count;
- printf("MM: find %s\n", name);
-
next = strpbrk(name, ".[-");
if (next)
{
if (*end == '.') p = find_struct(name, next, end);
else
{
- char c = *next;
+ char c = *next;
- *next = '\0';
- p = find_simple(name);
- *next = c;
+ *next = '\0';
+ p = find_simple(name);
+ *next = c;
+ switch (p->type->u.element->type)
+ {
+ case ECPGt_array:
+ return (new_variable(name, ECPGmake_array_type(p->type->u.element->u.element, p->type->u.element->size), p->brace_level));
+ case ECPGt_struct:
+ case ECPGt_union:
+ return (new_variable(name, ECPGmake_struct_type(p->type->u.element->u.members, p->type->u.element->type, p->type->u.element->struct_sizeof), p->brace_level));
+ default:
+ return (new_variable(name, ECPGmake_simple_type(p->type->u.element->type, p->type->u.element->size), p->brace_level));
+ }
}
}
else p = find_struct(name, next, next);
/* Insert a new variable into our request list. */
void
-add_variable(struct arguments ** list, struct variable * var, char * var_array_element, struct variable * ind, char * ind_array_element)
+add_variable(struct arguments ** list, struct variable * var, struct variable * ind)
{
struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
p->variable = var;
- p->var_array_element = var_array_element;
p->indicator = ind;
- p->ind_array_element = ind_array_element;
p->next = *list;
*list = p;
}
/* Append a new variable to our request list. */
void
-append_variable(struct arguments ** list, struct variable * var, char * var_array_element, struct variable * ind, char * ind_array_element)
+append_variable(struct arguments ** list, struct variable * var, struct variable * ind)
{
struct arguments *p,
*new = (struct arguments *) mm_alloc(sizeof(struct arguments));
for (p = *list; p && p->next; p = p->next);
new->variable = var;
- new->var_array_element = var_array_element;
new->indicator = ind;
- new->ind_array_element = ind_array_element;
new->next = NULL;
if (p)
dump_variables(list->next, mode);
/* Then the current element and its indicator */
- ECPGdump_a_type(yyout, list->variable->name, list->variable->type, list->var_array_element,
- list->indicator->name, list->indicator->type, list->ind_array_element,
+ ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
+ list->indicator->name, list->indicator->type,
NULL, NULL, 0, NULL, NULL);
/* Then release the list element. */
exec sql create table test (text char(5), num decimal(14,7));
value1 = PGTYPESnew();
- PGTYPESnumeric_iton(1407, value1);
- text = PGTYPESnumeric_ntoa(value1);
+ PGTYPESnumeric_from_int(1407, value1);
+ text = PGTYPESnumeric_to_asc(value1, 0);
printf("long = %s\n", text);
- value1 = PGTYPESnumeric_aton("2369.7", NULL);
- value2 = PGTYPESnumeric_aton("10.0", NULL);
+ value1 = PGTYPESnumeric_from_asc("2369.7", NULL);
+ value2 = PGTYPESnumeric_from_asc("10.0", NULL);
res = PGTYPESnew();
- decadd(value1, value2, res);
- text = PGTYPESnumeric_ntoa(res);
+ PGTYPESnumeric_add(value1, value2, res);
+ text = PGTYPESnumeric_to_asc(res, 0);
printf("add = %s\n", text);
PGTYPESnumeric_sub(res, value2, res);
- text = PGTYPESnumeric_ntoa(res);
+ text = PGTYPESnumeric_to_asc(res, 0);
printf("sub = %s\n", text);
PGTYPESnumeric_copy(res, &des);
exec sql insert into test (text, num) values ('test', :des);
- value2 = PGTYPESnumeric_aton("2369.7", NULL);
+ value2 = PGTYPESnumeric_from_asc("2369.7", NULL);
PGTYPESnumeric_mul(value1, value2, res);
exec sql select num into :des from test where text = 'test';
PGTYPESnumeric_mul(res, &des, res);
- text = PGTYPESnumeric_ntoa(res);
+ text = PGTYPESnumeric_to_asc(res, 0);
printf("mul = %s\n", text);
- value2 = PGTYPESnumeric_aton("10000", NULL);
+ value2 = PGTYPESnumeric_from_asc("10000", NULL);
PGTYPESnumeric_div(res, value2, res);
- text = PGTYPESnumeric_ntoa(res);
- PGTYPESnumeric_ntod(res, &d);
+ text = PGTYPESnumeric_to_asc(res, 0);
+ PGTYPESnumeric_to_double(res, &d);
printf("div = %s %e\n", text, d);
exec sql rollback;