diff options
Diffstat (limited to 'src/interfaces/ecpg/preproc')
-rw-r--r-- | src/interfaces/ecpg/preproc/Makefile | 2 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/ecpg_keywords.c | 4 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/extern.h | 10 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/keywords.c | 4 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/pgc.l | 12 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/preproc.y | 457 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/type.c | 43 |
7 files changed, 308 insertions, 224 deletions
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 5cb3861c22a..1410087832a 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=3 -PATCHLEVEL=0 +PATCHLEVEL=1 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \ diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c index 3badb939974..bc724c54b31 100644 --- a/src/interfaces/ecpg/preproc/ecpg_keywords.c +++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c @@ -24,12 +24,14 @@ static ScanKeyword ScanKeywords[] = { {"break", SQL_BREAK}, {"call", SQL_CALL}, {"connect", SQL_CONNECT}, + {"connection", SQL_CONNECTION}, {"continue", SQL_CONTINUE}, {"disconnect", SQL_DISCONNECT}, {"found", SQL_FOUND}, {"go", SQL_GO}, {"goto", SQL_GOTO}, - {"immediate", SQL_IMMEDIATE}, + {"identified", SQL_IDENTIFIED}, + {"immediate", SQL_IMMEDIATE}, {"indicator", SQL_INDICATOR}, {"open", SQL_OPEN}, {"release", SQL_RELEASE}, diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 6faa36be883..e18bb33219c 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -1,4 +1,5 @@ #include "parser/keywords.h" +#include <errno.h> /* variables */ @@ -47,7 +48,8 @@ extern void yyerror(char *); /* return codes */ #define OK 0 -#define NO_INCLUDE_FILE 1 -#define PARSE_ERROR 2 -#define OUT_OF_MEMORY 3 -#define ILLEGAL_OPTION 4 +#define PARSE_ERROR -1 +#define ILLEGAL_OPTION -2 + +#define NO_INCLUDE_FILE ENOENT +#define OUT_OF_MEMORY ENOMEM diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index 4d8722f69df..9f953cb98f5 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.1 1998/04/21 13:23:06 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.2 1998/05/18 16:05:00 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -189,6 +189,8 @@ static ScanKeyword ScanKeywords[] = { {"substring", SUBSTRING}, {"table", TABLE}, {"time", TIME}, + {"timezone_hour", TIMEZONE_HOUR}, + {"timezone_minute", TIMEZONE_MINUTE}, {"to", TO}, {"trailing", TRAILING}, {"transaction", TRANSACTION}, diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 146938bf7df..c9f0cd459b5 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -139,12 +139,13 @@ self [,()\[\].$\:\+\-\*\/\<\>\=\|] op_and_self [\~\!\@\#\%\^\&\|\`\?\$\:\+\-\*\/\<\>\=] operator {op_and_self}+ -xminteger {integer}/- -xmreal {real}/{space}*-{digit} xmstop - -integer -?{digit}+ -real -?{digit}+\.{digit}+([Ee][-+]?{digit}+)? +integer [\-]?{digit}+ +/* +real [\-]?{digit}+\.{digit}+([Ee][-+]?{digit}+)? +*/ +real [\-]?(((({digit}*\.{digit}+)|({digit}+\.{digit}*))([Ee][-+]?{digit}+)?)|({digit}+[Ee][-+]?{digit}+)) param \${integer} @@ -309,7 +310,8 @@ before_comment); <SQL>{typecast} { return TYPECAST; } -<SQL>{self}/-[\.0-9] { +<SQL>{self}/{space}*-[\.0-9] { + BEGIN(xm); return (yytext[0]); } <SQL>{self} { return (yytext[0]); } diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index b4fa4f2e38c..5e99e7190d9 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -70,11 +70,13 @@ whenever_action(int mode) { if (mode == 1 && when_nf.code != W_NOTHING) { + output_line_number(); fprintf(yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) "); print_action(&when_nf); } if (when_error.code != W_NOTHING) { + output_line_number(); fprintf(yyout, "\nif (sqlca.sqlcode < 0) "); print_action(&when_error); } @@ -112,7 +114,7 @@ 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'; + char *next = strchr(++str, '.'), c = '\0'; if (next != NULL) { @@ -129,6 +131,8 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members) /* found the end */ switch (members->typ->typ) { + case ECPGt_array: + return(new_variable(name, ECPGmake_array_type(members->typ->u.element, members->typ->size))); case ECPGt_struct: return(new_variable(name, ECPGmake_struct_type(members->typ->u.members))); default: @@ -138,8 +142,12 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members) else { *next = c; - if (c == '-') next++; - return(find_struct_member(name, next, members->typ->u.members)); + if (c == '-') + { + next++; + return(find_struct_member(name, next, members->typ->u.element->u.members)); + } + else return(find_struct_member(name, next, members->typ->u.members)); } } } @@ -159,9 +167,12 @@ find_struct(char * name, char *next) /* restore the name, we will need it later on */ *next = c; - if (*next == '-') next++; - - return (find_struct_member(name, next, p->type->u.members)); + if (c == '-') + { + next++; + return (find_struct_member(name, next, p->type->u.element->u.members)); + } + else return (find_struct_member(name, next, p->type->u.members)); } static struct variable * @@ -178,12 +189,20 @@ find_simple(char * name) return(NULL); } +/* Note that this function will end the program in case of an unknown */ +/* variable */ static struct variable * find_variable(char * name) { char * next; - struct variable * p = - ((next = strpbrk(name, ".-")) != NULL) ? find_struct(name, next) : find_simple(name); + struct variable * p; + + if ((next = strchr(name, '.')) != NULL) + p = find_struct(name, next); + else if ((next = strstr(name, "->")) != NULL) + p = find_struct(name, next); + else + p = find_simple(name); if (p == NULL) { @@ -231,7 +250,6 @@ struct arguments { struct arguments * next; }; - static struct arguments * argsinsert = NULL; static struct arguments * argsresult = NULL; @@ -495,8 +513,9 @@ output_statement(char * stmt, int mode) } /* special embedded SQL token */ -%token SQL_BREAK SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_DISCONNECT SQL_FOUND SQL_GO SQL_GOTO -%token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN SQL_RELEASE +%token SQL_BREAK SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE +%token SQL_DISCONNECT SQL_FOUND SQL_GO SQL_GOTO +%token SQL_IDENTIFIED SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN SQL_RELEASE %token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START %token SQL_STOP SQL_WHENEVER @@ -527,8 +546,9 @@ output_statement(char * stmt, int mode) PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC, REFERENCES, REVOKE, RIGHT, ROLLBACK, SECOND_P, SELECT, SET, SUBSTRING, - TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM, - UNION, UNIQUE, UPDATE, USING, + TABLE, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE, + TO, TRAILING, TRANSACTION, TRIM, + UNION, UNIQUE, UPDATE, USER, USING, VALUES, VARCHAR, VARYING, VIEW, WHERE, WITH, WORK, YEAR_P, ZONE @@ -559,7 +579,7 @@ output_statement(char * stmt, int mode) * * Todd A. Brandys */ -%token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL +%token PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL /* Special keywords, not in the query language - see the "lex" file */ %token <str> IDENT SCONST Op CSTRING CVARIABLE @@ -620,7 +640,7 @@ output_statement(char * stmt, int mode) %type <str> sortby OptUseOp opt_inh_star relation_name_list name_list %type <str> group_clause groupby_list groupby having_clause from_clause %type <str> from_list from_val join_expr join_outer join_spec join_list -%type <str> join_using where_clause relation_expr +%type <str> join_using where_clause relation_expr row_op sub_type %type <str> opt_column_list insert_rest InsertStmt %type <str> columnList DeleteStmt LockStmt UpdateStmt CursorStmt %type <str> NotifyStmt columnElem copy_dirn OptimizableStmt @@ -650,12 +670,16 @@ output_statement(char * stmt, int mode) %type <str> DestroydbStmt ClusterStmt grantee RevokeStmt %type <str> GrantStmt privileges operation_commalist operation -%type <str> ECPGWhenever ECPGConnect db_name ECPGOpen open_opts +%type <str> ECPGWhenever ECPGConnect connection_target ECPGOpen open_opts %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 ECPGDisconnect dis_name -%type <str> stmt symbol opt_symbol ECPGRelease execstring +%type <str> stmt symbol opt_symbol ECPGRelease execstring server_name +%type <str> connection_object opt_server opt_port +%type <str> user_name opt_user char_variable ora_user ident +%type <str> db_prefix server opt_options opt_connection_name +%type <str> ECPGSetConnection %type <type_enum> simple_type type struct_type @@ -721,12 +745,12 @@ stmt: AddAttrStmt { output_statement($1, 0); } | VariableShowStmt { output_statement($1, 0); } | VariableResetStmt { output_statement($1, 0); } | ECPGConnect { - fprintf(yyout, "ECPGconnect(\"%s\");", $1); + fprintf(yyout, "ECPGconnect(__LINE__, %s);", $1); whenever_action(0); free($1); } | ECPGDisconnect { - fprintf(yyout, "ECPGdisconnect(\"%s\");", $1); + fprintf(yyout, "ECPGdisconnect(__LINE__, \"%s\");", $1); whenever_action(0); free($1); } @@ -737,6 +761,11 @@ stmt: AddAttrStmt { output_statement($1, 0); } } | ECPGOpen { output_statement($1, 0); } | ECPGRelease { /* output already done */ } + | ECPGSetConnection { + fprintf(yyout, "ECPGsetcon(__LINE__, %s);", $1); + whenever_action(0); + free($1); + } | ECPGWhenever { fputs($1, yyout); output_line_number(); @@ -828,7 +857,7 @@ user_group_clause: IN GROUP user_group_list { $$ = cat2_str(make1_str("in group | /*EMPTY*/ { $$ = make1_str(""); } ; -user_valid_clause: VALID UNTIL SCONST { $$ = cat2_str(make1_str("valid until"), $3);; } +user_valid_clause: VALID UNTIL Sconst { $$ = cat2_str(make1_str("valid until"), $3);; } | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -853,6 +882,7 @@ VariableSetStmt: SET ColId TO var_value { $$ = cat2_str(make1_str("set time zone"), $4); } + ; var_value: Sconst { $$ = $1; } @@ -1136,7 +1166,9 @@ default_expr: AexprConst $$ = "current_timestamp"; } | CURRENT_USER - { $$ = make1_str("current user"); } + { $$ = make1_str("current_user"); } + | USER + { $$ = make1_str("user"); } ; /* ConstraintElem specifies constraint syntax which is not embedded into @@ -1459,7 +1491,7 @@ TriggerFuncArg: Iconst $$ = make_name(); } | Sconst { $$ = $1; } - | ecpg_ident { $$ = $1; } + | ident { $$ = $1; } ; DropTrigStmt: DROP TRIGGER name ON relation_name @@ -2434,8 +2466,10 @@ groupby: ColId having_clause: HAVING a_expr { +#if FALSE yyerror("HAVING clause not yet implemented"); -/* $$ = cat2_str(make1_str("having"), $2); use this line instead to enable HAVING */ +#endif + $$ = cat2_str(make1_str("having"), $2); } | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -2610,7 +2644,7 @@ Generic: generic } ; -generic: ecpg_ident { $$ = $1; } +generic: ident { $$ = $1; } | TYPE_P { $$ = make1_str("type"); } ; @@ -2724,7 +2758,7 @@ opt_decimal: '(' Iconst ',' Iconst ')' Character: character '(' Iconst ')' { if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar"))) - yyerror("parse error"); + yyerror("internal parsing error; unrecognized character type"); if (atol($3) < 1) { sprintf(errortext, "length for '%s' type must be at least 1",$1); yyerror(errortext); @@ -2749,10 +2783,9 @@ Character: character '(' Iconst ')' character: CHARACTER opt_varying opt_charset opt_collate { - if (strlen($4) > 0) { - sprintf(errortext, "COLLATE %s not yet implemented",$4); - yyerror(errortext); - } + if (strlen($4) > 0) + fprintf(stderr, "COLLATE %s not yet implemented",$4); + $$ = cat4_str(make1_str("character"), $2, $3, $4); } | CHAR opt_varying { $$ = cat2_str(make1_str("char"), $2); } @@ -2809,6 +2842,7 @@ opt_interval: datetime { $$ = $1; } | DAY_P TO MINUTE_P { $$ = make1_str("day to minute"); } | DAY_P TO SECOND_P { $$ = make1_str("day to second"); } | HOUR_P TO MINUTE_P { $$ = make1_str("hour to minute"); } + | MINUTE_P TO SECOND_P { $$ = make1_str("minute to second"); } | HOUR_P TO SECOND_P { $$ = make1_str("hour to second"); } | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -2831,6 +2865,11 @@ a_expr_or_null: a_expr /* Expressions using row descriptors * Define row_descriptor to allow yacc to break the reduce/reduce conflict * with singleton expressions. + * Eliminated lots of code by defining row_op and sub_type clauses. + * However, can not consolidate EXPR_LINK case with others subselects + * due to shift/reduce conflict with the non-subselect clause (the parser + * would have to look ahead more than one token to resolve the conflict). + * - thomas 1998-05-09 */ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { @@ -2840,134 +2879,18 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { $$ = make5_str(make1_str("("), $2, make1_str(") not in ("), $7, make1_str(")")); } - | '(' row_descriptor ')' Op '(' SubSelect ')' - { - $$ = make3_str(make5_str(make1_str("("), $2, make1_str(")"), $4, make1_str("(")), $6, make1_str(")")); - } - | '(' row_descriptor ')' '+' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")+("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '-' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")-("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '/' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")/("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '*' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")*("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '<' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")<("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '>' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")>("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '=' '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")=("), $6, make1_str(")")); - } - | '(' row_descriptor ')' Op ANY '(' SubSelect ')' - { - $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("any("), $7, make1_str(")"))); - } - | '(' row_descriptor ')' '+' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")+any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '-' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")-any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '/' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")/any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '*' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")*any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '<' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")<any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '>' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")>any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '=' ANY '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")=any("), $7, make1_str(")")); - } - | '(' row_descriptor ')' Op ALL '(' SubSelect ')' - { - $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("all("), $7, make1_str(")"))); - } - | '(' row_descriptor ')' '+' ALL '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")+all("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '-' ALL '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")-all("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '/' ALL '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")/all("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '*' ALL '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")*all("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '<' ALL '(' SubSelect ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")<all("), $7, make1_str(")")); - } - | '(' row_descriptor ')' '>' ALL '(' SubSelect ')' + | '(' row_descriptor ')' row_op sub_type '(' SubSelect ')' { - $$ = make5_str(make1_str("("), $2, make1_str(")>all("), $7, make1_str(")")); + $$ = make4_str(make5_str(make1_str("("), $2, make1_str(")"), $4, $5), make1_str("("), $7, make1_str(")")); } - | '(' row_descriptor ')' '=' ALL '(' SubSelect ')' + | '(' row_descriptor ')' row_op '(' SubSelect ')' { - $$ = make5_str(make1_str("("), $2, make1_str(")=all("), $7, make1_str(")")); + $$ = make3_str(make5_str(make1_str("("), $2, make1_str(")"), $4, make1_str("(")), $6, make1_str(")")); } - | '(' row_descriptor ')' Op '(' row_descriptor ')' + | '(' row_descriptor ')' row_op '(' row_descriptor ')' { $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("("), $6, make1_str(")"))); } - | '(' row_descriptor ')' '+' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")+("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '-' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")-("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '/' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")/("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '*' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")*("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '<' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")<("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '>' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")>("), $6, make1_str(")")); - } - | '(' row_descriptor ')' '=' '(' row_descriptor ')' - { - $$ = make5_str(make1_str("("), $2, make1_str(")=("), $6, make1_str(")")); - } ; row_descriptor: row_list ',' a_expr @@ -2976,6 +2899,21 @@ row_descriptor: row_list ',' a_expr } ; +row_op: Op { $$ = $1; } + | '<' { $$ = "<"; } + | '=' { $$ = "="; } + | '>' { $$ = ">"; } + | '+' { $$ = "+"; } + | '-' { $$ = "-"; } + | '*' { $$ = "*"; } + | '/' { $$ = "/"; } + ; + +sub_type: ANY { $$ = make1_str("ANY"); } + | ALL { $$ = make1_str("ALL"); } + ; + + row_list: row_list ',' a_expr { $$ = cat3_str($1, make1_str(","), $3); @@ -3089,6 +3027,11 @@ a_expr: attr opt_indirection { $$ = make1_str("current_user"); } + | USER + { + $$ = make1_str("user"); + } + | EXISTS '(' SubSelect ')' { $$ = make3_str(make1_str("exists("), $3, make1_str(")")); @@ -3358,6 +3301,10 @@ b_expr: attr opt_indirection { $$ = make1_str("current_user"); } + | USER + { + $$ = make1_str("user"); + } | POSITION '(' position_list ')' { $$ = make3_str(make1_str("position ("), $3, make1_str(")")); @@ -3417,12 +3364,9 @@ extract_list: extract_arg FROM a_expr { $$ = make1_str(";;"); } ; -/* Add in TIMEZONE_HOUR and TIMEZONE_MINUTE for SQL92 compliance - * for next release. Just set up extract_arg for now... - * - thomas 1998-04-08 - */ -extract_arg: datetime - { $$ = $1; } +extract_arg: datetime { $$ = $1; } + | TIMEZONE_HOUR { $$ = make1_str("timezone_hour"); } + | TIMEZONE_MINUTE { $$ = make1_str("timezone_minute"); } ; position_list: position_expr IN position_expr @@ -3660,9 +3604,9 @@ relation_name: SpecialRuleRelation ; database_name: ColId { $$ = $1; }; -access_method: ecpg_ident { $$ = $1; }; +access_method: ident { $$ = $1; }; attr_name: ColId { $$ = $1; }; -class: ecpg_ident { $$ = $1; }; +class: ident { $$ = $1; }; index_name: ColId { $$ = $1; }; /* Functions @@ -3673,7 +3617,7 @@ name: ColId { $$ = $1; }; func_name: ColId { $$ = $1; }; file_name: Sconst { $$ = $1; }; -recipe_name: ecpg_ident { $$ = $1; }; +recipe_name: ident { $$ = $1; }; /* Constants * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24 @@ -3723,8 +3667,9 @@ Sconst: SCONST { strcpy($$+1, $1); $$[strlen($1)+2]='\0'; $$[strlen($1)+1]='\''; + free($1); } -UserId: ecpg_ident { $$ = $1;}; +UserId: ident { $$ = $1;}; /* Column and type identifier * Does not include explicit datetime types @@ -3746,7 +3691,7 @@ TypeId: ColId * list due to shift/reduce conflicts in yacc. If so, move * down to the ColLabel entity. - thomas 1997-11-06 */ -ColId: ecpg_ident { $$ = $1; } +ColId: ident { $$ = $1; } | datetime { $$ = $1; } | ACTION { $$ = make1_str("action"); } | CACHE { $$ = make1_str("cache"); } @@ -3773,9 +3718,10 @@ ColId: ecpg_ident { $$ = $1; } | START { $$ = make1_str("start"); } | STATEMENT { $$ = make1_str("statement"); } | TIME { $$ = make1_str("time"); } + | TIMEZONE_HOUR { $$ = make1_str("timezone_hour"); } + | TIMEZONE_MINUTE { $$ = make1_str("timezone_minute"); } | TRIGGER { $$ = make1_str("trigger"); } | TYPE_P { $$ = make1_str("type"); } - | USER { $$ = make1_str("user"); } | VALID { $$ = make1_str("valid"); } | VERSION { $$ = make1_str("version"); } | ZONE { $$ = make1_str("zone"); } @@ -4011,8 +3957,8 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer if (struct_level == 0) new_variable($2, type); else - ECPGmake_struct_member($2, type, &(struct_member_list[struct_level-1])); - + ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]))->typ; + free($1); free($2); free($3.str); @@ -4028,10 +3974,114 @@ opt_pointer: /* empty */ { $$ = make1_str(""); } /* * the exec sql connect statement: connect to the given database */ -ECPGConnect: SQL_CONNECT db_name { $$ = $2; } +ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user + { + $$ = make5_str($3, make1_str(","), $5, make1_str(","), $4); + } + | SQL_CONNECT TO DEFAULT + { + $$ = make1_str("NULL,NULL,NULL,\"DEFAULT\""); + } + /* also allow ORACLE syntax */ + | SQL_CONNECT ora_user + { + $$ = make3_str(make1_str("NULL,"), $2, make1_str(",NULL")); + } + +connection_target: database_name opt_server opt_port + { + /* old style: dbname[@server][:port] */ + if (strlen($2) > 0 && *($2) != '@') + { + sprintf(errortext, "parse error at or near '%s'", $2); + yyerror(errortext); + } -db_name: database_name { $$ = $1; } - | cvariable { /* check if we have a char variable */ + $$ = make5_str(make1_str("\""), $1, $2, $3, make1_str("\"")); + } + | db_prefix server opt_port '/' database_name opt_options + { + /* new style: esql:postgresql://server[:port][/dbname] */ + if (strncmp($2, "://", 3) != 0) + { + sprintf(errortext, "parse error at or near '%s'", $2); + yyerror(errortext); + } + + $$ = make4_str(make5_str(make1_str("\""), $1, $2, $3, make1_str("/")), $5, $6, make1_str("\"")); + } + | char_variable + { + $$ = $1; + } + +db_prefix: ident cvariable + { + if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0) + { + sprintf(errortext, "parse error at or near '%s'", $2); + yyerror(errortext); + } + + if (strcmp($1, "esql") != 0 && strcmp($1, "ecpg") != 0 && strcmp($1, "sql") != 0 && strcmp($1, "isql") != 0 && strcmp($1, "proc") != 0) + { + sprintf(errortext, "Illegal connection type %s", $1); + yyerror(errortext); + } + + $$ = make3_str($1, make1_str(":"), $2); + } + +server: Op server_name + { + if (strcmp($1, "@") != 0 && strcmp($1, "://") != 0) + { + sprintf(errortext, "parse error at or near '%s'", $1); + yyerror(errortext); + } + + $$ = make2_str($1, $2); + } + +opt_server: server { $$ = $1; } + | /* empty */ { $$ = make1_str(""); } + +server_name: ColId { $$ = $1; } + | ColId '.' server_name { $$ = make3_str($1, make1_str("."), $3); } + +opt_port: ':' Iconst { $$ = make2_str(make1_str(":"), $2); } + | /* empty */ { $$ = make1_str(""); } + +opt_connection_name: AS connection_target { $$ = $2; } + | /* empty */ { $$ = make1_str("NULL"); } + +opt_user: USER ora_user { $$ = $2; } + | /* empty */ { $$ = make1_str("NULL,NULL"); } + +ora_user: user_name + { + $$ = make2_str($1, make1_str(",NULL")); + } + | user_name '/' ColId + { + $$ = make3_str($1, make1_str(","), $3); + } + | user_name SQL_IDENTIFIED BY user_name + { + $$ = make3_str($1, make1_str(","), $4); + } + | user_name USING user_name + { + $$ = make3_str($1, make1_str(","), $3); + } + +user_name: UserId { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } + | char_variable { $$ = $1; } + | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } + | SCONST { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } + +char_variable: cvariable + { /* check if we have a char variable */ struct variable *p = find_variable($1); enum ECPGttype typ = p->type->typ; @@ -4039,33 +4089,48 @@ db_name: database_name { $$ = $1; } if (typ == ECPGt_array) typ = p->type->u.element->typ; - if (typ != ECPGt_char && typ != ECPGt_unsigned_char) - yyerror("invalid datatype"); - $$ = $1; - } + switch (typ) + { + case ECPGt_char: + case ECPGt_unsigned_char: + $$ = $1; + break; + case ECPGt_varchar: + $$ = make2_str($1, make1_str(".arr")); + break; + default: + yyerror("invalid datatype"); + break; + } + } + +opt_options: Op ColId + { + if (strlen($1) == 0) + yyerror("parse error"); + + if (strcmp($1, "?") != 0) + { + sprintf(errortext, "parse error at or near %s", $1); + yyerror(errortext); + } + + $$ = make2_str(make1_str("?"), $2); + } + | /* empty */ { $$ = make1_str(""); } /* * the exec sql disconnect statement: disconnect from the given database */ ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; } -dis_name: database_name { $$ = $1; } - | cvariable { /* check if we have a char variable */ - struct variable *p = find_variable($1); - enum ECPGttype typ = p->type->typ; +dis_name: connection_object { $$ = $1; } + | CURRENT { $$ = make1_str("CURRENT"); } + | ALL { $$ = make1_str("ALL"); } + | /* empty */ { $$ = make1_str("CURRENT"); } - /* if array see what's inside */ - if (typ == ECPGt_array) - typ = p->type->u.element->typ; - - if (typ != ECPGt_char && typ != ECPGt_unsigned_char) - yyerror("invalid datatype"); - $$ = $1; - } - | CURRENT { $$ = make1_str(""); } - | DEFAULT { $$ = make1_str(""); } - | ALL { $$ = make1_str(""); } - | /* empty */ { $$ = make1_str(""); } +connection_object: connection_target { $$ = $1; } + | DEFAULT { $$ = make1_str("DEFAULT"); } /* * execute a given string as sql command @@ -4118,6 +4183,14 @@ ECPGRelease: TransactionStmt SQL_RELEASE free($1); } +/* + * set the actual connection, this needs a differnet handling as the other + * set commands + */ +ECPGSetConnection: SET SQL_CONNECTION connection_object + { + $$ = $3; + } /* * whenever statement: decide what to do in case of error/no data found * according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION @@ -4163,7 +4236,7 @@ action : SQL_CONTINUE { | DO name '(' dotext ')' { $<action>$.code = W_DO; $<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")")); - $<action>$.str = cat2_str(make1_str("do"), $<action>$.command); + $<action>$.str = cat2_str(make1_str("do"), strdup($<action>$.command)); } | DO SQL_BREAK { $<action>$.code = W_BREAK; @@ -4173,7 +4246,7 @@ action : SQL_CONTINUE { | SQL_CALL name '(' dotext ')' { $<action>$.code = W_DO; $<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")")); - $<action>$.str = cat2_str(make1_str("call"), $<action>$.command); + $<action>$.str = cat2_str(make1_str("call"), strdup($<action>$.command)); } /* some other stuff for ecpg */ @@ -4478,14 +4551,16 @@ civariableonly : cvariable name { add_variable(&argsinsert, find_variable($1), &no_indicator); } -cvariable: CVARIABLE { $$ = $1; } +cvariable: CVARIABLE { $$ = make1_str($1); } indicator: /* empty */ { $$ = NULL; } | cvariable { 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; } -ecpg_ident: IDENT { $$ = $1; } +ident: IDENT { $$ = make1_str($1); } + +ecpg_ident: ident { $$ = $1; } | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } /* * C stuff diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index cbc7446909e..ce0e1b0cd20 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -20,21 +20,6 @@ mm_alloc(size_t size) return (ptr); } -/* realloc + error check */ -void * -mm_realloc(void *ptr, size_t size) -{ - ptr = realloc(ptr, size); - - if (ptr == NULL) - { - fprintf(stderr, "Out of memory\n"); - exit(OUT_OF_MEMORY); - } - - return (ptr); -} - /* duplicate memberlist */ static struct ECPGstruct_member * struct_member_dup(struct ECPGstruct_member * rm) @@ -43,7 +28,22 @@ struct_member_dup(struct ECPGstruct_member * rm) while (rm) { - ECPGmake_struct_member(rm->name, rm->typ, &new); + struct ECPGtype *type; + + switch(rm->typ->typ) + { + case ECPGt_struct: + type = ECPGmake_struct_type(rm->typ->u.members); + break; + case ECPGt_array: + type = ECPGmake_array_type(ECPGmake_simple_type(rm->typ->u.element->typ, rm->typ->u.element->size), rm->typ->size); + break; + default: + type = ECPGmake_simple_type(rm->typ->typ, rm->typ->size); + break; + } + + ECPGmake_struct_member(rm->name, type, &new); rm = rm->next; } @@ -165,11 +165,11 @@ static const char *get_type(enum ECPGttype typ) size is the maxsize in case it is a varchar. Otherwise it is the size of the variable (required to do array fetches of structs). */ -void +static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, long varcharsize, long arrsiz, const char *siz, const char *prefix); -void +static void 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); @@ -223,7 +223,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 structs. */ -void +static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, long varcharsize, long arrsize, @@ -272,7 +272,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, /* Penetrate a struct and dump the contents. */ -void +static void 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) { @@ -319,6 +319,7 @@ ECPGfree_struct_member(struct ECPGstruct_member * rm) rm = rm->next; free(p->name); + free(p->typ); free(p); } } @@ -337,7 +338,7 @@ ECPGfree_type(struct ECPGtype * typ) else if (typ->u.element->typ == ECPGt_struct) { /* Array of structs. */ - ECPGfree_struct_member(typ->u.members); + ECPGfree_struct_member(typ->u.element->u.members); free(typ->u.members); } else |