mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
From: Michael Meskes <meskes@topsystem.de>
And the next update. Now you can use only parts of a struct like this: exec sql select a into :struct.string from foo;
This commit is contained in:
parent
3e3477f5a4
commit
718430ea40
@ -142,3 +142,10 @@ Fri Apr 24 13:50:15 CEST 1998
|
||||
|
||||
- Fixed some bugs.
|
||||
- Set version to 2.1.1
|
||||
|
||||
Mon Apr 27 14:26:55 CEST 1998
|
||||
|
||||
- Parser now able to understand and process syntax like :foo->bar
|
||||
and :foo.bar as variables.
|
||||
- Set version to 2.2.0
|
||||
|
||||
|
@ -53,6 +53,3 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar};
|
||||
commit release|commit work release auch disconnect
|
||||
|
||||
It is not neccessary to check for "not found" after all commands.
|
||||
|
||||
It would be nice to be able to specify parts of a structure like :foo.bar or
|
||||
:foo->bar.
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Complex types:
|
||||
* VARCHAR, VARCHAR2 - Strings with length (maxlen is given in the declaration)
|
||||
* Arrays of simple types and of VARCHAR, VARCHAR2 (size given in declaration)
|
||||
* Records build of simple types, arrays and other records.
|
||||
* Records build of simple types, arrays and other structs.
|
||||
*
|
||||
* Complicating things:
|
||||
* typedefs and struct names!
|
||||
@ -41,7 +41,7 @@ enum ECPGttype
|
||||
ECPGt_float, ECPGt_double,
|
||||
ECPGt_varchar, ECPGt_varchar2,
|
||||
ECPGt_array,
|
||||
ECPGt_record,
|
||||
ECPGt_struct,
|
||||
ECPGt_EOIT, /* End of insert types. */
|
||||
ECPGt_EORT, /* End of result types. */
|
||||
ECPGt_NO_INDICATOR /* no indicator */
|
||||
|
@ -2,8 +2,8 @@ SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
MAJOR_VERSION=2
|
||||
MINOR_VERSION=1
|
||||
PATCHLEVEL=1
|
||||
MINOR_VERSION=2
|
||||
PATCHLEVEL=0
|
||||
|
||||
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
||||
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
|
||||
|
@ -306,6 +306,7 @@ sql [sS][qQ][lL]
|
||||
return (yytext[0]);
|
||||
}
|
||||
<SQL>{self} { return (yytext[0]); }
|
||||
<SQL>"->" { return S_STRUCTPOINTER; }
|
||||
<SQL>{operator}/-[\.0-9] {
|
||||
yylval.str = strdup((char*)yytext);
|
||||
return (Op);
|
||||
|
@ -17,8 +17,8 @@ static int QueryIsRule = 0;
|
||||
static enum ECPGttype actual_type[128];
|
||||
static char *actual_storage[128];
|
||||
|
||||
/* temporarily store record members while creating the data structure */
|
||||
struct ECPGrecord_member *record_member_list[128] = { NULL };
|
||||
/* temporarily store struct members while creating the data structure */
|
||||
struct ECPGstruct_member *struct_member_list[128] = { NULL };
|
||||
|
||||
/* keep a list of cursors */
|
||||
struct cursor *cur = NULL;
|
||||
@ -89,26 +89,6 @@ int braces_open;
|
||||
static struct variable * allvariables = NULL;
|
||||
|
||||
static struct variable *
|
||||
find_variable(char * name)
|
||||
{
|
||||
struct variable * p;
|
||||
char * errorstring = (char *) mm_alloc(strlen(name) + 100);
|
||||
|
||||
for (p = allvariables; p; p = p->next)
|
||||
{
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p;
|
||||
}
|
||||
|
||||
sprintf(errorstring, "The variable %s is not declared", name);
|
||||
yyerror(errorstring);
|
||||
free (errorstring);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
new_variable(const char * name, struct ECPGtype * type)
|
||||
{
|
||||
struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable));
|
||||
@ -119,6 +99,97 @@ new_variable(const char * name, struct ECPGtype * type)
|
||||
|
||||
p->next = allvariables;
|
||||
allvariables = p;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
static struct variable * find_variable(char * name);
|
||||
|
||||
static struct variable *
|
||||
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
|
||||
{
|
||||
char *next = strpbrk(++str, ".-"), c = '\0';
|
||||
|
||||
if (next != NULL)
|
||||
{
|
||||
c = *next;
|
||||
*next = '\0';
|
||||
}
|
||||
|
||||
for (; members; members = members->next)
|
||||
{
|
||||
if (strcmp(members->name, str) == 0)
|
||||
{
|
||||
if (c == '\0')
|
||||
{
|
||||
/* found the end */
|
||||
switch (members->typ->typ)
|
||||
{
|
||||
case ECPGt_struct:
|
||||
return(new_variable(name, ECPGmake_struct_type(members->typ->u.members)));
|
||||
case ECPGt_varchar:
|
||||
return(new_variable(name, ECPGmake_varchar_type(members->typ->typ, members->typ->size)));
|
||||
default:
|
||||
return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*next = c;
|
||||
if (c == '-') next++;
|
||||
return(find_struct_member(name, next, members->typ->u.members));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static struct variable *
|
||||
find_struct(char * name, char *next)
|
||||
{
|
||||
struct variable * p;
|
||||
char c = *next;
|
||||
|
||||
/* first get the mother structure entry */
|
||||
*next = '\0';
|
||||
p = find_variable(name);
|
||||
|
||||
/* restore the name, we will need it later on */
|
||||
*next = c;
|
||||
if (*next == '-') next++;
|
||||
|
||||
return (find_struct_member(name, next, p->type->u.members));
|
||||
}
|
||||
|
||||
static struct variable *
|
||||
find_simple(char * name)
|
||||
{
|
||||
struct variable * p;
|
||||
|
||||
for (p = allvariables; p; p = p->next)
|
||||
{
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p;
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static struct variable *
|
||||
find_variable(char * name)
|
||||
{
|
||||
char * next;
|
||||
struct variable * p =
|
||||
((next = strpbrk(name, ".-")) != NULL) ? find_struct(name, next) : find_simple(name);
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
sprintf(errortext, "The variable %s is not declared", name);
|
||||
yyerror(errortext);
|
||||
}
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -215,7 +286,7 @@ check_indicator(struct ECPGtype *var)
|
||||
/* make sure this is a valid indicator variable */
|
||||
switch (var->typ)
|
||||
{
|
||||
struct ECPGrecord_member *p;
|
||||
struct ECPGstruct_member *p;
|
||||
|
||||
case ECPGt_short:
|
||||
case ECPGt_int:
|
||||
@ -225,7 +296,7 @@ check_indicator(struct ECPGtype *var)
|
||||
case ECPGt_unsigned_long:
|
||||
break;
|
||||
|
||||
case ECPGt_record:
|
||||
case ECPGt_struct:
|
||||
for (p = var->u.members; p; p = p->next)
|
||||
check_indicator(p->typ);
|
||||
break;
|
||||
@ -392,8 +463,8 @@ output_statement(const char * stmt)
|
||||
/* C token */
|
||||
%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN
|
||||
%token S_FLOAT S_INT
|
||||
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT S_UNSIGNED
|
||||
%token S_VARCHAR
|
||||
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
|
||||
%token S_STRUCTPOINTER S_UNSIGNED S_VARCHAR
|
||||
|
||||
/* I need this and don't know where it is defined inside the backend */
|
||||
%token TYPECAST
|
||||
@ -3704,7 +3775,7 @@ declaration: storage_clause type
|
||||
{
|
||||
actual_storage[struct_level] = $1;
|
||||
actual_type[struct_level] = $2;
|
||||
if ($2 != ECPGt_varchar && $2 != ECPGt_record)
|
||||
if ($2 != ECPGt_varchar && $2 != ECPGt_struct)
|
||||
fprintf(yyout, "%s %s", $1, ECPGtype_name($2));
|
||||
}
|
||||
variable_list ';' { fputc(';', yyout); }
|
||||
@ -3723,11 +3794,13 @@ type: simple_type
|
||||
struct_type: s_struct '{' variable_declarations '}'
|
||||
{
|
||||
struct_level--;
|
||||
$$ = actual_type[struct_level] = ECPGt_record;
|
||||
fputs("} ", yyout);
|
||||
$$ = ECPGt_struct;
|
||||
}
|
||||
|
||||
s_struct : S_STRUCT symbol
|
||||
{
|
||||
struct_member_list[struct_level] = NULL;
|
||||
struct_level++;
|
||||
fprintf(yyout, "struct %s {", $2);
|
||||
}
|
||||
@ -3764,14 +3837,13 @@ variable: opt_pointer symbol opt_index opt_initializer
|
||||
|
||||
switch (actual_type[struct_level])
|
||||
{
|
||||
case ECPGt_record:
|
||||
case ECPGt_struct:
|
||||
if (struct_level == 0)
|
||||
new_variable($2, ECPGmake_record_type(record_member_list[struct_level]));
|
||||
new_variable($2, ECPGmake_struct_type(struct_member_list[struct_level]));
|
||||
else
|
||||
ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
|
||||
ECPGmake_struct_member($2, ECPGmake_struct_type(struct_member_list[struct_level]), &(struct_member_list[struct_level-1]));
|
||||
|
||||
record_member_list[struct_level] = NULL;
|
||||
fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4);
|
||||
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
|
||||
|
||||
break;
|
||||
case ECPGt_varchar:
|
||||
@ -3781,7 +3853,7 @@ variable: opt_pointer symbol opt_index opt_initializer
|
||||
if (struct_level == 0)
|
||||
new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
|
||||
else
|
||||
ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
|
||||
ECPGmake_struct_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1]));
|
||||
|
||||
if (length > 0)
|
||||
fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2);
|
||||
@ -3794,7 +3866,7 @@ variable: opt_pointer symbol opt_index opt_initializer
|
||||
if (struct_level == 0)
|
||||
new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length));
|
||||
else
|
||||
ECPGmake_record_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
|
||||
ECPGmake_struct_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1]));
|
||||
|
||||
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
|
||||
|
||||
@ -4230,15 +4302,15 @@ civariableonly : cvariable name {
|
||||
}
|
||||
|
||||
cvariable: CVARIABLE { $$ = $1; }
|
||||
| CVARIABLE '.' identlist { $$ = $1; }
|
||||
| CVARIABLE '-' '>' identlist { $$ = $1; }
|
||||
| CVARIABLE '.' identlist { $$ = cat3_str($1, ".", $3); }
|
||||
| CVARIABLE S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
|
||||
|
||||
identlist: IDENT { $$ = $1; }
|
||||
| IDENT '.' identlist { $$ = $1; }
|
||||
| IDENT '-' '>' identlist { $$ = $1; }
|
||||
| IDENT '.' identlist { $$ = cat3_str($1, ".", $3); }
|
||||
| IDENT S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
|
||||
|
||||
indicator: /* empty */ { $$ = NULL; }
|
||||
| cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
|
||||
| cvariable { printf("## %s\n", $1); check_indicator((find_variable($1))->type); $$ = $1; }
|
||||
| SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
|
||||
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
|
||||
|
||||
|
@ -40,12 +40,12 @@ mm_realloc(void *ptr, size_t size)
|
||||
*/
|
||||
|
||||
/* The NAME argument is copied. The type argument is preserved as a pointer. */
|
||||
struct ECPGrecord_member *
|
||||
ECPGmake_record_member(char *name, struct ECPGtype * type, struct ECPGrecord_member ** start)
|
||||
struct ECPGstruct_member *
|
||||
ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
|
||||
{
|
||||
struct ECPGrecord_member *ptr,
|
||||
struct ECPGstruct_member *ptr,
|
||||
*ne =
|
||||
(struct ECPGrecord_member *) mm_alloc(sizeof(struct ECPGrecord_member));
|
||||
(struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
|
||||
|
||||
ne->name = strdup(name);
|
||||
ne->typ = type;
|
||||
@ -94,9 +94,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz)
|
||||
}
|
||||
|
||||
struct ECPGtype *
|
||||
ECPGmake_record_type(struct ECPGrecord_member * rm)
|
||||
ECPGmake_struct_type(struct ECPGstruct_member * rm)
|
||||
{
|
||||
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record, 1);
|
||||
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
|
||||
|
||||
ne->u.members = rm;
|
||||
|
||||
@ -116,14 +116,14 @@ ECPGmake_record_type(struct ECPGrecord_member * rm)
|
||||
reference-to-variable can be a reference to a struct element.
|
||||
arrsize is the size of the array in case of array fetches. Otherwise 0.
|
||||
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
||||
the variable (required to do array fetches of records).
|
||||
the variable (required to do array fetches of structs).
|
||||
*/
|
||||
void
|
||||
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||
long varcharsize,
|
||||
long arrsiz, const char *siz, const char *prefix);
|
||||
void
|
||||
ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz,
|
||||
ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz,
|
||||
struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix);
|
||||
|
||||
|
||||
@ -154,19 +154,19 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
|
||||
{
|
||||
abort(); /* Array of array, */
|
||||
}
|
||||
else if (typ->u.element->typ == ECPGt_record)
|
||||
else if (typ->u.element->typ == ECPGt_struct)
|
||||
{
|
||||
/* Array of records. */
|
||||
ECPGdump_a_record(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
|
||||
/* Array of structs. */
|
||||
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
else if (typ->typ == ECPGt_record)
|
||||
else if (typ->typ == ECPGt_struct)
|
||||
{
|
||||
ECPGdump_a_record(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
|
||||
ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -176,7 +176,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
|
||||
|
||||
|
||||
/* If siz is NULL, then the offset is 0, if not use siz as a
|
||||
string, it represents the offset needed if we are in an array of records. */
|
||||
string, it represents the offset needed if we are in an array of structs. */
|
||||
void
|
||||
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||
long varcharsize,
|
||||
@ -189,66 +189,66 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||
{
|
||||
case ECPGt_char:
|
||||
if (varcharsize == 0) /* pointer */
|
||||
fprintf(o, "\n\tECPGt_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
siz == NULL ? "sizeof(char)" : siz);
|
||||
else
|
||||
fprintf(o, "\n\tECPGt_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
siz == NULL ? "sizeof(char)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_char:
|
||||
if (varcharsize == 0) /* pointer */
|
||||
fprintf(o, "\n\tECPGt_unsigned_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
siz == NULL ? "sizeof(char)" : siz);
|
||||
else
|
||||
fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned char)" : siz);
|
||||
break;
|
||||
case ECPGt_short:
|
||||
fprintf(o, "\n\tECPGt_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(short)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_short:
|
||||
fprintf(o,
|
||||
"\n\tECPGt_unsigned_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
"\n\tECPGt_unsigned_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned short)" : siz);
|
||||
break;
|
||||
case ECPGt_int:
|
||||
fprintf(o, "\n\tECPGt_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(int)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_int:
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned int)" : siz);
|
||||
break;
|
||||
case ECPGt_long:
|
||||
fprintf(o, "\n\tECPGt_long,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_long,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(long)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_long:
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned int)" : siz);
|
||||
break;
|
||||
case ECPGt_float:
|
||||
fprintf(o, "\n\tECPGt_float,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_float,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(float)" : siz);
|
||||
break;
|
||||
case ECPGt_double:
|
||||
fprintf(o, "\n\tECPGt_double,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_double,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(double)" : siz);
|
||||
break;
|
||||
case ECPGt_bool:
|
||||
fprintf(o, "\n\tECPGt_bool,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_bool,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
||||
siz == NULL ? "sizeof(bool)" : siz);
|
||||
break;
|
||||
case ECPGt_varchar:
|
||||
case ECPGt_varchar2:
|
||||
if (siz == NULL)
|
||||
fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,sizeof(struct varchar_%s), ",
|
||||
fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,sizeof(struct varchar_%s), ",
|
||||
prefix ? prefix : "", name,
|
||||
varcharsize,
|
||||
arrsiz, name);
|
||||
else
|
||||
fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,%s, ",
|
||||
fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,%s, ",
|
||||
prefix ? prefix : "", name,
|
||||
varcharsize,
|
||||
arrsiz, siz);
|
||||
@ -263,17 +263,17 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||
}
|
||||
|
||||
|
||||
/* Penetrate a record and dump the contents. */
|
||||
/* Penetrate a struct and dump the contents. */
|
||||
void
|
||||
ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
|
||||
ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
|
||||
{
|
||||
|
||||
/*
|
||||
* If offset is NULL, then this is the first recursive level. If not
|
||||
* then we are in a record in a record and the offset is used as
|
||||
* then we are in a struct in a struct and the offset is used as
|
||||
* offset.
|
||||
*/
|
||||
struct ECPGrecord_member *p, *ind_p = NULL;
|
||||
struct ECPGstruct_member *p, *ind_p = NULL;
|
||||
char obuf[BUFSIZ];
|
||||
char pbuf[BUFSIZ], ind_pbuf[BUFSIZ];
|
||||
const char *offset;
|
||||
@ -306,18 +306,19 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
|
||||
/* Freeing is not really that important. Since we throw away the process
|
||||
anyway. Lets implement that last! */
|
||||
|
||||
void
|
||||
ECPGfree_record_member(struct ECPGrecord_member * rm)
|
||||
/* won't work anymore because a list of members may appear in several locations */
|
||||
/*void
|
||||
ECPGfree_struct_member(struct ECPGstruct_member * rm)
|
||||
{
|
||||
while (rm)
|
||||
{
|
||||
struct ECPGrecord_member *p = rm;
|
||||
struct ECPGstruct_member *p = rm;
|
||||
|
||||
rm = rm->next;
|
||||
free(p->name);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
void
|
||||
ECPGfree_type(struct ECPGtype * typ)
|
||||
@ -330,15 +331,17 @@ ECPGfree_type(struct ECPGtype * typ)
|
||||
free(typ->u.element);
|
||||
else if (typ->u.element->typ == ECPGt_array)
|
||||
abort(); /* Array of array, */
|
||||
else if (typ->u.element->typ == ECPGt_record)
|
||||
/* Array of records. */
|
||||
ECPGfree_record_member(typ->u.members);
|
||||
else if (typ->u.element->typ == ECPGt_struct)
|
||||
/* Array of structs. */
|
||||
free(typ->u.members);
|
||||
/* ECPGfree_struct_member(typ->u.members);*/
|
||||
else
|
||||
abort();
|
||||
}
|
||||
else if (typ->typ == ECPGt_record)
|
||||
else if (typ->typ == ECPGt_struct)
|
||||
{
|
||||
ECPGfree_record_member(typ->u.members);
|
||||
free(typ->u.members);
|
||||
/* ECPGfree_struct_member(typ->u.members);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include <ecpgtype.h>
|
||||
|
||||
struct ECPGtype;
|
||||
struct ECPGrecord_member
|
||||
struct ECPGstruct_member
|
||||
{
|
||||
char *name;
|
||||
struct ECPGtype *typ;
|
||||
struct ECPGrecord_member *next;
|
||||
struct ECPGstruct_member *next;
|
||||
};
|
||||
|
||||
struct ECPGtype
|
||||
@ -19,20 +19,20 @@ struct ECPGtype
|
||||
struct ECPGtype *element; /* For an array this is the type
|
||||
* of the element */
|
||||
|
||||
struct ECPGrecord_member *members;
|
||||
struct ECPGstruct_member *members;
|
||||
/* A pointer to a list of members. */
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Everything is malloced. */
|
||||
struct ECPGrecord_member *ECPGmake_record_member(char *, struct ECPGtype *, struct ECPGrecord_member **);
|
||||
struct ECPGstruct_member *ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member **);
|
||||
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long);
|
||||
struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long);
|
||||
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long);
|
||||
struct ECPGtype *ECPGmake_record_type(struct ECPGrecord_member *);
|
||||
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *);
|
||||
|
||||
/* Frees a type. */
|
||||
void ECPGfree_record_member(struct ECPGrecord_member *);
|
||||
void ECPGfree_struct_member(struct ECPGstruct_member *);
|
||||
void ECPGfree_type(struct ECPGtype *);
|
||||
|
||||
/* Dump a type.
|
||||
@ -43,7 +43,7 @@ void ECPGfree_type(struct ECPGtype *);
|
||||
reference-to-variable can be a reference to a struct element.
|
||||
arrsize is the size of the array in case of array fetches. Otherwise 0.
|
||||
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
||||
the variable (required to do array fetches of records).
|
||||
the variable (required to do array fetches of structs).
|
||||
*/
|
||||
void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, struct ECPGtype *, const char *, const char *);
|
||||
|
||||
|
@ -60,7 +60,7 @@ exec sql end declare section;
|
||||
|
||||
while (not_found == 0) {
|
||||
strcpy(msg, "fetch");
|
||||
exec sql fetch cur into :personal:ind_personal, :married:ind_married, :personal.birth.born;
|
||||
exec sql fetch cur into :personal:ind_personal, :married:ind_married;
|
||||
if (not_found == 0)
|
||||
printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user