1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Don't treat NEW and OLD as reserved words anymore. For the purposes of rules

it works just as well to have them be ordinary identifiers, and this gets rid
of a number of ugly special cases.  Plus we aren't interfering with non-rule
usage of these names.

catversion bump because the names change internally in stored rules.
This commit is contained in:
Tom Lane
2009-11-05 23:24:27 +00:00
parent 45d7e04fce
commit 593f4b854a
18 changed files with 84 additions and 156 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.118 2009/10/13 00:53:07 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.119 2009/11/05 23:24:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -361,10 +361,10 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
* OLD first, then NEW....
*/
rt_entry1 = addRangeTableEntryForRelation(NULL, viewRel,
makeAlias("*OLD*", NIL),
makeAlias("old", NIL),
false, false);
rt_entry2 = addRangeTableEntryForRelation(NULL, viewRel,
makeAlias("*NEW*", NIL),
makeAlias("new", NIL),
false, false);
/* Must override addRangeTableEntry's default access-check flags */
rt_entry1->requiredPerms = 0;

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.687 2009/11/04 23:15:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.688 2009/11/05 23:24:23 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -254,7 +254,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
%type <str> relation_name copy_file_name
%type <str> copy_file_name
database_name access_method_clause access_method attr_name
index_name name file_name cluster_index_specification
@ -263,7 +263,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <range> qualified_name OptConstrFromTable
%type <str> all_Op MathOp SpecialRuleRelation
%type <str> all_Op MathOp
%type <str> iso_level opt_encoding
%type <node> grantee
@ -502,11 +502,11 @@ static TypeName *TableFuncTypeName(List *columns);
MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NOCREATEDB
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PARTITION PASSWORD PLACING PLANS POSITION
@ -5886,20 +5886,18 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
*****************************************************************************/
RuleStmt: CREATE opt_or_replace RULE name AS
{ pg_yyget_extra(yyscanner)->QueryIsRule = TRUE; }
ON event TO qualified_name where_clause
DO opt_instead RuleActionList
{
RuleStmt *n = makeNode(RuleStmt);
n->replace = $2;
n->relation = $10;
n->relation = $9;
n->rulename = $4;
n->whereClause = $11;
n->event = $8;
n->instead = $13;
n->actions = $14;
n->whereClause = $10;
n->event = $7;
n->instead = $12;
n->actions = $13;
$$ = (Node *)n;
pg_yyget_extra(yyscanner)->QueryIsRule = FALSE;
}
;
@ -10109,16 +10107,11 @@ case_arg: a_expr { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
/*
* columnref starts with relation_name not ColId, so that OLD and NEW
* references can be accepted. Note that when there are more than two
* dotted names, the first name is not actually a relation name...
*/
columnref: relation_name
columnref: ColId
{
$$ = makeColumnRef($1, NIL, @1, yyscanner);
}
| relation_name indirection
| ColId indirection
{
$$ = makeColumnRef($1, $2, @1, yyscanner);
}
@ -10258,11 +10251,6 @@ target_el: a_expr AS ColLabel
*
*****************************************************************************/
relation_name:
SpecialRuleRelation { $$ = $1; }
| ColId { $$ = $1; }
;
qualified_name_list:
qualified_name { $$ = list_make1($1); }
| qualified_name_list ',' qualified_name { $$ = lappend($1, $3); }
@ -10276,7 +10264,7 @@ qualified_name_list:
* which may contain subscripts, and reject that case in the C code.
*/
qualified_name:
relation_name
ColId
{
$$ = makeNode(RangeVar);
$$->catalogname = NULL;
@ -10284,7 +10272,7 @@ qualified_name:
$$->relname = $1;
$$->location = @1;
}
| relation_name indirection
| ColId indirection
{
check_qualified_name($2, yyscanner);
$$ = makeNode(RangeVar);
@ -10343,7 +10331,7 @@ file_name: Sconst { $$ = $1; };
*/
func_name: type_function_name
{ $$ = list_make1(makeString($1)); }
| relation_name indirection
| ColId indirection
{
$$ = check_func_name(lcons(makeString($1), $2),
yyscanner);
@ -10912,12 +10900,10 @@ reserved_keyword:
| LIMIT
| LOCALTIME
| LOCALTIMESTAMP
| NEW
| NOT
| NULL_P
| OFF
| OFFSET
| OLD
| ON
| ONLY
| OR
@ -10946,30 +10932,6 @@ reserved_keyword:
| WITH
;
SpecialRuleRelation:
OLD
{
if (pg_yyget_extra(yyscanner)->QueryIsRule)
$$ = "*OLD*";
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("OLD used in query that is not in a rule"),
parser_errposition(@1)));
}
| NEW
{
if (pg_yyget_extra(yyscanner)->QueryIsRule)
$$ = "*NEW*";
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("NEW used in query that is not in a rule"),
parser_errposition(@1)));
}
;
%%
/*
@ -11461,7 +11423,6 @@ void
parser_init(base_yy_extra_type *yyext)
{
yyext->parsetree = NIL; /* in case grammar forgets to set it */
yyext->QueryIsRule = FALSE;
}
/*

View File

@ -19,7 +19,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.28 2009/10/13 00:53:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.29 2009/11/05 23:24:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1549,10 +1549,10 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
* qualification.
*/
oldrte = addRangeTableEntryForRelation(pstate, rel,
makeAlias("*OLD*", NIL),
makeAlias("old", NIL),
false, false);
newrte = addRangeTableEntryForRelation(pstate, rel,
makeAlias("*NEW*", NIL),
makeAlias("new", NIL),
false, false);
/* Must override addRangeTableEntry's default access-check flags */
oldrte->requiredPerms = 0;
@ -1653,10 +1653,10 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
* them in the joinlist.
*/
oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
makeAlias("*OLD*", NIL),
makeAlias("old", NIL),
false, false);
newrte = addRangeTableEntryForRelation(sub_pstate, rel,
makeAlias("*NEW*", NIL),
makeAlias("new", NIL),
false, false);
oldrte->requiredPerms = 0;
newrte->requiredPerms = 0;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.138 2009/06/11 14:49:01 momjian Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.139 2009/11/05 23:24:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -601,9 +601,9 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect)
* Recursively scan a query or expression tree and set the checkAsUser
* field to the given userid in all rtable entries.
*
* Note: for a view (ON SELECT rule), the checkAsUser field of the *OLD*
* Note: for a view (ON SELECT rule), the checkAsUser field of the OLD
* RTE entry will be overridden when the view rule is expanded, and the
* checkAsUser field of the *NEW* entry is irrelevant because that entry's
* checkAsUser field of the NEW entry is irrelevant because that entry's
* requiredPerms bits will always be zero. However, for other types of rules
* it's important to set these fields to match the rule owner. So we just set
* them always.

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.191 2009/10/28 17:36:50 tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.192 2009/11/05 23:24:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -325,7 +325,7 @@ rewriteRuleAction(Query *parsetree,
OffsetVarNodes((Node *) sub_action, rt_length, 0);
OffsetVarNodes(rule_qual, rt_length, 0);
/* but references to *OLD* should point at original rt_index */
/* but references to OLD should point at original rt_index */
ChangeVarNodes((Node *) sub_action,
PRS2_OLD_VARNO + rt_length, rt_index, 0);
ChangeVarNodes(rule_qual,
@ -1190,7 +1190,7 @@ ApplyRetrieveRule(Query *parsetree,
/*
* We move the view's permission check data down to its rangetable. The
* checks will actually be done against the *OLD* entry therein.
* checks will actually be done against the OLD entry therein.
*/
subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
Assert(subrte->relid == relation->rd_id);

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.124 2009/10/26 02:26:38 tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.125 2009/11/05 23:24:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -940,15 +940,15 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
/*
* Currently, this is ONLY applied to rule-action queries, and so we
* expect to find the *OLD* and *NEW* placeholder entries in the given
* expect to find the OLD and NEW placeholder entries in the given
* query. If they're not there, it must be an INSERT/SELECT in which
* they've been pushed down to the SELECT.
*/
if (list_length(parsetree->rtable) >= 2 &&
strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
"*OLD*") == 0 &&
"old") == 0 &&
strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
"*NEW*") == 0)
"new") == 0)
return parsetree;
Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
if (list_length(parsetree->jointree->fromlist) != 1)
@ -962,9 +962,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
elog(ERROR, "expected to find SELECT subquery");
if (list_length(selectquery->rtable) >= 2 &&
strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
"*OLD*") == 0 &&
"old") == 0 &&
strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
"*NEW*") == 0)
"new") == 0)
{
if (subquery_ptr)
*subquery_ptr = &(selectrte->subquery);

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.313 2009/10/28 18:51:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.314 2009/11/05 23:24:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -3572,14 +3572,7 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
if (schemaname)
appendStringInfo(buf, "%s.",
quote_identifier(schemaname));
if (strcmp(refname, "*NEW*") == 0)
appendStringInfoString(buf, "new");
else if (strcmp(refname, "*OLD*") == 0)
appendStringInfoString(buf, "old");
else
appendStringInfoString(buf, quote_identifier(refname));
appendStringInfoString(buf, quote_identifier(refname));
if (attname || showstar)
appendStringInfoChar(buf, '.');
}

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.549 2009/11/04 23:47:04 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.550 2009/11/05 23:24:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200911041
#define CATALOG_VERSION_NO 200911051
#endif

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.48 2009/09/22 23:52:53 petere Exp $
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.49 2009/11/05 23:24:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -93,8 +93,6 @@ typedef struct base_yy_extra_type
*/
List *parsetree; /* final parse result is delivered here */
bool QueryIsRule; /* signals we are parsing CREATE RULE */
} base_yy_extra_type;
/*

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.5 2009/10/12 20:39:42 tgl Exp $
* $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.6 2009/11/05 23:24:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -239,7 +239,6 @@ PG_KEYWORD("names", NAMES, UNRESERVED_KEYWORD)
PG_KEYWORD("national", NATIONAL, COL_NAME_KEYWORD)
PG_KEYWORD("natural", NATURAL, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("nchar", NCHAR, COL_NAME_KEYWORD)
PG_KEYWORD("new", NEW, RESERVED_KEYWORD)
PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD)
PG_KEYWORD("no", NO, UNRESERVED_KEYWORD)
PG_KEYWORD("nocreatedb", NOCREATEDB, UNRESERVED_KEYWORD)
@ -263,7 +262,6 @@ PG_KEYWORD("of", OF, UNRESERVED_KEYWORD)
PG_KEYWORD("off", OFF, RESERVED_KEYWORD)
PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD)
PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD)
PG_KEYWORD("old", OLD, RESERVED_KEYWORD)
PG_KEYWORD("on", ON, RESERVED_KEYWORD)
PG_KEYWORD("only", ONLY, RESERVED_KEYWORD)
PG_KEYWORD("operator", OPERATOR, UNRESERVED_KEYWORD)

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.5 2009/08/14 13:28:22 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.6 2009/11/05 23:24:27 tgl Exp $ */
ECPG: stmtClosePortalStmt block
{
@ -377,12 +377,6 @@ ECPG: FetchStmtMOVEname rule
add_additional_variables($3, false);
$$ = cat_str(3, make_str("fetch"), $2, $3);
}
ECPG: SpecialRuleRelationOLD addon
if (!QueryIsRule)
mmerror(PARSE_ERROR, ET_ERROR, "OLD used in query that is not in a rule");
ECPG: SpecialRuleRelationNEW addon
if (!QueryIsRule)
mmerror(PARSE_ERROR, ET_ERROR, "NEW used in query that is not in a rule");
ECPG: select_limitLIMITselect_limit_value','select_offset_value block
{
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.header,v 1.9 2009/09/08 04:25:00 tgl Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.header,v 1.10 2009/11/05 23:24:27 tgl Exp $ */
/* Copyright comment */
%{
@ -37,7 +37,7 @@ int ecpg_informix_var = 0;
char *connection = NULL;
char *input_filename = NULL;
static int QueryIsRule = 0, FoundInto = 0;
static int FoundInto = 0;
static int initializer = 0;
static int pacounter = 1;
static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.12 2009/09/22 23:43:42 tgl Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.13 2009/11/05 23:24:27 tgl Exp $ */
statements: /*EMPTY*/
| statements statement
@ -28,16 +28,6 @@ CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectSt
}
;
RuleStmt: CREATE opt_or_replace RULE name AS
{QueryIsRule = 1;}
ON event TO qualified_name where_clause
DO opt_instead RuleActionList
{
QueryIsRule=0;
$$ = cat_str(12, make_str("create"), $2, make_str("rule"), $4, make_str("as on"), $8, make_str("to"), $10, $11, make_str("do"), $13, $14);
}
;
at: AT connection_object
{
connection = $2;

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.2 2009/11/05 23:24:27 tgl Exp $ */
%type <str> ECPGAllocateDescr
%type <str> ECPGCKeywords
%type <str> ECPGColId
@ -90,7 +90,6 @@
%type <str> precision
%type <str> prepared_name
%type <str> quoted_ident_stringvar
%type <str> RuleStmt
%type <str> s_struct_union
%type <str> server
%type <str> server_name

View File

@ -1,5 +1,5 @@
#!/usr/bin/perl
# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parse.pl,v 1.3 2009/01/29 09:38:38 petere Exp $
# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parse.pl,v 1.4 2009/11/05 23:24:27 tgl Exp $
# parser generater for ecpg
# call with backend parser as stdin
#
@ -51,7 +51,6 @@ $replace_types{'stmtblock'} = 'ignore';
$replace_types{'stmtmulti'} = 'ignore';
$replace_types{'CreateAsStmt'} = 'ignore';
$replace_types{'DeallocateStmt'} = 'ignore';
$replace_types{'RuleStmt'} = 'ignore';
$replace_types{'ColLabel'} = 'ignore';
$replace_types{'unreserved_keyword'} = 'ignore';
$replace_types{'Sconst'} = 'ignore';