Annotation of embedaddon/php/ext/sqlite/libsqlite/src/pragma.c, revision 1.1
1.1 ! misho 1: /*
! 2: ** 2003 April 6
! 3: **
! 4: ** The author disclaims copyright to this source code. In place of
! 5: ** a legal notice, here is a blessing:
! 6: **
! 7: ** May you do good and not evil.
! 8: ** May you find forgiveness for yourself and forgive others.
! 9: ** May you share freely, never taking more than you give.
! 10: **
! 11: *************************************************************************
! 12: ** This file contains code used to implement the PRAGMA command.
! 13: **
! 14: ** $Id: pragma.c 195361 2005-09-07 15:11:33Z iliaa $
! 15: */
! 16: #include "sqliteInt.h"
! 17: #include <ctype.h>
! 18:
! 19: /*
! 20: ** Interpret the given string as a boolean value.
! 21: */
! 22: static int getBoolean(const char *z){
! 23: static char *azTrue[] = { "yes", "on", "true" };
! 24: int i;
! 25: if( z[0]==0 ) return 0;
! 26: if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
! 27: return atoi(z);
! 28: }
! 29: for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
! 30: if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
! 31: }
! 32: return 0;
! 33: }
! 34:
! 35: /*
! 36: ** Interpret the given string as a safety level. Return 0 for OFF,
! 37: ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
! 38: ** unrecognized string argument.
! 39: **
! 40: ** Note that the values returned are one less that the values that
! 41: ** should be passed into sqliteBtreeSetSafetyLevel(). The is done
! 42: ** to support legacy SQL code. The safety level used to be boolean
! 43: ** and older scripts may have used numbers 0 for OFF and 1 for ON.
! 44: */
! 45: static int getSafetyLevel(char *z){
! 46: static const struct {
! 47: const char *zWord;
! 48: int val;
! 49: } aKey[] = {
! 50: { "no", 0 },
! 51: { "off", 0 },
! 52: { "false", 0 },
! 53: { "yes", 1 },
! 54: { "on", 1 },
! 55: { "true", 1 },
! 56: { "full", 2 },
! 57: };
! 58: int i;
! 59: if( z[0]==0 ) return 1;
! 60: if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
! 61: return atoi(z);
! 62: }
! 63: for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
! 64: if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
! 65: }
! 66: return 1;
! 67: }
! 68:
! 69: /*
! 70: ** Interpret the given string as a temp db location. Return 1 for file
! 71: ** backed temporary databases, 2 for the Red-Black tree in memory database
! 72: ** and 0 to use the compile-time default.
! 73: */
! 74: static int getTempStore(const char *z){
! 75: if( z[0]>='0' && z[0]<='2' ){
! 76: return z[0] - '0';
! 77: }else if( sqliteStrICmp(z, "file")==0 ){
! 78: return 1;
! 79: }else if( sqliteStrICmp(z, "memory")==0 ){
! 80: return 2;
! 81: }else{
! 82: return 0;
! 83: }
! 84: }
! 85:
! 86: /*
! 87: ** If the TEMP database is open, close it and mark the database schema
! 88: ** as needing reloading. This must be done when using the TEMP_STORE
! 89: ** or DEFAULT_TEMP_STORE pragmas.
! 90: */
! 91: static int changeTempStorage(Parse *pParse, const char *zStorageType){
! 92: int ts = getTempStore(zStorageType);
! 93: sqlite *db = pParse->db;
! 94: if( db->temp_store==ts ) return SQLITE_OK;
! 95: if( db->aDb[1].pBt!=0 ){
! 96: if( db->flags & SQLITE_InTrans ){
! 97: sqliteErrorMsg(pParse, "temporary storage cannot be changed "
! 98: "from within a transaction");
! 99: return SQLITE_ERROR;
! 100: }
! 101: sqliteBtreeClose(db->aDb[1].pBt);
! 102: db->aDb[1].pBt = 0;
! 103: sqliteResetInternalSchema(db, 0);
! 104: }
! 105: db->temp_store = ts;
! 106: return SQLITE_OK;
! 107: }
! 108:
! 109: /*
! 110: ** Check to see if zRight and zLeft refer to a pragma that queries
! 111: ** or changes one of the flags in db->flags. Return 1 if so and 0 if not.
! 112: ** Also, implement the pragma.
! 113: */
! 114: static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
! 115: static const struct {
! 116: const char *zName; /* Name of the pragma */
! 117: int mask; /* Mask for the db->flags value */
! 118: } aPragma[] = {
! 119: { "vdbe_trace", SQLITE_VdbeTrace },
! 120: { "full_column_names", SQLITE_FullColNames },
! 121: { "short_column_names", SQLITE_ShortColNames },
! 122: { "show_datatypes", SQLITE_ReportTypes },
! 123: { "count_changes", SQLITE_CountRows },
! 124: { "empty_result_callbacks", SQLITE_NullCallback },
! 125: };
! 126: int i;
! 127: for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
! 128: if( sqliteStrICmp(zLeft, aPragma[i].zName)==0 ){
! 129: sqlite *db = pParse->db;
! 130: Vdbe *v;
! 131: if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){
! 132: sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC);
! 133: sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC);
! 134: sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0,
! 135: OP_Callback, 1, 0,
! 136: 0);
! 137: }else if( getBoolean(zRight) ){
! 138: db->flags |= aPragma[i].mask;
! 139: }else{
! 140: db->flags &= ~aPragma[i].mask;
! 141: }
! 142: return 1;
! 143: }
! 144: }
! 145: return 0;
! 146: }
! 147:
! 148: /*
! 149: ** Process a pragma statement.
! 150: **
! 151: ** Pragmas are of this form:
! 152: **
! 153: ** PRAGMA id = value
! 154: **
! 155: ** The identifier might also be a string. The value is a string, and
! 156: ** identifier, or a number. If minusFlag is true, then the value is
! 157: ** a number that was preceded by a minus sign.
! 158: */
! 159: void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
! 160: char *zLeft = 0;
! 161: char *zRight = 0;
! 162: sqlite *db = pParse->db;
! 163: Vdbe *v = sqliteGetVdbe(pParse);
! 164: if( v==0 ) return;
! 165:
! 166: zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
! 167: sqliteDequote(zLeft);
! 168: if( minusFlag ){
! 169: zRight = 0;
! 170: sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
! 171: }else{
! 172: zRight = sqliteStrNDup(pRight->z, pRight->n);
! 173: sqliteDequote(zRight);
! 174: }
! 175: if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
! 176: sqliteFree(zLeft);
! 177: sqliteFree(zRight);
! 178: return;
! 179: }
! 180:
! 181: /*
! 182: ** PRAGMA default_cache_size
! 183: ** PRAGMA default_cache_size=N
! 184: **
! 185: ** The first form reports the current persistent setting for the
! 186: ** page cache size. The value returned is the maximum number of
! 187: ** pages in the page cache. The second form sets both the current
! 188: ** page cache size value and the persistent page cache size value
! 189: ** stored in the database file.
! 190: **
! 191: ** The default cache size is stored in meta-value 2 of page 1 of the
! 192: ** database file. The cache size is actually the absolute value of
! 193: ** this memory location. The sign of meta-value 2 determines the
! 194: ** synchronous setting. A negative value means synchronous is off
! 195: ** and a positive value means synchronous is on.
! 196: */
! 197: if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
! 198: static VdbeOpList getCacheSize[] = {
! 199: { OP_ReadCookie, 0, 2, 0},
! 200: { OP_AbsValue, 0, 0, 0},
! 201: { OP_Dup, 0, 0, 0},
! 202: { OP_Integer, 0, 0, 0},
! 203: { OP_Ne, 0, 6, 0},
! 204: { OP_Integer, 0, 0, 0}, /* 5 */
! 205: { OP_ColumnName, 0, 1, "cache_size"},
! 206: { OP_Callback, 1, 0, 0},
! 207: };
! 208: int addr;
! 209: if( pRight->z==pLeft->z ){
! 210: addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
! 211: sqliteVdbeChangeP1(v, addr+5, MAX_PAGES);
! 212: }else{
! 213: int size = atoi(zRight);
! 214: if( size<0 ) size = -size;
! 215: sqliteBeginWriteOperation(pParse, 0, 0);
! 216: sqliteVdbeAddOp(v, OP_Integer, size, 0);
! 217: sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
! 218: addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
! 219: sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
! 220: sqliteVdbeAddOp(v, OP_Negative, 0, 0);
! 221: sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
! 222: sqliteEndWriteOperation(pParse);
! 223: db->cache_size = db->cache_size<0 ? -size : size;
! 224: sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
! 225: }
! 226: }else
! 227:
! 228: /*
! 229: ** PRAGMA cache_size
! 230: ** PRAGMA cache_size=N
! 231: **
! 232: ** The first form reports the current local setting for the
! 233: ** page cache size. The local setting can be different from
! 234: ** the persistent cache size value that is stored in the database
! 235: ** file itself. The value returned is the maximum number of
! 236: ** pages in the page cache. The second form sets the local
! 237: ** page cache size value. It does not change the persistent
! 238: ** cache size stored on the disk so the cache size will revert
! 239: ** to its default value when the database is closed and reopened.
! 240: ** N should be a positive integer.
! 241: */
! 242: if( sqliteStrICmp(zLeft,"cache_size")==0 ){
! 243: static VdbeOpList getCacheSize[] = {
! 244: { OP_ColumnName, 0, 1, "cache_size"},
! 245: { OP_Callback, 1, 0, 0},
! 246: };
! 247: if( pRight->z==pLeft->z ){
! 248: int size = db->cache_size;;
! 249: if( size<0 ) size = -size;
! 250: sqliteVdbeAddOp(v, OP_Integer, size, 0);
! 251: sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
! 252: }else{
! 253: int size = atoi(zRight);
! 254: if( size<0 ) size = -size;
! 255: if( db->cache_size<0 ) size = -size;
! 256: db->cache_size = size;
! 257: sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
! 258: }
! 259: }else
! 260:
! 261: /*
! 262: ** PRAGMA default_synchronous
! 263: ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL
! 264: **
! 265: ** The first form returns the persistent value of the "synchronous" setting
! 266: ** that is stored in the database. This is the synchronous setting that
! 267: ** is used whenever the database is opened unless overridden by a separate
! 268: ** "synchronous" pragma. The second form changes the persistent and the
! 269: ** local synchronous setting to the value given.
! 270: **
! 271: ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls
! 272: ** to make sure data is committed to disk. Write operations are very fast,
! 273: ** but a power failure can leave the database in an inconsistent state.
! 274: ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to
! 275: ** make sure data is being written to disk. The risk of corruption due to
! 276: ** a power loss in this mode is negligible but non-zero. If synchronous
! 277: ** is FULL, extra fsync()s occur to reduce the risk of corruption to near
! 278: ** zero, but with a write performance penalty. The default mode is NORMAL.
! 279: */
! 280: if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
! 281: static VdbeOpList getSync[] = {
! 282: { OP_ColumnName, 0, 1, "synchronous"},
! 283: { OP_ReadCookie, 0, 3, 0},
! 284: { OP_Dup, 0, 0, 0},
! 285: { OP_If, 0, 0, 0}, /* 3 */
! 286: { OP_ReadCookie, 0, 2, 0},
! 287: { OP_Integer, 0, 0, 0},
! 288: { OP_Lt, 0, 5, 0},
! 289: { OP_AddImm, 1, 0, 0},
! 290: { OP_Callback, 1, 0, 0},
! 291: { OP_Halt, 0, 0, 0},
! 292: { OP_AddImm, -1, 0, 0}, /* 10 */
! 293: { OP_Callback, 1, 0, 0}
! 294: };
! 295: if( pRight->z==pLeft->z ){
! 296: int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
! 297: sqliteVdbeChangeP2(v, addr+3, addr+10);
! 298: }else{
! 299: int addr;
! 300: int size = db->cache_size;
! 301: if( size<0 ) size = -size;
! 302: sqliteBeginWriteOperation(pParse, 0, 0);
! 303: sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
! 304: sqliteVdbeAddOp(v, OP_Dup, 0, 0);
! 305: addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
! 306: sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
! 307: sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
! 308: sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
! 309: db->safety_level = getSafetyLevel(zRight)+1;
! 310: if( db->safety_level==1 ){
! 311: sqliteVdbeAddOp(v, OP_Negative, 0, 0);
! 312: size = -size;
! 313: }
! 314: sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
! 315: sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
! 316: sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
! 317: sqliteEndWriteOperation(pParse);
! 318: db->cache_size = size;
! 319: sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
! 320: sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
! 321: }
! 322: }else
! 323:
! 324: /*
! 325: ** PRAGMA synchronous
! 326: ** PRAGMA synchronous=OFF|ON|NORMAL|FULL
! 327: **
! 328: ** Return or set the local value of the synchronous flag. Changing
! 329: ** the local value does not make changes to the disk file and the
! 330: ** default value will be restored the next time the database is
! 331: ** opened.
! 332: */
! 333: if( sqliteStrICmp(zLeft,"synchronous")==0 ){
! 334: static VdbeOpList getSync[] = {
! 335: { OP_ColumnName, 0, 1, "synchronous"},
! 336: { OP_Callback, 1, 0, 0},
! 337: };
! 338: if( pRight->z==pLeft->z ){
! 339: sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
! 340: sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
! 341: }else{
! 342: int size = db->cache_size;
! 343: if( size<0 ) size = -size;
! 344: db->safety_level = getSafetyLevel(zRight)+1;
! 345: if( db->safety_level==1 ) size = -size;
! 346: db->cache_size = size;
! 347: sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
! 348: sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
! 349: }
! 350: }else
! 351:
! 352: #ifndef NDEBUG
! 353: if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
! 354: if( getBoolean(zRight) ){
! 355: always_code_trigger_setup = 1;
! 356: }else{
! 357: always_code_trigger_setup = 0;
! 358: }
! 359: }else
! 360: #endif
! 361:
! 362: if( flagPragma(pParse, zLeft, zRight) ){
! 363: /* The flagPragma() call also generates any necessary code */
! 364: }else
! 365:
! 366: if( sqliteStrICmp(zLeft, "table_info")==0 ){
! 367: Table *pTab;
! 368: pTab = sqliteFindTable(db, zRight, 0);
! 369: if( pTab ){
! 370: static VdbeOpList tableInfoPreface[] = {
! 371: { OP_ColumnName, 0, 0, "cid"},
! 372: { OP_ColumnName, 1, 0, "name"},
! 373: { OP_ColumnName, 2, 0, "type"},
! 374: { OP_ColumnName, 3, 0, "notnull"},
! 375: { OP_ColumnName, 4, 0, "dflt_value"},
! 376: { OP_ColumnName, 5, 1, "pk"},
! 377: };
! 378: int i;
! 379: sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
! 380: sqliteViewGetColumnNames(pParse, pTab);
! 381: for(i=0; i<pTab->nCol; i++){
! 382: sqliteVdbeAddOp(v, OP_Integer, i, 0);
! 383: sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0);
! 384: sqliteVdbeOp3(v, OP_String, 0, 0,
! 385: pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
! 386: sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
! 387: sqliteVdbeOp3(v, OP_String, 0, 0,
! 388: pTab->aCol[i].zDflt, P3_STATIC);
! 389: sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
! 390: sqliteVdbeAddOp(v, OP_Callback, 6, 0);
! 391: }
! 392: }
! 393: }else
! 394:
! 395: if( sqliteStrICmp(zLeft, "index_info")==0 ){
! 396: Index *pIdx;
! 397: Table *pTab;
! 398: pIdx = sqliteFindIndex(db, zRight, 0);
! 399: if( pIdx ){
! 400: static VdbeOpList tableInfoPreface[] = {
! 401: { OP_ColumnName, 0, 0, "seqno"},
! 402: { OP_ColumnName, 1, 0, "cid"},
! 403: { OP_ColumnName, 2, 1, "name"},
! 404: };
! 405: int i;
! 406: pTab = pIdx->pTable;
! 407: sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
! 408: for(i=0; i<pIdx->nColumn; i++){
! 409: int cnum = pIdx->aiColumn[i];
! 410: sqliteVdbeAddOp(v, OP_Integer, i, 0);
! 411: sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
! 412: assert( pTab->nCol>cnum );
! 413: sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0);
! 414: sqliteVdbeAddOp(v, OP_Callback, 3, 0);
! 415: }
! 416: }
! 417: }else
! 418:
! 419: if( sqliteStrICmp(zLeft, "index_list")==0 ){
! 420: Index *pIdx;
! 421: Table *pTab;
! 422: pTab = sqliteFindTable(db, zRight, 0);
! 423: if( pTab ){
! 424: v = sqliteGetVdbe(pParse);
! 425: pIdx = pTab->pIndex;
! 426: }
! 427: if( pTab && pIdx ){
! 428: int i = 0;
! 429: static VdbeOpList indexListPreface[] = {
! 430: { OP_ColumnName, 0, 0, "seq"},
! 431: { OP_ColumnName, 1, 0, "name"},
! 432: { OP_ColumnName, 2, 1, "unique"},
! 433: };
! 434:
! 435: sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
! 436: while(pIdx){
! 437: sqliteVdbeAddOp(v, OP_Integer, i, 0);
! 438: sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0);
! 439: sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
! 440: sqliteVdbeAddOp(v, OP_Callback, 3, 0);
! 441: ++i;
! 442: pIdx = pIdx->pNext;
! 443: }
! 444: }
! 445: }else
! 446:
! 447: if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){
! 448: FKey *pFK;
! 449: Table *pTab;
! 450: pTab = sqliteFindTable(db, zRight, 0);
! 451: if( pTab ){
! 452: v = sqliteGetVdbe(pParse);
! 453: pFK = pTab->pFKey;
! 454: }
! 455: if( pTab && pFK ){
! 456: int i = 0;
! 457: static VdbeOpList indexListPreface[] = {
! 458: { OP_ColumnName, 0, 0, "id"},
! 459: { OP_ColumnName, 1, 0, "seq"},
! 460: { OP_ColumnName, 2, 0, "table"},
! 461: { OP_ColumnName, 3, 0, "from"},
! 462: { OP_ColumnName, 4, 1, "to"},
! 463: };
! 464:
! 465: sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
! 466: while(pFK){
! 467: int j;
! 468: for(j=0; j<pFK->nCol; j++){
! 469: sqliteVdbeAddOp(v, OP_Integer, i, 0);
! 470: sqliteVdbeAddOp(v, OP_Integer, j, 0);
! 471: sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0);
! 472: sqliteVdbeOp3(v, OP_String, 0, 0,
! 473: pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
! 474: sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0);
! 475: sqliteVdbeAddOp(v, OP_Callback, 5, 0);
! 476: }
! 477: ++i;
! 478: pFK = pFK->pNextFrom;
! 479: }
! 480: }
! 481: }else
! 482:
! 483: if( sqliteStrICmp(zLeft, "database_list")==0 ){
! 484: int i;
! 485: static VdbeOpList indexListPreface[] = {
! 486: { OP_ColumnName, 0, 0, "seq"},
! 487: { OP_ColumnName, 1, 0, "name"},
! 488: { OP_ColumnName, 2, 1, "file"},
! 489: };
! 490:
! 491: sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
! 492: for(i=0; i<db->nDb; i++){
! 493: if( db->aDb[i].pBt==0 ) continue;
! 494: assert( db->aDb[i].zName!=0 );
! 495: sqliteVdbeAddOp(v, OP_Integer, i, 0);
! 496: sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0);
! 497: sqliteVdbeOp3(v, OP_String, 0, 0,
! 498: sqliteBtreeGetFilename(db->aDb[i].pBt), 0);
! 499: sqliteVdbeAddOp(v, OP_Callback, 3, 0);
! 500: }
! 501: }else
! 502:
! 503:
! 504: /*
! 505: ** PRAGMA temp_store
! 506: ** PRAGMA temp_store = "default"|"memory"|"file"
! 507: **
! 508: ** Return or set the local value of the temp_store flag. Changing
! 509: ** the local value does not make changes to the disk file and the default
! 510: ** value will be restored the next time the database is opened.
! 511: **
! 512: ** Note that it is possible for the library compile-time options to
! 513: ** override this setting
! 514: */
! 515: if( sqliteStrICmp(zLeft, "temp_store")==0 ){
! 516: static VdbeOpList getTmpDbLoc[] = {
! 517: { OP_ColumnName, 0, 1, "temp_store"},
! 518: { OP_Callback, 1, 0, 0},
! 519: };
! 520: if( pRight->z==pLeft->z ){
! 521: sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0);
! 522: sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
! 523: }else{
! 524: changeTempStorage(pParse, zRight);
! 525: }
! 526: }else
! 527:
! 528: /*
! 529: ** PRAGMA default_temp_store
! 530: ** PRAGMA default_temp_store = "default"|"memory"|"file"
! 531: **
! 532: ** Return or set the value of the persistent temp_store flag. Any
! 533: ** change does not take effect until the next time the database is
! 534: ** opened.
! 535: **
! 536: ** Note that it is possible for the library compile-time options to
! 537: ** override this setting
! 538: */
! 539: if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){
! 540: static VdbeOpList getTmpDbLoc[] = {
! 541: { OP_ColumnName, 0, 1, "temp_store"},
! 542: { OP_ReadCookie, 0, 5, 0},
! 543: { OP_Callback, 1, 0, 0}};
! 544: if( pRight->z==pLeft->z ){
! 545: sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
! 546: }else{
! 547: sqliteBeginWriteOperation(pParse, 0, 0);
! 548: sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0);
! 549: sqliteVdbeAddOp(v, OP_SetCookie, 0, 5);
! 550: sqliteEndWriteOperation(pParse);
! 551: }
! 552: }else
! 553:
! 554: #ifndef NDEBUG
! 555: if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
! 556: extern void sqliteParserTrace(FILE*, char *);
! 557: if( getBoolean(zRight) ){
! 558: sqliteParserTrace(stdout, "parser: ");
! 559: }else{
! 560: sqliteParserTrace(0, 0);
! 561: }
! 562: }else
! 563: #endif
! 564:
! 565: if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
! 566: int i, j, addr;
! 567:
! 568: /* Code that initializes the integrity check program. Set the
! 569: ** error count 0
! 570: */
! 571: static VdbeOpList initCode[] = {
! 572: { OP_Integer, 0, 0, 0},
! 573: { OP_MemStore, 0, 1, 0},
! 574: { OP_ColumnName, 0, 1, "integrity_check"},
! 575: };
! 576:
! 577: /* Code to do an BTree integrity check on a single database file.
! 578: */
! 579: static VdbeOpList checkDb[] = {
! 580: { OP_SetInsert, 0, 0, "2"},
! 581: { OP_Integer, 0, 0, 0}, /* 1 */
! 582: { OP_OpenRead, 0, 2, 0},
! 583: { OP_Rewind, 0, 7, 0}, /* 3 */
! 584: { OP_Column, 0, 3, 0}, /* 4 */
! 585: { OP_SetInsert, 0, 0, 0},
! 586: { OP_Next, 0, 4, 0}, /* 6 */
! 587: { OP_IntegrityCk, 0, 0, 0}, /* 7 */
! 588: { OP_Dup, 0, 1, 0},
! 589: { OP_String, 0, 0, "ok"},
! 590: { OP_StrEq, 0, 12, 0}, /* 10 */
! 591: { OP_MemIncr, 0, 0, 0},
! 592: { OP_String, 0, 0, "*** in database "},
! 593: { OP_String, 0, 0, 0}, /* 13 */
! 594: { OP_String, 0, 0, " ***\n"},
! 595: { OP_Pull, 3, 0, 0},
! 596: { OP_Concat, 4, 1, 0},
! 597: { OP_Callback, 1, 0, 0},
! 598: };
! 599:
! 600: /* Code that appears at the end of the integrity check. If no error
! 601: ** messages have been generated, output OK. Otherwise output the
! 602: ** error message
! 603: */
! 604: static VdbeOpList endCode[] = {
! 605: { OP_MemLoad, 0, 0, 0},
! 606: { OP_Integer, 0, 0, 0},
! 607: { OP_Ne, 0, 0, 0}, /* 2 */
! 608: { OP_String, 0, 0, "ok"},
! 609: { OP_Callback, 1, 0, 0},
! 610: };
! 611:
! 612: /* Initialize the VDBE program */
! 613: sqliteVdbeAddOpList(v, ArraySize(initCode), initCode);
! 614:
! 615: /* Do an integrity check on each database file */
! 616: for(i=0; i<db->nDb; i++){
! 617: HashElem *x;
! 618:
! 619: /* Do an integrity check of the B-Tree
! 620: */
! 621: addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
! 622: sqliteVdbeChangeP1(v, addr+1, i);
! 623: sqliteVdbeChangeP2(v, addr+3, addr+7);
! 624: sqliteVdbeChangeP2(v, addr+6, addr+4);
! 625: sqliteVdbeChangeP2(v, addr+7, i);
! 626: sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
! 627: sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
! 628:
! 629: /* Make sure all the indices are constructed correctly.
! 630: */
! 631: sqliteCodeVerifySchema(pParse, i);
! 632: for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
! 633: Table *pTab = sqliteHashData(x);
! 634: Index *pIdx;
! 635: int loopTop;
! 636:
! 637: if( pTab->pIndex==0 ) continue;
! 638: sqliteVdbeAddOp(v, OP_Integer, i, 0);
! 639: sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0);
! 640: for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
! 641: if( pIdx->tnum==0 ) continue;
! 642: sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
! 643: sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0);
! 644: }
! 645: sqliteVdbeAddOp(v, OP_Integer, 0, 0);
! 646: sqliteVdbeAddOp(v, OP_MemStore, 1, 1);
! 647: loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0);
! 648: sqliteVdbeAddOp(v, OP_MemIncr, 1, 0);
! 649: for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
! 650: int k, jmp2;
! 651: static VdbeOpList idxErr[] = {
! 652: { OP_MemIncr, 0, 0, 0},
! 653: { OP_String, 0, 0, "rowid "},
! 654: { OP_Recno, 1, 0, 0},
! 655: { OP_String, 0, 0, " missing from index "},
! 656: { OP_String, 0, 0, 0}, /* 4 */
! 657: { OP_Concat, 4, 0, 0},
! 658: { OP_Callback, 1, 0, 0},
! 659: };
! 660: sqliteVdbeAddOp(v, OP_Recno, 1, 0);
! 661: for(k=0; k<pIdx->nColumn; k++){
! 662: int idx = pIdx->aiColumn[k];
! 663: if( idx==pTab->iPKey ){
! 664: sqliteVdbeAddOp(v, OP_Recno, 1, 0);
! 665: }else{
! 666: sqliteVdbeAddOp(v, OP_Column, 1, idx);
! 667: }
! 668: }
! 669: sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
! 670: if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
! 671: jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0);
! 672: addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr);
! 673: sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
! 674: sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v));
! 675: }
! 676: sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1);
! 677: sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v));
! 678: for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
! 679: static VdbeOpList cntIdx[] = {
! 680: { OP_Integer, 0, 0, 0},
! 681: { OP_MemStore, 2, 1, 0},
! 682: { OP_Rewind, 0, 0, 0}, /* 2 */
! 683: { OP_MemIncr, 2, 0, 0},
! 684: { OP_Next, 0, 0, 0}, /* 4 */
! 685: { OP_MemLoad, 1, 0, 0},
! 686: { OP_MemLoad, 2, 0, 0},
! 687: { OP_Eq, 0, 0, 0}, /* 7 */
! 688: { OP_MemIncr, 0, 0, 0},
! 689: { OP_String, 0, 0, "wrong # of entries in index "},
! 690: { OP_String, 0, 0, 0}, /* 10 */
! 691: { OP_Concat, 2, 0, 0},
! 692: { OP_Callback, 1, 0, 0},
! 693: };
! 694: if( pIdx->tnum==0 ) continue;
! 695: addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
! 696: sqliteVdbeChangeP1(v, addr+2, j+2);
! 697: sqliteVdbeChangeP2(v, addr+2, addr+5);
! 698: sqliteVdbeChangeP1(v, addr+4, j+2);
! 699: sqliteVdbeChangeP2(v, addr+4, addr+3);
! 700: sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
! 701: sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
! 702: }
! 703: }
! 704: }
! 705: addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode);
! 706: sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
! 707: }else
! 708:
! 709: {}
! 710: sqliteFree(zLeft);
! 711: sqliteFree(zRight);
! 712: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>