Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcb052e0

Browse files
committed
Fix rule rewriter so that new ordering of ON INSERT actions applies
in cases of qualified rules as well as unqualified ones. Tweak rulestest to avoid cluttering output with dummy SELECT results. Updatedocumentation to match code.
1 parent4fe42df commitcb052e0

File tree

5 files changed

+56
-29
lines changed

5 files changed

+56
-29
lines changed

‎doc/src/sgml/ref/create_rule.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_rule.sgml,v 1.23 2001/05/27 09:59:27 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_rule.sgml,v 1.24 2001/07/09 23:50:31 tgl Exp $
33
Postgres documentation
44
-->
55

@@ -167,7 +167,8 @@ CREATE
167167
<replaceable class="parameter">action</replaceable> part of the rule is
168168
executed. The <replaceable class="parameter">action</replaceable> is
169169
done instead of the original query if INSTEAD is specified; otherwise
170-
it is done before the original query is performed.
170+
it is done after the original query in the case of ON INSERT, or before
171+
the original query in the case of ON UPDATE or ON DELETE.
171172
Within both the <replaceable class="parameter">condition</replaceable>
172173
and <replaceable class="parameter">action</replaceable>, values from
173174
fields in the old instance and/or the new instance are substituted for

‎doc/src/sgml/rules.sgml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.14 2001/07/09 23:50:32 tgl Exp $ -->
2+
13
<Chapter Id="rules">
24
<Title>The <ProductName>Postgres</ProductName> Rule System</Title>
35

@@ -1014,6 +1016,16 @@
10141016
for a rule with one action.
10151017
</Para>
10161018

1019+
<Para>
1020+
For ON INSERT rules, the original query (if not suppressed by INSTEAD)
1021+
is done before any actions added by rules. This allows the actions to
1022+
see the inserted row(s). But for ON UPDATE and ON
1023+
DELETE rules, the original query is done after the actions added by rules.
1024+
This ensures that the actions can see the to-be-updated or to-be-deleted
1025+
rows; otherwise, the actions might do nothing because they find no rows
1026+
matching their qualifications.
1027+
</Para>
1028+
10171029
<Para>
10181030
The parsetrees generated from rule actions are thrown into the
10191031
rewrite system again and maybe more rules get applied resulting
@@ -1022,8 +1034,8 @@
10221034
or another resultrelation. Otherwise this recursive process will end up in a loop.
10231035
There is a compiled in recursion limit of currently 10 iterations.
10241036
If after 10 iterations there are still update rules to apply the
1025-
rule system assumes a loop over multiple rule definitions andaborts the
1026-
transaction.
1037+
rule system assumes a loop over multiple rule definitions andreports
1038+
an error.
10271039
</Para>
10281040

10291041
<Para>
@@ -1262,10 +1274,8 @@
12621274
</Para>
12631275

12641276
<Para>
1265-
It is important, that the original parsetree is executed last.
1266-
The <ProductName>Postgres</ProductName> "traffic cop" does
1267-
a command counter increment between the execution of the two
1268-
parsetrees so the second one can see changes made by the first.
1277+
Here we can see why it is important that the original parsetree is
1278+
executed last.
12691279
If the UPDATE would have been executed first, all the rows
12701280
are already set to zero, so the logging INSERT
12711281
would not find any row where 0 != shoelace_data.sl_avail.

‎src/backend/rewrite/rewriteHandler.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.96 2001/07/06 13:40:47 wieck Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.97 2001/07/09 23:50:32 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -831,7 +831,7 @@ deepRewriteQuery(Query *parsetree)
831831
numQueryRewriteInvoked-1);
832832
}
833833

834-
instead=FALSE;
834+
instead=false;
835835
result=RewriteQuery(parsetree,&instead,&qual_products);
836836

837837
foreach(n,result)
@@ -845,25 +845,41 @@ deepRewriteQuery(Query *parsetree)
845845
}
846846

