aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/view.c
diff options
context:
space:
mode:
authorStephen Frost <sfrost@snowman.net>2013-07-18 17:10:16 -0400
committerStephen Frost <sfrost@snowman.net>2013-07-18 17:10:16 -0400
commit4cbe3ac3e86790d05c569de4585e5075a62a9b41 (patch)
tree8adc929520d4103b4493c0c23bcb7d2b2c2a5a4d /src/backend/commands/view.c
parent6f9e39bc9993c18686f0950f9b9657c7c97c7450 (diff)
downloadpostgresql-4cbe3ac3e86790d05c569de4585e5075a62a9b41.tar.gz
postgresql-4cbe3ac3e86790d05c569de4585e5075a62a9b41.zip
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/commands/view.c')
-rw-r--r--src/backend/commands/view.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 6186a841556..832de439789 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -27,6 +27,7 @@
#include "parser/parse_relation.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteManip.h"
+#include "rewrite/rewriteHandler.h"
#include "rewrite/rewriteSupport.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@@ -38,6 +39,24 @@
static void checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc);
/*---------------------------------------------------------------------
+ * Validator for "check_option" reloption on views. The allowed values
+ * are "local" and "cascaded".
+ */
+void
+validateWithCheckOption(char *value)
+{
+ if (value == NULL ||
+ (pg_strcasecmp(value, "local") != 0 &&
+ pg_strcasecmp(value, "cascaded") != 0))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid value for \"check_option\" option"),
+ errdetail("Valid values are \"local\", and \"cascaded\".")));
+ }
+}
+
+/*---------------------------------------------------------------------
* DefineVirtualRelation
*
* Create the "view" relation. `DefineRelation' does all the work,
@@ -374,6 +393,9 @@ DefineView(ViewStmt *stmt, const char *queryString)
Query *viewParse;
Oid viewOid;
RangeVar *view;
+ ListCell *cell;
+ bool check_option;
+ bool security_barrier;
/*
* Run parse analysis to convert the raw parse tree to a Query. Note this
@@ -411,6 +433,52 @@ DefineView(ViewStmt *stmt, const char *queryString)
errmsg("views must not contain data-modifying statements in WITH")));
/*
+ * If the user specified the WITH CHECK OPTION, add it to the list of
+ * reloptions.
+ */
+ if (stmt->withCheckOption == LOCAL_CHECK_OPTION)
+ stmt->options = lappend(stmt->options,
+ makeDefElem("check_option",
+ (Node *) makeString("local")));
+ else if (stmt->withCheckOption == CASCADED_CHECK_OPTION)
+ stmt->options = lappend(stmt->options,
+ makeDefElem("check_option",
+ (Node *) makeString("cascaded")));
+
+ /*
+ * Check that the view is auto-updatable if WITH CHECK OPTION was
+ * specified.
+ */
+ check_option = false;
+ security_barrier = false;
+
+ foreach(cell, stmt->options)
+ {
+ DefElem *defel = (DefElem *) lfirst(cell);
+
+ if (pg_strcasecmp(defel->defname, "check_option") == 0)
+ check_option = true;
+ if (pg_strcasecmp(defel->defname, "security_barrier") == 0)
+ security_barrier = defGetBoolean(defel);
+ }
+
+ /*
+ * If the check option is specified, look to see if the view is
+ * actually auto-updatable or not.
+ */
+ if (check_option)
+ {
+ const char *view_updatable_error =
+ view_query_is_auto_updatable(viewParse, security_barrier);
+
+ if (view_updatable_error)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("WITH CHECK OPTION is supported only on auto-updatable views"),
+ errhint("%s", view_updatable_error)));
+ }
+
+ /*
* If a list of column names was given, run through and insert these into
* the actual query tree. - thomas 2000-03-08
*/