diff options
author | dan <dan@noemail.net> | 2009-08-19 08:18:32 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2009-08-19 08:18:32 +0000 |
commit | 69188d9a66e32f7d24c0eb333d5999096029f99c (patch) | |
tree | 5596cbec9254af3832cb8b82e9ada683cde6a503 /src | |
parent | e275dc3fb865fad483dad13a37a6b82314c698cb (diff) | |
download | sqlite-69188d9a66e32f7d24c0eb333d5999096029f99c.tar.gz sqlite-69188d9a66e32f7d24c0eb333d5999096029f99c.zip |
Add the SQLITE_ENABLE_STAT2 macro. If this is not defined at build-time, the stat2 table is not created, populated, or used.
FossilOrigin-Name: 362665e89c21fd603d9f8ad6c0ead590e885af7c
Diffstat (limited to 'src')
-rw-r--r-- | src/analyze.c | 111 | ||||
-rw-r--r-- | src/sqliteInt.h | 2 | ||||
-rw-r--r-- | src/test_config.c | 6 | ||||
-rw-r--r-- | src/utf.c | 2 | ||||
-rw-r--r-- | src/where.c | 8 |
5 files changed, 87 insertions, 42 deletions
diff --git a/src/analyze.c b/src/analyze.c index c6c279f27..2e00b54ab 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -18,12 +18,19 @@ /* ** This routine generates code that opens the sqlite_stat1 table for -** writing with cursor iStatCur. The sqlite_stat2 table is opened -** for writing using cursor (iStatCur+1). +** writing with cursor iStatCur. If the library was built with the +** SQLITE_ENABLE_STAT2 macro defined, then the sqlite_stat2 table is +** opened for writing using cursor (iStatCur+1) ** ** If the sqlite_stat1 tables does not previously exist, it is created. -** If it does previously exist, all entires associated with table zWhere -** are removed. If zWhere==0 then all entries are removed. +** Similarly, if the sqlite_stat2 table does not exist and the library +** is compiled with SQLITE_ENABLE_STAT2 defined, it is created. +** +** Argument zWhere may be a pointer to a buffer containing a table name, +** or it may be a NULL pointer. If it is not NULL, then all entries in +** the sqlite_stat1 and (if applicable) sqlite_stat2 tables associated +** with the named table are deleted. If zWhere==0, then code is generated +** to delete all stat table entries. */ static void openStatTable( Parse *pParse, /* Parsing context */ @@ -31,8 +38,16 @@ static void openStatTable( int iStatCur, /* Open the sqlite_stat1 table on this cursor */ const char *zWhere /* Delete entries associated with this table */ ){ - const char *aName[] = { "sqlite_stat1", "sqlite_stat2" }; - const char *aCols[] = { "tbl,idx,stat", "tbl,idx,sampleno,sample" }; + static struct { + const char *zName; + const char *zCols; + } aTable[] = { + { "sqlite_stat1", "tbl,idx,stat" }, +#ifdef SQLITE_ENABLE_STAT2 + { "sqlite_stat2", "tbl,idx,sampleno,sample" }, +#endif + }; + int aRoot[] = {0, 0}; int aCreateTbl[] = {0, 0}; @@ -45,15 +60,16 @@ static void openStatTable( assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; - for(i=0; i<ArraySize(aName); i++){ + for(i=0; i<ArraySize(aTable); i++){ + const char *zTab = aTable[i].zName; Table *pStat; - if( (pStat = sqlite3FindTable(db, aName[i], pDb->zName))==0 ){ + if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){ /* The sqlite_stat[12] table does not exist. Create it. Note that a ** side-effect of the CREATE TABLE statement is to leave 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.%s(%s)", pDb->zName, aName[i], aCols[i] + "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols ); aRoot[i] = pParse->regRoot; aCreateTbl[i] = 1; @@ -62,10 +78,10 @@ static void openStatTable( ** associated with the table zWhere. If zWhere is NULL, delete the ** entire contents of the table. */ aRoot[i] = pStat->tnum; - sqlite3TableLock(pParse, iDb, aRoot[i], 1, aName[i]); + sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); if( zWhere ){ sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE tbl=%Q", pDb->zName, aName[i], zWhere + "DELETE FROM %Q.%s WHERE tbl=%Q", pDb->zName, zTab, zWhere ); }else{ /* The sqlite_stat[12] table already exists. Delete all rows. */ @@ -75,7 +91,7 @@ static void openStatTable( } /* Open the sqlite_stat[12] tables for writing. */ - for(i=0; i<ArraySize(aName); i++){ + for(i=0; i<ArraySize(aTable); i++){ sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb); sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32); sqlite3VdbeChangeP5(v, aCreateTbl[i]); @@ -92,29 +108,30 @@ static void analyzeOneTable( int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ int iMem /* Available memory locations begin here */ ){ - Index *pIdx; /* An index to being analyzed */ - int iIdxCur; /* Index of VdbeCursor for index being analyzed */ - Vdbe *v; /* The virtual machine being built up */ - int i; /* Loop counter */ - int topOfLoop; /* The top of the loop */ - int endOfLoop; /* The end of the loop */ - int addr; /* The address of an instruction */ - int iDb; /* Index of database containing pTab */ - + Index *pIdx; /* An index to being analyzed */ + int iIdxCur; /* Cursor open on index being analyzed */ + Vdbe *v; /* The virtual machine being built up */ + int i; /* Loop counter */ + int topOfLoop; /* The top of the loop */ + int endOfLoop; /* The end of the loop */ + int addr; /* The address of an instruction */ + int iDb; /* Index of database containing pTab */ - /* Assign the required registers. */ int regTabname = iMem++; /* Register containing table name */ int regIdxname = iMem++; /* Register containing index name */ int regSampleno = iMem++; /* Register containing next sample number */ int regCol = iMem++; /* Content of a column analyzed table */ - int regSamplerecno = iMem++; /* Next sample index record number */ - int regRecno = iMem++; /* Register next index record number */ int regRec = iMem++; /* Register holding completed record */ int regTemp = iMem++; /* Temporary use register */ - int regTemp2 = iMem++; /* Temporary use register */ int regRowid = iMem++; /* Rowid for the inserted record */ + +#ifdef SQLITE_ENABLE_STAT2 + int regTemp2 = iMem++; /* Temporary use register */ + int regSamplerecno = iMem++; /* Next sample index record number */ + int regRecno = iMem++; /* Register next index record number */ int regCount = iMem++; /* Total number of records in table */ +#endif v = sqlite3GetVdbe(pParse); if( v==0 || NEVER(pTab==0) || pTab->pIndex==0 ){ @@ -149,14 +166,19 @@ static void analyzeOneTable( (char *)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); + /* Populate the registers containing the table and index names. */ + if( pTab->pIndex==pIdx ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); + } + sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); + +#ifdef SQLITE_ENABLE_STAT2 /* If this iteration of the loop is generating code to analyze the ** first index in the pTab->pIndex list, then register regCount has ** not been populated. In this case populate it now. */ if( pTab->pIndex==pIdx ){ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount); - sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); } - sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); /* Zero the regSampleno and regRecno registers. */ sqlite3VdbeAddOp2(v, OP_Integer, 0, regSampleno); @@ -171,6 +193,7 @@ static void analyzeOneTable( sqlite3VdbeAddOp3(v, OP_Lt, regSamplerecno, sqlite3VdbeCurrentAddr(v)+2, regCount); sqlite3VdbeAddOp2(v, OP_Integer, 0, regSamplerecno); +#endif /* Memory cells are used as follows. All memory cell addresses are ** offset by iMem. That is, cell 0 below is actually cell iMem, cell @@ -204,8 +227,8 @@ static void analyzeOneTable( for(i=0; i<nCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol); +#ifdef SQLITE_ENABLE_STAT2 if( i==0 ){ - /* Check if the record that cursor iIdxCur points to contains a ** value that should be stored in the sqlite_stat2 table. If so, ** store it. */ @@ -234,8 +257,11 @@ static void analyzeOneTable( sqlite3VdbeJumpHere(v, ne); sqlite3VdbeAddOp2(v, OP_AddImm, regRecno, 1); } - assert( sqlite3VdbeCurrentAddr(v)==(topOfLoop+14+2*i) ); +#else + assert( sqlite3VdbeCurrentAddr(v)==(topOfLoop+2+2*i) ); +#endif + sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1); /**** TODO: add collating sequence *****/ @@ -243,7 +269,11 @@ static void analyzeOneTable( } sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); for(i=0; i<nCol; i++){ +#ifdef SQLITE_ENABLE_STAT2 sqlite3VdbeJumpHere(v, topOfLoop+14+2*i); +#else + sqlite3VdbeJumpHere(v, topOfLoop+2+2*i); +#endif sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1); } @@ -495,6 +525,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ } /* Load the statistics from the sqlite_stat2 table. */ +#ifdef SQLITE_ENABLE_STAT2 if( rc==SQLITE_OK ){ sqlite3_stmt *pStmt = 0; @@ -522,12 +553,11 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ int eType = sqlite3_column_type(pStmt, 2); if( pIdx->aSample==0 ){ - pIdx->aSample = (IndexSample *)sqlite3DbMallocZero(db, - sizeof(IndexSample)*SQLITE_INDEX_SAMPLES - ); - if( pIdx->aSample==0 ){ - break; - } + static const int nByte = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES; + pIdx->aSample = (IndexSample *)sqlite3DbMallocZero(db, nByte); + if( pIdx->aSample==0 ){ + break; + } } if( pIdx->aSample ){ @@ -535,10 +565,10 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ if( pSample->eType==SQLITE_TEXT || pSample->eType==SQLITE_BLOB ){ sqlite3DbFree(db, pSample->u.z); } - pSample->eType = eType; - if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + pSample->eType = eType; + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ pSample->u.r = sqlite3_column_double(pStmt, 2); - }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ const char *z = (const char *)( (eType==SQLITE_BLOB) ? sqlite3_column_blob(pStmt, 2): @@ -553,8 +583,8 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ if( pSample->u.z ){ memcpy(pSample->u.z, z, n); }else{ - break; - } + break; + } } } } @@ -564,6 +594,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ } (void)sqlite3SafetyOn(db); } +#endif if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 56dd912ac..5fc38a5f2 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2798,7 +2798,9 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); char *sqlite3Utf16to8(sqlite3 *, const void*, int); +#ifdef SQLITE_ENABLE_STAT2 char *sqlite3Utf8to16(sqlite3 *, int, char *, int, int *); +#endif int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION diff --git a/src/test_config.c b/src/test_config.c index 8bf021566..f1d941387 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -396,6 +396,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double", Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_STAT2 + Tcl_SetVar2(interp, "sqlite_options", "stat2", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "stat2", "0", TCL_GLOBAL_ONLY); +#endif + #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 @@ -464,6 +464,7 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){ ** If a malloc failure occurs, NULL is returned and the db.mallocFailed ** flag set. */ +#ifdef SQLITE_ENABLE_STAT2 char *sqlite3Utf8to16(sqlite3 *db, int enc, char *z, int n, int *pnOut){ Mem m; memset(&m, 0, sizeof(m)); @@ -477,6 +478,7 @@ char *sqlite3Utf8to16(sqlite3 *db, int enc, char *z, int n, int *pnOut){ *pnOut = m.n; return m.z; } +#endif /* ** pZ is a UTF-16 encoded unicode string at least nChar characters long. diff --git a/src/where.c b/src/where.c index 16d89606c..3cdab3f70 100644 --- a/src/where.c +++ b/src/where.c @@ -1904,6 +1904,7 @@ static void bestVirtualIndex( ** Or, if an OOM occurs while converting text values between encodings, ** SQLITE_NOMEM is returned. */ +#ifdef SQLITE_ENABLE_STAT2 static int whereRangeRegion( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ @@ -1970,6 +1971,7 @@ static int whereRangeRegion( } return SQLITE_OK; } +#endif /* #ifdef SQLITE_ENABLE_STAT2 */ /* ** This function is used to estimate the number of rows that will be visited @@ -2015,10 +2017,12 @@ static int whereRangeScanEst( WhereTerm *pUpper, int *piEst /* OUT: Return value */ ){ + int rc = SQLITE_OK; + +#ifdef SQLITE_ENABLE_STAT2 sqlite3 *db = pParse->db; sqlite3_value *pLowerVal = 0; sqlite3_value *pUpperVal = 0; - int rc = SQLITE_OK; if( nEq==0 && p->aSample ){ int iEst; @@ -2053,8 +2057,8 @@ static int whereRangeScanEst( *piEst = iEst; return rc; } - fallback: +#endif assert( pLower || pUpper ); *piEst = (SQLITE_INDEX_SAMPLES-1) / ((pLower&&pUpper)?9:3); return rc; |