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>