Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d508b05

Browse files
committed
Adjust handling of command status strings in the presence of rules,
as per recent pghackers discussions. initdb forced due to change in fields of stored Query nodes.
1 parent ea3728e commit d508b05

File tree

10 files changed

+184
-62
lines changed

10 files changed

+184
-62
lines changed

doc/src/sgml/rules.sgml

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.24 2002/09/21 18:32:53 petere Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.25 2002/10/14 22:14:34 tgl Exp $ -->
22

33
<Chapter Id="rules">
44
<Title>The Rule System</Title>
@@ -189,15 +189,18 @@
189189
In INSERT queries the target list describes the new rows that
190190
should go into the result relation. It is the expressions in the VALUES
191191
clause or the ones from the SELECT clause in INSERT ... SELECT.
192-
Missing columns of the result relation will be filled in by the
192+
The first step of the rewrite process adds target list entries
193+
for any columns that were not assigned to by the original query
194+
and have defaults. Any remaining columns (with neither a given
195+
value nor a default) will be filled in by the
193196
planner with a constant NULL expression.
194197
</Para>
195198

196199
<Para>
197200
In UPDATE queries, the target list describes the new rows that should
198201
replace the old ones. In the rule system, it contains just the
199202
expressions from the SET attribute = expression part of the query.
200-
The planner will add missing columns by inserting expressions that
203+
The planner will handle missing columns by inserting expressions that
201204
copy the values from the old row into the new one. And it will add
202205
the special <acronym>CTID</> entry just as for DELETE too.
203206
</Para>
@@ -278,8 +281,8 @@
278281

279282
<Para>
280283
Views in <ProductName>PostgreSQL</ProductName> are implemented
281-
using the rule system. In fact there is absolutely no difference
282-
between a
284+
using the rule system. In fact there is essentially no difference
285+
between
283286

284287
<ProgramListing>
285288
CREATE VIEW myview AS SELECT * FROM mytab;
@@ -1133,7 +1136,7 @@ int4ne(NEW.sl_avail, OLD.sl_avail)
11331136
<ProgramListing>
11341137
INSERT INTO shoelace_log VALUES(
11351138
*NEW*.sl_name, *NEW*.sl_avail,
1136-
current_user, current_timestamp
1139+
current_user, current_timestamp)
11371140
FROM shoelace_data *NEW*, shoelace_data *OLD*;
11381141
</ProgramListing>
11391142

