mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08: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:
parent
45d7e04fce
commit
593f4b854a
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.26 2009/09/22 23:43:37 tgl Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.27 2009/11/05 23:24:22 tgl Exp $ -->
|
||||
|
||||
<appendix id="sql-keywords-appendix">
|
||||
<title><acronym>SQL</acronym> Key Words</title>
|
||||
@ -3089,7 +3089,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>NEW</token></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
@ -3393,7 +3393,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry><token>OLD</token></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry></entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
<entry>reserved</entry>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/rules.sgml,v 1.52 2008/12/16 03:12:08 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/rules.sgml,v 1.53 2009/11/05 23:24:22 tgl Exp $ -->
|
||||
|
||||
<chapter id="rules">
|
||||
<title>The Rule System</title>
|
||||
@ -435,8 +435,7 @@ CREATE VIEW shoe_ready AS
|
||||
<note>
|
||||
<para>
|
||||
The two extra range
|
||||
table entries for <literal>NEW</> and <literal>OLD</> (named <literal>*NEW*</> and <literal>*OLD*</> for
|
||||
historical reasons in the printed query tree) you can see in
|
||||
table entries for <literal>NEW</> and <literal>OLD</> that you can see in
|
||||
the <structname>pg_rewrite</structname> entry aren't of interest
|
||||
for <command>SELECT</command> rules.
|
||||
</para>
|
||||
@ -504,7 +503,7 @@ SELECT shoelace.sl_name, shoelace.sl_avail,
|
||||
SELECT s.sl_name, s.sl_avail,
|
||||
s.sl_color, s.sl_len, s.sl_unit,
|
||||
s.sl_len * u.un_fact AS sl_len_cm
|
||||
FROM shoelace *OLD*, shoelace *NEW*,
|
||||
FROM shoelace old, shoelace new,
|
||||
shoelace_data s, unit u
|
||||
WHERE s.sl_unit = u.un_name;
|
||||
</programlisting>
|
||||
@ -531,7 +530,7 @@ SELECT shoelace.sl_name, shoelace.sl_avail,
|
||||
</programlisting>
|
||||
|
||||
There is one difference however: the subquery's range table has two
|
||||
extra entries <literal>shoelace *OLD*</> and <literal>shoelace *NEW*</>. These entries don't
|
||||
extra entries <literal>shoelace old</> and <literal>shoelace new</>. These entries don't
|
||||
participate directly in the query, since they aren't referenced by
|
||||
the subquery's join tree or target list. The rewriter uses them
|
||||
to store the access privilege check information that was originally present
|
||||
@ -546,7 +545,7 @@ SELECT shoelace.sl_name, shoelace.sl_avail,
|
||||
the remaining range-table entries in the top query (in this example there
|
||||
are no more), and it will recursively check the range-table entries in
|
||||
the added subquery to see if any of them reference views. (But it
|
||||
won't expand <literal>*OLD*</> or <literal>*NEW*</> — otherwise we'd have infinite recursion!)
|
||||
won't expand <literal>old</> or <literal>new</> — otherwise we'd have infinite recursion!)
|
||||
In this example, there are no rewrite rules for <literal>shoelace_data</> or <literal>unit</>,
|
||||
so rewriting is complete and the above is the final result given to
|
||||
the planner.
|
||||
@ -1073,15 +1072,15 @@ NEW.sl_avail <> OLD.sl_avail
|
||||
|
||||
<programlisting>
|
||||
INSERT INTO shoelace_log VALUES (
|
||||
*NEW*.sl_name, *NEW*.sl_avail,
|
||||
new.sl_name, new.sl_avail,
|
||||
current_user, current_timestamp )
|
||||
FROM shoelace_data *NEW*, shoelace_data *OLD*;
|
||||
FROM shoelace_data new, shoelace_data old;
|
||||
</programlisting>
|
||||
|
||||
(This looks a little strange since you cannot normally write
|
||||
<literal>INSERT ... VALUES ... FROM</>. The <literal>FROM</>
|
||||
clause here is just to indicate that there are range-table entries
|
||||
in the query tree for <literal>*NEW*</> and <literal>*OLD*</>.
|
||||
in the query tree for <literal>new</> and <literal>old</>.
|
||||
These are needed so that they can be referenced by variables in
|
||||
the <command>INSERT</command> command's query tree.)
|
||||
</para>
|
||||
@ -1094,9 +1093,9 @@ INSERT INTO shoelace_log VALUES (
|
||||
|
||||
<programlisting>
|
||||
INSERT INTO shoelace_log VALUES (
|
||||
*NEW*.sl_name, *NEW*.sl_avail,
|
||||
new.sl_name, new.sl_avail,
|
||||
current_user, current_timestamp )
|
||||
FROM shoelace_data *NEW*, shoelace_data *OLD*,
|
||||
FROM shoelace_data new, shoelace_data old,
|
||||
<emphasis>shoelace_data shoelace_data</emphasis>;
|
||||
</programlisting>
|
||||
|
||||
@ -1105,11 +1104,11 @@ INSERT INTO shoelace_log VALUES (
|
||||
|
||||
<programlisting>
|
||||
INSERT INTO shoelace_log VALUES (
|
||||
*NEW*.sl_name, *NEW*.sl_avail,
|
||||
new.sl_name, new.sl_avail,
|
||||
current_user, current_timestamp )
|
||||
FROM shoelace_data *NEW*, shoelace_data *OLD*,
|
||||
FROM shoelace_data new, shoelace_data old,
|
||||
shoelace_data shoelace_data
|
||||
<emphasis>WHERE *NEW*.sl_avail <> *OLD*.sl_avail</emphasis>;
|
||||
<emphasis>WHERE new.sl_avail <> old.sl_avail</emphasis>;
|
||||
</programlisting>
|
||||
|
||||
(This looks even stranger, since <literal>INSERT ... VALUES</> doesn't have
|
||||
@ -1125,11 +1124,11 @@ INSERT INTO shoelace_log VALUES (
|
||||
|
||||
<programlisting>
|
||||
INSERT INTO shoelace_log VALUES (
|
||||
*NEW*.sl_name, *NEW*.sl_avail,
|
||||
new.sl_name, new.sl_avail,
|
||||
current_user, current_timestamp )
|
||||
FROM shoelace_data *NEW*, shoelace_data *OLD*,
|
||||
FROM shoelace_data new, shoelace_data old,
|
||||
shoelace_data shoelace_data
|
||||
WHERE *NEW*.sl_avail <> *OLD*.sl_avail
|
||||
WHERE new.sl_avail <> old.sl_avail
|
||||
<emphasis>AND shoelace_data.sl_name = 'sl7'</emphasis>;
|
||||
</programlisting>
|
||||
</para>
|
||||
@ -1143,9 +1142,9 @@ INSERT INTO shoelace_log VALUES (
|
||||
INSERT INTO shoelace_log VALUES (
|
||||
<emphasis>shoelace_data.sl_name</emphasis>, <emphasis>6</emphasis>,
|
||||
current_user, current_timestamp )
|
||||
FROM shoelace_data *NEW*, shoelace_data *OLD*,
|
||||
FROM shoelace_data new, shoelace_data old,
|
||||
shoelace_data shoelace_data
|
||||
WHERE <emphasis>6</emphasis> <> *OLD*.sl_avail
|
||||
WHERE <emphasis>6</emphasis> <> old.sl_avail
|
||||
AND shoelace_data.sl_name = 'sl7';
|
||||
</programlisting>
|
||||
|
||||
@ -1158,7 +1157,7 @@ INSERT INTO shoelace_log VALUES (
|
||||
INSERT INTO shoelace_log VALUES (
|
||||
shoelace_data.sl_name, 6,
|
||||
current_user, current_timestamp )
|
||||
FROM shoelace_data *NEW*, shoelace_data *OLD*,
|
||||
FROM shoelace_data new, shoelace_data old,
|
||||
shoelace_data shoelace_data
|
||||
WHERE 6 <> <emphasis>shoelace_data.sl_avail</emphasis>
|
||||
AND shoelace_data.sl_name = 'sl7';
|
||||
@ -1455,7 +1454,7 @@ SELECT shoelace_arrive.arr_name, shoelace_arrive.arr_quant
|
||||
UPDATE shoelace
|
||||
SET sl_avail = shoelace.sl_avail + shoelace_arrive.arr_quant
|
||||
FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok,
|
||||
shoelace_ok *OLD*, shoelace_ok *NEW*,
|
||||
shoelace_ok old, shoelace_ok new,
|
||||
shoelace shoelace
|
||||
WHERE shoelace.sl_name = shoelace_arrive.arr_name;
|
||||
</programlisting>
|
||||
@ -1473,9 +1472,9 @@ UPDATE shoelace_data
|
||||
sl_len = shoelace.sl_len,
|
||||
sl_unit = shoelace.sl_unit
|
||||
FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok,
|
||||
shoelace_ok *OLD*, shoelace_ok *NEW*,
|
||||
shoelace shoelace, shoelace *OLD*,
|
||||
shoelace *NEW*, shoelace_data shoelace_data
|
||||
shoelace_ok old, shoelace_ok new,
|
||||
shoelace shoelace, shoelace old,
|
||||
shoelace new, shoelace_data shoelace_data
|
||||
WHERE shoelace.sl_name = shoelace_arrive.arr_name
|
||||
AND shoelace_data.sl_name = shoelace.sl_name;
|
||||
</programlisting>
|
||||
@ -1493,10 +1492,10 @@ UPDATE shoelace_data
|
||||
sl_len = s.sl_len,
|
||||
sl_unit = s.sl_unit
|
||||
FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok,
|
||||
shoelace_ok *OLD*, shoelace_ok *NEW*,
|
||||
shoelace shoelace, shoelace *OLD*,
|
||||
shoelace *NEW*, shoelace_data shoelace_data,
|
||||
shoelace *OLD*, shoelace *NEW*,
|
||||
shoelace_ok old, shoelace_ok new,
|
||||
shoelace shoelace, shoelace old,
|
||||
shoelace new, shoelace_data shoelace_data,
|
||||
shoelace old, shoelace new,
|
||||
shoelace_data s, unit u
|
||||
WHERE s.sl_name = shoelace_arrive.arr_name
|
||||
AND shoelace_data.sl_name = s.sl_name;
|
||||
@ -1512,12 +1511,12 @@ SELECT s.sl_name,
|
||||
current_user,
|
||||
current_timestamp
|
||||
FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok,
|
||||
shoelace_ok *OLD*, shoelace_ok *NEW*,
|
||||
shoelace shoelace, shoelace *OLD*,
|
||||
shoelace *NEW*, shoelace_data shoelace_data,
|
||||
shoelace *OLD*, shoelace *NEW*,
|
||||
shoelace_ok old, shoelace_ok new,
|
||||
shoelace shoelace, shoelace old,
|
||||
shoelace new, shoelace_data shoelace_data,
|
||||
shoelace old, shoelace new,
|
||||
shoelace_data s, unit u,
|
||||
shoelace_data *OLD*, shoelace_data *NEW*
|
||||
shoelace_data old, shoelace_data new
|
||||
shoelace_log shoelace_log
|
||||
WHERE s.sl_name = shoelace_arrive.arr_name
|
||||
AND shoelace_data.sl_name = s.sl_name
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.137 2009/10/08 02:39:16 tgl Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.138 2009/11/05 23:24:22 tgl Exp $ -->
|
||||
|
||||
<chapter id="sql-syntax">
|
||||
<title>SQL Syntax</title>
|
||||
@ -1312,10 +1312,7 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
|
||||
<para>
|
||||
<replaceable>correlation</replaceable> is the name of a
|
||||
table (possibly qualified with a schema name), or an alias for a table
|
||||
defined by means of a <literal>FROM</literal> clause, or one of
|
||||
the key words <literal>NEW</literal> or <literal>OLD</literal>.
|
||||
(<literal>NEW</literal> and <literal>OLD</literal> can only appear in rewrite rules,
|
||||
while other correlation names can be used in any SQL statement.)
|
||||
defined by means of a <literal>FROM</literal> clause.
|
||||
The correlation name and separating dot can be omitted if the column name
|
||||
is unique across all the tables being used in the current query. (See also <xref linkend="queries">.)
|
||||
</para>
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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, '.');
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
|
Loading…
Reference in New Issue
Block a user