| The PostgreSQL 9.0 Reference Manual - Volume 2 - Programming Guide
by The PostgreSQL Global Development Group Paperback (6"x9"), 478 pages ISBN 9781906966065 RRP £14.95 ($19.95) Sales of this book support the PostgreSQL project! Get a printed copy>>> |
7.2.2 View Rules in Non-SELECT Statements
Two details of the query tree aren't touched in the description of view rules above. These are the command type and the result relation. In fact, view rules don't need this information.
There are only a few differences between a query tree for a
SELECT and one for any other
command. Obviously, they have a different command type and for a
command other than a SELECT, the result
relation points to the range-table entry where the result should
go. Everything else is absolutely the same. So having two tables
t1 and t2 with columns a and
b, the query trees for the two statements:
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a; UPDATE t1 SET b = t2.b FROM t2 WHERE t1.a = t2.a;
are nearly identical. In particular:
-
The range tables contain entries for the tables
t1andt2. -
The target lists contain one variable that points to column
bof the range table entry for tablet2. -
The qualification expressions compare the columns
aof both range-table entries for equality. -
The join trees show a simple join between
t1andt2.
The consequence is, that both query trees result in similar
execution plans: They are both joins over the two tables. For the
UPDATE the missing columns from t1 are added to
the target list by the planner and the final query tree will read
as:
UPDATE t1 SET a = t1.a, b = t2.b FROM t2 WHERE t1.a = t2.a;
and thus the executor run over the join will produce exactly the same result set as a:
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
will do. But there is a little problem in
UPDATE: The executor does not care what the
results from the join it is doing are meant for. It just produces
a result set of rows. The difference that one is a
SELECT command and the other is an
UPDATE is handled in the caller of the
executor. The caller still knows (looking at the query tree) that
this is an UPDATE, and it knows that this
result should go into table t1. But which of the rows that are
there has to be replaced by the new row?
To resolve this problem, another entry is added to the target list
in UPDATE (and also in
DELETE) statements: the current tuple ID
(CTID).
This is a system column containing the
file block number and position in the block for the row. Knowing
the table, the CTID can be used to retrieve the
original row of t1 to be updated. After adding the
CTID to the target list, the query actually looks like:
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
Now another detail of PostgreSQL enters
the stage. Old table rows aren't overwritten, and this
is why ROLLBACK is fast. In an UPDATE,
the new result row is inserted into the table (after stripping the
CTID) and in the row header of the old row, which the
CTID pointed to, the cmax and
xmax entries are set to the current command counter
and current transaction ID. Thus the old row is hidden, and after
the transaction commits the vacuum cleaner can really remove it.
Knowing all that, we can simply apply view rules in absolutely the same way to any command. There is no difference.
| ISBN 9781906966065 | The PostgreSQL 9.0 Reference Manual - Volume 2 - Programming Guide | See the print edition |