847847
/*
848-
* qual_products are the original query with the negated rule
849-
* qualification of an instead rule
848+
* For INSERTs, the original query is done first; for UPDATE/DELETE, it is
849+
* done last. This is needed because update and delete rule actions might
850+
* not do anything if they are invoked after the update or delete is
851+
* performed. The command counter increment between the query execution
852+
* makes the deleted (and maybe the updated) tuples disappear so the scans
853+
* for them in the rule actions cannot find them.
850854
*/
851-
if (qual_products!=NIL)
852-
rewritten=nconc(rewritten,qual_products);
853-
854-
/*
855-
* The original query is appended last (if no "instead" rule) because
856-
* update and delete rule actions might not do anything if they are
857-
* invoked after the update or delete is performed. The command
858-
* counter increment between the query execution makes the deleted
859-
* (and maybe the updated) tuples disappear so the scans for them in
860-
* the rule actions cannot find them.
861-
*/
862-
if (!instead)
863-
if (parsetree->commandType==CMD_INSERT)
855+
if (parsetree->commandType==CMD_INSERT)
856+
{
857+
/*
858+
* qual_products are the original query with the negated rule
859+
* qualification of an INSTEAD rule
860+
*/
861+
if (qual_products!=NIL)
862+
rewritten=nconc(qual_products,rewritten);
863+
/*
864+
* Add the unmodified original query, if no INSTEAD rule was seen.
865+
*/
866+
if (!instead)
864867
rewritten=lcons(parsetree,rewritten);
865-
else
868+
}
869+
else
870+
{
871+
/*
872+
* qual_products are the original query with the negated rule
873+
* qualification of an INSTEAD rule
874+
*/
875+
if (qual_products!=NIL)
876+
rewritten=nconc(rewritten,qual_products);
877+
/*
878+
* Add the unmodified original query, if no INSTEAD rule was seen.
879+
*/
880+
if (!instead)
866881
rewritten=lappend(rewritten,parsetree);
882+
}
867883

868884
returnrewritten;
869885
}

‎src/test/regress/expected/rules.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ create table rtest_nothn2 (a int4, b text);
107107
create table rtest_nothn3 (a int4, b text);
108108
create table rtest_nothn4 (a int4, b text);
109109
create rule rtest_nothn_r1 as on insert to rtest_nothn1
110-
where new.a >= 10 and new.a < 20 do instead(select 1);
110+
where new.a >= 10 and new.a < 20 do insteadnothing;
111111
create rule rtest_nothn_r2 as on insert to rtest_nothn1
112112
where new.a >= 30 and new.a < 40 do instead nothing;
113113
create rule rtest_nothn_r3 as on insert to rtest_nothn2
@@ -1313,7 +1313,7 @@ SELECT tablename, rulename, definition FROM pg_rules
13131313
rtest_emp | rtest_emp_del | CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (old.ename, "current_user"(), 'fired '::bpchar, '$0.00'::money, old.salary);
13141314
rtest_emp | rtest_emp_ins | CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'hired '::bpchar, new.salary, '$0.00'::money);
13151315
rtest_emp | rtest_emp_upd | CREATE RULE rtest_emp_upd AS ON UPDATE TO rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'honored '::bpchar, new.salary, old.salary);
1316-
rtest_nothn1 | rtest_nothn_r1 | CREATE RULE rtest_nothn_r1 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 10) AND (new.a < 20)) DO INSTEADSELECT 1;
1316+
rtest_nothn1 | rtest_nothn_r1 | CREATE RULE rtest_nothn_r1 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 10) AND (new.a < 20)) DO INSTEADNOTHING;
13171317
rtest_nothn1 | rtest_nothn_r2 | CREATE RULE rtest_nothn_r2 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 30) AND (new.a < 40)) DO INSTEAD NOTHING;
13181318
rtest_nothn2 | rtest_nothn_r3 | CREATE RULE rtest_nothn_r3 AS ON INSERT TO rtest_nothn2 WHERE (new.a >= 100) DO INSTEAD INSERT INTO rtest_nothn3 (a, b) VALUES (new.a, new.b);
13191319
rtest_nothn2 | rtest_nothn_r4 | CREATE RULE rtest_nothn_r4 AS ON INSERT TO rtest_nothn2 DO INSTEAD NOTHING;

‎src/test/regress/sql/rules.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ create table rtest_nothn3 (a int4, b text);
131131
createtablertest_nothn4 (a int4, btext);
132132

133133
createrulertest_nothn_r1ason insert to rtest_nothn1
134-
wherenew.a>=10andnew.a<20 do instead(select1);
134+
wherenew.a>=10andnew.a<20 do insteadnothing;
135135

136136
createrulertest_nothn_r2ason insert to rtest_nothn1
137137
wherenew.a>=30andnew.a<40 do instead nothing;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp