Add the SQLITE_DBCONFIG_ENABLE_VIEW option, together with a "db config"
command in the TCL interface that can access that option as well as all the
other sqlite3_db_config() boolean options.

FossilOrigin-Name: 61b4bccd2984f4c2cf50f58ef08677588e57aa7e079af07473b2e188d9ce4f52
diff --git a/src/main.c b/src/main.c
index 06a55ec..ecc7e5c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -836,6 +836,7 @@
       } aFlagOp[] = {
         { SQLITE_DBCONFIG_ENABLE_FKEY,           SQLITE_ForeignKeys    },
         { SQLITE_DBCONFIG_ENABLE_TRIGGER,        SQLITE_EnableTrigger  },
+        { SQLITE_DBCONFIG_ENABLE_VIEW,           SQLITE_EnableView     },
         { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer  },
         { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension  },
         { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE,      SQLITE_NoCkptOnClose  },
@@ -3075,6 +3076,7 @@
   db->nMaxSorterMmap = 0x7FFFFFFF;
   db->flags |= SQLITE_ShortColNames
                  | SQLITE_EnableTrigger
+                 | SQLITE_EnableView
                  | SQLITE_CacheSpill
 
 /* The SQLITE_DQS compile-time option determines the default settings
diff --git a/src/select.c b/src/select.c
index ca1256d..bd8fee8 100644
--- a/src/select.c
+++ b/src/select.c
@@ -4906,6 +4906,10 @@
         u8 eCodeOrig = pWalker->eCode;
         if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
         assert( pFrom->pSelect==0 );
+        if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
+          sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
+              pTab->zName);
+        }
         pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
         nCol = pTab->nCol;
         pTab->nCol = -1;
diff --git a/src/shell.c.in b/src/shell.c.in
index 19280e3..0ffd9ae 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -7135,6 +7135,7 @@
     } aDbConfig[] = {
         { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
         { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
+        { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
         { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
         { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
         { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index d68cef2..4b1d472 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -2093,6 +2093,17 @@
 ** following this call.  The second parameter may be a NULL pointer, in
 ** which case the trigger setting is not reported back. </dd>
 **
+** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
+** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
+** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
+** There should be two additional arguments.
+** The first argument is an integer which is 0 to disable views,
+** positive to enable views or negative to leave the setting unchanged.
+** The second parameter is a pointer to an integer into which
+** is written 0 or 1 to indicate whether views are disabled or enabled
+** following this call.  The second parameter may be a NULL pointer, in
+** which case the view setting is not reported back. </dd>
+**
 ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
 ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
 ** <dd> ^This option is used to enable or disable the
@@ -2265,7 +2276,8 @@
 #define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    1012 /* int int* */
 #define SQLITE_DBCONFIG_DQS_DML               1013 /* int int* */
 #define SQLITE_DBCONFIG_DQS_DDL               1014 /* int int* */
-#define SQLITE_DBCONFIG_MAX                   1014 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_ENABLE_VIEW           1015 /* int int* */
+#define SQLITE_DBCONFIG_MAX                   1015 /* Largest DBCONFIG */
 
 /*
 ** CAPI3REF: Enable Or Disable Extended Result Codes
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d6746aa..52c9821 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1537,16 +1537,17 @@
 #define SQLITE_Defensive      0x10000000  /* Input SQL is likely hostile */
 #define SQLITE_DqsDDL         0x20000000  /* dbl-quoted strings allowed in DDL*/
 #define SQLITE_DqsDML         0x40000000  /* dbl-quoted strings allowed in DML*/
+#define SQLITE_EnableView     0x80000000  /* Enable the use of views */
 
 /* Flags used only if debugging */
 #define HI(X)  ((u64)(X)<<32)
 #ifdef SQLITE_DEBUG
-#define SQLITE_SqlTrace       HI(0x0001)  /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing    HI(0x0002)  /* Debug listings of VDBE progs */
-#define SQLITE_VdbeTrace      HI(0x0004)  /* True to trace VDBE execution */
-#define SQLITE_VdbeAddopTrace HI(0x0008)  /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_VdbeEQP        HI(0x0010)  /* Debug EXPLAIN QUERY PLAN */
-#define SQLITE_ParserTrace    HI(0x0020)  /* PRAGMA parser_trace=ON */
+#define SQLITE_SqlTrace       HI(0x0100000) /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing    HI(0x0200000) /* Debug listings of VDBE progs */
+#define SQLITE_VdbeTrace      HI(0x0400000) /* True to trace VDBE execution */
+#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_VdbeEQP        HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_ParserTrace    HI(0x2000000) /* PRAGMA parser_trace=ON */
 #endif
 
 /*
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index a78d567..d296af8 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -1917,33 +1917,33 @@
     "authorizer",             "backup",                "bind_fallback",
     "busy",                   "cache",                 "changes",
     "close",                  "collate",               "collation_needed",
-    "commit_hook",            "complete",              "copy",
-    "deserialize",            "enable_load_extension", "errorcode",
-    "eval",                   "exists",                "function",
-    "incrblob",               "interrupt",             "last_insert_rowid",
-    "nullvalue",              "onecolumn",             "preupdate",
-    "profile",                "progress",              "rekey",
-    "restore",                "rollback_hook",         "serialize",
-    "status",                 "timeout",               "total_changes",
-    "trace",                  "trace_v2",              "transaction",
-    "unlock_notify",          "update_hook",           "version",
-    "wal_hook",               0                        
+    "commit_hook",            "complete",              "config",
+    "copy",                   "deserialize",           "enable_load_extension",
+    "errorcode",              "eval",                  "exists",
+    "function",               "incrblob",              "interrupt",
+    "last_insert_rowid",      "nullvalue",             "onecolumn",
+    "preupdate",              "profile",               "progress",
+    "rekey",                  "restore",               "rollback_hook",
+    "serialize",              "status",                "timeout",
+    "total_changes",          "trace",                 "trace_v2",
+    "transaction",            "unlock_notify",         "update_hook",
+    "version",                "wal_hook",              0
   };
   enum DB_enum {
     DB_AUTHORIZER,            DB_BACKUP,               DB_BIND_FALLBACK,
     DB_BUSY,                  DB_CACHE,                DB_CHANGES,
     DB_CLOSE,                 DB_COLLATE,              DB_COLLATION_NEEDED,
-    DB_COMMIT_HOOK,           DB_COMPLETE,             DB_COPY,
-    DB_DESERIALIZE,           DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE,
-    DB_EVAL,                  DB_EXISTS,               DB_FUNCTION,
-    DB_INCRBLOB,              DB_INTERRUPT,            DB_LAST_INSERT_ROWID,
-    DB_NULLVALUE,             DB_ONECOLUMN,            DB_PREUPDATE,
-    DB_PROFILE,               DB_PROGRESS,             DB_REKEY,
-    DB_RESTORE,               DB_ROLLBACK_HOOK,        DB_SERIALIZE,
-    DB_STATUS,                DB_TIMEOUT,              DB_TOTAL_CHANGES,
-    DB_TRACE,                 DB_TRACE_V2,             DB_TRANSACTION,
-    DB_UNLOCK_NOTIFY,         DB_UPDATE_HOOK,          DB_VERSION,
-    DB_WAL_HOOK             
+    DB_COMMIT_HOOK,           DB_COMPLETE,             DB_CONFIG,
+    DB_COPY,                  DB_DESERIALIZE,          DB_ENABLE_LOAD_EXTENSION,
+    DB_ERRORCODE,             DB_EVAL,                 DB_EXISTS,
+    DB_FUNCTION,              DB_INCRBLOB,             DB_INTERRUPT,
+    DB_LAST_INSERT_ROWID,     DB_NULLVALUE,            DB_ONECOLUMN,
+    DB_PREUPDATE,             DB_PROFILE,              DB_PROGRESS,
+    DB_REKEY,                 DB_RESTORE,              DB_ROLLBACK_HOOK,
+    DB_SERIALIZE,             DB_STATUS,               DB_TIMEOUT,
+    DB_TOTAL_CHANGES,         DB_TRACE,                DB_TRACE_V2,
+    DB_TRANSACTION,           DB_UNLOCK_NOTIFY,        DB_UPDATE_HOOK,
+    DB_VERSION,               DB_WAL_HOOK             
   };
   /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
 
@@ -2331,6 +2331,76 @@
     break;
   }
 
+  /*    $db config ?OPTION? ?BOOLEAN?
+  **
+  ** Configure the database connection using the sqlite3_db_config()
+  ** interface.
+  */
+  case DB_CONFIG: {
+    static const struct DbConfigChoices {
+      const char *zName;
+      int op;
+    } aDbConfig[] = {
+        { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
+        { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
+        { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
+        { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
+        { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
+        { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
+        { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
+        { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
+        { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
+        { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
+        { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
+        { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
+        { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
+        { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
+    };
+    Tcl_Obj *pResult;
+    int ii;
+    if( objc>4 ){
+      Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?");
+      return TCL_ERROR;
+    }
+    if( objc==2 ){
+      /* With no arguments, list all configuration options and with the
+      ** current value */
+      pResult = Tcl_NewListObj(0,0);
+      for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
+        int v = 0;
+        int rc = sqlite3_db_config(pDb->db, aDbConfig[ii].op, -1, &v);
+        if( rc!=SQLITE_OK ) continue;
+        Tcl_ListObjAppendElement(interp, pResult,
+           Tcl_NewStringObj(aDbConfig[ii].zName,-1));
+        Tcl_ListObjAppendElement(interp, pResult,
+           Tcl_NewIntObj(v));
+      }
+    }else{
+      const char *zOpt = Tcl_GetString(objv[2]);
+      int rc;
+      int onoff = -1;
+      int v = 0;
+      if( zOpt[0]=='-' ) zOpt++;
+      for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
+        if( strcmp(aDbConfig[ii].zName, zOpt)==0 ) break;
+      }
+      if( ii>=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){
+        Tcl_AppendResult(interp, "unknown config option: \"", zOpt,
+                                "\"", (void*)0);
+        return TCL_ERROR;
+      }
+      if( objc==4 ){
+        if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){
+          return TCL_ERROR;
+        }
+      }
+      rc = sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v);
+      pResult = Tcl_NewIntObj(v);
+    }
+    Tcl_SetObjResult(interp, pResult);
+    break;
+  }
+
   /*    $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
   **
   ** Copy data into table from filename, optionally using SEPARATOR