aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-12-08 18:25:48 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2012-12-08 18:26:21 -0500
commita99c42f291421572aef2b0a9360294c7d89b8bc7 (patch)
tree330ccf97fb7318f988d8218bb1a854bc84025d63 /src/backend/executor/execMain.c
parentd12d9f595e1c6bc6e62b7b423762fc03ad923899 (diff)
downloadpostgresql-a99c42f291421572aef2b0a9360294c7d89b8bc7.tar.gz
postgresql-a99c42f291421572aef2b0a9360294c7d89b8bc7.zip
Support automatically-updatable views.
This patch makes "simple" views automatically updatable, without the need to create either INSTEAD OF triggers or INSTEAD rules. "Simple" views are those classified as updatable according to SQL-92 rules. The rewriter transforms INSERT/UPDATE/DELETE commands on such views directly into an equivalent command on the underlying table, which will generally have noticeably better performance than is possible with either triggers or user-written rules. A view that has INSTEAD OF triggers or INSTEAD rules continues to operate the same as before. For the moment, security_barrier views are not considered simple. Also, we do not support WITH CHECK OPTION. These features may be added in future. Dean Rasheed, reviewed by Amit Kapila
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index dbd3755b1b5..0222d40b496 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -923,9 +923,8 @@ InitPlan(QueryDesc *queryDesc, int eflags)
/*
* Check that a proposed result relation is a legal target for the operation
*
- * In most cases parser and/or planner should have noticed this already, but
- * let's make sure. In the view case we do need a test here, because if the
- * view wasn't rewritten by a rule, it had better have an INSTEAD trigger.
+ * Generally the parser and/or planner should have noticed any such mistake
+ * already, but let's make sure.
*
* Note: when changing this function, you probably also need to look at
* CheckValidRowMarkRel.
@@ -953,6 +952,13 @@ CheckValidResultRel(Relation resultRel, CmdType operation)
RelationGetRelationName(resultRel))));
break;
case RELKIND_VIEW:
+ /*
+ * Okay only if there's a suitable INSTEAD OF trigger. Messages
+ * here should match rewriteHandler.c's rewriteTargetView, except
+ * that we omit errdetail because we haven't got the information
+ * handy (and given that we really shouldn't get here anyway,
+ * it's not worth great exertion to get).
+ */
switch (operation)
{
case CMD_INSERT:
@@ -961,7 +967,7 @@ CheckValidResultRel(Relation resultRel, CmdType operation)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot insert into view \"%s\"",
RelationGetRelationName(resultRel)),
- errhint("You need an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger.")));
+ errhint("To make the view insertable, provide an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger.")));
break;
case CMD_UPDATE:
if (!trigDesc || !trigDesc->trig_update_instead_row)
@@ -969,7 +975,7 @@ CheckValidResultRel(Relation resultRel, CmdType operation)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot update view \"%s\"",
RelationGetRelationName(resultRel)),
- errhint("You need an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger.")));
+ errhint("To make the view updatable, provide an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger.")));
break;
case CMD_DELETE:
if (!trigDesc || !trigDesc->trig_delete_instead_row)
@@ -977,7 +983,7 @@ CheckValidResultRel(Relation resultRel, CmdType operation)
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot delete from view \"%s\"",
RelationGetRelationName(resultRel)),
- errhint("You need an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger.")));
+ errhint("To make the view updatable, provide an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger.")));
break;
default:
elog(ERROR, "unrecognized CmdType: %d", (int) operation);
@@ -1028,7 +1034,7 @@ CheckValidRowMarkRel(Relation rel, RowMarkType markType)
RelationGetRelationName(rel))));
break;
case RELKIND_VIEW:
- /* Should not get here */
+ /* Should not get here; planner should have expanded the view */
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot lock rows in view \"%s\"",