From: dan Date: Mon, 6 May 2019 20:40:23 +0000 (+0000) Subject: Optimize further cases of restarting an RBU vacuum. X-Git-Tag: version-3.29.0~145^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57c45147207fcf1d94a8a3a324ecf4d19922dfa1;p=thirdparty%2Fsqlite.git Optimize further cases of restarting an RBU vacuum. FossilOrigin-Name: 6b3261bfa1d762aa29a57244a30cf5e35655f1fe9c30ee682c186dec29d7a2c2 --- diff --git a/ext/rbu/rbuvacuum4.test b/ext/rbu/rbuvacuum4.test new file mode 100644 index 0000000000..751d9e9250 --- /dev/null +++ b/ext/rbu/rbuvacuum4.test @@ -0,0 +1,86 @@ +# 2019 Jan 3 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file contains tests for the RBU module. More specifically, it +# contains tests to ensure that the sqlite3rbu_vacuum() API works as +# expected. +# + +source [file join [file dirname [info script]] rbu_common.tcl] +set testprefix rbuvacuum4 + +set step 1 + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); +} +do_rbu_vacuum_test 1.1 1 + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 2.0 { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c)) WITHOUT ROWID; + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); +} +do_rbu_vacuum_test 2.1 1 +do_execsql_test 2.2 { + SELECT * FROM t1; +} {1 2 3 4 5 6 7 8 9} + +#------------------------------------------------------------------------- +reset_db + +do_execsql_test 3.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 oN t1(b, c); + INSERT INTO t1 VALUES(1, 2, 3); + INSERT INTO t1 VALUES(4, 5, 6); + INSERT INTO t1 VALUES(7, 8, 9); +} + +do_rbu_vacuum_test 3.1 1 + +do_execsql_test 3.2 { + SELECT * FROM t1; +} {1 2 3 4 5 6 7 8 9} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE x1(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID; + INSERT INTO x1 VALUES(1, 1, 1, 1); + INSERT INTO x1 VALUES(1, 1, 2, 1); + INSERT INTO x1 VALUES(1, 2, 2, 1); + + INSERT INTO x1 VALUES(NULL, 2, 3, NULL); + INSERT INTO x1 VALUES(NULL, 2, 4, NULL); + INSERT INTO x1 VALUES(NULL, 2, 5, NULL); + + CREATE INDEX x1ad ON x1(d, a); +} + +do_rbu_vacuum_test 4.1.1 1 + +do_execsql_test 4.2 { + SELECT count(*) fROM x1 +} 6 + +do_rbu_vacuum_test 4.1.2 0 + +finish_test + + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 0551706a67..37acecff00 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -1476,6 +1476,7 @@ static char *rbuVacuumTableStart( zSelect = rbuMPrintf(p, "%z%squote(\"%w\")", zSelect, zSep2, zCol); zSep = ", "; zSep2 = "||','||"; + break; } } if( i==pIter->nTblCol ) break; @@ -1503,6 +1504,100 @@ static char *rbuVacuumTableStart( return zRet; } +char *rbuVacuumIndexStart( + sqlite3rbu *p, + RbuObjIter *pIter +){ + char *zOrder = 0; + char *zLhs = 0; + char *zSelect = 0; + char *zVector = 0; + char *zRet = 0; + int bFailed = 0; + + if( p->rc==SQLITE_OK ){ + const char *zSep = ""; + int iCol = 0; + sqlite3_stmt *pXInfo = 0; + p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) + ); + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ + int iCid = sqlite3_column_int(pXInfo, 1); + const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); + const char *zCol; + if( sqlite3_column_int(pXInfo, 3) ){ + bFailed = 1; + break; + } + + if( iCid<0 ){ + if( pIter->eType==RBU_PK_IPK ){ + int i; + for(i=0; pIter->abTblPk[i]==0; i++); + assert( inTblCol ); + zCol = pIter->azTblCol[i]; + }else{ + zCol = "_rowid_"; + } + }else{ + zCol = pIter->azTblCol[iCid]; + } + + zLhs = rbuMPrintf(p, "%z%s \"%w\" COLLATE %Q", + zLhs, zSep, zCol, zCollate + ); + zOrder = rbuMPrintf(p, "%z%s \"rbu_imp_%d%w\" COLLATE %Q DESC", + zOrder, zSep, iCol, zCol, zCollate + ); + zSelect = rbuMPrintf(p, "%z%s quote(\"rbu_imp_%d%w\")", + zSelect, zSep, iCol, zCol + ); + zSep = ", "; + iCol++; + } + rbuFinalize(p, pXInfo); + } + if( bFailed ) goto index_start_out; + + if( p->rc==SQLITE_OK ){ + int iCol; + sqlite3_stmt *pSel = 0; + + if( p->rc==SQLITE_OK ){ + p->rc = prepareFreeAndCollectError(p->dbMain, &pSel, &p->zErrmsg, + sqlite3_mprintf("SELECT %s FROM \"rbu_imp_%w\" ORDER BY %s LIMIT 1", + zSelect, pIter->zTbl, zOrder + ) + ); + } + if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){ + const char *zSep = ""; + for(iCol=0; iColnCol; iCol++){ + const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol); + if( zQuoted[0]=='N' ){ + bFailed = 1; + break; + } + zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted); + zSep = ", "; + } + + if( !bFailed ){ + zRet = rbuMPrintf(p, "(%s) > (%s)", zLhs, zVector); + } + } + rbuFinalize(p, pSel); + } + + index_start_out: + sqlite3_free(zOrder); + sqlite3_free(zSelect); + sqlite3_free(zVector); + sqlite3_free(zLhs); + return zRet; +} + /* ** This function is used to create a SELECT list (the list of SQL ** expressions that follows a SELECT keyword) for a SELECT statement @@ -2179,12 +2274,24 @@ static int rbuObjIterPrepareAll( if( p->rc==SQLITE_OK ){ char *zSql; if( rbuIsVacuum(p) ){ + const char *zStart = 0; + if( nOffset ){ + zStart = rbuVacuumIndexStart(p, pIter); + if( zStart ){ + sqlite3_free(zLimit); + zLimit = 0; + } + } + zSql = sqlite3_mprintf( - "SELECT %s, 0 AS rbu_control FROM '%q' %s ORDER BY %s%s", + "SELECT %s, 0 AS rbu_control FROM '%q' %s %s %s ORDER BY %s%s", zCollist, pIter->zDataTbl, - zPart, zCollist, zLimit + zPart, + (zStart ? (zPart ? "AND" : "WHERE") : ""), zStart, + zCollist, zLimit ); + sqlite3_free(zStart); }else if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ @@ -2207,7 +2314,11 @@ static int rbuObjIterPrepareAll( zCollist, zLimit ); } - p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); + if( p->rc==SQLITE_OK ){ + p->rc = prepareFreeAndCollectError(p->dbRbu,&pIter->pSelect,pz,zSql); + }else{ + sqlite3_free(zSql); + } } sqlite3_free(zImposterCols); diff --git a/manifest b/manifest index 9b38b304da..44ed7b69ca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimize\ssome\scases\sof\srestarting\san\sRBU\svacuum. -D 2019-05-04T20:04:42.728 +C Optimize\sfurther\scases\sof\srestarting\san\sRBU\svacuum. +D 2019-05-06T20:40:23.801 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -359,7 +359,8 @@ F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534 F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc -F ext/rbu/sqlite3rbu.c 03d4acabf6a51e0714eb4119379e06464f0158ca1d6a0ebd73769b82e7477a11 +F ext/rbu/rbuvacuum4.test fcae689344a28acf1013c9e2563d334f15ef741f5a16396945701ab90799e877 +F ext/rbu/sqlite3rbu.c e2669fb2a716615f38628a0477ecd665a040970501cba2511e9dffe066e2c9c8 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -1823,10 +1824,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c2e439bccc40825e211bfa9a88e6a251ff066ca7453d4e7cb5eab56ce7332635 -R 837402c2e896349b349ad51f4a993cdf -T *branch * rbu-opt -T *sym-rbu-opt * -T -sym-trunk * +P cdc09867ed6522026ae7bfac1f59cd79b60fba6d07d49b99b030a501a7059ee4 +R aeb9fedb3c4f55c16b474638fcef63d3 U dan -Z 5640124653d86c97ac59112e02d029e7 +Z ccdab55de99d2c516e9414504dca1a30 diff --git a/manifest.uuid b/manifest.uuid index ebf5ce1b08..049d28edef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cdc09867ed6522026ae7bfac1f59cd79b60fba6d07d49b99b030a501a7059ee4 \ No newline at end of file +6b3261bfa1d762aa29a57244a30cf5e35655f1fe9c30ee682c186dec29d7a2c2 \ No newline at end of file