Commit 7500a961 authored by Marc G. Fournier's avatar Marc G. Fournier

From: Michael Meskes <meskes@topsystem.de>

+ Thu Apr 23 09:27:16 CEST 1998
+
+       - Also allow call in whenever statement with the same functionality
+         as do.
+
+ Thu Apr 23 12:29:28 CEST 1998
+
+       - Also rewrote variable declaration part. It is now possible to
+         declare more than one variable per line.
+       - Set version to 2.1.0
+
+ Fri Apr 24 13:50:15 CEST 1998
+
+       - Fixed some bugs.
+       - Set version to 2.1.1
parent f2b64d35
...@@ -121,8 +121,24 @@ Mon Apr 20 16:13:25 CEST 1998 ...@@ -121,8 +121,24 @@ Mon Apr 20 16:13:25 CEST 1998
Mon Apr 20 16:39:23 CEST 1998 Mon Apr 20 16:39:23 CEST 1998
- Cursor is opened when the open command is issued, not at declare time. - Cursor is opened when the open command is issued, not at declare time.
- Set version to 2.0.0
Tue Apr 21 12:53:49 CEST 1998 Tue Apr 21 12:53:49 CEST 1998
- Set indicator to amount of data really written (truncation). - Set indicator to amount of data really written (truncation).
Thu Apr 23 09:27:16 CEST 1998
- Also allow call in whenever statement with the same functionality
as do.
Thu Apr 23 12:29:28 CEST 1998
- Also rewrote variable declaration part. It is now possible to
declare more than one variable per line.
- Set version to 2.1.0
Fri Apr 24 13:50:15 CEST 1998
- Fixed some bugs.
- Set version to 2.1.1
...@@ -35,8 +35,6 @@ There is no exec sql prepare statement. ...@@ -35,8 +35,6 @@ There is no exec sql prepare statement.
The complete structure definition has to be listed inside the declare The complete structure definition has to be listed inside the declare
section for ecpg to be able to understand it. section for ecpg to be able to understand it.
Each variable has to be defined on a line on its own.
There is no way yet to fill a complete array with one call except arrays of There is no way yet to fill a complete array with one call except arrays of
[unsigned] char which are considered strings. [unsigned] char which are considered strings.
...@@ -54,4 +52,7 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar}; ...@@ -54,4 +52,7 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar};
| CURRENT | CURRENT
commit release|commit work release auch disconnect commit release|commit work release auch disconnect
It is not neccessary to check for sql not found after all commands. 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.
...@@ -21,7 +21,6 @@ ifeq ($(PORTNAME), linux) ...@@ -21,7 +21,6 @@ ifeq ($(PORTNAME), linux)
install-shlib-dep := install-shlib install-shlib-dep := install-shlib
shlib := libecpg.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION) shlib := libecpg.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -shared -soname libecpg.so.$(SO_MAJOR_VERSION) LDFLAGS_SL = -shared -soname libecpg.so.$(SO_MAJOR_VERSION)
CFLAGS += $(CFLAGS_SL)
endif endif
endif endif
ifeq ($(PORTNAME), bsd) ifeq ($(PORTNAME), bsd)
...@@ -47,12 +46,12 @@ endif ...@@ -47,12 +46,12 @@ endif
all: libecpg.a $(shlib) all: libecpg.a $(shlib)
$(shlib): ecpglib.o typename.o $(shlib): ecpglib.sho typename.sho
$(LD) $(LDFLAGS_SL) -o $@ ecpglib.o typename.o $(LD) $(LDFLAGS_SL) -o $@ ecpglib.sho typename.sho
ln -sf $@ libecpg.so ln -sf $@ libecpg.so
clean: clean:
rm -f *.o *.a core a.out *~ $(shlib) libecpg.so rm -f *.o *.sho *.a core a.out *~ $(shlib) libecpg.so
dep depend: dep depend:
...@@ -70,6 +69,11 @@ uninstall:: ...@@ -70,6 +69,11 @@ uninstall::
libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o) libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o)
ecpglib.o : ecpglib.c ../include/ecpglib.h ../include/ecpgtype.h ecpglib.o : ecpglib.c ../include/ecpglib.h ../include/ecpgtype.h
$(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c ecpglib.c $(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c $< -o $@
typename.o : typename.c ../include/ecpgtype.h typename.o : typename.c ../include/ecpgtype.h
$(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c typename.c $(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c $< -o $@
ecpglib.sho : ecpglib.c ../include/ecpglib.h ../include/ecpgtype.h
$(CC) $(CFLAGS) $(CFLAGS_SL) -I../include $(PQ_INCLUDE) -c $< -o $@
typename.sho : typename.c ../include/ecpgtype.h
$(CC) $(CFLAGS) $(CFLAGS_SL) -I../include $(PQ_INCLUDE) -c $< -o $@
...@@ -2,8 +2,8 @@ SRCDIR= ../../.. ...@@ -2,8 +2,8 @@ SRCDIR= ../../..
include $(SRCDIR)/Makefile.global include $(SRCDIR)/Makefile.global
MAJOR_VERSION=2 MAJOR_VERSION=2
MINOR_VERSION=0 MINOR_VERSION=1
PATCHLEVEL=0 PATCHLEVEL=1
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \ -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
......
...@@ -27,7 +27,7 @@ static void ...@@ -27,7 +27,7 @@ static void
usage(char *progname) usage(char *progname)
{ {
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
fprintf(stderr, "Usage: %s: [-v] [-d] [-I include path] [ -o output file name] file1 [file2] ...\n", progname); fprintf(stderr, "Usage: %s: [-v] [-I include path] [ -o output file name] file1 [file2] ...\n", progname);
} }
static void static void
...@@ -51,7 +51,7 @@ main(int argc, char *const argv[]) ...@@ -51,7 +51,7 @@ main(int argc, char *const argv[])
add_include_path("/usr/local/include"); add_include_path("/usr/local/include");
add_include_path("."); add_include_path(".");
while ((c = getopt(argc, argv, "vdo:I:")) != EOF) while ((c = getopt(argc, argv, "vo:I:")) != EOF)
{ {
switch (c) switch (c)
{ {
...@@ -62,9 +62,6 @@ main(int argc, char *const argv[]) ...@@ -62,9 +62,6 @@ main(int argc, char *const argv[])
else else
out_option = 1; out_option = 1;
break; break;
case 'd':
debugging = 1;
break;
case 'I': case 'I':
add_include_path(optarg); add_include_path(optarg);
break; break;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
*/ */
static ScanKeyword ScanKeywords[] = { static ScanKeyword ScanKeywords[] = {
/* name value */ /* name value */
{"call", SQL_CALL},
{"connect", SQL_CONNECT}, {"connect", SQL_CONNECT},
{"continue", SQL_CONTINUE}, {"continue", SQL_CONTINUE},
{"found", SQL_FOUND}, {"found", SQL_FOUND},
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
/* variables */ /* variables */
extern int debugging, extern int braces_open;
braces_open;
extern char *yytext; extern char *yytext;
extern int yylineno, extern int yylineno,
yyleng; yyleng;
...@@ -23,6 +22,18 @@ struct cursor { char *name; ...@@ -23,6 +22,18 @@ struct cursor { char *name;
extern struct cursor *cur; extern struct cursor *cur;
/* This is a linked list of the variable names and types. */
struct variable
{
char * name;
struct ECPGtype * type;
int brace_level;
struct variable * next;
};
extern struct ECPGtype ecpg_no_indicator;
extern struct variable no_indicator;
/* functions */ /* functions */
extern void lex_init(void); extern void lex_init(void);
......
...@@ -70,6 +70,7 @@ struct _yy_buffer { YY_BUFFER_STATE buffer; ...@@ -70,6 +70,7 @@ struct _yy_buffer { YY_BUFFER_STATE buffer;
%x xb %x xb
%x xc %x xc
%x xd %x xd
%x xdc
%x xh %x xh
%x xm %x xm
%x xq %x xq
...@@ -261,7 +262,7 @@ sql [sS][qQ][lL] ...@@ -261,7 +262,7 @@ sql [sS][qQ][lL]
<xd>{xdstop} { <xd>{xdstop} {
BEGIN(SQL); BEGIN(SQL);
yylval.str = strdup(literal); yylval.str = strdup(literal);
return (IDENT); return (CSTRING);
} }
<xd>{xdinside} { <xd>{xdinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
...@@ -269,7 +270,22 @@ sql [sS][qQ][lL] ...@@ -269,7 +270,22 @@ sql [sS][qQ][lL]
memcpy(literal+llen, yytext, yyleng+1); memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng; llen += yyleng;
} }
<C>{xdstart} {
BEGIN(xdc);
llen = 0;
*literal = '\0';
}
<xdc>{xdstop} {
BEGIN(C);
yylval.str = strdup(literal);
return (CSTRING);
}
<xdc>{xdinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
}
<xm>{space}* { /* ignore */ } <xm>{space}* { /* ignore */ }
<xm>{xmstop} { <xm>{xmstop} {
...@@ -283,7 +299,7 @@ sql [sS][qQ][lL] ...@@ -283,7 +299,7 @@ sql [sS][qQ][lL]
<SQL>{self}/-[\.0-9] { <SQL>{self}/-[\.0-9] {
return (yytext[0]); return (yytext[0]);
} }
<SQL>{self} { return (yytext[0]); } <SQL>{self} { return (yytext[0]); }
<SQL>{operator}/-[\.0-9] { <SQL>{operator}/-[\.0-9] {
yylval.str = strdup((char*)yytext); yylval.str = strdup((char*)yytext);
return (Op); return (Op);
...@@ -379,6 +395,10 @@ sql [sS][qQ][lL] ...@@ -379,6 +395,10 @@ sql [sS][qQ][lL]
return (FCONST); return (FCONST);
} }
<SQL>:{identifier} {
yylval.str = strdup((char*)yytext+1);
return(CVARIABLE);
}
<SQL>{identifier} { <SQL>{identifier} {
int i; int i;
ScanKeyword *keyword; ScanKeyword *keyword;
...@@ -423,12 +443,14 @@ sql [sS][qQ][lL] ...@@ -423,12 +443,14 @@ sql [sS][qQ][lL]
} }
} }
<C>";" { return(';'); } <C>";" { return(';'); }
<C>"," { return(','); }
<C>"*" { return('*'); }
<C>{space} { ECHO; } <C>{space} { ECHO; }
\{ { return('{'); } <C>\{ { return('{'); }
\} { return('}'); } <C>\} { return('}'); }
\[ { return('['); } <C>\[ { return('['); }
\] { return(']'); } <C>\] { return(']'); }
\= { return('='); } <C>\= { return('='); }
<C>{other} { return (S_ANYTHING); } <C>{other} { return (S_ANYTHING); }
<C>{exec}{space}{sql}{space}{include} { BEGIN(incl); } <C>{exec}{space}{sql}{space}{include} { BEGIN(incl); }
<incl>{space} /* eat the whitespace */ <incl>{space} /* eat the whitespace */
......
...@@ -12,9 +12,10 @@ ...@@ -12,9 +12,10 @@
* Variables containing simple states. * Variables containing simple states.
*/ */
static int struct_level = 0; static int struct_level = 0;
static char *do_str = NULL, errortext[128]; static char errortext[128];
static int do_length = 0;
static int QueryIsRule = 0; static int QueryIsRule = 0;
static enum ECPGttype actual_type[128];
static char *actual_storage[128];
/* temporarily store record members while creating the data structure */ /* temporarily store record members while creating the data structure */
struct ECPGrecord_member *record_member_list[128] = { NULL }; struct ECPGrecord_member *record_member_list[128] = { NULL };
...@@ -22,6 +23,9 @@ struct ECPGrecord_member *record_member_list[128] = { NULL }; ...@@ -22,6 +23,9 @@ struct ECPGrecord_member *record_member_list[128] = { NULL };
/* keep a list of cursors */ /* keep a list of cursors */
struct cursor *cur = NULL; struct cursor *cur = NULL;
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
/* /*
* Handle the filename and line numbering. * Handle the filename and line numbering.
*/ */
...@@ -82,15 +86,6 @@ whenever_action() ...@@ -82,15 +86,6 @@ whenever_action()
*/ */
int braces_open; int braces_open;
/* This is a linked list of the variable names and types. */
struct variable
{
char * name;
struct ECPGtype * type;
int brace_level;
struct variable * next;
};
static struct variable * allvariables = NULL; static struct variable * allvariables = NULL;
static struct variable * static struct variable *
...@@ -105,7 +100,7 @@ find_variable(char * name) ...@@ -105,7 +100,7 @@ find_variable(char * name)
return p; return p;
} }
sprintf(errorstring, "The variable :%s is not declared", name); sprintf(errorstring, "The variable %s is not declared", name);
yyerror(errorstring); yyerror(errorstring);
free (errorstring); free (errorstring);
...@@ -167,9 +162,6 @@ struct arguments { ...@@ -167,9 +162,6 @@ struct arguments {
static struct arguments * argsinsert = NULL; static struct arguments * argsinsert = NULL;
static struct arguments * argsresult = NULL; static struct arguments * argsresult = NULL;
static struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
static struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
static void static void
reset_variables(void) reset_variables(void)
{ {
...@@ -209,7 +201,9 @@ dump_variables(struct arguments * list) ...@@ -209,7 +201,9 @@ dump_variables(struct arguments * list)
dump_variables(list->next); dump_variables(list->next);
/* Then the current element and its indicator */ /* Then the current element and its indicator */
ECPGdump_a_type(yyout, list->variable->name, list->variable->type, list->indicator->name, list->indicator->type, NULL, NULL); ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL,
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
/* Then release the list element. */ /* Then release the list element. */
free(list); free(list);
...@@ -360,7 +354,15 @@ make_name(void) ...@@ -360,7 +354,15 @@ make_name(void)
static void static void
output_statement(const char * stmt) output_statement(const char * stmt)
{ {
fprintf(yyout, "ECPGdo(__LINE__, \"%s\", ", stmt); int i, j=strlen(stmt);
fputs("ECPGdo(__LINE__, \"", yyout);
/* do this char by char as we have to filter '\"' */
for (i = 0;i < j; i++)
if (stmt[i] != '\"')
fputc(stmt[i], yyout);
fputs("\", ", yyout);
/* dump variables to C file*/ /* dump variables to C file*/
dump_variables(argsinsert); dump_variables(argsinsert);
...@@ -375,14 +377,14 @@ output_statement(const char * stmt) ...@@ -375,14 +377,14 @@ output_statement(const char * stmt)
double dval; double dval;
int ival; int ival;
char * str; char * str;
struct ECPGtemp_type type;
struct when action; struct when action;
struct index index;
int tagname; int tagname;
enum ECPGttype type_enum; enum ECPGttype type_enum;
} }
/* special embedded SQL token */ /* special embedded SQL token */
%token SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO %token SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO
%token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN %token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN
%token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START %token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
%token SQL_STOP SQL_WHENEVER %token SQL_STOP SQL_WHENEVER
...@@ -449,7 +451,7 @@ output_statement(const char * stmt) ...@@ -449,7 +451,7 @@ output_statement(const char * stmt)
%token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL %token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
/* Special keywords, not in the query language - see the "lex" file */ /* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT SCONST Op %token <str> IDENT SCONST Op CSTRING CVARIABLE
%token <ival> ICONST PARAM %token <ival> ICONST PARAM
%token <dval> FCONST %token <dval> FCONST
...@@ -538,11 +540,18 @@ output_statement(const char * stmt) ...@@ -538,11 +540,18 @@ output_statement(const char * stmt)
%type <str> GrantStmt privileges operation_commalist operation %type <str> GrantStmt privileges operation_commalist operation
%type <str> ECPGWhenever ECPGConnect db_name ECPGOpen open_opts %type <str> ECPGWhenever ECPGConnect db_name ECPGOpen open_opts
%type <str> indicator ECPGExecute c_expr %type <str> indicator ECPGExecute c_expr variable_list dotext
%type <str> storage_clause opt_initializer vartext c_anything blockstart
%type <str> blockend variable_list variable var_anything sql_anything
%type <str> opt_pointer ecpg_ident cvariable identlist
%type <str> stmt symbol %type <str> stmt symbol
%type <type_enum> simple_type type struct_type
%type <action> action %type <action> action
%type <index> opt_index
%% %%
prog: statements; prog: statements;
...@@ -551,9 +560,9 @@ statements: /* empty */ ...@@ -551,9 +560,9 @@ statements: /* empty */
statement: ecpgstart stmt SQL_SEMI statement: ecpgstart stmt SQL_SEMI
| ECPGDeclaration | ECPGDeclaration
| c_anything | c_anything { fputs($1, yyout); }
| blockstart | blockstart { fputs($1, yyout); }
| blockend | blockend { fputs($1, yyout); }
stmt: AddAttrStmt { output_statement($1); } stmt: AddAttrStmt { output_statement($1); }
| AlterUserStmt { output_statement($1); } | AlterUserStmt { output_statement($1); }
...@@ -1332,7 +1341,7 @@ TriggerFuncArg: Iconst ...@@ -1332,7 +1341,7 @@ TriggerFuncArg: Iconst
$$ = make_name(); $$ = make_name();
} }
| Sconst { $$ = $1; } | Sconst { $$ = $1; }
| IDENT { $$ = $1; } | ecpg_ident { $$ = $1; }
; ;
DropTrigStmt: DROP TRIGGER name ON relation_name DropTrigStmt: DROP TRIGGER name ON relation_name
...@@ -1829,7 +1838,7 @@ OptStmtMulti: OptStmtMulti OptimizableStmt ';' ...@@ -1829,7 +1838,7 @@ OptStmtMulti: OptStmtMulti OptimizableStmt ';'
event_object: relation_name '.' attr_name event_object: relation_name '.' attr_name
{ {
$$ = make3_str($1, ",", $3); $$ = cat3_str($1, ".", $3);
} }
| relation_name | relation_name
{ {
...@@ -2243,7 +2252,7 @@ sortby: ColId OptUseOp ...@@ -2243,7 +2252,7 @@ sortby: ColId OptUseOp
} }
| ColId '.' ColId OptUseOp | ColId '.' ColId OptUseOp
{ {
$$ = make4_str($1, ".", $3, $4); $$ = make2_str(cat3_str($1, ".", $3), $4);
} }
| Iconst OptUseOp | Iconst OptUseOp
{ {
...@@ -2292,7 +2301,7 @@ groupby: ColId ...@@ -2292,7 +2301,7 @@ groupby: ColId
} }
| ColId '.' ColId | ColId '.' ColId
{ {
$$ = make3_str($1, ",", $3); $$ = cat3_str($1, ",", $3);
} }
| Iconst | Iconst
{ {
...@@ -2383,7 +2392,7 @@ join_using: ColId ...@@ -2383,7 +2392,7 @@ join_using: ColId
} }
| ColId '.' ColId | ColId '.' ColId
{ {
$$ = make3_str($1, ".", $3); $$ = cat3_str($1, ".", $3);
} }
| Iconst | Iconst
{ {
...@@ -2455,7 +2464,7 @@ Generic: generic ...@@ -2455,7 +2464,7 @@ Generic: generic
} }
; ;
generic: IDENT { $$ = $1; } generic: ecpg_ident { $$ = $1; }
| TYPE_P { $$ = "type"; } | TYPE_P { $$ = "type"; }
; ;
...@@ -3409,20 +3418,20 @@ not_in_expr_nodes: AexprConst ...@@ -3409,20 +3418,20 @@ not_in_expr_nodes: AexprConst
attr: relation_name '.' attrs attr: relation_name '.' attrs
{ {
$$ = make3_str($1, ".", $3); $$ = cat3_str($1, ".", $3);
} }
| ParamNo '.' attrs | ParamNo '.' attrs
{ {
$$ = make3_str($1, ".", $3); $$ = cat3_str($1, ".", $3);
} }
; ;
attrs: attr_name attrs: attr_name
{ $$ = $1; } { $$ = $1; }
| attrs '.' attr_name | attrs '.' attr_name
{ $$ = make3_str($1, ".", $3); } { $$ = cat3_str($1, ".", $3); }
| attrs '.' '*' | attrs '.' '*'
{ $$ = make2_str($1, ".*"); } { $$ = cat2_str($1, ".*"); }
; ;
...@@ -3449,7 +3458,7 @@ res_target_el: ColId opt_indirection '=' a_expr_or_null ...@@ -3449,7 +3458,7 @@ res_target_el: ColId opt_indirection '=' a_expr_or_null
} }
| relation_name '.' '*' | relation_name '.' '*'
{ {
$$ = make2_str($1, ".*"); $$ = cat2_str($1, ".*");
} }
; ;
...@@ -3475,7 +3484,7 @@ res_target_el2: a_expr_or_null AS ColLabel ...@@ -3475,7 +3484,7 @@ res_target_el2: a_expr_or_null AS ColLabel
} }
| relation_name '.' '*' | relation_name '.' '*'
{ {
$$ = make2_str($1, ".*"); $$ = cat2_str($1, ".*");
} }
| '*' | '*'
{ {
...@@ -3505,9 +3514,9 @@ relation_name: SpecialRuleRelation ...@@ -3505,9 +3514,9 @@ relation_name: SpecialRuleRelation
; ;
database_name: ColId { $$ = $1; }; database_name: ColId { $$ = $1; };
access_method: IDENT { $$ = $1; }; access_method: ecpg_ident { $$ = $1; };
attr_name: ColId { $$ = $1; }; attr_name: ColId { $$ = $1; };
class: IDENT { $$ = $1; }; class: ecpg_ident { $$ = $1; };
index_name: ColId { $$ = $1; }; index_name: ColId { $$ = $1; };
/* Functions /* Functions
...@@ -3518,7 +3527,7 @@ name: ColId { $$ = $1; }; ...@@ -3518,7 +3527,7 @@ name: ColId { $$ = $1; };
func_name: ColId { $$ = $1; }; func_name: ColId { $$ = $1; };
file_name: Sconst { $$ = $1; }; file_name: Sconst { $$ = $1; };
recipe_name: IDENT { $$ = $1; }; recipe_name: ecpg_ident { $$ = $1; };
/* Constants /* Constants
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
...@@ -3569,7 +3578,7 @@ Sconst: SCONST { ...@@ -3569,7 +3578,7 @@ Sconst: SCONST {
$$[strlen($1)+2]='\0'; $$[strlen($1)+2]='\0';
$$[strlen($1)+1]='\''; $$[strlen($1)+1]='\'';
} }
UserId: IDENT { $$ = $1;}; UserId: ecpg_ident { $$ = $1;};
/* Column and type identifier /* Column and type identifier
* Does not include explicit datetime types * Does not include explicit datetime types
...@@ -3591,7 +3600,7 @@ TypeId: ColId ...@@ -3591,7 +3600,7 @@ TypeId: ColId
* list due to shift/reduce conflicts in yacc. If so, move * list due to shift/reduce conflicts in yacc. If so, move
* down to the ColLabel entity. - thomas 1997-11-06 * down to the ColLabel entity. - thomas 1997-11-06
*/ */
ColId: IDENT { $$ = $1; } ColId: ecpg_ident { $$ = $1; }
| datetime { $$ = $1; } | datetime { $$ = $1; }
| ACTION { $$ = "action"; } | ACTION { $$ = "action"; }
| CACHE { $$ = "cache"; } | CACHE { $$ = "cache"; }
...@@ -3688,169 +3697,139 @@ sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION SQL_SEMI { ...@@ -3688,169 +3697,139 @@ sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION SQL_SEMI {
output_line_number(); output_line_number();
} }
variable_declarations : /* empty */ variable_declarations: /* empty */
| variable_declarations variable_declaration; | declaration variable_declarations;
/* Here is where we can enter support for typedef. */ declaration: storage_clause type
variable_declaration: type initializer ';' { {
/* don't worry about our list when we're working on a struct */ actual_storage[struct_level] = $1;
if (struct_level == 0) actual_type[struct_level] = $2;
{ if ($2 != ECPGt_varchar && $2 != ECPGt_record)
new_variable($<type>1.name, $<type>1.typ); fprintf(yyout, "%s %s", $1, ECPGtype_name($2));
free((void *)$<type>1.name); }
} variable_list ';' { fputc(';', yyout); }
fputs(";", yyout);
}
initializer : /*empty */ storage_clause : S_EXTERN { $$ = "extern"; }
| '=' {fwrite(yytext, yyleng, 1, yyout);} vartext; | S_STATIC { $$ = "static"; }
| S_SIGNED { $$ = "signed"; }
type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; }; | S_CONST { $$ = "const"; }
type_detailed : varchar_type { $<type>$ = $<type>1; } | S_REGISTER { $$ = "register"; }
| simple_type { $<type>$ = $<type>1; } | S_AUTO { $$ = "auto"; }
| string_type { $<type>$ = $<type>1; } | /* empty */ { $$ = "" ; }
/* | array_type {$<type>$ = $<type>1; }
| pointer_type {$<type>$ = $<type>1; }*/
| struct_type {$<type>$ = $<type>1; };
varchar_type : varchar_tag symbol index {
if ($<ival>3 > 0L)
fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $2, $<ival>3, $2);
else
fprintf(yyout, "struct varchar_%s { int len; char arr[]; } %s", $2, $2);
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<ival>3);
}
else
ECPGmake_record_member($2, ECPGmake_varchar_type(ECPGt_varchar, $<ival>3), &(record_member_list[struct_level-1]));
}
varchar_tag: S_VARCHAR /*| S_VARCHAR2 */; type: simple_type
| struct_type
simple_type : simple_tag symbol { struct_type: s_struct '{' variable_declarations '}'
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $2); {
if (struct_level == 0) struct_level--;
{ $$ = actual_type[struct_level] = ECPGt_record;
$<type>$.name = $2; }
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
}
else
ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
}
string_type : char_tag symbol index { s_struct : S_STRUCT symbol
if ($<ival>3 > 0L) {
fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $2, $<ival>3); struct_level++;
else fprintf(yyout, "struct %s {", $2);
fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $2); }
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, $<ival>3);
}
else
ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, $<ival>3), &(record_member_list[struct_level-1]));
}
| char_tag '*' symbol {
fprintf(yyout, "%s *%s", ECPGtype_name($<type_enum>1), $3);
if (struct_level == 0)
{
$<type>$.name = $3;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 0);
}
else
ECPGmake_record_member($3, ECPGmake_simple_type($<type_enum>1, 0), &(record_member_list[struct_level-1]));
}
| char_tag symbol {
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $2);
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
}
else
ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
}
char_tag : S_CHAR { $<type_enum>$ = ECPGt_char; } simple_type: S_SHORT { $$ = ECPGt_short; }
| S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; } | S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; }
| S_INT { $$ = ECPGt_int; }
| S_UNSIGNED S_INT { $$ = ECPGt_unsigned_int; }
| S_LONG { $$ = ECPGt_long; }
| S_UNSIGNED S_LONG { $$ = ECPGt_unsigned_long; }
| S_FLOAT { $$ = ECPGt_float; }
| S_DOUBLE { $$ = ECPGt_double; }
| S_BOOL { $$ = ECPGt_bool; };
| S_CHAR { $$ = ECPGt_char; }
| S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; }
| S_VARCHAR { $$ = ECPGt_varchar; }
variable_list: variable
| variable_list ','
{
if (actual_type[struct_level] != ECPGt_varchar)
fputs(", ", yyout);
else
fputs(";\n ", yyout);
} variable
/* variable: opt_pointer symbol opt_index opt_initializer
array_type : simple_tag symbol index { {
if ($<ival>3 > 0) int length = $3.ival;
fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $2, $<ival>3);
else
fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $2);
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<ival>3);
}
else
ECPGmake_record_member($2, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<ival>3), &(record_member_list[struct_level-1]));
}
pointer_type : simple_tag '*' symbol { /* pointer has to get length 0 */
fprintf(yyout, "%s * %s", ECPGtype_name($<type_enum>1), $3); if (strlen($1) > 0)
if (struct_level == 0) length = 0;
{
$<type>$.name = $3;
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0);
}
else
ECPGmake_record_member($3, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0), &(record_member_list[struct_level-1]));
}
*/
s_struct : S_STRUCT symbol { switch (actual_type[struct_level])
struct_level++; {
fprintf(yyout, "struct %s {", $2); case ECPGt_record:
} if (struct_level == 0)
new_variable($2, ECPGmake_record_type(record_member_list[struct_level]));
else
ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
struct_type : s_struct '{' variable_declarations '}' symbol { record_member_list[struct_level] = NULL;
struct_level--; fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4);
if (struct_level == 0)
{ break;
$<type>$.name = $5; case ECPGt_varchar:
$<type>$.typ = ECPGmake_record_type(record_member_list[struct_level]); if (strlen($4) != 0)
} yyerror("varchar initilization impossible");
else
ECPGmake_record_member($5, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1])); if (struct_level == 0)
fprintf(yyout, "} %s", $5); new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
record_member_list[struct_level] = NULL; else
} ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_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);
else
fprintf(yyout, "%s struct varchar_%s { int len; char arr[]; } %s", actual_storage[struct_level], $2, $2);
break;
default:
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]));
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
break;
}
}
opt_initializer: /* empty */ { $$ = ""; }
| '=' vartext { $$ = cat2_str("=", $2); }
opt_pointer: /* empty */ { $$ = ""; }
| '*' { $$ = "*"; }
simple_tag : S_SHORT { $<type_enum>$ = ECPGt_short; } opt_index: '[' Iconst ']' {
| S_UNSIGNED S_SHORT { $<type_enum>$ = ECPGt_unsigned_short; } $$.ival = atol($2);
| S_INT { $<type_enum>$ = ECPGt_int; } $$.str = cat3_str("[", $2, "]");
| S_UNSIGNED S_INT { $<type_enum>$ = ECPGt_unsigned_int; } }
| S_LONG { $<type_enum>$ = ECPGt_long; } | '[' ']'
| S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; } {
| S_FLOAT { $<type_enum>$ = ECPGt_float; } $$.ival = 0;
| S_DOUBLE { $<type_enum>$ = ECPGt_double; } $$.str = "[]";
| S_BOOL { $<type_enum>$ = ECPGt_bool; }; }
| /* empty */ {
maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); } $$.ival = 1;
| S_STATIC { fwrite(yytext, yyleng, 1, yyout); } $$.str = "";
| S_SIGNED { fwrite(yytext, yyleng, 1, yyout); } }
| S_CONST { fwrite(yytext, yyleng, 1, yyout); }
| S_REGISTER { fwrite(yytext, yyleng, 1, yyout); }
| S_AUTO { fwrite(yytext, yyleng, 1, yyout); }
| /* empty */ { };
index : '[' Iconst ']' { $<ival>$ = atol($2); }
| '[' ']' { $<ival>$ = 0L; }
/* /*
* the exec sql connect statement: connect to the given database * the exec sql connect statement: connect to the given database
*/ */
ECPGConnect : SQL_CONNECT db_name { $$ = $2; } ECPGConnect: SQL_CONNECT db_name { $$ = $2; }
db_name : database_name { $$ = $1; } db_name: database_name { $$ = $1; }
| ':' name { /* check if we have a char variable */ | cvariable { /* check if we have a char variable */
struct variable *p = find_variable($2); struct variable *p = find_variable($1);
enum ECPGttype typ = p->type->typ; enum ECPGttype typ = p->type->typ;
/* if array see what's inside */ /* if array see what's inside */
...@@ -3859,13 +3838,13 @@ db_name : database_name { $$ = $1; } ...@@ -3859,13 +3838,13 @@ db_name : database_name { $$ = $1; }
if (typ != ECPGt_char && typ != ECPGt_unsigned_char) if (typ != ECPGt_char && typ != ECPGt_unsigned_char)
yyerror("invalid datatype"); yyerror("invalid datatype");
$$ = $2; $$ = $1;
} }
/* /*
* execute a given string as sql command * execute a given string as sql command
*/ */
ECPGExecute : EXECUTE SQL_IMMEDIATE ':' name { $$ = $4; }; ECPGExecute : EXECUTE SQL_IMMEDIATE cvariable { $$ = $3; };
/* /*
* open is an open cursor, at the moment this has to be removed * open is an open cursor, at the moment this has to be removed
...@@ -3890,12 +3869,15 @@ ECPGOpen: SQL_OPEN name open_opts { ...@@ -3890,12 +3869,15 @@ ECPGOpen: SQL_OPEN name open_opts {
}; };
open_opts: /* empty */ { $$ = ""; } open_opts: /* empty */ { $$ = ""; }
| USING ':' name { | USING cvariable {
yyerror ("open cursor with variables not implemented yet"); yyerror ("open cursor with variables not implemented yet");
} }
/* /*
* whenever statement: decide what to do in case of error/no dat * whenever statement: decide what to do in case of error/no data found
* according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION
* and SQLWARNING
*/ */
ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action { ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action {
when_error.code = $<action>3.code; when_error.code = $<action>3.code;
...@@ -3933,17 +3915,15 @@ action : SQL_CONTINUE { ...@@ -3933,17 +3915,15 @@ action : SQL_CONTINUE {
$<action>$.command = $3; $<action>$.command = $3;
$<action>$.str = make2_str("goto ", $3); $<action>$.str = make2_str("goto ", $3);
} }
| DO name '(' { | DO name '(' dotext ')' {
do_str = (char *) mm_alloc(do_length = strlen($2) + 4);
sprintf(do_str, "%s (", $2);
} dotext ')' {
do_str[strlen(do_str)+1]='\0';
do_str[strlen(do_str)]=')';
$<action>$.code = W_DO; $<action>$.code = W_DO;
$<action>$.command = do_str; $<action>$.command = cat4_str($2, "(", $4, ")");
$<action>$.str = make2_str("do ", do_str); $<action>$.str = make2_str("do", $<action>$.command);
do_str = NULL; }
do_length = 0; | SQL_CALL name '(' dotext ')' {
$<action>$.code = W_DO;
$<action>$.command = cat4_str($2, "(", $4, ")");
$<action>$.str = make2_str("call", $<action>$.command);
} }
/* some other stuff for ecpg */ /* some other stuff for ecpg */
...@@ -4231,59 +4211,94 @@ into_list : coutputvariable | into_list ',' coutputvariable; ...@@ -4231,59 +4211,94 @@ into_list : coutputvariable | into_list ',' coutputvariable;
ecpgstart: SQL_START { reset_variables();} ecpgstart: SQL_START { reset_variables();}
dotext: /* empty */ dotext: /* empty */ { $$ = ""; }
| dotext sql_anything { | dotext sql_anything { $$ = cat2_str($1, $2); }
if (strlen(do_str) + yyleng + 1 >= do_length)
do_str = mm_realloc(do_str, do_length += yyleng);
strcat(do_str, yytext); vartext: var_anything { $$ = $1; }
} | vartext var_anything { $$ = cat2_str($1, $2); }
vartext: both_anything { fwrite(yytext, yyleng, 1, yyout); } coutputvariable : cvariable indicator {
| vartext both_anything { fwrite(yytext, yyleng, 1, yyout); } add_variable(&argsresult, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2));
coutputvariable : ':' name indicator {
add_variable(&argsresult, find_variable($2), ($3 == NULL) ? &no_indicator : find_variable($3));
} }
cinputvariable : ':' name indicator { cinputvariable : cvariable indicator {
add_variable(&argsinsert, find_variable($2), ($3 == NULL) ? &no_indicator : find_variable($3)); add_variable(&argsinsert, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2));
} }
civariableonly : ':' name { civariableonly : cvariable name {
add_variable(&argsinsert, find_variable($2), &no_indicator); add_variable(&argsinsert, find_variable($1), &no_indicator);
} }
cvariable: CVARIABLE { $$ = $1; }
| CVARIABLE '.' identlist { $$ = $1; }
| CVARIABLE '-' '>' identlist { $$ = $1; }
identlist: IDENT { $$ = $1; }
| IDENT '.' identlist { $$ = $1; }
| IDENT '-' '>' identlist { $$ = $1; }
indicator: /* empty */ { $$ = NULL; } indicator: /* empty */ { $$ = NULL; }
| ':' name { check_indicator((find_variable($2))->type); $$ = $2; } | cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
| SQL_INDICATOR ':' name { check_indicator((find_variable($3))->type); $$ = $3; } | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
ecpg_ident: IDENT { $$ = $1; }
| CSTRING { $$ = cat3_str("\"", $1, "\""); }
/* /*
* C stuff * C stuff
*/ */
symbol: IDENT { $$ = $1; } symbol: ecpg_ident { $$ = $1; }
c_anything: both_anything { fwrite(yytext, yyleng, 1, yyout); } c_anything: ecpg_ident { $$ = $1; }
| ';' { fputc(';', yyout); } | Iconst { $$ = $1; }
| FCONST { $$ = make_name(); }
sql_anything: IDENT {} | ICONST {} | FCONST {} | '*' { $$ = "*"; }
| ';' { $$ = ";"; }
both_anything: IDENT {} | ICONST {} | FCONST {} | S_AUTO { $$ = "auto"; }
| S_AUTO | S_BOOL | S_CHAR | S_CONST | S_DOUBLE | S_EXTERN | S_FLOAT | S_BOOL { $$ = "bool"; }
| S_INT | S_LONG | S_REGISTER | S_SHORT | S_SIGNED | S_STATIC | S_CHAR { $$ = "char"; }
| S_STRUCT | S_UNSIGNED | S_VARCHAR | S_ANYTHING | S_CONST { $$ = "const"; }
| '[' | ']' | '(' | ')' | '=' | S_DOUBLE { $$ = "double"; }
| S_EXTERN { $$ = "extern"; }
| S_FLOAT { $$ = "float"; }
| S_INT { $$ = "int"; }
| S_LONG { $$ = "long"; }
| S_REGISTER { $$ = "register"; }
| S_SHORT { $$ = "short"; }
| S_SIGNED { $$ = "signed"; }
| S_STATIC { $$ = "static"; }
| S_STRUCT { $$ = "struct"; }
| S_UNSIGNED { $$ = "unsigned"; }
| S_VARCHAR { $$ = "varchar"; }
| S_ANYTHING { $$ = make_name(); }
| '[' { $$ = "["; }
| ']' { $$ = "]"; }
| '(' { $$ = "("; }
| ')' { $$ = ")"; }
| '=' { $$ = "="; }
| ',' { $$ = ","; }
sql_anything: ecpg_ident { $$ = $1; }
| Iconst { $$ = $1; }
| FCONST { $$ = make_name(); }
| ',' { $$ = ","; }
var_anything: ecpg_ident { $$ = $1; }
| Iconst { $$ = $1; }
| FCONST { $$ = make_name(); }
/*FIXME: | ',' { $$ = ","; }*/
| '{' { $$ = "{"; }
| '}' { $$ = "}"; }
blockstart : '{' { blockstart : '{' {
braces_open++; braces_open++;
fputc('{', yyout); $$ = "{";
} }
blockend : '}' { blockend : '}' {
remove_variables(braces_open--); remove_variables(braces_open--);
fputc('}', yyout); $$ = "}";
} }
%% %%
......
...@@ -130,6 +130,12 @@ ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz, ...@@ -130,6 +130,12 @@ ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz,
void void
ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix) ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix)
{ {
if (ind_typ == NULL)
{
ind_typ = &ecpg_no_indicator;
ind_name = "no_indicator";
}
if (IS_SIMPLE_TYPE(typ->typ)) if (IS_SIMPLE_TYPE(typ->typ))
{ {
ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix); ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix);
...@@ -267,7 +273,7 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, ...@@ -267,7 +273,7 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
* then we are in a record in a record and the offset is used as * then we are in a record in a record and the offset is used as
* offset. * offset.
*/ */
struct ECPGrecord_member *p, *ind_p; struct ECPGrecord_member *p, *ind_p = NULL;
char obuf[BUFSIZ]; char obuf[BUFSIZ];
char pbuf[BUFSIZ], ind_pbuf[BUFSIZ]; char pbuf[BUFSIZ], ind_pbuf[BUFSIZ];
const char *offset; const char *offset;
...@@ -288,9 +294,11 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, ...@@ -288,9 +294,11 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name); sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
ind_prefix = ind_pbuf; ind_prefix = ind_pbuf;
for (p = typ->u.members, ind_p = ind_typ->u.members; p; p = p->next, ind_p = ind_p->next) if (ind_typ != NULL) ind_p = ind_typ->u.members;
for (p = typ->u.members; p; p = p->next)
{ {
ECPGdump_a_type(o, p->name, p->typ, ind_p->name, ind_p->typ, prefix, ind_prefix); ECPGdump_a_type(o, p->name, p->typ, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->typ : NULL, prefix, ind_prefix);
if (ind_p != NULL) ind_p = ind_p->next;
} }
} }
......
...@@ -74,3 +74,9 @@ struct when ...@@ -74,3 +74,9 @@ struct when
char *command; char *command;
char *str; char *str;
}; };
struct index
{
int ival;
char *str;
};
...@@ -119,5 +119,7 @@ exec sql end declare section; ...@@ -119,5 +119,7 @@ exec sql end declare section;
exec sql drop table perftest1; exec sql drop table perftest1;
exec sql commit;
return (0); return (0);
} }
...@@ -24,7 +24,7 @@ exec sql begin declare section; ...@@ -24,7 +24,7 @@ exec sql begin declare section;
} ind_birth; } ind_birth;
} ind_personal; } ind_personal;
long ind_married; long ind_married;
char married[9]="a"; char married[9];
exec sql end declare section; exec sql end declare section;
char msg[128], command[128]; char msg[128], command[128];
FILE *dbgs; FILE *dbgs;
...@@ -60,7 +60,7 @@ exec sql end declare section; ...@@ -60,7 +60,7 @@ exec sql end declare section;
while (not_found == 0) { while (not_found == 0) {
strcpy(msg, "fetch"); strcpy(msg, "fetch");
exec sql fetch cur into :personal:ind_personal, :married:ind_married; exec sql fetch cur into :personal:ind_personal, :married:ind_married, :personal.birth.born;
if (not_found == 0) 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); 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);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment