aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/view.c
diff options
context:
space:
mode:
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
*/