From e845adf31f8f82cf3245f4c20b4a5d8ac4edfef0 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Wed, 5 May 2004 15:03:04 +0000 Subject: [PATCH] - Fixed bug in adjust_informix that treated arrays as simple variables. - Synced parser again. - Synced lexer. --- src/interfaces/ecpg/ChangeLog | 7 +++ src/interfaces/ecpg/ecpglib/data.c | 4 +- src/interfaces/ecpg/ecpglib/execute.c | 4 +- src/interfaces/ecpg/preproc/pgc.l | 75 ++++++++++++++++++---- src/interfaces/ecpg/preproc/preproc.y | 89 ++++++++++++++++----------- 5 files changed, 126 insertions(+), 53 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index b21b5646aa..b1f3a52c3f 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1777,6 +1777,13 @@ Thu Apr 22 14:13:57 CEST 2004 Thu Apr 29 16:06:37 CEST 2004 - Synced parser and keyword list. + +Wed May 5 11:51:47 CEST 2004 + + - Fixed bug in adjust_informix that treated arrays as simple + variables. + - Synced parser again. + - Synced lexer. - Set pgtypes library version to 1.2. - Set ecpg version to 3.2.0. - Set compat library version to 1.2. diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index 54d81fd684..5626b0debc 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.22 2003/11/29 19:52:08 pgsql Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.23 2004/05/05 15:03:04 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -44,7 +44,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, char *pval = (char *) PQgetvalue(results, act_tuple, act_field); int value_for_indicator = 0; - ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld array: %d\n", lineno, pval ? pval : "", offset, isarray); + ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld array: %s\n", lineno, pval ? pval : "", offset, isarray?"Yes":"No"); /* pval is a pointer to the value */ /* let's check if it really is an array if it should be one */ diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 758f878ff8..2cee7c70c9 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.32 2004/01/28 09:52:14 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.33 2004/05/05 15:03:04 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -333,7 +333,7 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia } PQclear(query); ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno); - ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %d\n", stmt->lineno, type, var->type, isarray); + ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %s\n", stmt->lineno, type, var->type, isarray?"Yes":"No"); return isarray; } diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 2202a17da3..a6d9d75543 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.127 2004/03/02 06:45:05 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.128 2004/05/05 15:03:04 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ extern YYSTYPE yylval; static int xcdepth = 0; /* depth of nesting in slash-star comments */ +static char *dolqstart; /* current $foo$ quote start string */ /* * literalbuf is used to accumulate literal values when multiple rules @@ -93,6 +94,7 @@ static struct _if_value * delimited identifiers (double-quoted identifiers) - thomas 1997-10-27 * hexadecimal numeric string - thomas 1997-11-16 * quoted strings - thomas 1997-07-30 + * $foo$ quoted strings */ %x xb @@ -101,6 +103,7 @@ static struct _if_value %x xdc %x xh %x xq +%x xdolq %x xpre %x xcond %x xskip @@ -128,7 +131,7 @@ xnstart [nN]{quote} xch 0[xX][0-9A-Fa-f]* /* Extended quote - * xqdouble implements SQL92 embedded quote + * xqdouble implements embedded quote * xqcat allows strings to cross input lines */ quote ' @@ -140,6 +143,17 @@ xqescape [\\][^0-7] xqoctesc [\\][0-7]{1,3} xqcat {quote}{whitespace_with_newline}{quote} +/* $foo$ style quotes ("dollar quoting") + * The quoted string starts with $foo$ where "foo" is an optional string + * in the form of an identifier, except that it may not contain "$", + * and extends to the first occurrence of an identical string. + * There is *no* processing of the quoted text. + */ +dolq_start [A-Za-z\200-\377_] +dolq_cont [A-Za-z\200-\377_0-9] +dolqdelim \$({dolq_start}{dolq_cont}*)?\$ +dolqinside [^$]+ + /* Double quote * Allows embedded spaces and other special characters into identifiers. */ @@ -171,8 +185,7 @@ xdcinside ({xdcqq}|{xdcqdq}|{xdcother}) * 2. In the operator rule, check for slash-star within the operator, and * if found throw it back with yyless(). This handles the plus-slash-star * problem. - * SQL92-style comments, which start with dash-dash, have similar interactions - * with the operator rule. + * Dash-dash comments have similar interactions with the operator rule. */ xcstart \/\*{op_chars}* xcstop \*+\/ @@ -279,9 +292,10 @@ cppinclude {space}*#{include}{space}* cppline {space}*#(.*\\{space})+.* /* - * Quoted strings must allow some special characters such as single-quote + * Dollar quoted strings are totally opaque, and no escaping is done on them. + * Other quoted strings must allow some special characters such as single-quote * and newline. - * Embedded single-quotes are implemented both in the SQL92-standard + * Embedded single-quotes are implemented both in the SQL standard * style of two adjacent single quotes "''" and in the Postgres/Java style * of escaped-quote "\'". * Other embedded escaped characters are matched explicitly and the leading @@ -341,7 +355,7 @@ cppline {space}*#(.*\\{space})+.* BEGIN(SQL); if (literalbuf[strspn(literalbuf, "01") + 1] != '\0') mmerror(PARSE_ERROR, ET_ERROR, "invalid bit string input."); - yylval.str = literalbuf; + yylval.str = mm_strdup(literalbuf); return BCONST; } @@ -358,7 +372,7 @@ cppline {space}*#(.*\\{space})+.* addlitchar('x'); } {xhstop} { - yylval.str = literalbuf; + yylval.str = mm_strdup(literalbuf); return XCONST; } @@ -388,8 +402,44 @@ cppline {space}*#(.*\\{space})+.* {xqescape} { addlit(yytext, yyleng); } {xqoctesc} { addlit(yytext, yyleng); } {xqcat} { /* ignore */ } - +. { + /* This is only needed for \ just before EOF */ + addlitchar(yytext[0]); + } <> { mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted string"); } +{dolqdelim} { + token_start = yytext; + dolqstart = mm_strdup(yytext); + BEGIN(xdolq); + startlit(); + } +{dolqdelim} { + if (strcmp(yytext, dolqstart) == 0) + { + free(dolqstart); + BEGIN(SQL); + yylval.str = mm_strdup(literalbuf); + return SCONST; + } + else + { + /* + * When we fail to match $...$ to dolqstart, transfer + * the $... part to the output, but put back the final + * $ for rescanning. Consider $delim$...$junk$delim$ + */ + addlit(yytext, yyleng-1); + yyless(yyleng-1); + } + } +{dolqinside} { + addlit(yytext, yyleng); + } +. { + /* This is only needed for $ inside the quoted text */ + addlitchar(yytext[0]); + } +<> { yyerror("unterminated dollar-quoted string"); } {xdstart} { state_before = YYSTATE; @@ -400,6 +450,7 @@ cppline {space}*#(.*\\{space})+.* BEGIN(state_before); if (literallen == 0) mmerror(PARSE_ERROR, ET_ERROR, "zero-length delimited identifier"); + /* The backend will truncate the idnetifier here. We do not as it does not change the result. */ yylval.str = mm_strdup(literalbuf); return CSTRING; } @@ -459,12 +510,12 @@ cppline {space}*#(.*\\{space})+.* nchars = slashstar - yytext; /* - * For SQL92 compatibility, '+' and '-' cannot be the + * For SQL compatibility, '+' and '-' cannot be the * last char of a multi-char operator unless the operator - * contains chars that are not in SQL92 operators. + * contains chars that are not in SQL operators. * The idea is to lex '=-' as two operators, but not * to forbid operator names like '?-' that could not be - * sequences of SQL92 operators. + * sequences of SQL operators. */ while (nchars > 1 && (yytext[nchars-1] == '+' || diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index aca66367ca..3dd7d8b361 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.278 2004/04/29 14:08:10 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.279 2004/05/05 15:03:04 meskes Exp $ */ /* Copyright comment */ %{ @@ -211,7 +211,7 @@ adjust_informix(struct arguments *list) if (atoi(ptr->variable->type->size) > 1) { - ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size), 0); + ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1")), ptr->variable->type->size), 0); sprintf(temp, "%d, (", ecpg_informix_var++); } else @@ -442,7 +442,7 @@ add_additional_variables(char *name, bool insert) %type TableConstraint OptTableElementList Xconst opt_transaction %type ConstraintElem key_actions ColQualList type_name %type target_list target_el update_target_list alias_clause -%type update_target_el qualified_name database_name +%type update_target_el qualified_name database_name alter_using %type access_method attr_name index_name name func_name %type file_name AexprConst c_expr ConstTypename var_list %type a_expr b_expr TruncateStmt CommentStmt OnCommitOption opt_by @@ -464,15 +464,15 @@ add_additional_variables(char *name, bool insert) %type copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary %type FetchStmt from_in CreateOpClassStmt like_including_defaults %type ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose -%type opt_full func_arg OptWithOids opt_freeze +%type opt_full func_arg OptWithOids opt_freeze alter_table_cmd %type analyze_keyword opt_name_list ExplainStmt index_params -%type index_elem opt_class access_method_clause +%type index_elem opt_class access_method_clause alter_table_cmds %type index_opt_unique IndexStmt func_return ConstInterval %type func_args_list func_args opt_with def_arg overlay_placing %type def_elem def_list definition DefineStmt select_with_parens %type opt_instead event RuleActionList opt_using CreateAssertStmt %type RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type -%type RuleStmt opt_column opt_name oper_argtypes NumConst +%type RuleStmt opt_column oper_argtypes NumConst %type MathOp RemoveFuncStmt aggr_argtype for_update_clause %type RemoveAggrStmt opt_procedural select_no_parens CreateCastStmt %type RemoveOperStmt RenameStmt all_Op opt_Trusted opt_lancompiler @@ -1140,45 +1140,58 @@ CheckPointStmt: CHECKPOINT { $$= make_str("checkpoint"); } *****************************************************************************/ AlterTableStmt: + ALTER TABLE relation_expr alter_table_cmds + { $$ = cat_str(3, make_str("alter table"), $3, $4); } + ; + +alter_table_cmds: + alter_table_cmd { $$ = $1; } + | alter_table_cmds ',' alter_table_cmd { $$ = cat_str(3, $1, make_str(","), $3); } + ; + +alter_table_cmd: + ADD opt_column columnDef /* ALTER TABLE ADD [COLUMN] */ - ALTER TABLE relation_expr ADD opt_column columnDef - { $$ = cat_str(5, make_str("alter table"), $3, make_str("add"), $5, $6); } + { $$ = cat_str(3, make_str("add"), $2, $3); } /* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |DROP DEFAULT} */ - | ALTER TABLE relation_expr ALTER opt_column ColId alter_column_default - { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, $7); } + | ALTER opt_column ColId alter_column_default + { $$ = cat_str(4, make_str("alter"), $2, $3, $4); } /* ALTER TABLE ALTER [COLUMN] DROP NOT NULL */ - | ALTER TABLE relation_expr ALTER opt_column ColId DROP NOT NULL_P - { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("drop not null")); } + | ALTER opt_column ColId DROP NOT NULL_P + { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("drop not null")); } /* ALTER TABLE ALTER [COLUMN] SET NOT NULL */ - | ALTER TABLE relation_expr ALTER opt_column ColId SET NOT NULL_P - { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set not null")); } + | ALTER opt_column ColId SET NOT NULL_P + { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("set not null")); } /* ALTER TABLE ALTER [COLUMN] SET STATISTICS */ - | ALTER TABLE relation_expr ALTER opt_column ColId SET STATISTICS PosIntConst - { $$ = cat_str(7, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set statistics"), $9); } + | ALTER opt_column ColId SET STATISTICS PosIntConst + { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set statistics"), $6); } /* ALTER TABLE ALTER [COLUMN] SET STORAGE */ - | ALTER TABLE relation_expr ALTER opt_column ColId SET STORAGE ColId - { $$ = cat_str(7, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set storage"), $9); } + | ALTER opt_column ColId SET STORAGE ColId + { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set storage"), $6); } /* ALTER TABLE DROP [COLUMN] {RESTRICT|CASCADE} */ - | ALTER TABLE relation_expr DROP opt_column ColId opt_drop_behavior - { $$ = cat_str(6, make_str("alter table"), $3, make_str("drop"), $5, $6, $7); } + | DROP opt_column ColId opt_drop_behavior + { $$ = cat_str(4, make_str("drop"), $2, $3, $4); } +/* ALTER TABLE ALTER [COLUMN] TYPE [ USING ] */ + | ALTER opt_column ColId TYPE_P Typename alter_using + { $$ = cat_str(6, make_str("alter"), $2, $3, make_str("type"), $5, $6); } /* ALTER TABLE ADD CONSTRAINT ... */ - | ALTER TABLE relation_expr ADD TableConstraint - { $$ = cat_str(4, make_str("alter table"), $3, make_str("add"), $5); } + | ADD TableConstraint + { $$ = cat_str(2, make_str("add"), $2); } /* ALTER TABLE DROP CONSTRAINT ... */ - | ALTER TABLE relation_expr DROP CONSTRAINT name opt_drop_behavior - { $$ = cat_str(5, make_str("alter table"), $3, make_str("drop constraint"), $6, $7); } + | DROP CONSTRAINT name opt_drop_behavior + { $$ = cat_str(3, make_str("drop constraint"), $3, $4); } /* ALTER TABLE SET WITHOUT OIDS */ - | ALTER TABLE relation_expr SET WITHOUT OIDS - { $$ = cat_str(3, make_str("alter table"), $3, make_str("set without oids")); } + | SET WITHOUT OIDS + { $$ = make_str("set without oids"); } /* ALTER TABLE CREATE TOAST TABLE */ - | ALTER TABLE qualified_name CREATE TOAST TABLE - { $$ = cat_str(3, make_str("alter table"), $3, make_str("create toast table")); } + | CREATE TOAST TABLE + { $$ = make_str("create toast table"); } /* ALTER TABLE OWNER TO UserId */ - | ALTER TABLE qualified_name OWNER TO UserId - { $$ = cat_str(4, make_str("alter table"), $3, make_str("owner to"), $6); } + | OWNER TO UserId + { $$ = cat_str(2, make_str("owner to"), $3); } /* ALTER TABLE CLUSTER ON */ - | ALTER TABLE qualified_name CLUSTER ON name - { $$ = cat_str(4, make_str("alter table"), $3, make_str("cluster on"), $6); } + | CLUSTER ON name + { $$ = cat_str(2, make_str("cluster on"), $3); } ; alter_column_default: @@ -1191,6 +1204,10 @@ opt_drop_behavior: CASCADE { $$ = make_str("cascade"); } | /* EMPTY */ { $$ = EMPTY; } ; +alter_using: USING a_expr { $$ = cat2_str(make_str("using"), $2); } + | /* EMPTY */ { $$ = EMPTY; } + ; + /***************************************************************************** * * QUERY : @@ -2310,7 +2327,9 @@ RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("rename to"), $9); } | ALTER SCHEMA name RENAME TO name { $$ = cat_str(4, make_str("alter schema"), $3, make_str("rename to"), $6); } - | ALTER TABLE relation_expr RENAME opt_column opt_name TO name + | ALTER TABLE relation_expr RENAME TO name + { $$ = cat_str(4, make_str("alter table"), $3, make_str("rename to"), $6); } + | ALTER TABLE relation_expr RENAME opt_column name TO name { $$ = cat_str(7, make_str("alter table"), $3, make_str("rename"), $5, $6, make_str("to"), $8); } | ALTER TRIGGER name ON relation_expr RENAME TO name { $$ = cat_str(6, make_str("alter trigger"), $3, make_str("on"), $5, make_str("rename to"), $8); } @@ -2318,10 +2337,6 @@ RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name { $$ = cat_str(4, make_str("alter user"), $3, make_str("rename to"), $6); } ; -opt_name: name { $$ = $1; } - | /*EMPTY*/ { $$ = EMPTY; } - ; - opt_column: COLUMN { $$ = make_str("column"); } | /*EMPTY*/ { $$ = EMPTY; } ;