@@ -1153,7 +1156,7 @@ INSERT INTO shoelace_log VALUES(
11531156
<ProgramListing>
11541157
INSERT INTO shoelace_log VALUES(
11551158
*NEW*.sl_name, *NEW*.sl_avail,
1156-
current_user, current_timestamp
1159+
current_user, current_timestamp)
11571160
FROM shoelace_data *NEW*, shoelace_data *OLD*,
11581161
<emphasis>shoelace_data shoelace_data</emphasis>;
11591162
</ProgramListing>
@@ -1164,7 +1167,7 @@ INSERT INTO shoelace_log VALUES(
11641167
<ProgramListing>
11651168
INSERT INTO shoelace_log VALUES(
11661169
*NEW*.sl_name, *NEW*.sl_avail,
1167-
current_user, current_timestamp
1170+
current_user, current_timestamp)
11681171
FROM shoelace_data *NEW*, shoelace_data *OLD*,
11691172
shoelace_data shoelace_data
11701173
<emphasis>WHERE int4ne(*NEW*.sl_avail, *OLD*.sl_avail)</emphasis>;
@@ -1174,29 +1177,31 @@ INSERT INTO shoelace_log VALUES(
11741177
a WHERE clause either, but the planner and executor will have no
11751178
difficulty with it. They need to support this same functionality
11761179
anyway for INSERT ... SELECT.
1180+
</para>
11771181

1182+
<para>
11781183
In step 3 the original parse tree's qualification is added,
11791184
restricting the result set further to only the rows touched
11801185
by the original parse tree.
11811186

11821187
<ProgramListing>
11831188
INSERT INTO shoelace_log VALUES(
11841189
*NEW*.sl_name, *NEW*.sl_avail,
1185-
current_user, current_timestamp
1190+
current_user, current_timestamp)
11861191
FROM shoelace_data *NEW*, shoelace_data *OLD*,
11871192
shoelace_data shoelace_data
11881193
WHERE int4ne(*NEW*.sl_avail, *OLD*.sl_avail)
11891194
<emphasis>AND bpchareq(shoelace_data.sl_name, 'sl7')</emphasis>;
11901195
</ProgramListing>
11911196

1192-
Step 4 substitutes NEW references by the target list entries from the
1193-
original parse tree or with the matching variable references
1197+
Step 4 replaces NEW references by the target list entries from the
1198+
original parse tree or by the matching variable references
11941199
from the result relation.
11951200

11961201
<ProgramListing>
11971202
INSERT INTO shoelace_log VALUES(
11981203
<emphasis>shoelace_data.sl_name</emphasis>, <emphasis>6</emphasis>,
1199-
current_user, current_timestamp
1204+
current_user, current_timestamp)
12001205
FROM shoelace_data *NEW*, shoelace_data *OLD*,
12011206
shoelace_data shoelace_data
12021207
WHERE int4ne(<emphasis>6</emphasis>, *OLD*.sl_avail)
@@ -1208,7 +1213,7 @@ INSERT INTO shoelace_log VALUES(
12081213
<ProgramListing>
12091214
INSERT INTO shoelace_log VALUES(
12101215
shoelace_data.sl_name, 6,
1211-
current_user, current_timestamp
1216+
current_user, current_timestamp)
12121217
FROM shoelace_data *NEW*, shoelace_data *OLD*,
12131218
shoelace_data shoelace_data
12141219
WHERE int4ne(6, <emphasis>shoelace_data.sl_avail</emphasis>)
@@ -1222,7 +1227,7 @@ INSERT INTO shoelace_log VALUES(
12221227
<ProgramListing>
12231228
INSERT INTO shoelace_log VALUES(
12241229
shoelace_data.sl_name, 6,
1225-
current_user, current_timestamp
1230+
current_user, current_timestamp)
12261231
FROM shoelace_data
12271232
WHERE 6 != shoelace_data.sl_avail
12281233
AND shoelace_data.sl_name = 'sl7';
@@ -1317,18 +1322,6 @@ CREATE RULE shoe_del_protect AS ON DELETE TO shoe
13171322
parse trees will be empty and the whole query will become
13181323
nothing because there is nothing left to be optimized or
13191324
executed after the rule system is done with it.
1320-
1321-
<Note>
1322-
<Title>Note</Title>
1323-
<Para>
1324-
This way might irritate frontend applications because
1325-
absolutely nothing happened on the database and thus, the
1326-
backend will not return anything for the query. Not
1327-
even a <symbol>PGRES_EMPTY_QUERY</symbol> will be available in <application>libpq</>.
1328-
In <application>psql</application>, nothing happens. This might change in the future.
1329-
</Para>
1330-
</Note>
1331-
13321325
</Para>
13331326

13341327
<Para>
@@ -1516,7 +1509,7 @@ UPDATE shoelace_data SET
15161509

15171510
Again an update rule has been applied and so the wheel
15181511
turns on and we are in rewrite round 3. This time rule
1519-
<literal>log_shoelace</literal> gets applied what produces the extra
1512+
<literal>log_shoelace</literal> gets applied, producing the extra
15201513
parse tree
15211514

15221515
<ProgramListing>
@@ -1648,7 +1641,7 @@ sl9 | 0|pink | 35|inch | 88.9
16481641
sl10 | 1000|magenta | 40|inch | 101.6
16491642
</ProgramListing>
16501643

1651-
For the 1000 magenta shoelaces we must debt Al before we can
1644+
For the 1000 magenta shoelaces we must debit Al before we can
16521645
throw 'em away, but that's another problem. The pink entry we delete.
16531646
To make it a little harder for <ProductName>PostgreSQL</ProductName>,
16541647
we don't delete it directly. Instead we create one more view
@@ -1799,6 +1792,56 @@ GRANT SELECT ON phone_number TO secretary;
17991792
</Para>
18001793
</Sect1>
18011794

1795+
<Sect1 id="rules-status">
1796+
<Title>Rules and Command Status</Title>
1797+
1798+
<Para>
1799+
The <ProductName>PostgreSQL</ProductName> server returns a command
1800+
status string, such as <literal>INSERT 149592 1</>, for each
1801+
query it receives. This is simple enough when there are no rules
1802+
involved, but what happens when the query is rewritten by rules?
1803+
</Para>
1804+
1805+
<Para>
1806+
As of <ProductName>PostgreSQL</ProductName> 7.3, rules affect the
1807+
command status as follows:
1808+
1809+
<orderedlist>
1810+
<listitem>
1811+
<para>
1812+
If there is no unconditional INSTEAD rule for the query, then
1813+
the originally given query will be executed, and its command
1814+
status will be returned as usual. (But note that if there were
1815+
any conditional INSTEAD rules, the negation of their qualifications
1816+
will have been added to the original query. This may reduce the
1817+
number of rows it processes, and if so the reported status will
1818+
be affected.)
1819+
</para>
1820+
</listitem>
1821+
1822+
<listitem>
1823+
<para>
1824+
If there is any unconditional INSTEAD rule for the query, then
1825+
the original query will not be executed at all. In this case,
1826+
the server will return the command status for the last query that
1827+
was inserted by an INSTEAD rule (conditional or unconditional)
1828+
and is of the same type (INSERT, UPDATE, or DELETE) as the original
1829+
query. If no query meeting those requirements is added by any
1830+
rule, then the returned command status shows the original query
1831+
type and zeroes for the tuple-count and OID fields.
1832+
</para>
1833+
</listitem>
1834+
</orderedlist>
1835+
</Para>
1836+
1837+
<Para>
1838+
The programmer can ensure that any desired INSTEAD rule is the one
1839+
that sets the command status in the second case, by giving it the
1840+
alphabetically last rule name among the active rules, so that it
1841+
fires last.
1842+
</Para>
1843+
</Sect1>
1844+
18021845
<Sect1 id="rules-triggers">
18031846
<Title>Rules versus Triggers</Title>
18041847

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.213 2002/09/22 19:42:51 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.214 2002/10/14 22:14:34 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1778,14 +1778,14 @@ _copyQuery(Query *from)
17781778
Query *newnode = makeNode(Query);
17791779

17801780
newnode->commandType = from->commandType;
1781+
newnode->querySource = from->querySource;
17811782
Node_Copy(from, newnode, utilityStmt);
17821783
newnode->resultRelation = from->resultRelation;
17831784
Node_Copy(from, newnode, into);
17841785
newnode->isPortal = from->isPortal;
17851786
newnode->isBinary = from->isBinary;
17861787
newnode->hasAggs = from->hasAggs;
17871788
newnode->hasSubLinks = from->hasSubLinks;
1788-
newnode->originalQuery = from->originalQuery;
17891789

17901790
Node_Copy(from, newnode, rtable);
17911791
Node_Copy(from, newnode, jointree);

src/backend/nodes/equalfuncs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
2222
* IDENTIFICATION
23-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.160 2002/09/22 19:42:51 tgl Exp $
23+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.161 2002/10/14 22:14:34 tgl Exp $
2424
*
2525
*-------------------------------------------------------------------------
2626
*/
@@ -573,6 +573,8 @@ _equalQuery(Query *a, Query *b)
573573
{
574574
if (a->commandType != b->commandType)
575575
return false;
576+
if (a->querySource != b->querySource)
577+
return false;
576578
if (!equal(a->utilityStmt, b->utilityStmt))
577579
return false;
578580
if (a->resultRelation != b->resultRelation)
@@ -587,7 +589,6 @@ _equalQuery(Query *a, Query *b)
587589
return false;
588590
if (a->hasSubLinks != b->hasSubLinks)
589591
return false;
590-
/* we deliberately ignore originalQuery */
591592
if (!equal(a->rtable, b->rtable))
592593
return false;
593594
if (!equal(a->jointree, b->jointree))

src/backend/nodes/outfuncs.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
66
* Portions Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.175 2002/09/22 19:42:51 tgl Exp $
8+
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.176 2002/10/14 22:14:34 tgl Exp $
99
*
1010
* NOTES
1111
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -229,7 +229,8 @@ _outIndexElem(StringInfo str, IndexElem *node)
229229
static void
230230
_outQuery(StringInfo str, Query *node)
231231
{
232-
appendStringInfo(str, " QUERY :command %d :utility ", node->commandType);
232+
appendStringInfo(str, " QUERY :command %d :source %d :utility ",
233+
(int) node->commandType, (int) node->querySource);
233234

234235
/*
235236
* Hack to work around missing outfuncs routines for a lot of the
@@ -299,6 +300,8 @@ _outQuery(StringInfo str, Query *node)
299300

300301
appendStringInfo(str, " :resultRelations ");
301302
_outIntList(str, node->resultRelations);
303+
304+
/* planner-internal fields are not written out */
302305
}
303306

304307
static void

src/backend/nodes/readfuncs.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.134 2002/09/22 19:42:51 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.135 2002/10/14 22:14:34 tgl Exp $
1212
*
1313
* NOTES
1414
* Most of the read functions for plan nodes are tested. (In fact, they
@@ -123,6 +123,10 @@ _readQuery(void)
123123
token = pg_strtok(&length); /* get commandType */
124124
local_node->commandType = atoi(token);
125125

126+
token = pg_strtok(&length); /* skip :source */
127+
token = pg_strtok(&length); /* get querySource */
128+
local_node->querySource = atoi(token);
129+
126130
token = pg_strtok(&length); /* skip :utility */
127131
local_node->utilityStmt = nodeRead(true);
128132

@@ -149,9 +153,6 @@ _readQuery(void)
149153
token = pg_strtok(&length); /* get hasSubLinks */
150154
local_node->hasSubLinks = strtobool(token);
151155

152-
/* we always want originalQuery to be false in a read-in query */
153-
local_node->originalQuery = false;
154-
155156
token = pg_strtok(&length); /* skip :rtable */
156157
local_node->rtable = nodeRead(true);
157158

@@ -188,6 +189,8 @@ _readQuery(void)
188189
token = pg_strtok(&length); /* skip :resultRelations */
189190
local_node->resultRelations = toIntList(nodeRead(true));
190191

192+
/* planner-internal fields are left zero */
193+
191194
return local_node;
192195
}
193196

src/backend/parser/analyze.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.250 2002/09/22 00:37:09 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.251 2002/10/14 22:14:35 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -164,13 +164,13 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
164164
/*
165165
* Make sure that only the original query is marked original. We have
166166
* to do this explicitly since recursive calls of parse_analyze will
167-
* have set originalQuery in some of the added-on queries.
167+
* have marked some of the added-on queries as "original".
168168
*/
169169
foreach(listscan, result)
170170
{
171171
Query *q = lfirst(listscan);
172172

173-
q->originalQuery = (q == query);
173+
q->querySource = (q == query ? QSRC_ORIGINAL : QSRC_PARSER);
174174
}
175175

176176
pfree(pstate);

0 commit comments

Comments
 (0)