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>
189189 In INSERT queries the target list describes the new rows that
190190should go into the result relation. It is the expressions in the VALUES
191191clause 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
193196planner with a constant NULL expression.
194197 </Para>
195198
196199 <Para>
197200 In UPDATE queries, the target list describes the new rows that should
198201replace the old ones. In the rule system, it contains just the
199202expressions from the SET attribute = expression part of the query.
200- The planner willadd missing columns by inserting expressions that
203+ The planner willhandle missing columns by inserting expressions that
201204copy the values from the old row into the new one. And it will add
202205the special <acronym>CTID</> entry just as for DELETE too.
203206 </Para>
278281
279282<Para>
280283 Views in <ProductName>PostgreSQL</ProductName> are implemented
281- using the rule system. In fact there isabsolutely no difference
282- between a
284+ using the rule system. In fact there isessentially no difference
285+ between
283286
284287<ProgramListing>
285288CREATE VIEW myview AS SELECT * FROM mytab;
@@ -1133,7 +1136,7 @@ int4ne(NEW.sl_avail, OLD.sl_avail)
11331136<ProgramListing>
11341137INSERT 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>
11541157INSERT 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>
11651168INSERT 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>
11831188INSERT 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 4substitutes NEW references by the target list entries from the
1193- original parse tree orwith the matching variable references
1197+ Step 4replaces NEW references by the target list entries from the
1198+ original parse tree orby the matching variable references
11941199 from the result relation.
11951200
11961201<ProgramListing>
11971202INSERT 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>
12091214INSERT 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>
12231228INSERT 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
16481641sl10 | 1000|magenta | 40|inch | 101.6
16491642</ProgramListing>
16501643
1651- For the 1000 magenta shoelaces we mustdebt Al before we can
1644+ For the 1000 magenta shoelaces we mustdebit 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