From: dan Date: Wed, 25 Oct 2017 18:17:24 +0000 (+0000) Subject: Add tests cases and fix minor issues in the rtreecheck() function. X-Git-Tag: version-3.22.0~233 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e2b38c53b56b2ee025e7e0616bf9c2da3665bea;p=thirdparty%2Fsqlite.git Add tests cases and fix minor issues in the rtreecheck() function. FossilOrigin-Name: d6130cd226c0ca95e02f0cbabfdc27071acdcf83e0d0cb0eaa47d992479ed9a1 --- diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index c7bf671c96..ff15a192a1 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -3659,7 +3659,11 @@ static sqlite3_stmt *rtreeCheckPrepare( z = sqlite3_vmprintf(zFmt, ap); if( pCheck->rc==SQLITE_OK ){ - pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0); + if( z==0 ){ + pCheck->rc = SQLITE_NOMEM; + }else{ + pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0); + } } sqlite3_free(z); @@ -3781,7 +3785,7 @@ static void rtreeCheckMapping( ); }else if( rc==SQLITE_ROW ){ i64 ii = sqlite3_column_int64(pStmt, 0); - if( ii!=iVal ){ + if( ii!=iVal ){ rtreeCheckAppendMsg(pCheck, "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)", iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal @@ -3791,10 +3795,22 @@ static void rtreeCheckMapping( rtreeCheckReset(pCheck, pStmt); } +/* +** Argument pCell points to an array of coordinates stored on an rtree page. +** This function checks that the coordinates are internally consistent (no +** x1>x2 conditions) and adds an error message to the RtreeCheck object +** if they are not. +** +** Additionally, if pParent is not NULL, then it is assumed to point to +** the array of coordinates on the parent page that bound the page +** containing pCell. In this case it is also verified that the two +** sets of coordinates are mutually consistent and an error message added +** to the RtreeCheck object if they are not. +*/ static void rtreeCheckCellCoord( RtreeCheck *pCheck, - i64 iNode, - int iCell, + i64 iNode, /* Node id to use in error messages */ + int iCell, /* Cell number to use in error messages */ u8 *pCell, /* Pointer to cell coordinates */ u8 *pParent /* Pointer to parent coordinates */ ){ @@ -3829,6 +3845,14 @@ static void rtreeCheckCellCoord( } } +/* +** Run rtreecheck() checks on node iNode, which is at depth iDepth within +** the r-tree structure. Argument aParent points to the array of coordinates +** that bound node iNode on the parent node. +** +** If any problems are discovered, an error message is appended to the +** report accumulated in the RtreeCheck object. +*/ static void rtreeCheckNode( RtreeCheck *pCheck, int iDepth, /* Depth of iNode (0==leaf) */ @@ -3864,19 +3888,20 @@ static void rtreeCheckNode( "Node %lld is too small for cell count of %d (%d bytes)", iNode, nCell, nNode ); - } - for(i=0; inDim*2*4)]; - i64 iVal = readInt64(pCell); - rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent); - - if( iDepth>0 ){ - rtreeCheckMapping(pCheck, 0, iVal, iNode); - rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal); - pCheck->nNonLeaf++; - }else{ - rtreeCheckMapping(pCheck, 1, iVal, iNode); - pCheck->nLeaf++; + }else{ + for(i=0; inDim*2*4)]; + i64 iVal = readInt64(pCell); + rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent); + + if( iDepth>0 ){ + rtreeCheckMapping(pCheck, 0, iVal, iNode); + rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal); + pCheck->nNonLeaf++; + }else{ + rtreeCheckMapping(pCheck, 1, iVal, iNode); + pCheck->nLeaf++; + } } } } @@ -3884,9 +3909,14 @@ static void rtreeCheckNode( } } -static void rtreeCheckCount( - RtreeCheck *pCheck, const char *zTbl, i64 nExpected -){ +/* +** The second argument to this function must be either "_rowid" or +** "_parent". This function checks that the number of entries in the +** %_rowid or %_parent table is exactly nExpect. If not, it adds +** an error message to the report in the RtreeCheck object indicated +** by the first argument. +*/ +static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){ if( pCheck->rc==SQLITE_OK ){ sqlite3_stmt *pCount; pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'", @@ -3895,9 +3925,9 @@ static void rtreeCheckCount( if( pCount ){ if( sqlite3_step(pCount)==SQLITE_ROW ){ i64 nActual = sqlite3_column_int64(pCount, 0); - if( nActual!=nExpected ){ + if( nActual!=nExpect ){ rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table" - " - expected %lld, actual %lld" , zTbl, nExpected, nActual + " - expected %lld, actual %lld" , zTbl, nExpect, nActual ); } } @@ -3906,7 +3936,11 @@ static void rtreeCheckCount( } } -static int rtreeCheck( +/* +** This function does the bulk of the work for the rtree integrity-check. +** It is called by rtreecheck(), which is the SQL function implementation. +*/ +static int rtreeCheckTable( sqlite3 *db, /* Database handle to access db through */ const char *zDb, /* Name of db ("main", "temp" etc.) */ const char *zTab, /* Name of rtree table to check */ @@ -3945,11 +3979,13 @@ static int rtreeCheck( } /* Do the actual integrity-check */ - if( check.rc==SQLITE_OK ){ - rtreeCheckNode(&check, 0, 0, 1); + if( check.nDim>=1 ){ + if( check.rc==SQLITE_OK ){ + rtreeCheckNode(&check, 0, 0, 1); + } + rtreeCheckCount(&check, "_rowid", check.nLeaf); + rtreeCheckCount(&check, "_parent", check.nNonLeaf); } - rtreeCheckCount(&check, "_rowid", check.nLeaf); - rtreeCheckCount(&check, "_parent", check.nNonLeaf); /* Finalize SQL statements used by the integrity-check */ sqlite3_finalize(check.pGetNode); @@ -4018,7 +4054,7 @@ static void rtreecheck( }else{ zTab = (const char*)sqlite3_value_text(apArg[1]); } - rc = rtreeCheck(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport); + rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport); if( rc==SQLITE_OK ){ sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT); }else{ diff --git a/ext/rtree/rtreecheck.test b/ext/rtree/rtreecheck.test index eb0e8f0acb..cbe8b513c9 100644 --- a/ext/rtree/rtreecheck.test +++ b/ext/rtree/rtreecheck.test @@ -35,6 +35,12 @@ proc swap_int32 {blob i0 i1} { binary format I* $L } +proc set_int32 {blob idx val} { + binary scan $blob I* L + lset L $idx $val + binary format I* $L +} + do_catchsql_test 1.0 { SELECT rtreecheck(); } {1 {wrong number of arguments to function rtreecheck()}} @@ -85,7 +91,6 @@ do_execsql_test 2.5 { SELECT rtreecheck('r1') } {{Found (3 -> 2) in %_rowid table, expected (3 -> 1)}} -################ reset_db do_execsql_test 3.0 { CREATE VIRTUAL TABLE r1 USING rtree_i32(id, x1, x2); @@ -101,13 +106,53 @@ do_execsql_test 3.0 { SELECT rtreecheck('r1') } {ok} -breakpoint do_execsql_test 3.1 { CREATE VIRTUAL TABLE r2 USING rtree_i32(id, x1, x2); INSERT INTO r2 VALUES(2, -1*(1<<31), -1*(1<<31)+5); SELECT rtreecheck('r2') } {ok} +do_execsql_test 3.2 { + BEGIN; + UPDATE r2_node SET data = X'123456'; + SELECT rtreecheck('r2')!="ok"; +} {1} + +do_execsql_test 3.3 { + ROLLBACK; + UPDATE r2_node SET data = X'00001234'; + SELECT rtreecheck('r2')!="ok"; +} {1} + +do_execsql_test 4.0 { + CREATE TABLE notanrtree(i); + SELECT rtreecheck('notanrtree'); +} {{Schema corrupt or not an rtree}} + +#------------------------------------------------------------------------- +# +reset_db +db func set_int32 set_int32 +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE r3 USING rtree_i32(id, x1, x2, y1, y2); + WITH x(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 + ) + INSERT INTO r3 SELECT i, i, i, i, i FROM x; +} +do_execsql_test 5.1 { + BEGIN; + UPDATE r3_node SET data = set_int32(data, 3, 5000); + UPDATE r3_node SET data = set_int32(data, 4, 5000); + SELECT rtreecheck('r3')=='ok' +} 0 +do_execsql_test 5.2 { + ROLLBACK; + BEGIN; + UPDATE r3_node SET data = set_int32(data, 3, 0); + UPDATE r3_node SET data = set_int32(data, 4, 0); + SELECT rtreecheck('r3')=='ok' +} 0 finish_test diff --git a/manifest b/manifest index 1b6fc596a8..367a1a1375 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sSQL\sscalar\sfunction\srtreecheck()\sto\sthe\srtree\smodule.\sFor\srunning\schecks\sto\sensure\sthe\sshadow\stables\sused\sby\san\srtree\svirtual\stable\sare\sinternally\sconsistent. -D 2017-10-25T18:01:58.383 +C Add\stests\scases\sand\sfix\sminor\sissues\sin\sthe\srtreecheck()\sfunction. +D 2017-10-25T18:17:24.834 F Makefile.in e016061b23e60ac9ec27c65cb577292b6bde0307ca55abd874ab3487b3b1beb2 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 37740aba9c4bb359c627eadccf1cfd7be4f5f847078723777ea7763969e533b1 @@ -329,7 +329,7 @@ F ext/rbu/test_rbu.c 7073979b9cc80912bb03599ac8d85ab5d3bf03cfacd3463f2dcdd782299 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 F ext/repair/checkfreelist.c 0abb84b4545016d57ba1a2aa8884c72c73ed838968909858c03bc1f38fb6b054 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 49ced71763c4bd170ceb0b46ab34c749f3356a8c0e36ce6b9e2f36dc63716609 +F ext/rtree/rtree.c cc91b6905bf55512c6ebc7dfdd37ac81c86f1753db8cfa6d62f0ee864464044f F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test 82a353747fcab1083d114b2ac84723dfefdbf86c1a6e1df57bf588c7d4285436 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -349,7 +349,7 @@ F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd F ext/rtree/rtreeG.test fd3af1ca944a0bdb0cbb5455a4905c9f012e2fffcab6b791f07afa0dcbbcae0e F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed -F ext/rtree/rtreecheck.test f610cb77ca1ba611e656018a7d960cd46054baecd2f12d1149bf1fec121aa230 +F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de @@ -1666,8 +1666,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 adfa7ed2de3e833fff65935455e71236a59602aaf7b97ece667ab300dca9f673 61870b42b033189509b244c76d28932f7a447b887ffe04a3c81461148e54cfb5 -R bbf1f0574f080f1a74b750b54fc22d8d -T +closed 61870b42b033189509b244c76d28932f7a447b887ffe04a3c81461148e54cfb5 -U mistachkin -Z cbebd749084c1ed38ad0d901e97967c8 +P 7d26498063bbc4525976ace698fafcf161d939908f4ffb36d7a4df8fb1bce1fb +R b18b38b834db7af5e4754d71c435762f +U dan +Z f91c79bfd0a67ab59612bc897b82c53b diff --git a/manifest.uuid b/manifest.uuid index 74306142d2..cb99ca30c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d26498063bbc4525976ace698fafcf161d939908f4ffb36d7a4df8fb1bce1fb \ No newline at end of file +d6130cd226c0ca95e02f0cbabfdc27071acdcf83e0d0cb0eaa47d992479ed9a1 \ No newline at end of file