📄 pragma.c
字号:
/*** 2003 April 6**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.***************************************************************************** This file contains code used to implement the PRAGMA command.**** $Id: pragma.c,v 1.19 2004/04/23 17:04:45 drh Exp $*/#include "sqliteInt.h"#include <ctype.h>/*** Interpret the given string as a boolean value.*/static int getBoolean(const char *z){ static char *azTrue[] = { "yes", "on", "true" }; int i; if( z[0]==0 ) return 0; if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){ return atoi(z); } for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){ if( sqliteStrICmp(z,azTrue[i])==0 ) return 1; } return 0;}/*** 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.**** Note that the values returned are one less that the values that** should be passed into sqliteBtreeSetSafetyLevel(). 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 int getSafetyLevel(char *z){ static const struct { const char *zWord; int val; } aKey[] = { { "no", 0 }, { "off", 0 }, { "false", 0 }, { "yes", 1 }, { "on", 1 }, { "true", 1 }, { "full", 2 }, }; int i; if( z[0]==0 ) return 1; if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){ return atoi(z); } for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){ if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val; } return 1;}/*** Interpret the given string as a temp db location. Return 1 for file** backed temporary databases, 2 for the Red-Black tree in memory database** and 0 to use the compile-time default.*/static int getTempStore(const char *z){ if( z[0]>='0' && z[0]<='2' ){ return z[0] - '0'; }else if( sqliteStrICmp(z, "file")==0 ){ return 1; }else if( sqliteStrICmp(z, "memory")==0 ){ return 2; }else{ return 0; }}/*** If the TEMP database is open, close it and mark the database schema** as needing reloading. This must be done when using the TEMP_STORE** or DEFAULT_TEMP_STORE pragmas.*/static int changeTempStorage(Parse *pParse, const char *zStorageType){ int ts = getTempStore(zStorageType); sqlite *db = pParse->db; if( db->temp_store==ts ) return SQLITE_OK; if( db->aDb[1].pBt!=0 ){ if( db->flags & SQLITE_InTrans ){ sqliteErrorMsg(pParse, "temporary storage cannot be changed " "from within a transaction"); return SQLITE_ERROR; } sqliteBtreeClose(db->aDb[1].pBt); db->aDb[1].pBt = 0; sqliteResetInternalSchema(db, 0); } db->temp_store = ts; return SQLITE_OK;}/*** 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.*/static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ static const struct { const char *zName; /* Name of the pragma */ int mask; /* Mask for the db->flags value */ } aPragma[] = { { "vdbe_trace", SQLITE_VdbeTrace }, { "full_column_names", SQLITE_FullColNames }, { "short_column_names", SQLITE_ShortColNames }, { "show_datatypes", SQLITE_ReportTypes }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, }; int i; for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){ if( sqliteStrICmp(zLeft, aPragma[i].zName)==0 ){ sqlite *db = pParse->db; Vdbe *v; if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){ sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC); sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC); sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0, OP_Callback, 1, 0, 0); }else if( getBoolean(zRight) ){ db->flags |= aPragma[i].mask; }else{ db->flags &= ~aPragma[i].mask; } return 1; } } return 0;}/*** Process a pragma statement. **** Pragmas are of this form:**** PRAGMA id = value**** The identifier might also be a string. The value is a string, and** identifier, or a number. If minusFlag is true, then the value is** a number that was preceded by a minus sign.*/void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ char *zLeft = 0; char *zRight = 0; sqlite *db = pParse->db; Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return; zLeft = sqliteStrNDup(pLeft->z, pLeft->n); sqliteDequote(zLeft); if( minusFlag ){ zRight = 0; sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0); }else{ zRight = sqliteStrNDup(pRight->z, pRight->n); sqliteDequote(zRight); } if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){ sqliteFree(zLeft); sqliteFree(zRight); return; } /* ** PRAGMA default_cache_size ** PRAGMA default_cache_size=N ** ** The first form reports the current persistent setting for the ** page cache size. The value returned is the maximum number of ** pages in the page cache. The second form sets both the current ** page cache size value and the persistent page cache size value ** stored in the database file. ** ** The default cache size is stored in meta-value 2 of page 1 of the ** database file. The cache size is actually the absolute value of ** this memory location. The sign of meta-value 2 determines the ** synchronous setting. A negative value means synchronous is off ** and a positive value means synchronous is on. */ if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){ static VdbeOpList getCacheSize[] = { { OP_ReadCookie, 0, 2, 0}, { OP_AbsValue, 0, 0, 0}, { OP_Dup, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 6, 0}, { OP_Integer, 0, 0, 0}, /* 5 */ { OP_ColumnName, 0, 1, "cache_size"}, { OP_Callback, 1, 0, 0}, }; int addr; if( pRight->z==pLeft->z ){ addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqliteVdbeChangeP1(v, addr+5, MAX_PAGES); }else{ int size = atoi(zRight); if( size<0 ) size = -size; sqliteBeginWriteOperation(pParse, 0, 0); sqliteVdbeAddOp(v, OP_Integer, size, 0); sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeAddOp(v, OP_Ge, 0, addr+3); sqliteVdbeAddOp(v, OP_Negative, 0, 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); sqliteEndWriteOperation(pParse); db->cache_size = db->cache_size<0 ? -size : size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); } }else /* ** PRAGMA cache_size ** PRAGMA 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. */ if( sqliteStrICmp(zLeft,"cache_size")==0 ){ static VdbeOpList getCacheSize[] = { { OP_ColumnName, 0, 1, "cache_size"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ int size = db->cache_size;; if( size<0 ) size = -size; sqliteVdbeAddOp(v, OP_Integer, size, 0); sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); }else{ int size = atoi(zRight); if( size<0 ) size = -size; if( db->cache_size<0 ) size = -size; db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); } }else /* ** PRAGMA default_synchronous ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL ** ** The first form returns the persistent value of the "synchronous" setting ** that is stored in the database. This is the synchronous setting that ** is used whenever the database is opened unless overridden by a separate ** "synchronous" pragma. The second form changes the persistent and the ** local synchronous setting to the value given. ** ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls ** to make sure data is committed to disk. Write operations are very fast, ** but a power failure can leave the database in an inconsistent state. ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to ** make sure data is being written to disk. The risk of corruption due to ** a power loss in this mode is negligible but non-zero. If synchronous ** is FULL, extra fsync()s occur to reduce the risk of corruption to near ** zero, but with a write performance penalty. The default mode is NORMAL. */ if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){ static VdbeOpList getSync[] = { { OP_ColumnName, 0, 1, "synchronous"}, { OP_ReadCookie, 0, 3, 0}, { OP_Dup, 0, 0, 0}, { OP_If, 0, 0, 0}, /* 3 */ { OP_ReadCookie, 0, 2, 0}, { OP_Integer, 0, 0, 0}, { OP_Lt, 0, 5, 0}, { OP_AddImm, 1, 0, 0}, { OP_Callback, 1, 0, 0}, { OP_Halt, 0, 0, 0}, { OP_AddImm, -1, 0, 0}, /* 10 */ { OP_Callback, 1, 0, 0} }; if( pRight->z==pLeft->z ){ int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); sqliteVdbeChangeP2(v, addr+3, addr+10); }else{ int addr; int size = db->cache_size; if( size<0 ) size = -size; sqliteBeginWriteOperation(pParse, 0, 0); sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); sqliteVdbeAddOp(v, OP_Dup, 0, 0); addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeAddOp(v, OP_Ne, 0, addr+3); sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0); sqliteVdbeAddOp(v, OP_AbsValue, 0, 0); db->safety_level = getSafetyLevel(zRight)+1; if( db->safety_level==1 ){ sqliteVdbeAddOp(v, OP_Negative, 0, 0); size = -size; } sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 3); sqliteEndWriteOperation(pParse); db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); } }else /* ** PRAGMA synchronous ** PRAGMA synchronous=OFF|ON|NORMAL|FULL ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the ** default value will be restored the next time the database is ** opened. */ if( sqliteStrICmp(zLeft,"synchronous")==0 ){ static VdbeOpList getSync[] = { { OP_ColumnName, 0, 1, "synchronous"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0); sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); }else{ int size = db->cache_size; if( size<0 ) size = -size; db->safety_level = getSafetyLevel(zRight)+1; if( db->safety_level==1 ) size = -size; db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); } }else#ifndef NDEBUG if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){ if( getBoolean(zRight) ){ always_code_trigger_setup = 1; }else{ always_code_trigger_setup = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -