diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 43e110bf78..bb8517a4b0 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -758,5 +758,22 @@ Thu Dec 23 13:25:05 CET 1999 Thu Jan 6 09:52:27 CET 2000 - Synced preproc.y with gram.y. - - Made sure Bruce's additions also make it into my source tree. - Set ecpg version to 2.6.14. + +Wed Jan 12 15:50:39 CET 2000 + + - Made sure Rene Hogendoorn's patches make it into ecpg completely + except for the FETCH syntax change. + +Fri Jan 14 21:17:46 CET 2000 + + - Applied a minor patch to ecpglib.c. + - Fixed initialization bugs. + +Mon Jan 17 21:55:40 CET 2000 + + - Synced preproc.y with gram.y. + - Changed FETCH syntax using Rene's final patch. Made it more + standard compliant. + - Set library version to 3.0.10. + - Set ecpg version to 2.7.0. diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO index 13b6e60a25..16af868643 100644 --- a/src/interfaces/ecpg/TODO +++ b/src/interfaces/ecpg/TODO @@ -13,19 +13,17 @@ stderr. Instead it should be listed as a warning. The error handling has to be improved by adding additional error-rules to the parser. -it would be nice to be able to use :var[:index] as cvariable +it would be nice to be able to use :var[:index] as cvariable for an array var + +How can one insert arrays from c variables? support for dynamic SQL with unknown number of variables with DESCRIPTORS -The line numbering is not exact. - What happens to the output variable during read if there was an indicator-error? Add a semantic check level, e.g. check if a table really exists. -How can one insert arrays from c variables? - Missing statements: - exec sql ifdef - exec sql allocate diff --git a/src/interfaces/ecpg/lib/Makefile.in b/src/interfaces/ecpg/lib/Makefile.in index 49f019659d..0fcbc7b808 100644 --- a/src/interfaces/ecpg/lib/Makefile.in +++ b/src/interfaces/ecpg/lib/Makefile.in @@ -6,13 +6,13 @@ # Copyright (c) 1994, Regents of the University of California # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.55 2000/01/10 15:41:27 momjian Exp $ +# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.56 2000/01/18 13:03:47 meskes Exp $ # #------------------------------------------------------------------------- NAME= ecpg SO_MAJOR_VERSION= 3 -SO_MINOR_VERSION= 1.0 +SO_MINOR_VERSION= 0.10 SRCDIR= @top_srcdir@ include $(SRCDIR)/Makefile.global diff --git a/src/interfaces/ecpg/lib/typename.c b/src/interfaces/ecpg/lib/typename.c index 8a9923d940..af87b160aa 100644 --- a/src/interfaces/ecpg/lib/typename.c +++ b/src/interfaces/ecpg/lib/typename.c @@ -8,7 +8,7 @@ ECPGtype_name(enum ECPGttype typ) { switch (typ) { - case ECPGt_char: + case ECPGt_char: return "char"; case ECPGt_unsigned_char: return "unsigned char"; diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 7d70b0f8cd..129ec03d63 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -3,7 +3,7 @@ include $(SRCDIR)/Makefile.global MAJOR_VERSION=2 MINOR_VERSION=7 -PATCHLEVEL=14 +PATCHLEVEL=0 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \ diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 21b2bc34f0..46c29ba2a2 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -17,12 +17,11 @@ struct cursor *cur = NULL; struct typedefs *types = NULL; struct _defines *defines = NULL; - static void usage(char *progname) { fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); - fprintf(stderr, "Usage: %s: [-v] [-t] [-I include path] [ -o output file name] file1 [file2] ...\n", progname); + fprintf(stderr, "Usage: %s: [-v] [-t] [-I include path] [ -o output file name] [-D define name] file1 [file2] ...\n", progname); } static void @@ -35,6 +34,18 @@ add_include_path(char *path) include_paths->next = ip; } +static void +add_preprocessor_define(char *define) +{ + struct _defines *pd = defines; + + defines = mm_alloc(sizeof(struct _defines)); + defines->old = strdup(define); + defines->new = strdup(""); + defines->pertinent = true; + defines->next = pd; +} + int main(int argc, char *const argv[]) { @@ -49,7 +60,7 @@ main(int argc, char *const argv[]) add_include_path("/usr/local/include"); add_include_path("."); - while ((c = getopt(argc, argv, "vo:I:t")) != EOF) + while ((c = getopt(argc, argv, "vo:I:tD:")) != EOF) { switch (c) { @@ -73,6 +84,9 @@ main(int argc, char *const argv[]) case 'v': verbose = true; break; + case 'D': + add_preprocessor_define(optarg); + break; default: usage(argv[0]); return ILLEGAL_OPTION; @@ -106,7 +120,10 @@ main(int argc, char *const argv[]) strcpy(input_filename, argv[fnr]); - ptr2ext = strrchr(input_filename, '.'); + /* take care of relative paths */ + ptr2ext = strrchr(input_filename, '/'); + ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.')); + /* no extension? */ if (ptr2ext == NULL) { @@ -120,7 +137,7 @@ main(int argc, char *const argv[]) ptr2ext[4] = '\0'; } - if (out_option == 0)/* calculate the output name */ + if (out_option == 0) /* calculate the output name */ { output_filename = strdup(input_filename); @@ -179,16 +196,29 @@ main(int argc, char *const argv[]) ptr = ptr->next; free(this); } + cur = NULL; - /* remove old defines as well */ - for (defptr = defines; defptr != NULL;) + /* remove non-pertinent old defines as well */ + while ( defines && !defines->pertinent ) { + defptr = defines; + defines = defines->next; + + free(defptr->new); + free(defptr->old); + free(defptr); + } + + for (defptr = defines; defptr != NULL; defptr = defptr->next ) { - struct _defines *this = defptr; + struct _defines *this = defptr->next; + + if ( this && !this->pertinent ) { + defptr->next = this->next; - free(defptr->new); - free(defptr->old); - defptr = defptr->next; + free(this->new); + free(this->old); free(this); + } } /* and old typedefs */ @@ -197,17 +227,25 @@ main(int argc, char *const argv[]) struct typedefs *this = typeptr; free(typeptr->name); - free(typeptr->type); ECPGfree_struct_member(typeptr->struct_member_list); + free(typeptr->type); typeptr = typeptr->next; free(this); } - + types = NULL; + + /* initialize whenever structures */ + memset(&when_error, 0, sizeof(struct when)); + memset(&when_nf, 0, sizeof(struct when)); + memset(&when_warn, 0, sizeof(struct when)); + + /* and structure member lists */ + memset(struct_member_list, 0, sizeof(struct_member_list)); /* initialize lex */ lex_init(); /* we need two includes */ - fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/* These two include files are added by the preprocessor */\n#include \n#include \n\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); + fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/* These two include files are added by the preprocessor */\n#include \n#include \n#line 1 \"%s\"\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL, input_filename); /* and parse the source */ yyparse(); diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 41ce5c41c4..c37e552b98 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -2,6 +2,10 @@ #include "type.h" #include +/* defines */ + +#define STRUCT_DEPTH 128 + /* variables */ extern int braces_open, @@ -23,6 +27,8 @@ extern struct ECPGtype ecpg_no_indicator; extern struct variable no_indicator; extern struct arguments *argsinsert; extern struct arguments *argsresult; +extern struct when when_error, when_nf, when_warn; +extern struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH]; /* functions */ @@ -39,9 +45,9 @@ extern void yyerror(char *); /* return codes */ #define OK 0 -#define PARSE_ERROR -1 +#define PARSE_ERROR -1 #define ILLEGAL_OPTION -2 -#define INDICATOR_NOT_ARRAY -3 +#define INDICATOR_NOT_ARRAY -3 -#define NO_INCLUDE_FILE ENOENT -#define OUT_OF_MEMORY ENOMEM +#define NO_INCLUDE_FILE ENOENT +#define OUT_OF_MEMORY ENOMEM diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index e8a9fb11d6..c43ffcfa57 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -15,7 +15,6 @@ #include "mb/pg_wchar.h" #endif -#define STRUCT_DEPTH 128 #define EMPTY make_str("") /* @@ -27,6 +26,7 @@ static char *connection = NULL; static int QueryIsRule = 0, ForUpdateNotAllowed = 0, FoundInto = 0; static struct this_type actual_type[STRUCT_DEPTH]; static char *actual_storage[STRUCT_DEPTH]; +static char *actual_startline[STRUCT_DEPTH]; /* temporarily store struct members while creating the data structure */ struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL }; @@ -69,7 +69,7 @@ void output_line_number() { if (input_filename) - fprintf(yyout, "\n#line %d \"%s\"\n", yylineno + 1, input_filename); + fprintf(yyout, "\n#line %d \"%s\"\n", yylineno, input_filename); } static void @@ -83,7 +83,7 @@ output_simple_statement(char *cmd) /* * store the whenever action here */ -static struct when when_error, when_nf, when_warn; +struct when when_error, when_nf, when_warn; static void print_action(struct when *w) @@ -479,6 +479,20 @@ make_name(void) return(name); } +static char * +hashline_number() +{ + if (input_filename) + { + char* line = mm_alloc(strlen("\n#line %d \"%s\"\n") + 21 + strlen(input_filename)); + sprintf(line, "\n#line %d \"%s\"\n", yylineno, input_filename); + + return line; + } + + return EMPTY; +} + static void output_statement(char * stmt, int mode) { @@ -742,8 +756,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %type file_name AexprConst ParamNo TypeId com_expr %type in_expr_nodes a_expr b_expr TruncateStmt CommentStmt %type opt_indirection expr_list extract_list extract_arg -%type position_list substr_list substr_from -%type trim_list in_expr substr_for attr attrs +%type position_list substr_list substr_from alter_column_action +%type trim_list in_expr substr_for attr attrs drop_behavior %type Typename SimpleTypename Generic Numeric generic opt_float opt_numeric %type opt_decimal Character character opt_varying opt_charset %type opt_collate Datetime datetime opt_timezone opt_interval @@ -751,13 +765,13 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %type SelectStmt SubSelect result OptTemp OptTempType OptTempScope %type opt_table opt_all opt_unique sort_clause sortby_list %type sortby OptUseOp opt_inh_star relation_name_list name_list -%type group_clause having_clause from_clause +%type group_clause having_clause from_clause %type table_list join_outer where_clause relation_expr sub_type %type opt_column_list insert_rest InsertStmt OptimizableStmt %type columnList DeleteStmt LockStmt UpdateStmt CursorStmt %type NotifyStmt columnElem copy_dirn UnlistenStmt copy_null %type copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary -%type opt_with_copy FetchStmt opt_direction fetch_how_many opt_portal_name +%type opt_with_copy FetchStmt direction fetch_how_many from_in %type ClosePortalStmt DropStmt VacuumStmt opt_verbose %type opt_analyze opt_va_list va_list ExplainStmt index_params %type index_list func_index index_elem opt_type opt_class access_method_clause @@ -771,16 +785,17 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %type RemoveAggrStmt remove_type RemoveStmt ExtendStmt %type RemoveOperStmt RenameStmt all_Op user_valid_clause %type VariableSetStmt var_value zone_value VariableShowStmt -%type VariableResetStmt AddAttrStmt alter_clause DropUserStmt +%type VariableResetStmt AlterTableStmt DropUserStmt %type user_passwd_clause user_createdb_clause opt_trans -%type user_createuser_clause user_group_list user_group_clause +%type user_createuser_clause user_list user_group_clause %type CreateUserStmt AlterUserStmt CreateSeqStmt OptSeqList %type OptSeqElem TriggerForSpec TriggerForOpt TriggerForType %type DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt %type TriggerActionTime CreateTrigStmt DropPLangStmt PLangTrusted %type CreatePLangStmt IntegerOnly TriggerFuncArgs TriggerFuncArg -%type ViewStmt LoadStmt CreatedbStmt opt_database1 opt_database2 location -%type DropdbStmt ClusterStmt grantee RevokeStmt encoding +%type ViewStmt LoadStmt CreatedbStmt createdb_opt_encoding +%type createdb_opt_location opt_encoding AlterTableStmt +%type DropdbStmt ClusterStmt grantee RevokeStmt %type GrantStmt privileges operation_commalist operation %type opt_cursor opt_lmode ConstraintsSetStmt comment_tg %type case_expr when_clause_list case_default case_arg when_clause @@ -808,7 +823,7 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %type enum_type civariableonly ECPGCursorStmt ECPGDeallocate %type ECPGFree ECPGDeclare ECPGVar sql_variable_declarations %type sql_declaration sql_variable_list sql_variable opt_at -%type struct_type s_struct declaration variable_declarations +%type struct_type s_struct declaration declarations variable_declarations %type s_struct s_union union_type ECPGSetAutocommit on_off %type simple_type varchar_type @@ -836,7 +851,7 @@ statement: ecpgstart opt_at stmt ';' { connection = NULL; } opt_at: SQL_AT connection_target { connection = $2; } -stmt: AddAttrStmt { output_statement($1, 0); } +stmt: AlterTableStmt { output_statement($1, 0); } | AlterGroupStmt { output_statement($1, 0); } | AlterUserStmt { output_statement($1, 0); } | ClosePortalStmt { output_statement($1, 0); } @@ -1033,15 +1048,14 @@ CreateUserStmt: CREATE USER UserId *****************************************************************************/ AlterUserStmt: ALTER USER UserId user_createdb_clause - user_createuser_clause user_group_clause user_valid_clause + user_createuser_clause user_valid_clause { - $$ = cat_str(6, make_str("alter user"), $3, $4, $5, $6, $7); + $$ = cat_str(5, make_str("alter user"), $3, $4, $5, $6); } - |ALTER USER UserId WITH sysid_clause user_passwd_clause - user_createdb_clause user_createuser_clause user_group_clause - user_valid_clause + |ALTER USER UserId WITH PASSWORD Sconst + user_createdb_clause user_createuser_clause user_valid_clause { - $$ = cat_str(9, make_str("alter user"), $3, make_str("with"), $5, $6, $7, $8, $9, $10); + $$ = cat_str(7, make_str("alter user"), $3, make_str("with password"), $6, $7, $8, $9); } ; @@ -1052,17 +1066,20 @@ AlterUserStmt: ALTER USER UserId user_createdb_clause * *****************************************************************************/ -DropUserStmt: DROP USER UserId +DropUserStmt: DROP USER user_list { $$ = cat2_str(make_str("drop user"), $3); } ; -user_passwd_clause: PASSWORD UserId { $$ = cat2_str(make_str("password") , $2); } +user_passwd_clause: PASSWORD Sconst { $$ = cat2_str(make_str("password") , $2); } | /*EMPTY*/ { $$ = EMPTY; } ; -sysid_clause: SYSID Iconst { $$ = cat2_str(make_str("sysid"), $2); } +sysid_clause: SYSID Iconst { if (atoi($2) <= 0) + mmerror(ET_ERROR, "sysid must be positive"); + + $$ = cat2_str(make_str("sysid"), $2); } | /*EMPTY*/ { $$ = EMPTY; } ; @@ -1088,7 +1105,7 @@ user_createuser_clause: CREATEUSER | /*EMPTY*/ { $$ = NULL; } ; -user_group_list: user_group_list ',' UserId +user_list: user_list ',' UserId { $$ = cat_str(3, $1, make_str(","), $3); } @@ -1098,7 +1115,7 @@ user_group_list: user_group_list ',' UserId } ; -user_group_clause: IN GROUP user_group_list +user_group_clause: IN GROUP user_list { $$ = cat2_str(make_str("in group"), $3); } @@ -1126,7 +1143,7 @@ CreateGroupStmt: CREATE GROUP UserId } ; -users_in_new_group_clause: USER user_group_list { $$ = cat2_str(make_str("user"), $2); } +users_in_new_group_clause: USER user_list { $$ = cat2_str(make_str("user"), $2); } | /* EMPTY */ { $$ = EMPTY; } ; @@ -1137,17 +1154,12 @@ users_in_new_group_clause: USER user_group_list { $$ = cat2_str(make_str("use * * *****************************************************************************/ -AlterGroupStmt: ALTER GROUP UserId WITH SYSID Iconst - { - $$ = cat_str(4, make_str("alter group"), $3, make_str("with sysid"), $6); - } - | - ALTER GROUP UserId ADD USER user_group_list +AlterGroupStmt: ALTER GROUP UserId ADD USER user_list { $$ = cat_str(4, make_str("alter group"), $3, make_str("add user"), $6); } | - ALTER GROUP UserId DROP USER user_group_list + ALTER GROUP UserId DROP USER user_list { $$ = cat_str(4, make_str("alter group"), $3, make_str("drop user"), $6); } @@ -1191,12 +1203,12 @@ VariableSetStmt: SET ColId TO var_value { $$ = cat2_str(make_str("set transaction isolation level"), $5); } - | SET NAMES encoding + | SET NAMES opt_encoding { #ifdef MULTIBYTE $$ = cat2_str(make_str("set names"), $3); #else - mmerror(ET_ERROR, "SET NAMES is not supported"); + mmerror(ET_ERROR, "SET NAMES is not supported."); #endif } ; @@ -1215,6 +1227,11 @@ zone_value: Sconst { $$ = $1; } | LOCAL { $$ = make_str("local"); } ; +opt_encoding: Sconst { $$ = $1; } + | DEFAULT { $$ = make_str("default"); } + | /*EMPTY*/ { $$ = EMPTY; } + ; + VariableShowStmt: SHOW ColId { $$ = cat2_str(make_str("show"), $2); @@ -1283,33 +1300,50 @@ constraints_set_mode: DEFERRED /***************************************************************************** * * QUERY : - * addattr ( attr1 = type1 .. attrn = typen ) to [*] + * + * ALTER TABLE variations * *****************************************************************************/ -AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause - { - $$ = cat_str(4, make_str("alter table"), $3, $4, $5); - } +AlterTableStmt: +/* ALTER TABLE ADD [COLUMN] */ + ALTER TABLE relation_name opt_inh_star ADD opt_column columnDef + { + $$ = cat_str(5, make_str("alter table"), $3, $4, make_str("add"), $6, $7); + } +/* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |DROP +DEFAULT} */ + | ALTER TABLE relation_name opt_inh_star ALTER opt_column ColId + alter_column_action + { + $$ = cat_str(6, make_str("alter table"), $3, $4, make_str("alter"), $6, $7, $8); + } +/* ALTER TABLE DROP [COLUMN] {RESTRICT|CASCADE} */ + | ALTER TABLE relation_name opt_inh_star DROP opt_column ColId + drop_behavior + { + $$ = cat_str(6, make_str("alter table"), $3, $4, make_str("drop"), $6, $7, $8); + } +/* ALTER TABLE ADD CONSTRAINT ... */ + | ALTER TABLE relation_name opt_inh_star ADD TableConstraint + { + $$ = cat_str(4, make_str("alter table"), $3, $4, make_str("add"), $6); + } +/* ALTER TABLE DROP CONSTRAINT ... */ + | ALTER TABLE relation_name opt_inh_star DROP CONSTRAINT name drop_behavior + { + $$ = cat_str(5, make_str("alter table"), $3, $4, make_str("drop constraint"), $7, $8); + } ; -alter_clause: ADD opt_column columnDef - { - $$ = cat_str(3, make_str("add"), $2, $3); - } - | ADD '(' OptTableElementList ')' - { - $$ = cat_str(2, make_str("add("), $3, make_str(")")); - } - | DROP opt_column ColId - { mmerror(ET_ERROR, "ALTER TABLE/DROP COLUMN not yet implemented"); } - | ALTER opt_column ColId SET DEFAULT a_expr - { mmerror(ET_ERROR, "ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); } - | ALTER opt_column ColId DROP DEFAULT - { mmerror(ET_ERROR, "ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); } - | ADD ConstraintElem - { mmerror(ET_ERROR, "ALTER TABLE/ADD CONSTRAINT not yet implemented"); } - ; +alter_column_action: + SET DEFAULT a_expr_or_null { $$ = cat2_str(make_str("set default"), $3); } + | DROP DEFAULT { $$ = make_str("drop default"); } + ; + +drop_behavior: CASCADE { $$ = make_str("cascade"); } + | RESTRICT { $$ = make_str("restrict"); } + ; /***************************************************************************** * @@ -1927,28 +1961,58 @@ TruncateStmt: TRUNCATE TABLE relation_name * *****************************************************************************/ -FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name INTO into_list +FetchStmt: FETCH direction fetch_how_many from_in name INTO into_list { if (strcmp($2, "relative") == 0 && atol($3) == 0L) mmerror(ET_ERROR, "FETCH/RELATIVE at current position is not supported"); + $$ = cat_str(5, make_str("fetch"), $2, $3, $4, $5); + } + | FETCH fetch_how_many from_in name INTO into_list + { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); } - | MOVE opt_direction fetch_how_many opt_portal_name - { + | FETCH direction from_in name INTO into_list + { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); } + | FETCH from_in name INTO into_list + { + $$ = cat_str(3, make_str("fetch"), $2, $3); + } + | FETCH name INTO into_list + { + $$ = cat2_str(make_str("fetch"), $2); + } + | MOVE direction fetch_how_many from_in name + { + $$ = cat_str(5, make_str("move"), $2, $3, $4, $5); + } + | MOVE fetch_how_many from_in name + { + $$ = cat_str(4, make_str("move"), $2, $3, $4); + } + | MOVE direction from_in name + { + $$ = cat_str(4, make_str("move"), $2, $3, $4); + } + | MOVE from_in name + { + $$ = cat_str(3, make_str("move"), $2, $3); + } + | MOVE name + { + $$ = cat2_str(make_str("move"), $2); + } ; -opt_direction: FORWARD { $$ = make_str("forward"); } +direction: FORWARD { $$ = make_str("forward"); } | BACKWARD { $$ = make_str("backward"); } | RELATIVE { $$ = make_str("relative"); } - | ABSOLUTE - { + | ABSOLUTE { mmerror(ET_WARN, "FETCH/ABSOLUTE not supported, backend will use RELATIVE"); $$ = make_str("absolute"); } - | /*EMPTY*/ { $$ = EMPTY; /* default */ } ; fetch_how_many: Iconst { $$ = $1; } @@ -1956,14 +2020,11 @@ fetch_how_many: Iconst { $$ = $1; } | ALL { $$ = make_str("all"); } | NEXT { $$ = make_str("next"); } | PRIOR { $$ = make_str("prior"); } - | /*EMPTY*/ { $$ = EMPTY; /*default*/ } ; -opt_portal_name: IN name { $$ = cat2_str(make_str("in"), $2); } - | FROM name { $$ = cat2_str(make_str("from"), $2); } -/* | name { $$ = cat2_str(make_str("in"), $1); }*/ - | /*EMPTY*/ { $$ = EMPTY; } - ; +from_in: IN { $$ = make_str("in"); } + | FROM { $$ = make_str("from"); } + ; /***************************************************************************** * @@ -2498,49 +2559,56 @@ LoadStmt: LOAD file_name /***************************************************************************** * - * QUERY: - * createdb dbname + * CREATE DATABASE + * * *****************************************************************************/ -CreatedbStmt: CREATE DATABASE database_name WITH opt_database1 opt_database2 - { - if (strlen($5) == 0 || strlen($6) == 0) - mmerror(ET_ERROR, "CREATE DATABASE WITH requires at least an option"); -#ifndef MULTIBYTE - if (strlen($6) != 0) - mmerror(ET_ERROR, "WITH ENCODING is not supported"); -#endif - $$ = cat_str(5, make_str("create database"), $3, make_str("with"), $5, $6); - } +CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_location createdb_opt_encoding + { + if (strlen($5) == 0 || strlen($6) == 0) + mmerror(ET_ERROR, "CREATE DATABASE WITH requires at least an option"); + $$ = cat_str(5, make_str("create database"), $3, make_str("with"), $5, $6); + } | CREATE DATABASE database_name - { - $$ = cat2_str(make_str("create database"), $3); - } + { + $$ = cat2_str(make_str("create database"), $3); + } ; -opt_database1: LOCATION '=' location { $$ = cat2_str(make_str("location ="), $3); } +createdb_opt_location: LOCATION '=' Sconst { $$ = cat2_str(make_str("location ="), $3); } + | LOCATION '=' DEFAULT { $$ = make_str("location = default"); } | /*EMPTY*/ { $$ = EMPTY; } ; -opt_database2: ENCODING '=' encoding { $$ = cat2_str(make_str("encoding ="), $3); } +createdb_opt_encoding: ENCODING '=' Sconst + { +#ifndef MULTIBYTE + mmerror(ET_ERROR, "WITH ENCODING is not supported."); +#endif + $$ = cat2_str(make_str("encoding ="), $3); + } + | ENCODING '=' Iconst + { +#ifndef MULTIBYTE + mmerror(ET_ERROR, "WITH ENCODING is not supported."); +#endif + $$ = cat2_str(make_str("encoding ="), $3); + } + | ENCODING '=' DEFAULT + { +#ifndef MULTIBYTE + mmerror(ET_ERROR, "WITH ENCODING is not supported."); +#endif + $$ = make_str("encoding = default"); + } | /*EMPTY*/ { $$ = NULL; } ; -location: Sconst { $$ = $1; } - | DEFAULT { $$ = make_str("default"); } - | /*EMPTY*/ { $$ = EMPTY; } - ; - -encoding: Sconst { $$ = $1; } - | DEFAULT { $$ = make_str("default"); } - | /*EMPTY*/ { $$ = EMPTY; } - ; - /***************************************************************************** * - * QUERY: - * dropdb dbname + * DROP DATABASE + * * *****************************************************************************/ @@ -4247,44 +4315,46 @@ ColId: ident { $$ = $1; } * rather than in ColId if there was a shift/reduce conflict * when used as a full identifier. - thomas 1997-11-06 */ -ColLabel: ColId { $$ = $1; } - | ABORT_TRANS { $$ = make_str("abort"); } - | ANALYZE { $$ = make_str("analyze"); } - | BINARY { $$ = make_str("binary"); } - | CASE { $$ = make_str("case"); } - | CLUSTER { $$ = make_str("cluster"); } - | COALESCE { $$ = make_str("coalesce"); } - | CONSTRAINT { $$ = make_str("constraint"); } - | COPY { $$ = make_str("copy"); } - | CURRENT { $$ = make_str("current"); } - | DO { $$ = make_str("do"); } - | ELSE { $$ = make_str("else"); } - | END_TRANS { $$ = make_str("end"); } - | EXPLAIN { $$ = make_str("explain"); } - | EXTEND { $$ = make_str("extend"); } - | FALSE_P { $$ = make_str("false"); } - | FOREIGN { $$ = make_str("foreign"); } - | GROUP { $$ = make_str("group"); } - | LISTEN { $$ = make_str("listen"); } - | LOAD { $$ = make_str("load"); } - | LOCK_P { $$ = make_str("lock"); } - | MOVE { $$ = make_str("move"); } - | NEW { $$ = make_str("new"); } - | NONE { $$ = make_str("none"); } - | NULLIF { $$ = make_str("nullif"); } - | ORDER { $$ = make_str("order"); } - | POSITION { $$ = make_str("position"); } - | PRECISION { $$ = make_str("precision"); } - | RESET { $$ = make_str("reset"); } - | SETOF { $$ = make_str("setof"); } - | SHOW { $$ = make_str("show"); } - | TABLE { $$ = make_str("table"); } - | THEN { $$ = make_str("then"); } - | TRANSACTION { $$ = make_str("transaction"); } - | TRUE_P { $$ = make_str("true"); } - | VACUUM { $$ = make_str("vacuum"); } - | VERBOSE { $$ = make_str("verbose"); } - | WHEN { $$ = make_str("when"); } +ColLabel: ColId { $$ = $1; } + | ABORT_TRANS { $$ = make_str("abort"); } + | ANALYZE { $$ = make_str("analyze"); } + | BINARY { $$ = make_str("binary"); } + | CASE { $$ = make_str("case"); } + | CLUSTER { $$ = make_str("cluster"); } + | COALESCE { $$ = make_str("coalesce"); } + | CONSTRAINT { $$ = make_str("constraint"); } + | COPY { $$ = make_str("copy"); } + | CURRENT { $$ = make_str("current"); } + | DECIMAL { $$ = make_str("decimal"); } + | DO { $$ = make_str("do"); } + | ELSE { $$ = make_str("else"); } + | END_TRANS { $$ = make_str("end"); } + | EXPLAIN { $$ = make_str("explain"); } + | EXTEND { $$ = make_str("extend"); } + | FALSE_P { $$ = make_str("false"); } + | FOREIGN { $$ = make_str("foreign"); } + | GROUP { $$ = make_str("group"); } + | LISTEN { $$ = make_str("listen"); } + | LOAD { $$ = make_str("load"); } + | LOCK_P { $$ = make_str("lock"); } + | MOVE { $$ = make_str("move"); } + | NEW { $$ = make_str("new"); } + | NONE { $$ = make_str("none"); } + | NULLIF { $$ = make_str("nullif"); } + | NUMERIC { $$ = make_str("numeric"); } + | ORDER { $$ = make_str("order"); } + | POSITION { $$ = make_str("position"); } + | PRECISION { $$ = make_str("precision"); } + | RESET { $$ = make_str("reset"); } + | SETOF { $$ = make_str("setof"); } + | SHOW { $$ = make_str("show"); } + | TABLE { $$ = make_str("table"); } + | THEN { $$ = make_str("then"); } + | TRANSACTION { $$ = make_str("transaction"); } + | TRUE_P { $$ = make_str("true"); } + | VACUUM { $$ = make_str("vacuum"); } + | VERBOSE { $$ = make_str("verbose"); } + | WHEN { $$ = make_str("when"); } ; SpecialRuleRelation: CURRENT @@ -4532,7 +4602,6 @@ ECPGDeallocate: SQL_DEALLOCATE SQL_PREPARE ident { $$ = cat_str(3, make_str("ECP ECPGDeclaration: sql_startdeclare { fputs("/* exec sql begin declare section */", yyout); - output_line_number(); } variable_declarations sql_enddeclare { @@ -4545,18 +4614,16 @@ sql_startdeclare : ecpgstart BEGIN_TRANS DECLARE SQL_SECTION ';' {} sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION ';' {} -variable_declarations: /* empty */ - { - $$ = EMPTY; - } - | declaration variable_declarations - { - $$ = cat2_str($1, $2); - } +variable_declarations: /* empty */ { $$ = EMPTY; } + | declarations { $$ = $1; } + +declarations: declaration { $$ = $1; } + | declarations declaration { $$ = cat2_str($1, $2); } declaration: storage_clause { actual_storage[struct_level] = mm_strdup($1); + actual_startline[struct_level] = hashline_number(); } type { @@ -4566,7 +4633,7 @@ declaration: storage_clause } variable_list ';' { - $$ = cat_str(4, $1, $3.type_str, $5, make_str(";\n")); + $$ = cat_str(5, actual_startline[struct_level], $1, $3.type_str, $5, make_str(";\n")); } storage_clause : S_EXTERN { $$ = make_str("extern"); } @@ -4928,7 +4995,8 @@ ECPGTypedef: TYPE_P symbol IS ctype opt_type_array_bounds opt_reference this->type->type_str = mm_strdup($2); this->type->type_dimension = dimension; /* dimension of array */ this->type->type_index = length; /* lenght of string */ - this->struct_member_list = struct_member_list[struct_level]; + this->struct_member_list = ($4.type_enum == ECPGt_struct || $4.type_enum == ECPGt_union) ? + struct_member_list[struct_level] : NULL; if ($4.type_enum != ECPGt_varchar && $4.type_enum != ECPGt_char && @@ -5473,7 +5541,7 @@ c_stuff: c_anything { $$ = $1; } } c_list: c_term { $$ = $1; } - | c_term ',' c_list { $$ = cat_str(3, $1, make_str(","), $3); } + | c_list ',' c_term { $$ = cat_str(3, $1, make_str(","), $3); } c_term: c_stuff { $$ = $1; } | '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); } diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 30580a775c..461eddc6e7 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -123,7 +123,7 @@ get_type(enum ECPGttype typ) { switch (typ) { - case ECPGt_char: + case ECPGt_char: return ("ECPGt_char"); break; case ECPGt_unsigned_char: @@ -367,17 +367,17 @@ ECPGfree_type(struct ECPGtype * typ) { switch (typ->typ) { - case ECPGt_array: + case ECPGt_array: switch (typ->u.element->typ) { - case ECPGt_array: + case ECPGt_array: yyerror("internal error, found multi-dimensional array\n"); break; case ECPGt_struct: case ECPGt_union: /* Array of structs. */ ECPGfree_struct_member(typ->u.element->u.members); - free(typ->u.members); + free(typ->u.element); break; default: if (!IS_SIMPLE_TYPE(typ->u.element->typ)) @@ -389,7 +389,6 @@ ECPGfree_type(struct ECPGtype * typ) case ECPGt_struct: case ECPGt_union: ECPGfree_struct_member(typ->u.members); - free(typ->u.members); break; default: sprintf(errortext, "illegal variable type %d\n", typ->typ); diff --git a/src/interfaces/ecpg/test/header_test.h b/src/interfaces/ecpg/test/header_test.h index 72408ae9bb..71017aacbb 100644 --- a/src/interfaces/ecpg/test/header_test.h +++ b/src/interfaces/ecpg/test/header_test.h @@ -1,12 +1,19 @@ exec sql include sqlca; -exec sql whenever sqlerror do PrintAndStop(msg); -exec sql whenever sqlwarning do warn(); - -void PrintAndStop(msg) +void Finish(msg) { fprintf(stderr, "Error in statement '%s':\n", msg); sqlprint(); + + /* finish transaction */ + exec sql rollback; + + /* and remove test table */ + exec sql drop table meskes; + exec sql commit; + + exec sql disconnect; + exit(-1); } @@ -14,3 +21,6 @@ void warn(void) { fprintf(stderr, "Warning: At least one column was truncated\n"); } + +exec sql whenever sqlerror do Finish(msg); +exec sql whenever sqlwarning do warn(); diff --git a/src/interfaces/ecpg/test/perftest.pgc b/src/interfaces/ecpg/test/perftest.pgc index 6ec604d47f..3bd4982eef 100644 --- a/src/interfaces/ecpg/test/perftest.pgc +++ b/src/interfaces/ecpg/test/perftest.pgc @@ -38,6 +38,12 @@ exec sql end declare section; exec sql create unique index number2 on perftest2(number); + exec sql commit; + + exec sql set autocommit to on; + + exec sql begin transaction; + gettimeofday(&tvs, NULL); for (i = 0;i < 1407; i++) @@ -49,14 +55,16 @@ exec sql end declare section; sprintf(text, "%ld", i); exec sql insert into perftest1(number, ascii) values (:i, :text); exec sql insert into perftest2(number, next_number) values (:i, :i+1); - - exec sql commit; } + exec sql commit; + gettimeofday(&tve, NULL); print_result(tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec, "insert"); + exec sql begin transaction; + gettimeofday(&tvs, NULL); for (i = 0;i < 1407; i++) @@ -66,14 +74,16 @@ exec sql end declare section; exec sql end declare section; exec sql select ascii into :text from perftest1 where number = :i; - - exec sql commit; } + exec sql commit; + gettimeofday(&tve, NULL); print_result(tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec, "selection&projection"); + exec sql begin transaction; + gettimeofday(&tvs, NULL); for (i = 0;i < 1407; i++) @@ -83,14 +93,16 @@ exec sql end declare section; exec sql end declare section; exec sql select perftest1.ascii into :text from perftest1, perftest2 where perftest1.number = perftest2.number and perftest2.number = :i; - - exec sql commit; } + exec sql commit; + gettimeofday(&tve, NULL); print_result(tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec, "join"); + exec sql begin transaction; + gettimeofday(&tvs, NULL); exec sql update perftest2 set next_number = next_number + 1; @@ -101,6 +113,8 @@ exec sql end declare section; print_result(tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec, "update"); + exec sql begin transaction; + gettimeofday(&tvs, NULL); exec sql delete from perftest2; @@ -111,6 +125,8 @@ exec sql end declare section; print_result(tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec, "delete"); + exec sql set autocommit = off; + exec sql drop index number2; exec sql drop table perftest2; diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc index be3a2fc61e..d8980ade54 100644 --- a/src/interfaces/ecpg/test/test1.pgc +++ b/src/interfaces/ecpg/test/test1.pgc @@ -1,4 +1,19 @@ -exec sql include header_test; +exec sql include sqlca; + +exec sql whenever sqlerror do PrintAndStop(msg); +exec sql whenever sqlwarning do warn(); + +void PrintAndStop(msg) +{ + fprintf(stderr, "Error in statement '%s':\n", msg); + sqlprint(); + exit(-1); +} + +void warn(void) +{ + fprintf(stderr, "Warning: At least one column was truncated\n"); +} exec sql include sqlca; diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc index 87f5f9c5ef..3288b7df6a 100644 --- a/src/interfaces/ecpg/test/test2.pgc +++ b/src/interfaces/ecpg/test/test2.pgc @@ -62,7 +62,7 @@ exec sql end declare section; while (1) { strcpy(msg, "fetch"); - exec sql fetch in cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint; + exec sql fetch from cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint; printf("%8.8s", personal.name.arr); if (ind_personal.ind_birth.born >= 0) printf(", born %d", personal.birth.born); @@ -81,7 +81,7 @@ exec sql end declare section; strcpy(msg, "close"); exec sql close cur; - /* and now the same query with prepare */ + /* and now a same query with prepare */ exec sql prepare MM from :query; exec sql declare prep cursor for MM; diff --git a/src/interfaces/ecpg/test/test3.pgc b/src/interfaces/ecpg/test/test3.pgc index 12a7e3f9e2..8e0f6c30c6 100644 --- a/src/interfaces/ecpg/test/test3.pgc +++ b/src/interfaces/ecpg/test/test3.pgc @@ -54,7 +54,7 @@ exec sql end declare section; while (1) { strcpy(msg, "fetch"); - exec sql fetch in cur into :personal:ind_personal, :married:ind_married, :children:ind_children; + exec sql fetch cur into :personal:ind_personal, :married:ind_married, :children:ind_children; printf("%8.8s", personal.name.arr); if (ind_personal.ind_birth.born >= 0) printf(", born %d", personal.birth.born); @@ -73,7 +73,7 @@ exec sql end declare section; strcpy(msg, "close"); exec sql close cur; - /* and now the same query with prepare */ + /* and now a query with prepare */ exec sql prepare MM from "select name, born, age, married, children from meskes where name = ?"; exec sql declare prep cursor for MM;