1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-03 15:22:11 +03:00

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
This commit is contained in:
Stephen Frost
2013-07-18 17:10:16 -04:00
parent 6f9e39bc99
commit 4cbe3ac3e8
33 changed files with 1245 additions and 107 deletions

View File

@@ -178,6 +178,7 @@ _copyModifyTable(const ModifyTable *from)
COPY_NODE_FIELD(resultRelations);
COPY_SCALAR_FIELD(resultRelIndex);
COPY_NODE_FIELD(plans);
COPY_NODE_FIELD(withCheckOptionLists);
COPY_NODE_FIELD(returningLists);
COPY_NODE_FIELD(fdwPrivLists);
COPY_NODE_FIELD(rowMarks);
@@ -2003,6 +2004,18 @@ _copyRangeTblEntry(const RangeTblEntry *from)
return newnode;
}
static WithCheckOption *
_copyWithCheckOption(const WithCheckOption *from)
{
WithCheckOption *newnode = makeNode(WithCheckOption);
COPY_STRING_FIELD(viewname);
COPY_NODE_FIELD(qual);
COPY_SCALAR_FIELD(cascaded);
return newnode;
}
static SortGroupClause *
_copySortGroupClause(const SortGroupClause *from)
{
@@ -2446,6 +2459,7 @@ _copyQuery(const Query *from)
COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(jointree);
COPY_NODE_FIELD(targetList);
COPY_NODE_FIELD(withCheckOptions);
COPY_NODE_FIELD(returningList);
COPY_NODE_FIELD(groupClause);
COPY_NODE_FIELD(havingQual);
@@ -3075,6 +3089,7 @@ _copyViewStmt(const ViewStmt *from)
COPY_NODE_FIELD(query);
COPY_SCALAR_FIELD(replace);
COPY_NODE_FIELD(options);
COPY_SCALAR_FIELD(withCheckOption);
return newnode;
}
@@ -4517,6 +4532,9 @@ copyObject(const void *from)
case T_RangeTblEntry:
retval = _copyRangeTblEntry(from);
break;
case T_WithCheckOption:
retval = _copyWithCheckOption(from);
break;
case T_SortGroupClause:
retval = _copySortGroupClause(from);
break;

View File

