diff options
Diffstat (limited to 'src/backend/commands/view.c')
-rw-r--r-- | src/backend/commands/view.c | 68 |
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 */ |