summaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
authorStephen Frost2013-07-18 21:10:16 +0000
committerStephen Frost2013-07-18 21:10:16 +0000
commit4cbe3ac3e86790d05c569de4585e5075a62a9b41 (patch)
tree8adc929520d4103b4493c0c23bcb7d2b2c2a5a4d /src/backend/optimizer
parent6f9e39bc9993c18686f0950f9b9657c7c97c7450 (diff)
WITH CHECK OPTION support for auto-updatable VIEWs
For simple views which are automatically updatable, this patch allows the user to specify what level of checking should be done on records being inserted or updated. For 'LOCAL CHECK', new tuples are validated against the conditionals of the view they are being inserted into, while for 'CASCADED CHECK' the new tuples are validated against the conditionals for all views involved (from the top down). This option is part of the SQL specification. Dean Rasheed, reviewed by Pavel Stehule
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c15
-rw-r--r--src/backend/optimizer/plan/planner.c30
2 files changed, 37 insertions, 8 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 2560e9cbc1e..7fed5e97945 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -4702,16 +4702,16 @@ make_result(PlannerInfo *root,
* Build a ModifyTable plan node
*
* Currently, we don't charge anything extra for the actual table modification
- * work, nor for the RETURNING expressions if any. It would only be window
- * dressing, since these are always top-level nodes and there is no way for
- * the costs to change any higher-level planning choices. But we might want
- * to make it look better sometime.
+ * work, nor for the WITH CHECK OPTIONS or RETURNING expressions if any. It
+ * would only be window dressing, since these are always top-level nodes and
+ * there is no way for the costs to change any higher-level planning choices.
+ * But we might want to make it look better sometime.
*/
ModifyTable *
make_modifytable(PlannerInfo *root,
CmdType operation, bool canSetTag,
- List *resultRelations,
- List *subplans, List *returningLists,
+ List *resultRelations, List *subplans,
+ List *withCheckOptionLists, List *returningLists,
List *rowMarks, int epqParam)
{
ModifyTable *node = makeNode(ModifyTable);
@@ -4723,6 +4723,8 @@ make_modifytable(PlannerInfo *root,
int i;
Assert(list_length(resultRelations) == list_length(subplans));
+ Assert(withCheckOptionLists == NIL ||
+ list_length(resultRelations) == list_length(withCheckOptionLists));
Assert(returningLists == NIL ||
list_length(resultRelations) == list_length(returningLists));
@@ -4759,6 +4761,7 @@ make_modifytable(PlannerInfo *root,
node->resultRelations = resultRelations;
node->resultRelIndex = -1; /* will be set correctly in setrefs.c */
node->plans = subplans;
+ node->withCheckOptionLists = withCheckOptionLists;
node->returningLists = returningLists;
node->rowMarks = rowMarks;
node->epqParam = epqParam;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index d80c26420fa..01e2fa32a3c 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -294,6 +294,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
int num_old_subplans = list_length(glob->subplans);
PlannerInfo *root;
Plan *plan;
+ List *newWithCheckOptions;
List *newHaving;
bool hasOuterJoins;
ListCell *l;
@@ -421,6 +422,18 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
preprocess_expression(root, (Node *) parse->targetList,
EXPRKIND_TARGET);
+ newWithCheckOptions = NIL;
+ foreach(l, parse->withCheckOptions)
+ {
+ WithCheckOption *wco = (WithCheckOption *) lfirst(l);
+
+ wco->qual = preprocess_expression(root, wco->qual,
+ EXPRKIND_QUAL);
+ if (wco->qual != NULL)
+ newWithCheckOptions = lappend(newWithCheckOptions, wco);
+ }
+ parse->withCheckOptions = newWithCheckOptions;
+
parse->returningList = (List *)
preprocess_expression(root, (Node *) parse->returningList,
EXPRKIND_TARGET);
@@ -559,12 +572,19 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
/* If it's not SELECT, we need a ModifyTable node */
if (parse->commandType != CMD_SELECT)
{
+ List *withCheckOptionLists;
List *returningLists;
List *rowMarks;
/*
- * Set up the RETURNING list-of-lists, if needed.
+ * Set up the WITH CHECK OPTION and RETURNING lists-of-lists, if
+ * needed.
*/
+ if (parse->withCheckOptions)
+ withCheckOptionLists = list_make1(parse->withCheckOptions);
+ else
+ withCheckOptionLists = NIL;
+
if (parse->returningList)
returningLists = list_make1(parse->returningList);
else
@@ -585,6 +605,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
parse->canSetTag,
list_make1_int(parse->resultRelation),
list_make1(plan),
+ withCheckOptionLists,
returningLists,
rowMarks,
SS_assign_special_param(root));
@@ -770,6 +791,7 @@ inheritance_planner(PlannerInfo *root)
RelOptInfo **save_rel_array = NULL;
List *subplans = NIL;
List *resultRelations = NIL;
+ List *withCheckOptionLists = NIL;
List *returningLists = NIL;
List *rowMarks;
ListCell *lc;
@@ -930,7 +952,10 @@ inheritance_planner(PlannerInfo *root)
/* Build list of target-relation RT indexes */
resultRelations = lappend_int(resultRelations, appinfo->child_relid);
- /* Build list of per-relation RETURNING targetlists */
+ /* Build lists of per-relation WCO and RETURNING targetlists */
+ if (parse->withCheckOptions)
+ withCheckOptionLists = lappend(withCheckOptionLists,
+ subroot.parse->withCheckOptions);
if (parse->returningList)
returningLists = lappend(returningLists,
subroot.parse->returningList);
@@ -979,6 +1004,7 @@ inheritance_planner(PlannerInfo *root)
parse->canSetTag,
resultRelations,
subplans,
+ withCheckOptionLists,
returningLists,
rowMarks,
SS_assign_special_param(root));