@@ -853,6 +853,7 @@ _equalQuery(const Query *a, const Query *b)
COMPARE_NODE_FIELD(rtable);
COMPARE_NODE_FIELD(jointree);
COMPARE_NODE_FIELD(targetList);
COMPARE_NODE_FIELD(withCheckOptions);
COMPARE_NODE_FIELD(returningList);
COMPARE_NODE_FIELD(groupClause);
COMPARE_NODE_FIELD(havingQual);
@@ -1382,6 +1383,7 @@ _equalViewStmt(const ViewStmt *a, const ViewStmt *b)
COMPARE_NODE_FIELD(query);
COMPARE_SCALAR_FIELD(replace);
COMPARE_NODE_FIELD(options);
COMPARE_SCALAR_FIELD(withCheckOption);
return true;
}
@@ -2253,6 +2255,16 @@ _equalRangeTblEntry(const RangeTblEntry *a, const RangeTblEntry *b)
return true;
}
static bool
_equalWithCheckOption(const WithCheckOption *a, const WithCheckOption *b)
{
COMPARE_STRING_FIELD(viewname);
COMPARE_NODE_FIELD(qual);
COMPARE_SCALAR_FIELD(cascaded);
return true;
}
static bool
_equalSortGroupClause(const SortGroupClause *a, const SortGroupClause *b)
{
@@ -2987,6 +2999,9 @@ equal(const void *a, const void *b)
case T_RangeTblEntry:
retval = _equalRangeTblEntry(a, b);
break;
case T_WithCheckOption:
retval = _equalWithCheckOption(a, b);
break;
case T_SortGroupClause:
retval = _equalSortGroupClause(a, b);
break;

View File

@@ -1556,6 +1556,8 @@ expression_tree_walker(Node *node,
case T_SortGroupClause:
/* primitive node types with no expression subnodes */
break;
case T_WithCheckOption:
return walker(((WithCheckOption *) node)->qual, context);
case T_Aggref:
{
Aggref *expr = (Aggref *) node;
@@ -1873,6 +1875,8 @@ query_tree_walker(Query *query,
if (walker((Node *) query->targetList, context))
return true;
if (walker((Node *) query->withCheckOptions, context))
return true;
if (walker((Node *) query->returningList, context))
return true;
if (walker((Node *) query->jointree, context))
@@ -2074,6 +2078,15 @@ expression_tree_mutator(Node *node,
case T_RangeTblRef:
case T_SortGroupClause:
return (Node *) copyObject(node);
case T_WithCheckOption:
{
WithCheckOption *wco = (WithCheckOption *) node;
WithCheckOption *newnode;
FLATCOPY(newnode, wco, WithCheckOption);
MUTATE(newnode->qual, wco->qual, Node *);
return (Node *) newnode;
}
case T_Aggref:
{
Aggref *aggref = (Aggref *) node;
@@ -2589,6 +2602,7 @@ query_tree_mutator(Query *query,
}
MUTATE(query->targetList, query->targetList, List *);
MUTATE(query->withCheckOptions, query->withCheckOptions, List *);
MUTATE(query->returningList, query->returningList, List *);
MUTATE(query->jointree, query->jointree, FromExpr *);
MUTATE(query->setOperations, query->setOperations, Node *);

View File

@@ -332,6 +332,7 @@ _outModifyTable(StringInfo str, const ModifyTable *node)
WRITE_NODE_FIELD(resultRelations);
WRITE_INT_FIELD(resultRelIndex);
WRITE_NODE_FIELD(plans);
WRITE_NODE_FIELD(withCheckOptionLists);
WRITE_NODE_FIELD(returningLists);
WRITE_NODE_FIELD(fdwPrivLists);
WRITE_NODE_FIELD(rowMarks);
@@ -2247,6 +2248,7 @@ _outQuery(StringInfo str, const Query *node)
WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(jointree);
WRITE_NODE_FIELD(targetList);
WRITE_NODE_FIELD(withCheckOptions);
WRITE_NODE_FIELD(returningList);
WRITE_NODE_FIELD(groupClause);
WRITE_NODE_FIELD(havingQual);
@@ -2260,6 +2262,16 @@ _outQuery(StringInfo str, const Query *node)
WRITE_NODE_FIELD(constraintDeps);
}
static void
_outWithCheckOption(StringInfo str, const WithCheckOption *node)
{
WRITE_NODE_TYPE("WITHCHECKOPTION");
WRITE_STRING_FIELD(viewname);
WRITE_NODE_FIELD(qual);
WRITE_BOOL_FIELD(cascaded);
}
static void
_outSortGroupClause(StringInfo str, const SortGroupClause *node)
{
@@ -3114,6 +3126,9 @@ _outNode(StringInfo str, const void *obj)
case T_Query:
_outQuery(str, obj);
break;
case T_WithCheckOption:
_outWithCheckOption(str, obj);
break;
case T_SortGroupClause:
_outSortGroupClause(str, obj);
break;

View File

@@ -210,6 +210,7 @@ _readQuery(void)
READ_NODE_FIELD(rtable);
READ_NODE_FIELD(jointree);
READ_NODE_FIELD(targetList);
READ_NODE_FIELD(withCheckOptions);
READ_NODE_FIELD(returningList);
READ_NODE_FIELD(groupClause);
READ_NODE_FIELD(havingQual);
@@ -254,6 +255,21 @@ _readDeclareCursorStmt(void)
READ_DONE();
}
/*
* _readWithCheckOption
*/
static WithCheckOption *
_readWithCheckOption(void)
{
READ_LOCALS(WithCheckOption);
READ_STRING_FIELD(viewname);
READ_NODE_FIELD(qual);
READ_BOOL_FIELD(cascaded);
READ_DONE();
}
/*
* _readSortGroupClause
*/
@@ -1260,6 +1276,8 @@ parseNodeString(void)
if (MATCH("QUERY", 5))
return_value = _readQuery();
else if (MATCH("WITHCHECKOPTION", 15))
return_value = _readWithCheckOption();
else if (MATCH("SORTGROUPCLAUSE", 15))
return_value = _readSortGroupClause();
else if (MATCH("WINDOWCLAUSE", 12))