diff options
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/analyze.c')
| -rw-r--r-- | ext/pdo_sqlite/sqlite/src/analyze.c | 166 |
1 files changed, 94 insertions, 72 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/analyze.c b/ext/pdo_sqlite/sqlite/src/analyze.c index dc1f33286d..1d441019c3 100644 --- a/ext/pdo_sqlite/sqlite/src/analyze.c +++ b/ext/pdo_sqlite/sqlite/src/analyze.c @@ -33,20 +33,25 @@ static void openStatTable( sqlite3 *db = pParse->db; Db *pDb; int iRootPage; + int createStat1 = 0; Table *pStat; Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){ /* The sqlite_stat1 tables does not exist. Create it. ** Note that a side-effect of the CREATE TABLE statement is to leave - ** the rootpage of the new table on the top of the stack. This is + ** the rootpage of the new table in register pParse->regRoot. This is ** important because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)", pDb->zName ); - iRootPage = 0; /* Cause rootpage to be taken from top of stack */ + iRootPage = pParse->regRoot; + createStat1 = 1; /* Cause rootpage to be taken from top of stack */ }else if( zWhere ){ /* The sqlite_stat1 table exists. Delete all entries associated with ** the table zWhere. */ @@ -58,7 +63,7 @@ static void openStatTable( }else{ /* The sqlite_stat1 table already exists. Delete all rows. */ iRootPage = pStat->tnum; - sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb); + sqlite3VdbeAddOp2(v, OP_Clear, pStat->tnum, iDb); } /* Open the sqlite_stat1 table for writing. Unless it was created @@ -66,12 +71,12 @@ static void openStatTable( ** If this vdbe did create the sqlite_stat1 table, then it must have ** already obtained a schema-lock, making the write-lock redundant. */ - if( iRootPage>0 ){ + if( !createStat1 ){ sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); } - sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage); - sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3); + sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb); + sqlite3VdbeChangeP5(v, createStat1); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3); } /* @@ -95,11 +100,11 @@ static void analyzeOneTable( int iDb; /* Index of database containing pTab */ v = sqlite3GetVdbe(pParse); - if( pTab==0 || pTab->pIndex==0 ){ + if( v==0 || pTab==0 || pTab->pIndex==0 ){ /* Do no analysis for tables that have no indices */ return; } - + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION @@ -115,19 +120,27 @@ static void analyzeOneTable( iIdxCur = pParse->nTab; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + int regFields; /* Register block for building records */ + int regRec; /* Register holding completed record */ + int regTemp; /* Temporary use register */ + int regCol; /* Content of a column from the table being analyzed */ + int regRowid; /* Rowid for the inserted record */ + int regF2; /* Open a cursor to the index to be analyzed */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); - sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - VdbeComment((v, "# %s", pIdx->zName)); - sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, - (char *)pKey, P3_KEYINFO_HANDOFF); + sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, + (char *)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); nCol = pIdx->nColumn; - if( iMem+nCol*2>=pParse->nMem ){ - pParse->nMem = iMem+nCol*2+1; + regFields = iMem+nCol*2; + regTemp = regRowid = regCol = regFields+3; + regRec = regCol+1; + if( regRec>pParse->nMem ){ + pParse->nMem = regRec; } - sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, nCol+1); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, nCol+1); /* Memory cells are used as follows: ** @@ -143,37 +156,37 @@ static void analyzeOneTable( ** are initialized to NULL. */ for(i=0; i<=nCol; i++){ - sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i); } for(i=0; i<nCol; i++){ - sqlite3VdbeAddOp(v, OP_MemNull, iMem+nCol+i+1, 0); + sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1); } /* Do the analysis. */ endOfLoop = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop); + sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem); + sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); for(i=0; i<nCol; i++){ - sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i); - sqlite3VdbeAddOp(v, OP_MemLoad, iMem+nCol+i+1, 0); - sqlite3VdbeAddOp(v, OP_Ne, 0x100, 0); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol); + sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1); + /**** TODO: add collating sequence *****/ + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } - sqlite3VdbeAddOp(v, OP_Goto, 0, endOfLoop); + sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); for(i=0; i<nCol; i++){ - addr = sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem+i+1); - sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr); - sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i); - sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, 1); + sqlite3VdbeJumpHere(v, topOfLoop + 2*(i + 1)); + sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1); } sqlite3VdbeResolveLabel(v, endOfLoop); - sqlite3VdbeAddOp(v, OP_Next, iIdxCur, topOfLoop); - sqlite3VdbeAddOp(v, OP_Close, iIdxCur, 0); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); + sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); /* Store the results. ** - ** The result is a single row of the sqlite_stmt1 table. The first + ** The result is a single row of the sqlite_stat1 table. The first ** two columns are the names of the table and index. The third column ** is a string composed of a list of integer statistics about the ** index. The first integer in the list is the total number of entires @@ -189,29 +202,24 @@ static void analyzeOneTable( ** If K>0 then it is always the case the D>0 so division by zero ** is never possible. */ - sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0); - addr = sqlite3VdbeAddOp(v, OP_IfNot, 0, 0); - sqlite3VdbeAddOp(v, OP_NewRowid, iStatCur, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0); - sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, " ", 0); + addr = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); + sqlite3VdbeAddOp4(v, OP_String8, 0, regFields, 0, pTab->zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, regFields+1, 0, pIdx->zName, 0); + regF2 = regFields+2; + sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regF2); for(i=0; i<nCol; i++){ - sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0); - sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0); - sqlite3VdbeAddOp(v, OP_Add, 0, 0); - sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); - sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0); - sqlite3VdbeAddOp(v, OP_Divide, 0, 0); - sqlite3VdbeAddOp(v, OP_ToInt, 0, 0); - if( i==nCol-1 ){ - sqlite3VdbeAddOp(v, OP_Concat, nCol*2-1, 0); - }else{ - sqlite3VdbeAddOp(v, OP_Dup, 1, 0); - } + sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0); + sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); + sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp); + sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1); + sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp); + sqlite3VdbeAddOp1(v, OP_ToInt, regTemp); + sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); } - sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "aaa", 0); - sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeJumpHere(v, addr); } } @@ -222,7 +230,9 @@ static void analyzeOneTable( */ static void loadAnalysis(Parse *pParse, int iDb){ Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3VdbeAddOp(v, OP_LoadAnalysis, iDb, 0); + if( v ){ + sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); + } } /* @@ -238,7 +248,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){ sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab++; openStatTable(pParse, iDb, iStatCur, 0); - iMem = pParse->nMem; + iMem = pParse->nMem+1; for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, iStatCur, iMem); @@ -255,11 +265,12 @@ static void analyzeTable(Parse *pParse, Table *pTab){ int iStatCur; assert( pTab!=0 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab++; openStatTable(pParse, iDb, iStatCur, pTab->zName); - analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem); + analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem+1); loadAnalysis(pParse, iDb); } @@ -285,6 +296,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return; } @@ -301,11 +313,13 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ if( iDb>=0 ){ analyzeDatabase(pParse, iDb); }else{ - z = sqlite3NameFromToken(pName1); - pTab = sqlite3LocateTable(pParse, z, 0); - sqliteFree(z); - if( pTab ){ - analyzeTable(pParse, pTab); + z = sqlite3NameFromToken(db, pName1); + if( z ){ + pTab = sqlite3LocateTable(pParse, 0, z, 0); + sqlite3_free(z); + if( pTab ){ + analyzeTable(pParse, pTab); + } } } }else{ @@ -313,11 +327,13 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ zDb = db->aDb[iDb].zName; - z = sqlite3NameFromToken(pTableName); - pTab = sqlite3LocateTable(pParse, z, zDb); - sqliteFree(z); - if( pTab ){ - analyzeTable(pParse, pTab); + z = sqlite3NameFromToken(db, pTableName); + if( z ){ + pTab = sqlite3LocateTable(pParse, 0, z, zDb); + sqlite3_free(z); + if( pTab ){ + analyzeTable(pParse, pTab); + } } } } @@ -371,10 +387,15 @@ static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){ /* ** Load the content of the sqlite_stat1 table into the index hash tables. */ -void sqlite3AnalysisLoad(sqlite3 *db, int iDb){ +int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ analysisInfo sInfo; HashElem *i; char *zSql; + int rc; + + assert( iDb>=0 && iDb<db->nDb ); + assert( db->aDb[iDb].pBt!=0 ); + assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); /* Clear any prior statistics */ for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ @@ -386,17 +407,18 @@ void sqlite3AnalysisLoad(sqlite3 *db, int iDb){ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zName; if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ - return; + return SQLITE_ERROR; } /* Load new statistics out of the sqlite_stat1 table */ - zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1", + zSql = sqlite3MPrintf(db, "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); - sqlite3SafetyOff(db); - sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); - sqlite3SafetyOn(db); - sqliteFree(zSql); + (void)sqlite3SafetyOff(db); + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + (void)sqlite3SafetyOn(db); + sqlite3_free(zSql); + return rc; } |
