2 39.2. Views and the Rule System #
4 39.2.1. How SELECT Rules Work
5 39.2.2. View Rules in Non-SELECT Statements
6 39.2.3. The Power of Views in PostgreSQL
7 39.2.4. Updating a View
9 Views in PostgreSQL are implemented using the rule system. A view is
10 basically an empty table (having no actual storage) with an ON SELECT
11 DO INSTEAD rule. Conventionally, that rule is named _RETURN. So a view
13 CREATE VIEW myview AS SELECT * FROM mytab;
15 is very nearly the same thing as
16 CREATE TABLE myview (same column list as mytab);
17 CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD
20 although you can't actually write that, because tables are not allowed
21 to have ON SELECT rules.
23 A view can also have other kinds of DO INSTEAD rules, allowing INSERT,
24 UPDATE, or DELETE commands to be performed on the view despite its lack
25 of underlying storage. This is discussed further below, in
28 39.2.1. How SELECT Rules Work #
30 Rules ON SELECT are applied to all queries as the last step, even if
31 the command given is an INSERT, UPDATE or DELETE. And they have
32 different semantics from rules on the other command types in that they
33 modify the query tree in place instead of creating a new one. So SELECT
34 rules are described first.
36 Currently, there can be only one action in an ON SELECT rule, and it
37 must be an unconditional SELECT action that is INSTEAD. This
38 restriction was required to make rules safe enough to open them for
39 ordinary users, and it restricts ON SELECT rules to act like views.
41 The examples for this chapter are two join views that do some
42 calculations and some more views using them in turn. One of the two
43 first views is customized later by adding rules for INSERT, UPDATE, and
44 DELETE operations so that the final result will be a view that behaves
45 like a real table with some magic functionality. This is not such a
46 simple example to start from and this makes things harder to get into.
47 But it's better to have one example that covers all the points
48 discussed step by step rather than having many different ones that
51 The real tables we need in the first two rule system descriptions are
53 CREATE TABLE shoe_data (
54 shoename text, -- primary key
55 sh_avail integer, -- available number of pairs
56 slcolor text, -- preferred shoelace color
57 slminlen real, -- minimum shoelace length
58 slmaxlen real, -- maximum shoelace length
59 slunit text -- length unit
62 CREATE TABLE shoelace_data (
63 sl_name text, -- primary key
64 sl_avail integer, -- available number of pairs
65 sl_color text, -- shoelace color
66 sl_len real, -- shoelace length
67 sl_unit text -- length unit
71 un_name text, -- primary key
72 un_fact real -- factor to transform to cm
75 As you can see, they represent shoe-store data.
77 The views are created as:
83 sh.slminlen * un.un_fact AS slminlen_cm,
85 sh.slmaxlen * un.un_fact AS slmaxlen_cm,
87 FROM shoe_data sh, unit un
88 WHERE sh.slunit = un.un_name;
90 CREATE VIEW shoelace AS
96 s.sl_len * u.un_fact AS sl_len_cm
97 FROM shoelace_data s, unit u
98 WHERE s.sl_unit = u.un_name;
100 CREATE VIEW shoe_ready AS
105 least(rsh.sh_avail, rsl.sl_avail) AS total_avail
106 FROM shoe rsh, shoelace rsl
107 WHERE rsl.sl_color = rsh.slcolor
108 AND rsl.sl_len_cm >= rsh.slminlen_cm
109 AND rsl.sl_len_cm <= rsh.slmaxlen_cm;
111 The CREATE VIEW command for the shoelace view (which is the simplest
112 one we have) will create a relation shoelace and an entry in pg_rewrite
113 that tells that there is a rewrite rule that must be applied whenever
114 the relation shoelace is referenced in a query's range table. The rule
115 has no rule qualification (discussed later, with the non-SELECT rules,
116 since SELECT rules currently cannot have them) and it is INSTEAD. Note
117 that rule qualifications are not the same as query qualifications. The
118 action of our rule has a query qualification. The action of the rule is
119 one query tree that is a copy of the SELECT statement in the view
124 The two extra range table entries for NEW and OLD that you can see in
125 the pg_rewrite entry aren't of interest for SELECT rules.
127 Now we populate unit, shoe_data and shoelace_data and run a simple
129 INSERT INTO unit VALUES ('cm', 1.0);
130 INSERT INTO unit VALUES ('m', 100.0);
131 INSERT INTO unit VALUES ('inch', 2.54);
133 INSERT INTO shoe_data VALUES ('sh1', 2, 'black', 70.0, 90.0, 'cm');
134 INSERT INTO shoe_data VALUES ('sh2', 0, 'black', 30.0, 40.0, 'inch');
135 INSERT INTO shoe_data VALUES ('sh3', 4, 'brown', 50.0, 65.0, 'cm');
136 INSERT INTO shoe_data VALUES ('sh4', 3, 'brown', 40.0, 50.0, 'inch');
138 INSERT INTO shoelace_data VALUES ('sl1', 5, 'black', 80.0, 'cm');
139 INSERT INTO shoelace_data VALUES ('sl2', 6, 'black', 100.0, 'cm');
140 INSERT INTO shoelace_data VALUES ('sl3', 0, 'black', 35.0 , 'inch');
141 INSERT INTO shoelace_data VALUES ('sl4', 8, 'black', 40.0 , 'inch');
142 INSERT INTO shoelace_data VALUES ('sl5', 4, 'brown', 1.0 , 'm');
143 INSERT INTO shoelace_data VALUES ('sl6', 0, 'brown', 0.9 , 'm');
144 INSERT INTO shoelace_data VALUES ('sl7', 7, 'brown', 60 , 'cm');
145 INSERT INTO shoelace_data VALUES ('sl8', 1, 'brown', 40 , 'inch');
147 SELECT * FROM shoelace;
149 sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm
150 -----------+----------+----------+--------+---------+-----------
151 sl1 | 5 | black | 80 | cm | 80
152 sl2 | 6 | black | 100 | cm | 100
153 sl7 | 7 | brown | 60 | cm | 60
154 sl3 | 0 | black | 35 | inch | 88.9
155 sl4 | 8 | black | 40 | inch | 101.6
156 sl8 | 1 | brown | 40 | inch | 101.6
157 sl5 | 4 | brown | 1 | m | 100
158 sl6 | 0 | brown | 0.9 | m | 90
161 This is the simplest SELECT you can do on our views, so we take this
162 opportunity to explain the basics of view rules. The SELECT * FROM
163 shoelace was interpreted by the parser and produced the query tree:
164 SELECT shoelace.sl_name, shoelace.sl_avail,
165 shoelace.sl_color, shoelace.sl_len,
166 shoelace.sl_unit, shoelace.sl_len_cm
167 FROM shoelace shoelace;
169 and this is given to the rule system. The rule system walks through the
170 range table and checks if there are rules for any relation. When
171 processing the range table entry for shoelace (the only one up to now)
172 it finds the _RETURN rule with the query tree:
173 SELECT s.sl_name, s.sl_avail,
174 s.sl_color, s.sl_len, s.sl_unit,
175 s.sl_len * u.un_fact AS sl_len_cm
176 FROM shoelace old, shoelace new,
177 shoelace_data s, unit u
178 WHERE s.sl_unit = u.un_name;
180 To expand the view, the rewriter simply creates a subquery range-table
181 entry containing the rule's action query tree, and substitutes this
182 range table entry for the original one that referenced the view. The
183 resulting rewritten query tree is almost the same as if you had typed:
184 SELECT shoelace.sl_name, shoelace.sl_avail,
185 shoelace.sl_color, shoelace.sl_len,
186 shoelace.sl_unit, shoelace.sl_len_cm
187 FROM (SELECT s.sl_name,
192 s.sl_len * u.un_fact AS sl_len_cm
193 FROM shoelace_data s, unit u
194 WHERE s.sl_unit = u.un_name) shoelace;
196 There is one difference however: the subquery's range table has two
197 extra entries shoelace old and shoelace new. These entries don't
198 participate directly in the query, since they aren't referenced by the
199 subquery's join tree or target list. The rewriter uses them to store
200 the access privilege check information that was originally present in
201 the range-table entry that referenced the view. In this way, the
202 executor will still check that the user has proper privileges to access
203 the view, even though there's no direct use of the view in the
206 That was the first rule applied. The rule system will continue checking
207 the remaining range-table entries in the top query (in this example
208 there are no more), and it will recursively check the range-table
209 entries in the added subquery to see if any of them reference views.
210 (But it won't expand old or new — otherwise we'd have infinite
211 recursion!) In this example, there are no rewrite rules for
212 shoelace_data or unit, so rewriting is complete and the above is the
213 final result given to the planner.
215 Now we want to write a query that finds out for which shoes currently
216 in the store we have the matching shoelaces (color and length) and
217 where the total number of exactly matching pairs is greater than or
219 SELECT * FROM shoe_ready WHERE total_avail >= 2;
221 shoename | sh_avail | sl_name | sl_avail | total_avail
222 ----------+----------+---------+----------+-------------
223 sh1 | 2 | sl1 | 5 | 2
224 sh3 | 4 | sl7 | 7 | 4
227 The output of the parser this time is the query tree:
228 SELECT shoe_ready.shoename, shoe_ready.sh_avail,
229 shoe_ready.sl_name, shoe_ready.sl_avail,
230 shoe_ready.total_avail
231 FROM shoe_ready shoe_ready
232 WHERE shoe_ready.total_avail >= 2;
234 The first rule applied will be the one for the shoe_ready view and it
235 results in the query tree:
236 SELECT shoe_ready.shoename, shoe_ready.sh_avail,
237 shoe_ready.sl_name, shoe_ready.sl_avail,
238 shoe_ready.total_avail
239 FROM (SELECT rsh.shoename,
243 least(rsh.sh_avail, rsl.sl_avail) AS total_avail
244 FROM shoe rsh, shoelace rsl
245 WHERE rsl.sl_color = rsh.slcolor
246 AND rsl.sl_len_cm >= rsh.slminlen_cm
247 AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
248 WHERE shoe_ready.total_avail >= 2;
250 Similarly, the rules for shoe and shoelace are substituted into the
251 range table of the subquery, leading to a three-level final query tree:
252 SELECT shoe_ready.shoename, shoe_ready.sh_avail,
253 shoe_ready.sl_name, shoe_ready.sl_avail,
254 shoe_ready.total_avail
255 FROM (SELECT rsh.shoename,
259 least(rsh.sh_avail, rsl.sl_avail) AS total_avail
260 FROM (SELECT sh.shoename,
264 sh.slminlen * un.un_fact AS slminlen_cm,
266 sh.slmaxlen * un.un_fact AS slmaxlen_cm,
268 FROM shoe_data sh, unit un
269 WHERE sh.slunit = un.un_name) rsh,
275 s.sl_len * u.un_fact AS sl_len_cm
276 FROM shoelace_data s, unit u
277 WHERE s.sl_unit = u.un_name) rsl
278 WHERE rsl.sl_color = rsh.slcolor
279 AND rsl.sl_len_cm >= rsh.slminlen_cm
280 AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready
281 WHERE shoe_ready.total_avail > 2;
283 This might look inefficient, but the planner will collapse this into a
284 single-level query tree by “pulling up” the subqueries, and then it
285 will plan the joins just as if we'd written them out manually. So
286 collapsing the query tree is an optimization that the rewrite system
287 doesn't have to concern itself with.
289 39.2.2. View Rules in Non-SELECT Statements #
291 Two details of the query tree aren't touched in the description of view
292 rules above. These are the command type and the result relation. In
293 fact, the command type is not needed by view rules, but the result
294 relation may affect the way in which the query rewriter works, because
295 special care needs to be taken if the result relation is a view.
297 There are only a few differences between a query tree for a SELECT and
298 one for any other command. Obviously, they have a different command
299 type and for a command other than a SELECT, the result relation points
300 to the range-table entry where the result should go. Everything else is
301 absolutely the same. So having two tables t1 and t2 with columns a and
302 b, the query trees for the two statements:
303 SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
305 UPDATE t1 SET b = t2.b FROM t2 WHERE t1.a = t2.a;
307 are nearly identical. In particular:
308 * The range tables contain entries for the tables t1 and t2.
309 * The target lists contain one variable that points to column b of
310 the range table entry for table t2.
311 * The qualification expressions compare the columns a of both
312 range-table entries for equality.
313 * The join trees show a simple join between t1 and t2.
315 The consequence is, that both query trees result in similar execution
316 plans: They are both joins over the two tables. For the UPDATE the
317 missing columns from t1 are added to the target list by the planner and
318 the final query tree will read as:
319 UPDATE t1 SET a = t1.a, b = t2.b FROM t2 WHERE t1.a = t2.a;
321 and thus the executor run over the join will produce exactly the same
323 SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
325 But there is a little problem in UPDATE: the part of the executor plan
326 that does the join does not care what the results from the join are
327 meant for. It just produces a result set of rows. The fact that one is
328 a SELECT command and the other is an UPDATE is handled higher up in the
329 executor, where it knows that this is an UPDATE, and it knows that this
330 result should go into table t1. But which of the rows that are there
331 has to be replaced by the new row?
333 To resolve this problem, another entry is added to the target list in
334 UPDATE (and also in DELETE) statements: the current tuple ID (CTID).
335 This is a system column containing the file block number and position
336 in the block for the row. Knowing the table, the CTID can be used to
337 retrieve the original row of t1 to be updated. After adding the CTID to
338 the target list, the query actually looks like:
339 SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
341 Now another detail of PostgreSQL enters the stage. Old table rows
342 aren't overwritten, and this is why ROLLBACK is fast. In an UPDATE, the
343 new result row is inserted into the table (after stripping the CTID)
344 and in the row header of the old row, which the CTID pointed to, the
345 cmax and xmax entries are set to the current command counter and
346 current transaction ID. Thus the old row is hidden, and after the
347 transaction commits the vacuum cleaner can eventually remove the dead
350 Knowing all that, we can simply apply view rules in absolutely the same
351 way to any command. There is no difference.
353 39.2.3. The Power of Views in PostgreSQL #
355 The above demonstrates how the rule system incorporates view
356 definitions into the original query tree. In the second example, a
357 simple SELECT from one view created a final query tree that is a join
358 of 4 tables (unit was used twice with different names).
360 The benefit of implementing views with the rule system is that the
361 planner has all the information about which tables have to be scanned
362 plus the relationships between these tables plus the restrictive
363 qualifications from the views plus the qualifications from the original
364 query in one single query tree. And this is still the situation when
365 the original query is already a join over views. The planner has to
366 decide which is the best path to execute the query, and the more
367 information the planner has, the better this decision can be. And the
368 rule system as implemented in PostgreSQL ensures that this is all
369 information available about the query up to that point.
371 39.2.4. Updating a View #
373 What happens if a view is named as the target relation for an INSERT,
374 UPDATE, DELETE, or MERGE? Doing the substitutions described above would
375 give a query tree in which the result relation points at a subquery
376 range-table entry, which will not work. There are several ways in which
377 PostgreSQL can support the appearance of updating a view, however. In
378 order of user-experienced complexity those are: automatically
379 substitute in the underlying table for the view, execute a user-defined
380 trigger, or rewrite the query per a user-defined rule. These options
383 If the subquery selects from a single base relation and is simple
384 enough, the rewriter can automatically replace the subquery with the
385 underlying base relation so that the INSERT, UPDATE, DELETE, or MERGE
386 is applied to the base relation in the appropriate way. Views that are
387 “simple enough” for this are called automatically updatable. For
388 detailed information on the kinds of view that can be automatically
389 updated, see CREATE VIEW.
391 Alternatively, the operation may be handled by a user-provided INSTEAD
392 OF trigger on the view (see CREATE TRIGGER). Rewriting works slightly
393 differently in this case. For INSERT, the rewriter does nothing at all
394 with the view, leaving it as the result relation for the query. For
395 UPDATE, DELETE, and MERGE, it's still necessary to expand the view
396 query to produce the “old” rows that the command will attempt to
397 update, delete, or merge. So the view is expanded as normal, but
398 another unexpanded range-table entry is added to the query to represent
399 the view in its capacity as the result relation.
401 The problem that now arises is how to identify the rows to be updated
402 in the view. Recall that when the result relation is a table, a special
403 CTID entry is added to the target list to identify the physical
404 locations of the rows to be updated. This does not work if the result
405 relation is a view, because a view does not have any CTID, since its
406 rows do not have actual physical locations. Instead, for an UPDATE,
407 DELETE, or MERGE operation, a special wholerow entry is added to the
408 target list, which expands to include all columns from the view. The
409 executor uses this value to supply the “old” row to the INSTEAD OF
410 trigger. It is up to the trigger to work out what to update based on
411 the old and new row values.
413 Another possibility is for the user to define INSTEAD rules that
414 specify substitute actions for INSERT, UPDATE, and DELETE commands on a
415 view. These rules will rewrite the command, typically into a command
416 that updates one or more tables, rather than views. That is the topic
417 of Section 39.4. Note that this will not work with MERGE, which
418 currently does not support rules on the target relation other than
421 Note that rules are evaluated first, rewriting the original query
422 before it is planned and executed. Therefore, if a view has INSTEAD OF
423 triggers as well as rules on INSERT, UPDATE, or DELETE, then the rules
424 will be evaluated first, and depending on the result, the triggers may
427 Automatic rewriting of an INSERT, UPDATE, DELETE, or MERGE query on a
428 simple view is always tried last. Therefore, if a view has rules or
429 triggers, they will override the default behavior of automatically
432 If there are no INSTEAD rules or INSTEAD OF triggers for the view, and
433 the rewriter cannot automatically rewrite the query as an update on the
434 underlying base relation, an error will be thrown because the executor
435 cannot update a view as such.