From 69188d9a66e32f7d24c0eb333d5999096029f99c Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 19 Aug 2009 08:18:32 +0000 Subject: [PATCH] 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 --- manifest | 24 +++++----- manifest.uuid | 2 +- src/analyze.c | 111 +++++++++++++++++++++++++++++---------------- src/sqliteInt.h | 2 + src/test_config.c | 6 +++ src/utf.c | 2 + src/where.c | 8 +++- test/analyze2.test | 21 +++++---- test/auth.test | 7 ++- 9 files changed, 118 insertions(+), 65 deletions(-) diff --git a/manifest b/manifest index 201500ef2f..d81a2f723e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\ssqlite_stat2\sschema\sto\sbe\smore\sflexible. -D 2009-08-18T16:24:59 +C Add\sthe\sSQLITE_ENABLE_STAT2\smacro.\sIf\sthis\sis\snot\sdefined\sat\sbuild-time,\sthe\sstat2\stable\sis\snot\screated,\spopulated,\sor\sused. +D 2009-08-19T08:18:32 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 0f7761c5d1c62ae7a841e3393ffaff1fa0f5c00a F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -100,7 +100,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c 8b42cace4f8e312de596807ba2685179da64fec4 -F src/analyze.c 7f086e4da3db68c9fad2a4d61d90a62683084a57 +F src/analyze.c 1a5bf2adeb31f603a34e769a49937100a6da240a F src/attach.c 13995348fc5a26cdd136a50806faf292aabc173f F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3 @@ -163,7 +163,7 @@ F src/select.c 67b0778c9585905c8aa75aaa469e76ef3c1d315a F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb F src/sqlite.h.in a6850e9034df1336e8139c4d6964d7d2f0f52337 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 -F src/sqliteInt.h a11d40fc24390e5e0665cf8b1addbe162b9f76c3 +F src/sqliteInt.h d1a1a37db2d1f597c69ad5884e3e9463a1bd0827 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d @@ -181,7 +181,7 @@ F src/test_async.c 731d23f953ece5bf40ce87810cfb7607218953c5 F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad F src/test_backup.c 1384a18985a5a2d275c2662e48473bf1542ebd08 F src/test_btree.c 5adbba9b138988a3cf4d3b5424dbc7c85651da02 -F src/test_config.c 63d1b08809ca182ee75429573111b44735861c64 +F src/test_config.c 97d840717efcca8cad5e353debc69780ea8ad7ce F src/test_devsym.c 9f4bc2551e267ce7aeda195f3897d0f30c5228f4 F src/test_func.c 26ac62d8ed7a9f45a1e05baffb1c1e55fe2a06f2 F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f @@ -201,7 +201,7 @@ F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241 F src/tokenize.c af8a56e6a50c5042fc305bfa796275e9bf26ff2b F src/trigger.c 9bc5278d509d81ff0f9b52f0ce7239563d188e32 F src/update.c 4da327f706c0d0dfedf4d92154b1b5688bdea0ac -F src/utf.c 9b022ac1c1f306733d57daa0df0b8beb7c17e95e +F src/utf.c 3ca2c9461b8e942c68da28bfccd448663f536a6f F src/util.c c2416f60ae704a8c4990e4909aa810f90cbffa07 F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0 F src/vdbe.c 464e2e30b1287554a23cdaa0b6b010a9dcb5eb29 @@ -213,7 +213,7 @@ F src/vdbeblob.c a3f3e0e877fc64ea50165eec2855f5ada4477611 F src/vdbemem.c afd6ce02945e659f65642f290a37ccf4a88c4dcb F src/vtab.c aedd76e8670d5a5379f93804398d3ba960125547 F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04 -F src/where.c 9d4c2f178f842c1ed18c068880f324479ea2cb38 +F src/where.c 2e61e33f3649ef5940ef63ed285d37d03bc03dc5 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45 @@ -223,7 +223,7 @@ F test/alter3.test 25b95a136708f22b87184fa6a4309eea03d65153 F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/analyze.test ad5329098fe4de4a96852231d53e3e9e6283ad4b -F test/analyze2.test 30987f595f9e34b95bae81794e99b5ca2be7e46c +F test/analyze2.test f58acc55f582996dc68ec9d28ede4ebb68afd11f F test/async.test 8c75d31b8330f8b70cf2571b014d4476a063efdb F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e @@ -233,7 +233,7 @@ F test/attach.test 1d1be27b9e4c654f9bb14d011a4a87753c0b197a F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437 F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61 -F test/auth.test 393be593c72bc452cd2fe6e026682752aa258559 +F test/auth.test 8e9a21d7321c9ad20d26f630acc02e15f2f2a3b6 F test/auth2.test ee3ba272e2b975e913afc9b041ee75706e190005 F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5 F test/autoinc.test 71bc5183c93ed5e2b8b3a71c218d777b55e4fffc @@ -744,7 +744,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 -P dd96bda2a85c1d94fb4a0bf5f27e2977f7f7e42e -R 3ad6c851396bbe27ea036387da51f58c +P ded9dec6459baf21e01f63250db5ace57f390e7a +R 183c0e0c3d4fd9f579a812122a3f1cb5 U dan -Z ea071f69e4d6383649120789bd868cdf +Z 9353561137495233ae51d7a49e9232d2 diff --git a/manifest.uuid b/manifest.uuid index 2293825c06..e76c8e22be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ded9dec6459baf21e01f63250db5ace57f390e7a \ No newline at end of file +362665e89c21fd603d9f8ad6c0ead590e885af7c \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index c6c279f278..2e00b54ab7 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; izName))==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; ipIndex==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; iaSample==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 56dd912ac7..5fc38a5f2a 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 8bf021566d..f1d9413876 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 diff --git a/src/utf.c b/src/utf.c index 89eb83f79a..159ac90b90 100644 --- a/src/utf.c +++ b/src/utf.c @@ -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 16d89606c7..3cdab3f709 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; diff --git a/test/analyze2.test b/test/analyze2.test index 829cef9627..7c78882b05 100644 --- a/test/analyze2.test +++ b/test/analyze2.test @@ -14,9 +14,16 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -sqlite3_db_config_lookaside db 0 0 0 +ifcapable !stat2 { + finish_test + return +} -do_test analyze2-0.1 { +proc eqp sql { + uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] +} + +do_test analyze2-1.1 { execsql { CREATE TABLE t1(x PRIMARY KEY) } for {set i 0} {$i < 1000} {incr i} { execsql { INSERT INTO t1 VALUES($i) } @@ -37,7 +44,7 @@ do_test analyze2-0.1 { t1 sqlite_autoindex_t1_1 9 999 \ ] -do_test analyze2-0.2 { +do_test analyze2-1.2 { execsql { DELETE FROM t1 WHERe x>9; ANALYZE; @@ -45,7 +52,7 @@ do_test analyze2-0.2 { } } {t1 sqlite_autoindex_t1_1 {0 1 2 3 4 5 6 7 8 9}} -do_test analyze2-0.3 { +do_test analyze2-1.3 { execsql { DELETE FROM t1 WHERE x>5; ANALYZE; @@ -53,7 +60,7 @@ do_test analyze2-0.3 { } } {} -do_test analyze2-0.4 { +do_test analyze2-1.4 { execsql { DELETE FROM t1; ANALYZE; @@ -61,10 +68,6 @@ do_test analyze2-0.4 { } } {} -proc eqp sql { - uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] -} - do_test analyze2-1.1 { execsql { DROP TABLE t1; diff --git a/test/auth.test b/test/auth.test index 600a552755..ecf038d10e 100644 --- a/test/auth.test +++ b/test/auth.test @@ -2309,6 +2309,11 @@ ifcapable compound&&subquery { } } } + ifcapable stat2 { + set stat2 "sqlite_stat2 " + } else { + set stat2 "" + } do_test auth-5.2 { execsql { SELECT name FROM ( @@ -2316,7 +2321,7 @@ ifcapable compound&&subquery { WHERE type='table' ORDER BY name } - } {sqlite_stat1 sqlite_stat2 t1 t2 t3 t4} + } "sqlite_stat1 ${stat2}t1 t2 t3 t4" } # Ticket #3944