Index: third_party/sqlite/src/src/pragma.c |
diff --git a/third_party/sqlite/src/src/pragma.c b/third_party/sqlite/src/src/pragma.c |
index 75ab26d441a0463a1d15e16b160d7c338f592596..543f265ba9ea1ae5e8e0fff897f91f76aa334450 100644 |
--- a/third_party/sqlite/src/src/pragma.c |
+++ b/third_party/sqlite/src/src/pragma.c |
@@ -13,21 +13,479 @@ |
*/ |
#include "sqliteInt.h" |
-/* Ignore this whole file if pragmas are disabled |
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE) |
+# if defined(__APPLE__) |
+# define SQLITE_ENABLE_LOCKING_STYLE 1 |
+# else |
+# define SQLITE_ENABLE_LOCKING_STYLE 0 |
+# endif |
+#endif |
+ |
+/*************************************************************************** |
+** The next block of code, including the PragTyp_XXXX macro definitions and |
+** the aPragmaName[] object is composed of generated code. DO NOT EDIT. |
+** |
+** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun |
+** that script. Then copy/paste the output in place of the following: |
*/ |
-#if !defined(SQLITE_OMIT_PRAGMA) |
+#define PragTyp_HEADER_VALUE 0 |
+#define PragTyp_AUTO_VACUUM 1 |
+#define PragTyp_FLAG 2 |
+#define PragTyp_BUSY_TIMEOUT 3 |
+#define PragTyp_CACHE_SIZE 4 |
+#define PragTyp_CASE_SENSITIVE_LIKE 5 |
+#define PragTyp_COLLATION_LIST 6 |
+#define PragTyp_COMPILE_OPTIONS 7 |
+#define PragTyp_DATA_STORE_DIRECTORY 8 |
+#define PragTyp_DATABASE_LIST 9 |
+#define PragTyp_DEFAULT_CACHE_SIZE 10 |
+#define PragTyp_ENCODING 11 |
+#define PragTyp_FOREIGN_KEY_CHECK 12 |
+#define PragTyp_FOREIGN_KEY_LIST 13 |
+#define PragTyp_INCREMENTAL_VACUUM 14 |
+#define PragTyp_INDEX_INFO 15 |
+#define PragTyp_INDEX_LIST 16 |
+#define PragTyp_INTEGRITY_CHECK 17 |
+#define PragTyp_JOURNAL_MODE 18 |
+#define PragTyp_JOURNAL_SIZE_LIMIT 19 |
+#define PragTyp_LOCK_PROXY_FILE 20 |
+#define PragTyp_LOCKING_MODE 21 |
+#define PragTyp_PAGE_COUNT 22 |
+#define PragTyp_MMAP_SIZE 23 |
+#define PragTyp_PAGE_SIZE 24 |
+#define PragTyp_SECURE_DELETE 25 |
+#define PragTyp_SHRINK_MEMORY 26 |
+#define PragTyp_SOFT_HEAP_LIMIT 27 |
+#define PragTyp_STATS 28 |
+#define PragTyp_SYNCHRONOUS 29 |
+#define PragTyp_TABLE_INFO 30 |
+#define PragTyp_TEMP_STORE 31 |
+#define PragTyp_TEMP_STORE_DIRECTORY 32 |
+#define PragTyp_THREADS 33 |
+#define PragTyp_WAL_AUTOCHECKPOINT 34 |
+#define PragTyp_WAL_CHECKPOINT 35 |
+#define PragTyp_ACTIVATE_EXTENSIONS 36 |
+#define PragTyp_HEXKEY 37 |
+#define PragTyp_KEY 38 |
+#define PragTyp_REKEY 39 |
+#define PragTyp_LOCK_STATUS 40 |
+#define PragTyp_PARSER_TRACE 41 |
+#define PragFlag_NeedSchema 0x01 |
+static const struct sPragmaNames { |
+ const char *const zName; /* Name of pragma */ |
+ u8 ePragTyp; /* PragTyp_XXX value */ |
+ u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
+ u32 iArg; /* Extra argument */ |
+} aPragmaNames[] = { |
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) |
+ { /* zName: */ "activate_extensions", |
+ /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ { /* zName: */ "application_id", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_AUTOVACUUM) |
+ { /* zName: */ "auto_vacuum", |
+ /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) |
+ { /* zName: */ "automatic_index", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_AutoIndex }, |
+#endif |
+#endif |
+ { /* zName: */ "busy_timeout", |
+ /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ { /* zName: */ "cache_size", |
+ /* ePragTyp: */ PragTyp_CACHE_SIZE, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "cache_spill", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_CacheSpill }, |
+#endif |
+ { /* zName: */ "case_sensitive_like", |
+ /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "checkpoint_fullfsync", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_CkptFullFSync }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ { /* zName: */ "collation_list", |
+ /* ePragTyp: */ PragTyp_COLLATION_LIST, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) |
+ { /* zName: */ "compile_options", |
+ /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "count_changes", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_CountRows }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN |
+ { /* zName: */ "data_store_directory", |
+ /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ { /* zName: */ "database_list", |
+ /* ePragTyp: */ PragTyp_DATABASE_LIST, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
+ { /* zName: */ "default_cache_size", |
+ /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
+ { /* zName: */ "defer_foreign_keys", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_DeferFKs }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "empty_result_callbacks", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_NullCallback }, |
+#endif |
+#if !defined(SQLITE_OMIT_UTF16) |
+ { /* zName: */ "encoding", |
+ /* ePragTyp: */ PragTyp_ENCODING, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
+ { /* zName: */ "foreign_key_check", |
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) |
+ { /* zName: */ "foreign_key_list", |
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
+ { /* zName: */ "foreign_keys", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_ForeignKeys }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ { /* zName: */ "freelist_count", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "full_column_names", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_FullColNames }, |
+ { /* zName: */ "fullfsync", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_FullFSync }, |
+#endif |
+#if defined(SQLITE_HAS_CODEC) |
+ { /* zName: */ "hexkey", |
+ /* ePragTyp: */ PragTyp_HEXKEY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "hexrekey", |
+ /* ePragTyp: */ PragTyp_HEXKEY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_CHECK) |
+ { /* zName: */ "ignore_check_constraints", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_IgnoreChecks }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_AUTOVACUUM) |
+ { /* zName: */ "incremental_vacuum", |
+ /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ { /* zName: */ "index_info", |
+ /* ePragTyp: */ PragTyp_INDEX_INFO, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "index_list", |
+ /* ePragTyp: */ PragTyp_INDEX_LIST, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
+ { /* zName: */ "integrity_check", |
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ { /* zName: */ "journal_mode", |
+ /* ePragTyp: */ PragTyp_JOURNAL_MODE, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "journal_size_limit", |
+ /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if defined(SQLITE_HAS_CODEC) |
+ { /* zName: */ "key", |
+ /* ePragTyp: */ PragTyp_KEY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "legacy_file_format", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_LegacyFileFmt }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE |
+ { /* zName: */ "lock_proxy_file", |
+ /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
+ { /* zName: */ "lock_status", |
+ /* ePragTyp: */ PragTyp_LOCK_STATUS, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ { /* zName: */ "locking_mode", |
+ /* ePragTyp: */ PragTyp_LOCKING_MODE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "max_page_count", |
+ /* ePragTyp: */ PragTyp_PAGE_COUNT, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "mmap_size", |
+ /* ePragTyp: */ PragTyp_MMAP_SIZE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "page_count", |
+ /* ePragTyp: */ PragTyp_PAGE_COUNT, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "page_size", |
+ /* ePragTyp: */ PragTyp_PAGE_SIZE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if defined(SQLITE_DEBUG) |
+ { /* zName: */ "parser_trace", |
+ /* ePragTyp: */ PragTyp_PARSER_TRACE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "query_only", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_QueryOnly }, |
+#endif |
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
+ { /* zName: */ "quick_check", |
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "read_uncommitted", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_ReadUncommitted }, |
+ { /* zName: */ "recursive_triggers", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_RecTriggers }, |
+#endif |
+#if defined(SQLITE_HAS_CODEC) |
+ { /* zName: */ "rekey", |
+ /* ePragTyp: */ PragTyp_REKEY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "reverse_unordered_selects", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_ReverseOrder }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ { /* zName: */ "schema_version", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ { /* zName: */ "secure_delete", |
+ /* ePragTyp: */ PragTyp_SECURE_DELETE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "short_column_names", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_ShortColNames }, |
+#endif |
+ { /* zName: */ "shrink_memory", |
+ /* ePragTyp: */ PragTyp_SHRINK_MEMORY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "soft_heap_limit", |
+ /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if defined(SQLITE_DEBUG) |
+ { /* zName: */ "sql_trace", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_SqlTrace }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ { /* zName: */ "stats", |
+ /* ePragTyp: */ PragTyp_STATS, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ { /* zName: */ "synchronous", |
+ /* ePragTyp: */ PragTyp_SYNCHRONOUS, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ { /* zName: */ "table_info", |
+ /* ePragTyp: */ PragTyp_TABLE_INFO, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ { /* zName: */ "temp_store", |
+ /* ePragTyp: */ PragTyp_TEMP_STORE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "temp_store_directory", |
+ /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+ { /* zName: */ "threads", |
+ /* ePragTyp: */ PragTyp_THREADS, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ { /* zName: */ "user_version", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if defined(SQLITE_DEBUG) |
+ { /* zName: */ "vdbe_addoptrace", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_VdbeAddopTrace }, |
+ { /* zName: */ "vdbe_debug", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, |
+ { /* zName: */ "vdbe_eqp", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_VdbeEQP }, |
+ { /* zName: */ "vdbe_listing", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_VdbeListing }, |
+ { /* zName: */ "vdbe_trace", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_VdbeTrace }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_WAL) |
+ { /* zName: */ "wal_autocheckpoint", |
+ /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ 0 }, |
+ { /* zName: */ "wal_checkpoint", |
+ /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, |
+ /* ePragFlag: */ PragFlag_NeedSchema, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ { /* zName: */ "writable_schema", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlag: */ 0, |
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
+#endif |
+}; |
+/* Number of pragmas: 57 on by default, 70 total. */ |
+/* End of the automatically generated pragma table. |
+***************************************************************************/ |
/* |
** Interpret the given string as a safety level. Return 0 for OFF, |
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or |
-** unrecognized string argument. |
+** unrecognized string argument. The FULL option is disallowed |
+** if the omitFull parameter it 1. |
** |
** Note that the values returned are one less that the values that |
** should be passed into sqlite3BtreeSetSafetyLevel(). The is done |
** to support legacy SQL code. The safety level used to be boolean |
** and older scripts may have used numbers 0 for OFF and 1 for ON. |
*/ |
-static u8 getSafetyLevel(const char *z){ |
+static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ |
/* 123456789 123456789 */ |
static const char zText[] = "onoffalseyestruefull"; |
static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; |
@@ -38,21 +496,27 @@ static u8 getSafetyLevel(const char *z){ |
return (u8)sqlite3Atoi(z); |
} |
n = sqlite3Strlen30(z); |
- for(i=0; i<ArraySize(iLength); i++){ |
+ for(i=0; i<ArraySize(iLength)-omitFull; i++){ |
if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ |
return iValue[i]; |
} |
} |
- return 1; |
+ return dflt; |
} |
/* |
** Interpret the given string as a boolean value. |
*/ |
-static u8 getBoolean(const char *z){ |
- return getSafetyLevel(z)&1; |
+u8 sqlite3GetBoolean(const char *z, u8 dflt){ |
+ return getSafetyLevel(z,1,dflt)!=0; |
} |
+/* The sqlite3GetBoolean() function is used by other modules but the |
+** remainder of this file is specific to PRAGMA processing. So omit |
+** the rest of the file if PRAGMAs are omitted from the build. |
+*/ |
+#if !defined(SQLITE_OMIT_PRAGMA) |
+ |
/* |
** Interpret the given string as a locking mode value. |
*/ |
@@ -115,7 +579,7 @@ static int invalidateTempStorage(Parse *pParse){ |
} |
sqlite3BtreeClose(db->aDb[1].pBt); |
db->aDb[1].pBt = 0; |
- sqlite3ResetInternalSchema(db, -1); |
+ sqlite3ResetAllSchemasOfConnection(db); |
} |
return SQLITE_OK; |
} |
@@ -155,90 +619,35 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){ |
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); |
} |
-#ifndef SQLITE_OMIT_FLAG_PRAGMAS |
+ |
/* |
-** Check to see if zRight and zLeft refer to a pragma that queries |
-** or changes one of the flags in db->flags. Return 1 if so and 0 if not. |
-** Also, implement the pragma. |
+** Set the safety_level and pager flags for pager iDb. Or if iDb<0 |
+** set these values for all pagers. |
*/ |
-static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ |
- static const struct sPragmaType { |
- const char *zName; /* Name of the pragma */ |
- int mask; /* Mask for the db->flags value */ |
- } aPragma[] = { |
- { "full_column_names", SQLITE_FullColNames }, |
- { "short_column_names", SQLITE_ShortColNames }, |
- { "count_changes", SQLITE_CountRows }, |
- { "empty_result_callbacks", SQLITE_NullCallback }, |
- { "legacy_file_format", SQLITE_LegacyFileFmt }, |
- { "fullfsync", SQLITE_FullFSync }, |
- { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, |
- { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
- { "automatic_index", SQLITE_AutoIndex }, |
-#endif |
-#ifdef SQLITE_DEBUG |
- { "sql_trace", SQLITE_SqlTrace }, |
- { "vdbe_listing", SQLITE_VdbeListing }, |
- { "vdbe_trace", SQLITE_VdbeTrace }, |
-#endif |
-#ifndef SQLITE_OMIT_CHECK |
- { "ignore_check_constraints", SQLITE_IgnoreChecks }, |
-#endif |
- /* The following is VERY experimental */ |
- { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
- { "omit_readlock", SQLITE_NoReadlock }, |
- |
- /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted |
- ** flag if there are any active statements. */ |
- { "read_uncommitted", SQLITE_ReadUncommitted }, |
- { "recursive_triggers", SQLITE_RecTriggers }, |
- |
- /* This flag may only be set if both foreign-key and trigger support |
- ** are present in the build. */ |
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
- { "foreign_keys", SQLITE_ForeignKeys }, |
-#endif |
- }; |
- int i; |
- const struct sPragmaType *p; |
- for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){ |
- if( sqlite3StrICmp(zLeft, p->zName)==0 ){ |
- sqlite3 *db = pParse->db; |
- Vdbe *v; |
- v = sqlite3GetVdbe(pParse); |
- assert( v!=0 ); /* Already allocated by sqlite3Pragma() */ |
- if( ALWAYS(v) ){ |
- if( zRight==0 ){ |
- returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); |
- }else{ |
- int mask = p->mask; /* Mask of bits to set or clear. */ |
- if( db->autoCommit==0 ){ |
- /* Foreign key support may not be enabled or disabled while not |
- ** in auto-commit mode. */ |
- mask &= ~(SQLITE_ForeignKeys); |
- } |
- |
- if( getBoolean(zRight) ){ |
- db->flags |= mask; |
- }else{ |
- db->flags &= ~mask; |
- } |
- |
- /* Many of the flag-pragmas modify the code generated by the SQL |
- ** compiler (eg. count_changes). So add an opcode to expire all |
- ** compiled SQL statements after modifying a pragma value. |
- */ |
- sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); |
- } |
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS |
+static void setAllPagerFlags(sqlite3 *db){ |
+ if( db->autoCommit ){ |
+ Db *pDb = db->aDb; |
+ int n = db->nDb; |
+ assert( SQLITE_FullFSync==PAGER_FULLFSYNC ); |
+ assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC ); |
+ assert( SQLITE_CacheSpill==PAGER_CACHESPILL ); |
+ assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL) |
+ == PAGER_FLAGS_MASK ); |
+ assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level ); |
+ while( (n--) > 0 ){ |
+ if( pDb->pBt ){ |
+ sqlite3BtreeSetPagerFlags(pDb->pBt, |
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) ); |
} |
- |
- return 1; |
+ pDb++; |
} |
} |
- return 0; |
} |
-#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ |
+#else |
+# define setAllPagerFlags(X) /* no-op */ |
+#endif |
+ |
/* |
** Return a human-readable name for a constraint resolution action. |
@@ -309,10 +718,14 @@ void sqlite3Pragma( |
char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */ |
const char *zDb = 0; /* The database name */ |
Token *pId; /* Pointer to <id> token */ |
+ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ |
int iDb; /* Database index for <database> */ |
- sqlite3 *db = pParse->db; |
- Db *pDb; |
- Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); |
+ int lwr, upr, mid; /* Binary search bounds */ |
+ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ |
+ sqlite3 *db = pParse->db; /* The database connection */ |
+ Db *pDb; /* The specific database being pragmaed */ |
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ |
+ |
if( v==0 ) return; |
sqlite3VdbeRunOnlyOnce(v); |
pParse->nMem = 2; |
@@ -343,8 +756,62 @@ void sqlite3Pragma( |
if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ |
goto pragma_out; |
} |
- |
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS |
+ |
+ /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS |
+ ** connection. If it returns SQLITE_OK, then assume that the VFS |
+ ** handled the pragma and generate a no-op prepared statement. |
+ */ |
+ aFcntl[0] = 0; |
+ aFcntl[1] = zLeft; |
+ aFcntl[2] = zRight; |
+ aFcntl[3] = 0; |
+ db->busyHandler.nBusy = 0; |
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); |
+ if( rc==SQLITE_OK ){ |
+ if( aFcntl[0] ){ |
+ int mem = ++pParse->nMem; |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); |
+ sqlite3VdbeSetNumCols(v, 1); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); |
+ sqlite3_free(aFcntl[0]); |
+ } |
+ goto pragma_out; |
+ } |
+ if( rc!=SQLITE_NOTFOUND ){ |
+ if( aFcntl[0] ){ |
+ sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); |
+ sqlite3_free(aFcntl[0]); |
+ } |
+ pParse->nErr++; |
+ pParse->rc = rc; |
+ goto pragma_out; |
+ } |
+ |
+ /* Locate the pragma in the lookup table */ |
+ lwr = 0; |
+ upr = ArraySize(aPragmaNames)-1; |
+ while( lwr<=upr ){ |
+ mid = (lwr+upr)/2; |
+ rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName); |
+ if( rc==0 ) break; |
+ if( rc<0 ){ |
+ upr = mid - 1; |
+ }else{ |
+ lwr = mid + 1; |
+ } |
+ } |
+ if( lwr>upr ) goto pragma_out; |
+ |
+ /* Make sure the database schema is loaded if the pragma requires that */ |
+ if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){ |
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
+ } |
+ |
+ /* Jump to the appropriate pragma handler */ |
+ switch( aPragmaNames[mid].ePragTyp ){ |
+ |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
/* |
** PRAGMA [database.]default_cache_size |
** PRAGMA [database.]default_cache_size=N |
@@ -361,25 +828,26 @@ void sqlite3Pragma( |
** size. But continue to take the absolute value of the default cache |
** size of historical compatibility. |
*/ |
- if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ |
+ case PragTyp_DEFAULT_CACHE_SIZE: { |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
static const VdbeOpList getCacheSize[] = { |
{ OP_Transaction, 0, 0, 0}, /* 0 */ |
{ OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ |
- { OP_IfPos, 1, 7, 0}, |
+ { OP_IfPos, 1, 8, 0}, |
{ OP_Integer, 0, 2, 0}, |
{ OP_Subtract, 1, 2, 1}, |
- { OP_IfPos, 1, 7, 0}, |
+ { OP_IfPos, 1, 8, 0}, |
{ OP_Integer, 0, 1, 0}, /* 6 */ |
+ { OP_Noop, 0, 0, 0}, |
{ OP_ResultRow, 1, 1, 0}, |
}; |
int addr; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
sqlite3VdbeUsesBtree(v, iDb); |
if( !zRight ){ |
sqlite3VdbeSetNumCols(v, 1); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); |
pParse->nMem += 2; |
- addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); |
+ addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn); |
sqlite3VdbeChangeP1(v, addr, iDb); |
sqlite3VdbeChangeP1(v, addr+1, iDb); |
sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); |
@@ -392,8 +860,11 @@ void sqlite3Pragma( |
pDb->pSchema->cache_size = size; |
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
} |
- }else |
+ break; |
+ } |
+#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */ |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
/* |
** PRAGMA [database.]page_size |
** PRAGMA [database.]page_size=N |
@@ -403,7 +874,7 @@ void sqlite3Pragma( |
** database page size value. The value can only be set if |
** the database has not yet been created. |
*/ |
- if( sqlite3StrICmp(zLeft,"page_size")==0 ){ |
+ case PragTyp_PAGE_SIZE: { |
Btree *pBt = pDb->pBt; |
assert( pBt!=0 ); |
if( !zRight ){ |
@@ -414,11 +885,12 @@ void sqlite3Pragma( |
** buffer that the pager module resizes using sqlite3_realloc(). |
*/ |
db->nextPagesize = sqlite3Atoi(zRight); |
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ |
db->mallocFailed = 1; |
} |
} |
- }else |
+ break; |
+ } |
/* |
** PRAGMA [database.]secure_delete |
@@ -428,12 +900,12 @@ void sqlite3Pragma( |
** secure_delete flag. The second form changes the secure_delete |
** flag setting and reports thenew value. |
*/ |
- if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){ |
+ case PragTyp_SECURE_DELETE: { |
Btree *pBt = pDb->pBt; |
int b = -1; |
assert( pBt!=0 ); |
if( zRight ){ |
- b = getBoolean(zRight); |
+ b = sqlite3GetBoolean(zRight, 0); |
} |
if( pId2->n==0 && b>=0 ){ |
int ii; |
@@ -443,7 +915,8 @@ void sqlite3Pragma( |
} |
b = sqlite3BtreeSecureDelete(pBt, b); |
returnSingleInt(pParse, "secure_delete", b); |
- }else |
+ break; |
+ } |
/* |
** PRAGMA [database.]max_page_count |
@@ -454,32 +927,35 @@ void sqlite3Pragma( |
** second form attempts to change this setting. Both |
** forms return the current setting. |
** |
+ ** The absolute value of N is used. This is undocumented and might |
+ ** change. The only purpose is to provide an easy way to test |
+ ** the sqlite3AbsInt32() function. |
+ ** |
** PRAGMA [database.]page_count |
** |
** Return the number of pages in the specified database. |
*/ |
- if( sqlite3StrICmp(zLeft,"page_count")==0 |
- || sqlite3StrICmp(zLeft,"max_page_count")==0 |
- ){ |
+ case PragTyp_PAGE_COUNT: { |
int iReg; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
sqlite3CodeVerifySchema(pParse, iDb); |
iReg = ++pParse->nMem; |
- if( zLeft[0]=='p' ){ |
+ if( sqlite3Tolower(zLeft[0])=='p' ){ |
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); |
}else{ |
- sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3Atoi(zRight)); |
+ sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, |
+ sqlite3AbsInt32(sqlite3Atoi(zRight))); |
} |
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); |
sqlite3VdbeSetNumCols(v, 1); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
- }else |
+ break; |
+ } |
/* |
** PRAGMA [database.]locking_mode |
** PRAGMA [database.]locking_mode = (normal|exclusive) |
*/ |
- if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){ |
+ case PragTyp_LOCKING_MODE: { |
const char *zRet = "normal"; |
int eMode = getLockingMode(zRight); |
@@ -512,7 +988,8 @@ void sqlite3Pragma( |
eMode = sqlite3PagerLockingMode(pPager, eMode); |
} |
- assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE); |
+ assert( eMode==PAGER_LOCKINGMODE_NORMAL |
+ || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); |
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ |
zRet = "exclusive"; |
} |
@@ -520,23 +997,18 @@ void sqlite3Pragma( |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC); |
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
- }else |
+ break; |
+ } |
/* |
** PRAGMA [database.]journal_mode |
** PRAGMA [database.]journal_mode = |
** (delete|persist|off|truncate|memory|wal|off) |
*/ |
- if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){ |
+ case PragTyp_JOURNAL_MODE: { |
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ |
int ii; /* Loop counter */ |
- /* Force the schema to be loaded on all databases. This cases all |
- ** database files to be opened and the journal_modes set. */ |
- if( sqlite3ReadSchema(pParse) ){ |
- goto pragma_out; |
- } |
- |
sqlite3VdbeSetNumCols(v, 1); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC); |
@@ -568,7 +1040,8 @@ void sqlite3Pragma( |
} |
} |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
- }else |
+ break; |
+ } |
/* |
** PRAGMA [database.]journal_size_limit |
@@ -576,16 +1049,17 @@ void sqlite3Pragma( |
** |
** Get or set the size limit on rollback journal files. |
*/ |
- if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){ |
+ case PragTyp_JOURNAL_SIZE_LIMIT: { |
Pager *pPager = sqlite3BtreePager(pDb->pBt); |
i64 iLimit = -2; |
if( zRight ){ |
- sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8); |
+ sqlite3DecOrHexToI64(zRight, &iLimit); |
if( iLimit<-1 ) iLimit = -1; |
} |
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); |
returnSingleInt(pParse, "journal_size_limit", iLimit); |
- }else |
+ break; |
+ } |
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ |
@@ -597,57 +1071,48 @@ void sqlite3Pragma( |
** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL |
*/ |
#ifndef SQLITE_OMIT_AUTOVACUUM |
- if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){ |
+ case PragTyp_AUTO_VACUUM: { |
Btree *pBt = pDb->pBt; |
assert( pBt!=0 ); |
- if( sqlite3ReadSchema(pParse) ){ |
- goto pragma_out; |
- } |
if( !zRight ){ |
- int auto_vacuum; |
- if( ALWAYS(pBt) ){ |
- auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt); |
- }else{ |
- auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM; |
- } |
- returnSingleInt(pParse, "auto_vacuum", auto_vacuum); |
+ returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt)); |
}else{ |
int eAuto = getAutoVacuum(zRight); |
assert( eAuto>=0 && eAuto<=2 ); |
db->nextAutovac = (u8)eAuto; |
- if( ALWAYS(eAuto>=0) ){ |
- /* Call SetAutoVacuum() to set initialize the internal auto and |
- ** incr-vacuum flags. This is required in case this connection |
- ** creates the database file. It is important that it is created |
- ** as an auto-vacuum capable db. |
+ /* Call SetAutoVacuum() to set initialize the internal auto and |
+ ** incr-vacuum flags. This is required in case this connection |
+ ** creates the database file. It is important that it is created |
+ ** as an auto-vacuum capable db. |
+ */ |
+ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); |
+ if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ |
+ /* When setting the auto_vacuum mode to either "full" or |
+ ** "incremental", write the value of meta[6] in the database |
+ ** file. Before writing to meta[6], check that meta[3] indicates |
+ ** that this really is an auto-vacuum capable database. |
*/ |
- int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); |
- if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ |
- /* When setting the auto_vacuum mode to either "full" or |
- ** "incremental", write the value of meta[6] in the database |
- ** file. Before writing to meta[6], check that meta[3] indicates |
- ** that this really is an auto-vacuum capable database. |
- */ |
- static const VdbeOpList setMeta6[] = { |
- { OP_Transaction, 0, 1, 0}, /* 0 */ |
- { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
- { OP_If, 1, 0, 0}, /* 2 */ |
- { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
- { OP_Integer, 0, 1, 0}, /* 4 */ |
- { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ |
- }; |
- int iAddr; |
- iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); |
- sqlite3VdbeChangeP1(v, iAddr, iDb); |
- sqlite3VdbeChangeP1(v, iAddr+1, iDb); |
- sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); |
- sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); |
- sqlite3VdbeChangeP1(v, iAddr+5, iDb); |
- sqlite3VdbeUsesBtree(v, iDb); |
- } |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
+ static const VdbeOpList setMeta6[] = { |
+ { OP_Transaction, 0, 1, 0}, /* 0 */ |
+ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
+ { OP_If, 1, 0, 0}, /* 2 */ |
+ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
+ { OP_Integer, 0, 1, 0}, /* 4 */ |
+ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ |
+ }; |
+ int iAddr; |
+ iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); |
+ sqlite3VdbeChangeP1(v, iAddr, iDb); |
+ sqlite3VdbeChangeP1(v, iAddr+1, iDb); |
+ sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); |
+ sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); |
+ sqlite3VdbeChangeP1(v, iAddr+5, iDb); |
+ sqlite3VdbeUsesBtree(v, iDb); |
} |
} |
- }else |
+ break; |
+ } |
#endif |
/* |
@@ -656,22 +1121,20 @@ void sqlite3Pragma( |
** Do N steps of incremental vacuuming on a database. |
*/ |
#ifndef SQLITE_OMIT_AUTOVACUUM |
- if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){ |
+ case PragTyp_INCREMENTAL_VACUUM: { |
int iLimit, addr; |
- if( sqlite3ReadSchema(pParse) ){ |
- goto pragma_out; |
- } |
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ |
iLimit = 0x7fffffff; |
} |
sqlite3BeginWriteOperation(pParse, 0, iDb); |
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); |
- addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); |
+ addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); VdbeCoverage(v); |
sqlite3VdbeAddOp1(v, OP_ResultRow, 1); |
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); |
- sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); |
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v); |
sqlite3VdbeJumpHere(v, addr); |
- }else |
+ break; |
+ } |
#endif |
#ifndef SQLITE_OMIT_PAGER_PRAGMAS |
@@ -680,26 +1143,67 @@ void sqlite3Pragma( |
** PRAGMA [database.]cache_size=N |
** |
** The first form reports the current local setting for the |
- ** page cache size. The local setting can be different from |
- ** the persistent cache size value that is stored in the database |
- ** file itself. The value returned is the maximum number of |
- ** pages in the page cache. The second form sets the local |
- ** page cache size value. It does not change the persistent |
- ** cache size stored on the disk so the cache size will revert |
- ** to its default value when the database is closed and reopened. |
- ** N should be a positive integer. |
+ ** page cache size. The second form sets the local |
+ ** page cache size value. If N is positive then that is the |
+ ** number of pages in the cache. If N is negative, then the |
+ ** number of pages is adjusted so that the cache uses -N kibibytes |
+ ** of memory. |
*/ |
- if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
+ case PragTyp_CACHE_SIZE: { |
assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
if( !zRight ){ |
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); |
}else{ |
- int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); |
+ int size = sqlite3Atoi(zRight); |
pDb->pSchema->cache_size = size; |
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
} |
- }else |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [database.]mmap_size(N) |
+ ** |
+ ** Used to set mapping size limit. The mapping size limit is |
+ ** used to limit the aggregate size of all memory mapped regions of the |
+ ** database file. If this parameter is set to zero, then memory mapping |
+ ** is not used at all. If N is negative, then the default memory map |
+ ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set. |
+ ** The parameter N is measured in bytes. |
+ ** |
+ ** This value is advisory. The underlying VFS is free to memory map |
+ ** as little or as much as it wants. Except, if N is set to 0 then the |
+ ** upper layers will never invoke the xFetch interfaces to the VFS. |
+ */ |
+ case PragTyp_MMAP_SIZE: { |
+ sqlite3_int64 sz; |
+#if SQLITE_MAX_MMAP_SIZE>0 |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ if( zRight ){ |
+ int ii; |
+ sqlite3DecOrHexToI64(zRight, &sz); |
+ if( sz<0 ) sz = sqlite3GlobalConfig.szMmap; |
+ if( pId2->n==0 ) db->szMmap = sz; |
+ for(ii=db->nDb-1; ii>=0; ii--){ |
+ if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ |
+ sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz); |
+ } |
+ } |
+ } |
+ sz = -1; |
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz); |
+#else |
+ sz = 0; |
+ rc = SQLITE_OK; |
+#endif |
+ if( rc==SQLITE_OK ){ |
+ returnSingleInt(pParse, "mmap_size", sz); |
+ }else if( rc!=SQLITE_NOTFOUND ){ |
+ pParse->nErr++; |
+ pParse->rc = rc; |
+ } |
+ break; |
+ } |
/* |
** PRAGMA temp_store |
@@ -712,13 +1216,14 @@ void sqlite3Pragma( |
** Note that it is possible for the library compile-time options to |
** override this setting |
*/ |
- if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ |
+ case PragTyp_TEMP_STORE: { |
if( !zRight ){ |
returnSingleInt(pParse, "temp_store", db->temp_store); |
}else{ |
changeTempStorage(pParse, zRight); |
} |
- }else |
+ break; |
+ } |
/* |
** PRAGMA temp_store_directory |
@@ -730,7 +1235,7 @@ void sqlite3Pragma( |
** If temporary directory is changed, then invalidateTempStorage. |
** |
*/ |
- if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){ |
+ case PragTyp_TEMP_STORE_DIRECTORY: { |
if( !zRight ){ |
if( sqlite3_temp_directory ){ |
sqlite3VdbeSetNumCols(v, 1); |
@@ -742,7 +1247,6 @@ void sqlite3Pragma( |
}else{ |
#ifndef SQLITE_OMIT_WSD |
if( zRight[0] ){ |
- int rc; |
int res; |
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
if( rc!=SQLITE_OK || res==0 ){ |
@@ -764,30 +1268,69 @@ void sqlite3Pragma( |
} |
#endif /* SQLITE_OMIT_WSD */ |
} |
- }else |
+ break; |
+ } |
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE) |
-# if defined(__APPLE__) |
-# define SQLITE_ENABLE_LOCKING_STYLE 1 |
-# else |
-# define SQLITE_ENABLE_LOCKING_STYLE 0 |
-# endif |
+#if SQLITE_OS_WIN |
+ /* |
+ ** PRAGMA data_store_directory |
+ ** PRAGMA data_store_directory = ""|"directory_name" |
+ ** |
+ ** Return or set the local value of the data_store_directory flag. Changing |
+ ** the value sets a specific directory to be used for database files that |
+ ** were specified with a relative pathname. Setting to a null string reverts |
+ ** to the default database directory, which for database files specified with |
+ ** a relative path will probably be based on the current directory for the |
+ ** process. Database file specified with an absolute path are not impacted |
+ ** by this setting, regardless of its value. |
+ ** |
+ */ |
+ case PragTyp_DATA_STORE_DIRECTORY: { |
+ if( !zRight ){ |
+ if( sqlite3_data_directory ){ |
+ sqlite3VdbeSetNumCols(v, 1); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, |
+ "data_store_directory", SQLITE_STATIC); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
+ } |
+ }else{ |
+#ifndef SQLITE_OMIT_WSD |
+ if( zRight[0] ){ |
+ int res; |
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
+ if( rc!=SQLITE_OK || res==0 ){ |
+ sqlite3ErrorMsg(pParse, "not a writable directory"); |
+ goto pragma_out; |
+ } |
+ } |
+ sqlite3_free(sqlite3_data_directory); |
+ if( zRight[0] ){ |
+ sqlite3_data_directory = sqlite3_mprintf("%s", zRight); |
+ }else{ |
+ sqlite3_data_directory = 0; |
+ } |
+#endif /* SQLITE_OMIT_WSD */ |
+ } |
+ break; |
+ } |
#endif |
+ |
#if SQLITE_ENABLE_LOCKING_STYLE |
/* |
- ** PRAGMA [database.]lock_proxy_file |
- ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path" |
- ** |
- ** Return or set the value of the lock_proxy_file flag. Changing |
- ** the value sets a specific file to be used for database access locks. |
- ** |
- */ |
- if( sqlite3StrICmp(zLeft, "lock_proxy_file")==0 ){ |
+ ** PRAGMA [database.]lock_proxy_file |
+ ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path" |
+ ** |
+ ** Return or set the value of the lock_proxy_file flag. Changing |
+ ** the value sets a specific file to be used for database access locks. |
+ ** |
+ */ |
+ case PragTyp_LOCK_PROXY_FILE: { |
if( !zRight ){ |
Pager *pPager = sqlite3BtreePager(pDb->pBt); |
char *proxy_file_path = NULL; |
sqlite3_file *pFile = sqlite3PagerFile(pPager); |
- sqlite3OsFileControl(pFile, SQLITE_GET_LOCKPROXYFILE, |
+ sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, |
&proxy_file_path); |
if( proxy_file_path ){ |
@@ -813,7 +1356,8 @@ void sqlite3Pragma( |
goto pragma_out; |
} |
} |
- }else |
+ break; |
+ } |
#endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
/* |
@@ -825,8 +1369,7 @@ void sqlite3Pragma( |
** default value will be restored the next time the database is |
** opened. |
*/ |
- if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
+ case PragTyp_SYNCHRONOUS: { |
if( !zRight ){ |
returnSingleInt(pParse, "synchronous", pDb->safety_level-1); |
}else{ |
@@ -834,17 +1377,49 @@ void sqlite3Pragma( |
sqlite3ErrorMsg(pParse, |
"Safety level may not be changed inside a transaction"); |
}else{ |
- pDb->safety_level = getSafetyLevel(zRight)+1; |
+ pDb->safety_level = getSafetyLevel(zRight,0,1)+1; |
+ setAllPagerFlags(db); |
} |
} |
- }else |
+ break; |
+ } |
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ |
#ifndef SQLITE_OMIT_FLAG_PRAGMAS |
- if( flagPragma(pParse, zLeft, zRight) ){ |
- /* The flagPragma() subroutine also generates any necessary code |
- ** there is nothing more to do here */ |
- }else |
+ case PragTyp_FLAG: { |
+ if( zRight==0 ){ |
+ returnSingleInt(pParse, aPragmaNames[mid].zName, |
+ (db->flags & aPragmaNames[mid].iArg)!=0 ); |
+ }else{ |
+ int mask = aPragmaNames[mid].iArg; /* Mask of bits to set or clear. */ |
+ if( db->autoCommit==0 ){ |
+ /* Foreign key support may not be enabled or disabled while not |
+ ** in auto-commit mode. */ |
+ mask &= ~(SQLITE_ForeignKeys); |
+ } |
+#if SQLITE_USER_AUTHENTICATION |
+ if( db->auth.authLevel==UAUTH_User ){ |
+ /* Do not allow non-admin users to modify the schema arbitrarily */ |
+ mask &= ~(SQLITE_WriteSchema); |
+ } |
+#endif |
+ |
+ if( sqlite3GetBoolean(zRight, 0) ){ |
+ db->flags |= mask; |
+ }else{ |
+ db->flags &= ~mask; |
+ if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; |
+ } |
+ |
+ /* Many of the flag-pragmas modify the code generated by the SQL |
+ ** compiler (eg. count_changes). So add an opcode to expire all |
+ ** compiled SQL statements after modifying a pragma value. |
+ */ |
+ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); |
+ setAllPagerFlags(db); |
+ } |
+ break; |
+ } |
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ |
#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS |
@@ -860,16 +1435,17 @@ void sqlite3Pragma( |
** notnull: True if 'NOT NULL' is part of column declaration |
** dflt_value: The default value for the column, if any. |
*/ |
- if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
+ case PragTyp_TABLE_INFO: if( zRight ){ |
Table *pTab; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
pTab = sqlite3FindTable(db, zRight, zDb); |
if( pTab ){ |
- int i; |
+ int i, k; |
int nHidden = 0; |
Column *pCol; |
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
sqlite3VdbeSetNumCols(v, 6); |
pParse->nMem = 6; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
@@ -892,27 +1468,67 @@ void sqlite3Pragma( |
}else{ |
sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
} |
- sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6); |
+ if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ |
+ k = 0; |
+ }else if( pPk==0 ){ |
+ k = 1; |
+ }else{ |
+ for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Integer, k, 6); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
} |
} |
- }else |
+ } |
+ break; |
+ |
+ case PragTyp_STATS: { |
+ Index *pIdx; |
+ HashElem *i; |
+ v = sqlite3GetVdbe(pParse); |
+ sqlite3VdbeSetNumCols(v, 4); |
+ pParse->nMem = 4; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC); |
+ for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ |
+ Table *pTab = sqliteHashData(i); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0); |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, 2); |
+ sqlite3VdbeAddOp2(v, OP_Integer, |
+ (int)sqlite3LogEstToInt(pTab->szTabRow), 3); |
+ sqlite3VdbeAddOp2(v, OP_Integer, |
+ (int)sqlite3LogEstToInt(pTab->nRowLogEst), 4); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); |
+ sqlite3VdbeAddOp2(v, OP_Integer, |
+ (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3); |
+ sqlite3VdbeAddOp2(v, OP_Integer, |
+ (int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0]), 4); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
+ } |
+ } |
+ } |
+ break; |
- if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ |
+ case PragTyp_INDEX_INFO: if( zRight ){ |
Index *pIdx; |
Table *pTab; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
pIdx = sqlite3FindIndex(db, zRight, zDb); |
if( pIdx ){ |
int i; |
pTab = pIdx->pTable; |
sqlite3VdbeSetNumCols(v, 3); |
pParse->nMem = 3; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); |
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); |
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); |
- for(i=0; i<pIdx->nColumn; i++){ |
- int cnum = pIdx->aiColumn[i]; |
+ for(i=0; i<pIdx->nKeyCol; i++){ |
+ i16 cnum = pIdx->aiColumn[i]; |
sqlite3VdbeAddOp2(v, OP_Integer, i, 1); |
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); |
assert( pTab->nCol>cnum ); |
@@ -920,38 +1536,34 @@ void sqlite3Pragma( |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
} |
} |
- }else |
+ } |
+ break; |
- if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){ |
+ case PragTyp_INDEX_LIST: if( zRight ){ |
Index *pIdx; |
Table *pTab; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
+ int i; |
pTab = sqlite3FindTable(db, zRight, zDb); |
if( pTab ){ |
v = sqlite3GetVdbe(pParse); |
- pIdx = pTab->pIndex; |
- if( pIdx ){ |
- int i = 0; |
- sqlite3VdbeSetNumCols(v, 3); |
- pParse->nMem = 3; |
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); |
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); |
- while(pIdx){ |
- sqlite3VdbeAddOp2(v, OP_Integer, i, 1); |
- sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); |
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); |
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
- ++i; |
- pIdx = pIdx->pNext; |
- } |
+ sqlite3VdbeSetNumCols(v, 3); |
+ pParse->nMem = 3; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); |
+ for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ |
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); |
+ sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
} |
} |
- }else |
+ } |
+ break; |
- if( sqlite3StrICmp(zLeft, "database_list")==0 ){ |
+ case PragTyp_DATABASE_LIST: { |
int i; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
sqlite3VdbeSetNumCols(v, 3); |
pParse->nMem = 3; |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); |
@@ -966,9 +1578,10 @@ void sqlite3Pragma( |
sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
} |
- }else |
+ } |
+ break; |
- if( sqlite3StrICmp(zLeft, "collation_list")==0 ){ |
+ case PragTyp_COLLATION_LIST: { |
int i = 0; |
HashElem *p; |
sqlite3VdbeSetNumCols(v, 2); |
@@ -981,14 +1594,14 @@ void sqlite3Pragma( |
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); |
} |
- }else |
+ } |
+ break; |
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ |
#ifndef SQLITE_OMIT_FOREIGN_KEY |
- if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){ |
+ case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ |
FKey *pFK; |
Table *pTab; |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
pTab = sqlite3FindTable(db, zRight, zDb); |
if( pTab ){ |
v = sqlite3GetVdbe(pParse); |
@@ -997,6 +1610,7 @@ void sqlite3Pragma( |
int i = 0; |
sqlite3VdbeSetNumCols(v, 8); |
pParse->nMem = 8; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC); |
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC); |
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC); |
@@ -1027,59 +1641,191 @@ void sqlite3Pragma( |
} |
} |
} |
- }else |
+ } |
+ break; |
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
+ |
+#ifndef SQLITE_OMIT_FOREIGN_KEY |
+#ifndef SQLITE_OMIT_TRIGGER |
+ case PragTyp_FOREIGN_KEY_CHECK: { |
+ FKey *pFK; /* A foreign key constraint */ |
+ Table *pTab; /* Child table contain "REFERENCES" keyword */ |
+ Table *pParent; /* Parent table that child points to */ |
+ Index *pIdx; /* Index in the parent table */ |
+ int i; /* Loop counter: Foreign key number for pTab */ |
+ int j; /* Loop counter: Field of the foreign key */ |
+ HashElem *k; /* Loop counter: Next table in schema */ |
+ int x; /* result variable */ |
+ int regResult; /* 3 registers to hold a result row */ |
+ int regKey; /* Register to hold key for checking the FK */ |
+ int regRow; /* Registers to hold a row from pTab */ |
+ int addrTop; /* Top of a loop checking foreign keys */ |
+ int addrOk; /* Jump here if the key is OK */ |
+ int *aiCols; /* child to parent column mapping */ |
+ |
+ regResult = pParse->nMem+1; |
+ pParse->nMem += 4; |
+ regKey = ++pParse->nMem; |
+ regRow = ++pParse->nMem; |
+ v = sqlite3GetVdbe(pParse); |
+ sqlite3VdbeSetNumCols(v, 4); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); |
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); |
+ while( k ){ |
+ if( zRight ){ |
+ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); |
+ k = 0; |
+ }else{ |
+ pTab = (Table*)sqliteHashData(k); |
+ k = sqliteHashNext(k); |
+ } |
+ if( pTab==0 || pTab->pFKey==0 ) continue; |
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); |
+ if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; |
+ sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, |
+ P4_TRANSIENT); |
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb); |
+ if( pParent==0 ) continue; |
+ pIdx = 0; |
+ sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); |
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); |
+ if( x==0 ){ |
+ if( pIdx==0 ){ |
+ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
+ } |
+ }else{ |
+ k = 0; |
+ break; |
+ } |
+ } |
+ assert( pParse->nErr>0 || pFK==0 ); |
+ if( pFK ) break; |
+ if( pParse->nTab<i ) pParse->nTab = i; |
+ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); |
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb); |
+ pIdx = 0; |
+ aiCols = 0; |
+ if( pParent ){ |
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); |
+ assert( x==0 ); |
+ } |
+ addrOk = sqlite3VdbeMakeLabel(v); |
+ if( pParent && pIdx==0 ){ |
+ int iKey = pFK->aCol[0].iFrom; |
+ assert( iKey>=0 && iKey<pTab->nCol ); |
+ if( iKey!=pTab->iPKey ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); |
+ sqlite3ColumnDefault(v, pTab, iKey, regRow); |
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, |
+ sqlite3VdbeCurrentAddr(v)+3); VdbeCoverage(v); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); |
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
+ }else{ |
+ for(j=0; j<pFK->nCol; j++){ |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, |
+ aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); |
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); |
+ } |
+ if( pParent ){ |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, |
+ sqlite3IndexAffinityStr(v,pIdx), pFK->nCol); |
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); |
+ VdbeCoverage(v); |
+ } |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, |
+ pFK->zTo, P4_TRANSIENT); |
+ sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); |
+ sqlite3VdbeResolveLabel(v, addrOk); |
+ sqlite3DbFree(db, aiCols); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addrTop); |
+ } |
+ } |
+ break; |
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
#ifndef NDEBUG |
- if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
+ case PragTyp_PARSER_TRACE: { |
if( zRight ){ |
- if( getBoolean(zRight) ){ |
+ if( sqlite3GetBoolean(zRight, 0) ){ |
sqlite3ParserTrace(stderr, "parser: "); |
}else{ |
sqlite3ParserTrace(0, 0); |
} |
} |
- }else |
+ } |
+ break; |
#endif |
/* Reinstall the LIKE and GLOB functions. The variant of LIKE |
** used will be case sensitive or not depending on the RHS. |
*/ |
- if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ |
+ case PragTyp_CASE_SENSITIVE_LIKE: { |
if( zRight ){ |
- sqlite3RegisterLikeFunctions(db, getBoolean(zRight)); |
+ sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); |
} |
- }else |
+ } |
+ break; |
#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 |
#endif |
#ifndef SQLITE_OMIT_INTEGRITY_CHECK |
- /* Pragma "quick_check" is an experimental reduced version of |
+ /* Pragma "quick_check" is reduced version of |
** integrity_check designed to detect most database corruption |
** without most of the overhead of a full integrity-check. |
*/ |
- if( sqlite3StrICmp(zLeft, "integrity_check")==0 |
- || sqlite3StrICmp(zLeft, "quick_check")==0 |
- ){ |
+ case PragTyp_INTEGRITY_CHECK: { |
int i, j, addr, mxErr; |
/* Code that appears at the end of the integrity check. If no error |
** messages have been generated, output OK. Otherwise output the |
** error message |
*/ |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
static const VdbeOpList endCode[] = { |
- { OP_AddImm, 1, 0, 0}, /* 0 */ |
- { OP_IfNeg, 1, 0, 0}, /* 1 */ |
- { OP_String8, 0, 3, 0}, /* 2 */ |
+ { OP_IfNeg, 1, 0, 0}, /* 0 */ |
+ { OP_String8, 0, 3, 0}, /* 1 */ |
{ OP_ResultRow, 3, 1, 0}, |
}; |
- int isQuick = (zLeft[0]=='q'); |
+ int isQuick = (sqlite3Tolower(zLeft[0])=='q'); |
+ |
+ /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check", |
+ ** then iDb is set to the index of the database identified by <db>. |
+ ** In this case, the integrity of database iDb only is verified by |
+ ** the VDBE created below. |
+ ** |
+ ** Otherwise, if the command was simply "PRAGMA integrity_check" (or |
+ ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb |
+ ** to -1 here, to indicate that the VDBE should verify the integrity |
+ ** of all attached databases. */ |
+ assert( iDb>=0 ); |
+ assert( iDb==0 || pId2->z ); |
+ if( pId2->z==0 ) iDb = -1; |
/* Initialize the VDBE program */ |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
pParse->nMem = 6; |
sqlite3VdbeSetNumCols(v, 1); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); |
@@ -1101,9 +1847,11 @@ void sqlite3Pragma( |
int cnt = 0; |
if( OMIT_TEMPDB && i==1 ) continue; |
+ if( iDb>=0 && i!=iDb ) continue; |
sqlite3CodeVerifySchema(pParse, i); |
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ |
+ VdbeCoverage(v); |
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
sqlite3VdbeJumpHere(v, addr); |
@@ -1112,28 +1860,30 @@ void sqlite3Pragma( |
** Begin by filling registers 2, 3, ... with the root pages numbers |
** for all tables and indices in the database. |
*/ |
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ assert( sqlite3SchemaMutexHeld(db, i, 0) ); |
pTbls = &db->aDb[i].pSchema->tblHash; |
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
Table *pTab = sqliteHashData(x); |
Index *pIdx; |
- sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); |
- cnt++; |
+ if( HasRowid(pTab) ){ |
+ sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); |
+ VdbeComment((v, "%s", pTab->zName)); |
+ cnt++; |
+ } |
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt); |
+ VdbeComment((v, "%s", pIdx->zName)); |
cnt++; |
} |
} |
/* Make sure sufficient number of registers have been allocated */ |
- if( pParse->nMem < cnt+4 ){ |
- pParse->nMem = cnt+4; |
- } |
+ pParse->nMem = MAX( pParse->nMem, cnt+8 ); |
/* Do the b-tree integrity checks */ |
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); |
sqlite3VdbeChangeP5(v, (u8)i); |
- addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); |
+ addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); |
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), |
P4_DYNAMIC); |
@@ -1146,77 +1896,127 @@ void sqlite3Pragma( |
*/ |
for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ |
Table *pTab = sqliteHashData(x); |
- Index *pIdx; |
+ Index *pIdx, *pPk; |
+ Index *pPrior = 0; |
int loopTop; |
+ int iDataCur, iIdxCur; |
+ int r1 = -1; |
if( pTab->pIndex==0 ) continue; |
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ |
+ VdbeCoverage(v); |
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
sqlite3VdbeJumpHere(v, addr); |
- sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); |
- sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */ |
- loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0); |
- sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */ |
+ sqlite3ExprCacheClear(pParse); |
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, |
+ 1, 0, &iDataCur, &iIdxCur); |
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); |
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
- int jmp2; |
- int r1; |
- static const VdbeOpList idxErr[] = { |
- { OP_AddImm, 1, -1, 0}, |
- { OP_String8, 0, 3, 0}, /* 1 */ |
- { OP_Rowid, 1, 4, 0}, |
- { OP_String8, 0, 5, 0}, /* 3 */ |
- { OP_String8, 0, 6, 0}, /* 4 */ |
- { OP_Concat, 4, 3, 3}, |
- { OP_Concat, 5, 3, 3}, |
- { OP_Concat, 6, 3, 3}, |
- { OP_ResultRow, 3, 1, 0}, |
- { OP_IfPos, 1, 0, 0}, /* 9 */ |
- { OP_Halt, 0, 0, 0}, |
- }; |
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0); |
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1); |
- addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); |
- sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC); |
- sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC); |
- sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_TRANSIENT); |
- sqlite3VdbeJumpHere(v, addr+9); |
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ |
+ } |
+ pParse->nMem = MAX(pParse->nMem, 8+j); |
+ sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); |
+ loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); |
+ /* Verify that all NOT NULL columns really are NOT NULL */ |
+ for(j=0; j<pTab->nCol; j++){ |
+ char *zErr; |
+ int jmp2, jmp3; |
+ if( j==pTab->iPKey ) continue; |
+ if( pTab->aCol[j].notNull==0 ) continue; |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); |
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); |
+ jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
+ zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, |
+ pTab->aCol[j].zName); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); |
+ jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp0(v, OP_Halt); |
sqlite3VdbeJumpHere(v, jmp2); |
+ sqlite3VdbeJumpHere(v, jmp3); |
} |
- sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1); |
- sqlite3VdbeJumpHere(v, loopTop); |
+ /* Validate index entries for the current row */ |
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
- static const VdbeOpList cntIdx[] = { |
- { OP_Integer, 0, 3, 0}, |
- { OP_Rewind, 0, 0, 0}, /* 1 */ |
- { OP_AddImm, 3, 1, 0}, |
- { OP_Next, 0, 0, 0}, /* 3 */ |
- { OP_Eq, 2, 0, 3}, /* 4 */ |
- { OP_AddImm, 1, -1, 0}, |
- { OP_String8, 0, 2, 0}, /* 6 */ |
- { OP_String8, 0, 3, 0}, /* 7 */ |
- { OP_Concat, 3, 2, 2}, |
- { OP_ResultRow, 2, 1, 0}, |
- }; |
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); |
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
- sqlite3VdbeJumpHere(v, addr); |
- addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); |
- sqlite3VdbeChangeP1(v, addr+1, j+2); |
- sqlite3VdbeChangeP2(v, addr+1, addr+4); |
- sqlite3VdbeChangeP1(v, addr+3, j+2); |
- sqlite3VdbeChangeP2(v, addr+3, addr+2); |
- sqlite3VdbeJumpHere(v, addr+4); |
- sqlite3VdbeChangeP4(v, addr+6, |
+ int jmp2, jmp3, jmp4, jmp5; |
+ int ckUniq = sqlite3VdbeMakeLabel(v); |
+ if( pPk==pIdx ) continue; |
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, |
+ pPrior, r1); |
+ pPrior = pIdx; |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ |
+ /* Verify that an index entry exists for the current table row */ |
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, |
+ pIdx->nColumn); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, |
+ " missing from index ", P4_STATIC); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
+ jmp5 = sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, |
+ pIdx->zName, P4_TRANSIENT); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); |
+ jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp0(v, OP_Halt); |
+ sqlite3VdbeJumpHere(v, jmp2); |
+ /* For UNIQUE indexes, verify that only one entry exists with the |
+ ** current key. The entry is unique if (1) any column is NULL |
+ ** or (2) the next entry has a different key */ |
+ if( IsUniqueIndex(pIdx) ){ |
+ int uniqOk = sqlite3VdbeMakeLabel(v); |
+ int jmp6; |
+ int kk; |
+ for(kk=0; kk<pIdx->nKeyCol; kk++){ |
+ int iCol = pIdx->aiColumn[kk]; |
+ assert( iCol>=0 && iCol<pTab->nCol ); |
+ if( pTab->aCol[iCol].notNull ) continue; |
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); |
+ VdbeCoverage(v); |
+ } |
+ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, uniqOk); |
+ sqlite3VdbeJumpHere(v, jmp6); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, |
+ pIdx->nKeyCol); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
+ "non-unique entry in index ", P4_STATIC); |
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, jmp5); |
+ sqlite3VdbeResolveLabel(v, uniqOk); |
+ } |
+ sqlite3VdbeJumpHere(v, jmp4); |
+ sqlite3ResolvePartIdxLabel(pParse, jmp3); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, loopTop-1); |
+#ifndef SQLITE_OMIT_BTREECOUNT |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, |
"wrong # of entries in index ", P4_STATIC); |
- sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT); |
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
+ if( pPk==pIdx ) continue; |
+ addr = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); |
+ sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); |
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); |
} |
+#endif /* SQLITE_OMIT_BTREECOUNT */ |
} |
} |
- addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); |
- sqlite3VdbeChangeP2(v, addr, -mxErr); |
- sqlite3VdbeJumpHere(v, addr+1); |
- sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); |
- }else |
+ addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
+ sqlite3VdbeChangeP3(v, addr, -mxErr); |
+ sqlite3VdbeJumpHere(v, addr); |
+ sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC); |
+ } |
+ break; |
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ |
#ifndef SQLITE_OMIT_UTF16 |
@@ -1242,7 +2042,7 @@ void sqlite3Pragma( |
** new database files created using this database handle. It is only |
** useful if invoked immediately after the main database i |
*/ |
- if( sqlite3StrICmp(zLeft, "encoding")==0 ){ |
+ case PragTyp_ENCODING: { |
static const struct EncName { |
char *zName; |
u8 enc; |
@@ -1289,7 +2089,8 @@ void sqlite3Pragma( |
} |
} |
} |
- }else |
+ } |
+ break; |
#endif /* SQLITE_OMIT_UTF16 */ |
#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS |
@@ -1300,6 +2101,11 @@ void sqlite3Pragma( |
** PRAGMA [database.]user_version |
** PRAGMA [database.]user_version = <integer> |
** |
+ ** PRAGMA [database.]freelist_count = <integer> |
+ ** |
+ ** PRAGMA [database.]application_id |
+ ** PRAGMA [database.]application_id = <integer> |
+ ** |
** The pragma's schema_version and user_version are used to set or get |
** the value of the schema-version and user-version, respectively. Both |
** the schema-version and the user-version are 32-bit signed integers |
@@ -1318,13 +2124,13 @@ void sqlite3Pragma( |
** The user-version is not used internally by SQLite. It may be used by |
** applications for any purpose. |
*/ |
- if( sqlite3StrICmp(zLeft, "schema_version")==0 |
- || sqlite3StrICmp(zLeft, "user_version")==0 |
- || sqlite3StrICmp(zLeft, "freelist_count")==0 |
- ){ |
+ case PragTyp_HEADER_VALUE: { |
int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ |
sqlite3VdbeUsesBtree(v, iDb); |
switch( zLeft[0] ){ |
+ case 'a': case 'A': |
+ iCookie = BTREE_APPLICATION_ID; |
+ break; |
case 'f': case 'F': |
iCookie = BTREE_FREE_PAGE_COUNT; |
break; |
@@ -1343,7 +2149,7 @@ void sqlite3Pragma( |
{ OP_Integer, 0, 1, 0}, /* 1 */ |
{ OP_SetCookie, 0, 0, 1}, /* 2 */ |
}; |
- int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); |
+ int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); |
sqlite3VdbeChangeP1(v, addr, iDb); |
sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); |
sqlite3VdbeChangeP1(v, addr+2, iDb); |
@@ -1355,14 +2161,15 @@ void sqlite3Pragma( |
{ OP_ReadCookie, 0, 1, 0}, /* 1 */ |
{ OP_ResultRow, 1, 1, 0} |
}; |
- int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); |
+ int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0); |
sqlite3VdbeChangeP1(v, addr, iDb); |
sqlite3VdbeChangeP1(v, addr+1, iDb); |
sqlite3VdbeChangeP3(v, addr+1, iCookie); |
sqlite3VdbeSetNumCols(v, 1); |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); |
} |
- }else |
+ } |
+ break; |
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ |
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
@@ -1372,7 +2179,7 @@ void sqlite3Pragma( |
** Return the names of all compile-time options used in this build, |
** one option per row. |
*/ |
- if( sqlite3StrICmp(zLeft, "compile_options")==0 ){ |
+ case PragTyp_COMPILE_OPTIONS: { |
int i = 0; |
const char *zOpt; |
sqlite3VdbeSetNumCols(v, 1); |
@@ -1382,7 +2189,8 @@ void sqlite3Pragma( |
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
} |
- }else |
+ } |
+ break; |
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
#ifndef SQLITE_OMIT_WAL |
@@ -1391,7 +2199,7 @@ void sqlite3Pragma( |
** |
** Checkpoint the database. |
*/ |
- if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){ |
+ case PragTyp_WAL_CHECKPOINT: { |
int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); |
int eMode = SQLITE_CHECKPOINT_PASSIVE; |
if( zRight ){ |
@@ -1401,7 +2209,6 @@ void sqlite3Pragma( |
eMode = SQLITE_CHECKPOINT_RESTART; |
} |
} |
- if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
sqlite3VdbeSetNumCols(v, 3); |
pParse->nMem = 3; |
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); |
@@ -1410,7 +2217,8 @@ void sqlite3Pragma( |
sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
- }else |
+ } |
+ break; |
/* |
** PRAGMA wal_autocheckpoint |
@@ -1420,21 +2228,87 @@ void sqlite3Pragma( |
** after accumulating N frames in the log. Or query for the current value |
** of N. |
*/ |
- if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){ |
+ case PragTyp_WAL_AUTOCHECKPOINT: { |
if( zRight ){ |
sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); |
} |
returnSingleInt(pParse, "wal_autocheckpoint", |
db->xWalCallback==sqlite3WalDefaultHook ? |
SQLITE_PTR_TO_INT(db->pWalArg) : 0); |
- }else |
+ } |
+ break; |
#endif |
+ /* |
+ ** PRAGMA shrink_memory |
+ ** |
+ ** This pragma attempts to free as much memory as possible from the |
+ ** current database connection. |
+ */ |
+ case PragTyp_SHRINK_MEMORY: { |
+ sqlite3_db_release_memory(db); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA busy_timeout |
+ ** PRAGMA busy_timeout = N |
+ ** |
+ ** Call sqlite3_busy_timeout(db, N). Return the current timeout value |
+ ** if one is set. If no busy handler or a different busy handler is set |
+ ** then 0 is returned. Setting the busy_timeout to 0 or negative |
+ ** disables the timeout. |
+ */ |
+ /*case PragTyp_BUSY_TIMEOUT*/ default: { |
+ assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT ); |
+ if( zRight ){ |
+ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); |
+ } |
+ returnSingleInt(pParse, "timeout", db->busyTimeout); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA soft_heap_limit |
+ ** PRAGMA soft_heap_limit = N |
+ ** |
+ ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted, |
+ ** use -1. |
+ */ |
+ case PragTyp_SOFT_HEAP_LIMIT: { |
+ sqlite3_int64 N; |
+ if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ |
+ sqlite3_soft_heap_limit64(N); |
+ } |
+ returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1)); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA threads |
+ ** PRAGMA threads = N |
+ ** |
+ ** Configure the maximum number of worker threads. Return the new |
+ ** maximum, which might be less than requested. |
+ */ |
+ case PragTyp_THREADS: { |
+ sqlite3_int64 N; |
+ if( zRight |
+ && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK |
+ && N>=0 |
+ ){ |
+ sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff)); |
+ } |
+ returnSingleInt(pParse, "threads", |
+ sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); |
+ break; |
+ } |
+ |
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
/* |
** Report the current state of file logs for all databases |
*/ |
- if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ |
+ case PragTyp_LOCK_STATUS: { |
static const char *const azLockName[] = { |
"unlocked", "shared", "reserved", "pending", "exclusive" |
}; |
@@ -1445,13 +2319,12 @@ void sqlite3Pragma( |
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC); |
for(i=0; i<db->nDb; i++){ |
Btree *pBt; |
- Pager *pPager; |
const char *zState = "unknown"; |
int j; |
if( db->aDb[i].zName==0 ) continue; |
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC); |
pBt = db->aDb[i].pBt; |
- if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ |
+ if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ |
zState = "closed"; |
}else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, |
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ |
@@ -1460,35 +2333,39 @@ void sqlite3Pragma( |
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); |
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); |
} |
- |
- }else |
+ break; |
+ } |
#endif |
#ifdef SQLITE_HAS_CODEC |
- if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ |
- sqlite3_key(db, zRight, sqlite3Strlen30(zRight)); |
- }else |
- if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){ |
- sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight)); |
- }else |
- if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 || |
- sqlite3StrICmp(zLeft, "hexrekey")==0) ){ |
- int i, h1, h2; |
- char zKey[40]; |
- for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){ |
- h1 += 9*(1&(h1>>6)); |
- h2 += 9*(1&(h2>>6)); |
- zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4); |
- } |
- if( (zLeft[3] & 0xf)==0xb ){ |
- sqlite3_key(db, zKey, i/2); |
- }else{ |
- sqlite3_rekey(db, zKey, i/2); |
+ case PragTyp_KEY: { |
+ if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); |
+ break; |
+ } |
+ case PragTyp_REKEY: { |
+ if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); |
+ break; |
+ } |
+ case PragTyp_HEXKEY: { |
+ if( zRight ){ |
+ u8 iByte; |
+ int i; |
+ char zKey[40]; |
+ for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){ |
+ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); |
+ if( (i&1)!=0 ) zKey[i/2] = iByte; |
+ } |
+ if( (zLeft[3] & 0xf)==0xb ){ |
+ sqlite3_key_v2(db, zDb, zKey, i/2); |
+ }else{ |
+ sqlite3_rekey_v2(db, zDb, zKey, i/2); |
+ } |
} |
- }else |
+ break; |
+ } |
#endif |
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) |
- if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ |
+ case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){ |
#ifdef SQLITE_HAS_CODEC |
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ |
sqlite3_activate_see(&zRight[4]); |
@@ -1499,23 +2376,12 @@ void sqlite3Pragma( |
sqlite3_activate_cerod(&zRight[6]); |
} |
#endif |
- }else |
+ } |
+ break; |
#endif |
- |
- {/* Empty ELSE clause */} |
+ } /* End of the PRAGMA switch */ |
- /* |
- ** Reset the safety level, in case the fullfsync flag or synchronous |
- ** setting changed. |
- */ |
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS |
- if( db->autoCommit ){ |
- sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, |
- (db->flags&SQLITE_FullFSync)!=0, |
- (db->flags&SQLITE_CkptFullFSync)!=0); |
- } |
-#endif |
pragma_out: |
sqlite3DbFree(db, zLeft); |
sqlite3DbFree(db, zRight); |