Add SQL scalar function rtreecheck() to the rtree module. For running checks
to ensure the shadow tables used by an rtree virtual table are internally consistent. FossilOrigin-Name: dde0bb3eab1316c3247b1755594527ca70955aab4ad4907190731f7ec092b327
This commit is contained in:
parent
b5d013edd1
commit
1917e92fdb
@ -209,7 +209,7 @@ struct RtreeSearchPoint {
|
||||
** The smallest possible node-size is (512-64)==448 bytes. And the largest
|
||||
** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
|
||||
** Therefore all non-root nodes must contain at least 3 entries. Since
|
||||
** 2^40 is greater than 2^64, an r-tree structure always has a depth of
|
||||
** 3^40 is greater than 2^64, an r-tree structure always has a depth of
|
||||
** 40 or less.
|
||||
*/
|
||||
#define RTREE_MAX_DEPTH 40
|
||||
@ -3608,6 +3608,425 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Context object passed between the various routines that make up the
|
||||
** implementation of integrity-check function rtreecheck().
|
||||
*/
|
||||
typedef struct RtreeCheck RtreeCheck;
|
||||
struct RtreeCheck {
|
||||
sqlite3 *db; /* Database handle */
|
||||
const char *zDb; /* Database containing rtree table */
|
||||
const char *zTab; /* Name of rtree table */
|
||||
int bInt; /* True for rtree_i32 table */
|
||||
int nDim; /* Number of dimensions for this rtree tbl */
|
||||
sqlite3_stmt *pGetNode; /* Statement used to retrieve nodes */
|
||||
sqlite3_stmt *aCheckMapping[2]; /* Statements to query %_parent/%_rowid */
|
||||
int nLeaf; /* Number of leaf cells in table */
|
||||
int nNonLeaf; /* Number of non-leaf cells in table */
|
||||
int rc; /* Return code */
|
||||
char *zReport; /* Message to report */
|
||||
int nErr; /* Number of lines in zReport */
|
||||
};
|
||||
|
||||
#define RTREE_CHECK_MAX_ERROR 100
|
||||
|
||||
/*
|
||||
** Reset SQL statement pStmt. If the sqlite3_reset() call returns an error,
|
||||
** and RtreeCheck.rc==SQLITE_OK, set RtreeCheck.rc to the error code.
|
||||
*/
|
||||
static void rtreeCheckReset(RtreeCheck *pCheck, sqlite3_stmt *pStmt){
|
||||
int rc = sqlite3_reset(pStmt);
|
||||
if( pCheck->rc==SQLITE_OK ) pCheck->rc = rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The second and subsequent arguments to this function are a format string
|
||||
** and printf style arguments. This function formats the string and attempts
|
||||
** to compile it as an SQL statement.
|
||||
**
|
||||
** If successful, a pointer to the new SQL statement is returned. Otherwise,
|
||||
** NULL is returned and an error code left in RtreeCheck.rc.
|
||||
*/
|
||||
static sqlite3_stmt *rtreeCheckPrepare(
|
||||
RtreeCheck *pCheck, /* RtreeCheck object */
|
||||
const char *zFmt, ... /* Format string and trailing args */
|
||||
){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
char *z = sqlite3_vmprintf(zFmt, ap);
|
||||
sqlite3_stmt *pRet = 0;
|
||||
|
||||
if( pCheck->rc==SQLITE_OK ){
|
||||
pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0);
|
||||
}
|
||||
|
||||
sqlite3_free(z);
|
||||
va_end(ap);
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** The second and subsequent arguments to this function are a printf()
|
||||
** style format string and arguments. This function formats the string and
|
||||
** appends it to the report being accumuated in pCheck.
|
||||
*/
|
||||
static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){
|
||||
char *z = sqlite3_vmprintf(zFmt, ap);
|
||||
if( z==0 ){
|
||||
pCheck->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pCheck->zReport = sqlite3_mprintf("%z%s%z",
|
||||
pCheck->zReport, (pCheck->zReport ? "\n" : ""), z
|
||||
);
|
||||
if( pCheck->zReport==0 ){
|
||||
pCheck->rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
pCheck->nErr++;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is a no-op if there is already an error code stored
|
||||
** in the RtreeCheck object indicated by the first argument. NULL is
|
||||
** returned in this case.
|
||||
**
|
||||
** Otherwise, the contents of rtree table node iNode are loaded from
|
||||
** the database and copied into a buffer obtained from sqlite3_malloc().
|
||||
** If no error occurs, a pointer to the buffer is returned and (*pnNode)
|
||||
** is set to the size of the buffer in bytes.
|
||||
**
|
||||
** Or, if an error does occur, NULL is returned and an error code left
|
||||
** in the RtreeCheck object. The final value of *pnNode is undefined in
|
||||
** this case.
|
||||
*/
|
||||
static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
|
||||
u8 *pRet = 0; /* Return value */
|
||||
|
||||
assert( pCheck->rc==SQLITE_OK );
|
||||
if( pCheck->pGetNode==0 ){
|
||||
pCheck->pGetNode = rtreeCheckPrepare(pCheck,
|
||||
"SELECT data FROM %Q.'%q_node' WHERE nodeno=?",
|
||||
pCheck->zDb, pCheck->zTab
|
||||
);
|
||||
}
|
||||
|
||||
if( pCheck->rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pCheck->pGetNode, 1, iNode);
|
||||
if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
|
||||
int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
|
||||
const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
|
||||
pRet = sqlite3_malloc(nNode);
|
||||
if( pRet==0 ){
|
||||
pCheck->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memcpy(pRet, pNode, nNode);
|
||||
*pnNode = nNode;
|
||||
}
|
||||
}
|
||||
rtreeCheckReset(pCheck, pCheck->pGetNode);
|
||||
if( pCheck->rc==SQLITE_OK && pRet==0 ){
|
||||
rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode);
|
||||
}
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to check that the %_parent (if bLeaf==0) or %_rowid
|
||||
** (if bLeaf==1) table contains a specified entry. The schemas of the
|
||||
** two tables are:
|
||||
**
|
||||
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
|
||||
**
|
||||
** In both cases, this function checks that there exists an entry with
|
||||
** IPK value iKey and the second column set to iVal.
|
||||
**
|
||||
*/
|
||||
static void rtreeCheckMapping(
|
||||
RtreeCheck *pCheck, /* RtreeCheck object */
|
||||
int bLeaf, /* True for a leaf cell, false for interior */
|
||||
i64 iKey, /* Key for mapping */
|
||||
i64 iVal /* Expected value for mapping */
|
||||
){
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
const char *azSql[2] = {
|
||||
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?",
|
||||
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?"
|
||||
};
|
||||
|
||||
assert( bLeaf==0 || bLeaf==1 );
|
||||
if( pCheck->aCheckMapping[bLeaf]==0 ){
|
||||
pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck,
|
||||
azSql[bLeaf], pCheck->zDb, pCheck->zTab
|
||||
);
|
||||
}
|
||||
if( pCheck->rc!=SQLITE_OK ) return;
|
||||
|
||||
pStmt = pCheck->aCheckMapping[bLeaf];
|
||||
sqlite3_bind_int64(pStmt, 1, iKey);
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_DONE ){
|
||||
rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table",
|
||||
iKey, iVal, (bLeaf ? "%_rowid" : "%_parent")
|
||||
);
|
||||
}else if( rc==SQLITE_ROW ){
|
||||
i64 ii = sqlite3_column_int64(pStmt, 0);
|
||||
if( ii!=iVal ){
|
||||
rtreeCheckAppendMsg(pCheck,
|
||||
"Found (%lld -> %lld) in %s table, expected (%lld -> %lld)",
|
||||
iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal
|
||||
);
|
||||
}
|
||||
}
|
||||
rtreeCheckReset(pCheck, pStmt);
|
||||
}
|
||||
|
||||
static void rtreeCheckCellCoord(
|
||||
RtreeCheck *pCheck,
|
||||
i64 iNode,
|
||||
int iCell,
|
||||
u8 *pCell, /* Pointer to cell coordinates */
|
||||
u8 *pParent /* Pointer to parent coordinates */
|
||||
){
|
||||
RtreeCoord c1, c2;
|
||||
RtreeCoord p1, p2;
|
||||
int i;
|
||||
|
||||
for(i=0; i<pCheck->nDim; i++){
|
||||
readCoord(&pCell[4*2*i], &c1);
|
||||
readCoord(&pCell[4*(2*i + 1)], &c2);
|
||||
|
||||
/* printf("%e, %e\n", c1.u.f, c2.u.f); */
|
||||
if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){
|
||||
rtreeCheckAppendMsg(pCheck,
|
||||
"Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode
|
||||
);
|
||||
}
|
||||
|
||||
if( pParent ){
|
||||
readCoord(&pParent[4*2*i], &p1);
|
||||
readCoord(&pParent[4*(2*i + 1)], &p2);
|
||||
|
||||
if( (pCheck->bInt ? c1.i<p1.i : c1.f<p1.f)
|
||||
|| (pCheck->bInt ? c2.i>p2.i : c2.f>p2.f)
|
||||
){
|
||||
rtreeCheckAppendMsg(pCheck,
|
||||
"Dimension %d of cell %d on node %lld is corrupt relative to parent"
|
||||
, i, iCell, iNode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rtreeCheckNode(
|
||||
RtreeCheck *pCheck,
|
||||
int iDepth, /* Depth of iNode (0==leaf) */
|
||||
u8 *aParent, /* Buffer containing parent coords */
|
||||
i64 iNode /* Node to check */
|
||||
){
|
||||
u8 *aNode = 0;
|
||||
int nNode = 0;
|
||||
|
||||
assert( iNode==1 || aParent!=0 );
|
||||
assert( pCheck->nDim>0 );
|
||||
|
||||
aNode = rtreeCheckGetNode(pCheck, iNode, &nNode);
|
||||
if( aNode ){
|
||||
if( nNode<4 ){
|
||||
rtreeCheckAppendMsg(pCheck,
|
||||
"Node %lld is too small (%d bytes)", iNode, nNode
|
||||
);
|
||||
}else{
|
||||
int nCell; /* Number of cells on page */
|
||||
int i; /* Used to iterate through cells */
|
||||
if( aParent==0 ){
|
||||
iDepth = readInt16(aNode);
|
||||
if( iDepth>RTREE_MAX_DEPTH ){
|
||||
rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth);
|
||||
sqlite3_free(aNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
nCell = readInt16(&aNode[2]);
|
||||
if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){
|
||||
rtreeCheckAppendMsg(pCheck,
|
||||
"Node %lld is too small for cell count of %d (%d bytes)",
|
||||
iNode, nCell, nNode
|
||||
);
|
||||
}
|
||||
for(i=0; i<nCell; i++){
|
||||
u8 *pCell = &aNode[4 + i*(8 + pCheck->nDim*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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_free(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtreeCheckCount(
|
||||
RtreeCheck *pCheck, const char *zTbl, i64 nExpected
|
||||
){
|
||||
if( pCheck->rc==SQLITE_OK ){
|
||||
sqlite3_stmt *pCount;
|
||||
pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'",
|
||||
pCheck->zDb, pCheck->zTab, zTbl
|
||||
);
|
||||
if( pCount ){
|
||||
if( sqlite3_step(pCount)==SQLITE_ROW ){
|
||||
i64 nActual = sqlite3_column_int64(pCount, 0);
|
||||
if( nActual!=nExpected ){
|
||||
rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table"
|
||||
" - expected %lld, actual %lld" , zTbl, nExpected, nActual
|
||||
);
|
||||
}
|
||||
}
|
||||
pCheck->rc = sqlite3_finalize(pCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rtreeCheck(
|
||||
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 */
|
||||
char **pzReport /* OUT: sqlite3_malloc'd report text */
|
||||
){
|
||||
RtreeCheck check; /* Common context for various routines */
|
||||
sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */
|
||||
int bEnd = 0; /* True if transaction should be closed */
|
||||
|
||||
/* Initialize the context object */
|
||||
memset(&check, 0, sizeof(check));
|
||||
check.db = db;
|
||||
check.zDb = zDb;
|
||||
check.zTab = zTab;
|
||||
|
||||
/* If there is not already an open transaction, open one now. This is
|
||||
** to ensure that the queries run as part of this integrity-check operate
|
||||
** on a consistent snapshot. */
|
||||
if( sqlite3_get_autocommit(db) ){
|
||||
check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
bEnd = 1;
|
||||
}
|
||||
|
||||
/* Find number of dimensions in the rtree table. */
|
||||
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
|
||||
if( pStmt ){
|
||||
int rc;
|
||||
check.nDim = (sqlite3_column_count(pStmt) - 1) / 2;
|
||||
if( check.nDim<1 ){
|
||||
rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree");
|
||||
}else if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER);
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc!=SQLITE_CORRUPT ) check.rc = rc;
|
||||
}
|
||||
|
||||
/* Do the actual integrity-check */
|
||||
if( check.rc==SQLITE_OK ){
|
||||
rtreeCheckNode(&check, 0, 0, 1);
|
||||
}
|
||||
rtreeCheckCount(&check, "_rowid", check.nLeaf);
|
||||
rtreeCheckCount(&check, "_parent", check.nNonLeaf);
|
||||
|
||||
/* Finalize SQL statements used by the integrity-check */
|
||||
sqlite3_finalize(check.pGetNode);
|
||||
sqlite3_finalize(check.aCheckMapping[0]);
|
||||
sqlite3_finalize(check.aCheckMapping[1]);
|
||||
|
||||
/* If one was opened, close the transaction */
|
||||
if( bEnd ){
|
||||
int rc = sqlite3_exec(db, "END", 0, 0, 0);
|
||||
if( check.rc==SQLITE_OK ) check.rc = rc;
|
||||
}
|
||||
*pzReport = check.zReport;
|
||||
return check.rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage:
|
||||
**
|
||||
** rtreecheck(<rtree-table>);
|
||||
** rtreecheck(<database>, <rtree-table>);
|
||||
**
|
||||
** Invoking this SQL function runs an integrity-check on the named rtree
|
||||
** table. The integrity-check verifies the following:
|
||||
**
|
||||
** 1. For each cell in the r-tree structure (%_node table), that:
|
||||
**
|
||||
** a) for each dimension, (coord1 <= coord2).
|
||||
**
|
||||
** b) unless the cell is on the root node, that the cell is bounded
|
||||
** by the parent cell on the parent node.
|
||||
**
|
||||
** c) for leaf nodes, that there is an entry in the %_rowid
|
||||
** table corresponding to the cell's rowid value that
|
||||
** points to the correct node.
|
||||
**
|
||||
** d) for cells on non-leaf nodes, that there is an entry in the
|
||||
** %_parent table mapping from the cell's child node to the
|
||||
** node that it resides on.
|
||||
**
|
||||
** 2. That there are the same number of entries in the %_rowid table
|
||||
** as there are leaf cells in the r-tree structure, and that there
|
||||
** is a leaf cell that corresponds to each entry in the %_rowid table.
|
||||
**
|
||||
** 3. That there are the same number of entries in the %_parent table
|
||||
** as there are non-leaf cells in the r-tree structure, and that
|
||||
** there is a non-leaf cell that corresponds to each entry in the
|
||||
** %_parent table.
|
||||
*/
|
||||
static void rtreecheck(
|
||||
sqlite3_context *ctx,
|
||||
int nArg,
|
||||
sqlite3_value **apArg
|
||||
){
|
||||
if( nArg!=1 && nArg!=2 ){
|
||||
sqlite3_result_error(ctx,
|
||||
"wrong number of arguments to function rtreecheck()", -1
|
||||
);
|
||||
}else{
|
||||
int rc;
|
||||
char *zReport = 0;
|
||||
const char *zDb = (const char*)sqlite3_value_text(apArg[0]);
|
||||
const char *zTab;
|
||||
if( nArg==1 ){
|
||||
zTab = zDb;
|
||||
zDb = "main";
|
||||
}else{
|
||||
zTab = (const char*)sqlite3_value_text(apArg[1]);
|
||||
}
|
||||
rc = rtreeCheck(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_error_code(ctx, rc);
|
||||
}
|
||||
sqlite3_free(zReport);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register the r-tree module with database handle db. This creates the
|
||||
** virtual table module "rtree" and the debugging/analysis scalar
|
||||
@ -3621,6 +4040,9 @@ int sqlite3RtreeInit(sqlite3 *db){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
#ifdef SQLITE_RTREE_INT_ONLY
|
||||
void *c = (void *)RTREE_COORD_INT32;
|
||||
|
@ -519,7 +519,7 @@ foreach {tn sql_template testdata} {
|
||||
do_test $testname.2 [list sql_uses_stmt db $sql] $uses
|
||||
do_execsql_test $testname.3 { SELECT * FROM t1 ORDER BY idx } $data
|
||||
|
||||
do_test $testname.4 { rtree_check db t1 } 0
|
||||
do_rtree_integrity_test $testname.4 t1
|
||||
db close
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,7 @@ foreach module {rtree_i32 rtree} {
|
||||
set rc
|
||||
} {1}
|
||||
|
||||
do_test rtree2-$module.$nDim.3 {
|
||||
rtree_check db t1
|
||||
} 0
|
||||
do_rtree_integrity_test rtree2-$module.$nDim.3 t1
|
||||
|
||||
set OPS [list < > <= >= =]
|
||||
for {set ii 0} {$ii < $::NSELECT} {incr ii} {
|
||||
@ -133,9 +131,7 @@ foreach module {rtree_i32 rtree} {
|
||||
}
|
||||
set rc
|
||||
} {1}
|
||||
do_test rtree2-$module.$nDim.5.$ii.2 {
|
||||
rtree_check db t1
|
||||
} {0}
|
||||
do_rtree_integrity_test rtree2-$module.$nDim.5.$ii.2 t1
|
||||
}
|
||||
|
||||
do_test rtree2-$module.$nDim.6 {
|
||||
|
@ -15,6 +15,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !rtree {
|
||||
@ -246,6 +247,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} {
|
||||
} [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
|
||||
}
|
||||
|
||||
do_rtree_integrity_test rtree4-$nDim.3 rx
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
@ -16,6 +16,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !rtree {
|
||||
@ -76,5 +77,6 @@ do_test rtree5-1.13 {
|
||||
y1=-2147483648 AND y2=-2147483643
|
||||
}
|
||||
} {2 2147483643 2147483647 -2147483648 -2147483643}
|
||||
do_rtree_integrity_test rtree5-1.14 t1
|
||||
|
||||
finish_test
|
||||
|
@ -17,6 +17,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !rtree||!vacuum {
|
||||
@ -67,4 +68,6 @@ do_test rtree7-1.5 {
|
||||
}
|
||||
} {51 102 153 204}
|
||||
|
||||
do_rtree_integrity_test rtree7-1.6 rt
|
||||
|
||||
finish_test
|
||||
|
@ -14,6 +14,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
@ -64,6 +65,7 @@ do_test rtree8-1.2.2 { nested_select 1 } {51}
|
||||
# nodes internally.
|
||||
#
|
||||
populate_t1 1500
|
||||
do_rtree_integrity_test rtree8-1.3.0 t1
|
||||
do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {164}
|
||||
do_test rtree8-1.3.2 {
|
||||
set rowids [execsql {SELECT min(rowid) FROM t1_rowid GROUP BY nodeno}]
|
||||
@ -158,13 +160,15 @@ do_test rtree8-5.2 {
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
do_test rtree8-5.3 {
|
||||
do_rtree_integrity_test rtree8-5.3 t2
|
||||
do_test rtree8-5.4 {
|
||||
execsql BEGIN
|
||||
for {set i 0} {$i < 200} {incr i} {
|
||||
execsql { DELETE FROM t2 WHERE id = $i }
|
||||
}
|
||||
execsql COMMIT
|
||||
} {}
|
||||
do_rtree_integrity_test rtree8-5.5 t2
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -15,6 +15,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
ifcapable rtree_int_only { finish_test; return }
|
||||
@ -42,6 +43,7 @@ for {set i 0} {$i < 1000} {incr i} {
|
||||
set z [expr ($i/100)%10]
|
||||
execsql { INSERT INTO rt VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
|
||||
}
|
||||
do_rtree_integrity_test rtree9-2.0 rt
|
||||
do_execsql_test rtree9-2.1 {
|
||||
SELECT id FROM rt WHERE id MATCH cube(2.5, 2.5, 2.5, 1, 1, 1) ORDER BY id;
|
||||
} {222 223 232 233 322 323 332 333}
|
||||
@ -50,7 +52,7 @@ do_execsql_test rtree9-2.2 {
|
||||
} {555 556 565 566 655 656 665 666}
|
||||
|
||||
|
||||
do_execsql_test rtree9-3.1 {
|
||||
do_execsql_test rtree9-3.0 {
|
||||
CREATE VIRTUAL TABLE rt32 USING rtree_i32(id, x1, x2, y1, y2, z1, z2);
|
||||
} {}
|
||||
for {set i 0} {$i < 1000} {incr i} {
|
||||
@ -59,6 +61,7 @@ for {set i 0} {$i < 1000} {incr i} {
|
||||
set z [expr ($i/100)%10]
|
||||
execsql { INSERT INTO rt32 VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
|
||||
}
|
||||
do_rtree_integrity_test rtree9-3.1 rt32
|
||||
do_execsql_test rtree9-3.2 {
|
||||
SELECT id FROM rt32 WHERE id MATCH cube(3, 3, 3, 1, 1, 1) ORDER BY id;
|
||||
} {222 223 224 232 233 234 242 243 244 322 323 324 332 333 334 342 343 344 422 423 424 432 433 434 442 443 444}
|
||||
@ -121,5 +124,6 @@ do_execsql_test rtree9-5.3 {
|
||||
UPDATE rt2 SET xmin=xmin+5, ymin=ymin+5, xmax=xmax+5, ymax=ymax+5;
|
||||
SELECT id FROM rt2 WHERE id MATCH circle(5.0, 5.0, 2.0);
|
||||
} {1 2 3 4 13 14 15 16 17}
|
||||
do_rtree_integrity_test rtree9-5.4 rt2
|
||||
|
||||
finish_test
|
||||
|
@ -108,6 +108,12 @@ do_corruption_tests rtreeA-1.1 {
|
||||
4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-1.1.1 {
|
||||
SELECT rtreecheck('main', 't1')
|
||||
} {{Node 1 missing from database
|
||||
Wrong number of entries in %_rowid table - expected 0, actual 500
|
||||
Wrong number of entries in %_parent table - expected 0, actual 23}}
|
||||
|
||||
do_execsql_test rtreeA-1.2.0 { DROP TABLE t1_node } {}
|
||||
do_corruption_tests rtreeA-1.2 -error "database disk image is malformed" {
|
||||
1 "SELECT * FROM t1"
|
||||
@ -157,6 +163,10 @@ do_corruption_tests rtreeA-3.1 {
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-3.1.0.3 {
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
} {1}
|
||||
|
||||
do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
|
||||
do_corruption_tests rtreeA-3.2 {
|
||||
1 "SELECT * FROM t1"
|
||||
@ -176,6 +186,12 @@ do_corruption_tests rtreeA-3.3 {
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-3.3.3.4 {
|
||||
SELECT rtreecheck('main', 't1')
|
||||
} {{Rtree depth out of range (65535)
|
||||
Wrong number of entries in %_rowid table - expected 0, actual 499
|
||||
Wrong number of entries in %_parent table - expected 0, actual 23}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Set the "number of entries" field on some nodes incorrectly.
|
||||
#
|
||||
@ -203,6 +219,10 @@ do_corruption_tests rtreeA-5.1 {
|
||||
2 "DELETE FROM t1"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-5.2 {
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
} {1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Add some bad entries to the %_parent table.
|
||||
#
|
||||
@ -216,6 +236,10 @@ do_corruption_tests rtreeA-6.1 {
|
||||
2 "UPDATE t1 SET x1=x1+1, x2=x2+1"
|
||||
}
|
||||
|
||||
do_execsql_test rtreeA-6.2 {
|
||||
SELECT rtreecheck('main', 't1')!="ok"
|
||||
} {1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Truncated blobs in the _node table.
|
||||
#
|
||||
@ -233,5 +257,5 @@ do_test rtreeA-7.120 {
|
||||
} {SQLITE_CORRUPT_VTAB}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
@ -44,4 +45,6 @@ ifcapable rtree_int_only {
|
||||
} {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}}
|
||||
}
|
||||
|
||||
do_rtree_integrity_test rtreeB-1.2 t1
|
||||
|
||||
finish_test
|
||||
|
@ -15,6 +15,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
set testprefix rtreeC
|
||||
@ -180,6 +181,7 @@ do_execsql_test 5.1 {
|
||||
|
||||
INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
|
||||
}
|
||||
do_rtree_integrity_test 5.1.1 rt
|
||||
|
||||
# First test a query with no ANALYZE data at all. The outer loop is
|
||||
# real table "t1".
|
||||
|
@ -15,6 +15,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
ifcapable rtree_int_only { finish_test; return }
|
||||
@ -25,7 +26,7 @@ ifcapable rtree_int_only { finish_test; return }
|
||||
#
|
||||
register_circle_geom db
|
||||
|
||||
do_execsql_test rtreeE-1.1 {
|
||||
do_execsql_test rtreeE-1.0.0 {
|
||||
PRAGMA page_size=512;
|
||||
CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1);
|
||||
|
||||
@ -47,6 +48,7 @@ do_execsql_test rtreeE-1.1 {
|
||||
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
|
||||
INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y;
|
||||
} {}
|
||||
do_rtree_integrity_test rtreeE-1.0.1 rt1
|
||||
|
||||
# Queries against each of the three clusters */
|
||||
do_execsql_test rtreeE-1.1 {
|
||||
@ -111,6 +113,7 @@ do_test rtreeE-2.1 {
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
do_rtree_integrity_test rtreeE-2.1.1 rt2
|
||||
|
||||
for {set i 1} {$i<=200} {incr i} {
|
||||
set dx [expr {int(rand()*100)}]
|
||||
|
@ -28,6 +28,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
@ -78,4 +79,6 @@ do_execsql_test rtreeF-1.5 {
|
||||
SELECT y FROM t2 ORDER BY y;
|
||||
} {1 4 5 | 1 4}
|
||||
|
||||
do_rtree_integrity_test rtreeF-1.6 t3
|
||||
|
||||
finish_test
|
||||
|
@ -15,6 +15,7 @@
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
@ -37,6 +38,7 @@ do_execsql_test rtreeG-1.2 {
|
||||
INSERT INTO t1 VALUES(1,10,15,5,23),(2,20,21,5,23),(3,10,15,20,30);
|
||||
SELECT id from t1 WHERE x0>8 AND x1<16 AND y0>2 AND y1<25;
|
||||
} {1}
|
||||
do_rtree_integrity_test rtreeG-1.2.integrity t1
|
||||
do_test rtreeG-1.2log {
|
||||
set ::log
|
||||
} {}
|
||||
|
@ -190,3 +190,8 @@ proc rtree_treedump {db zTab} {
|
||||
set d [rtree_depth $db $zTab]
|
||||
rtree_nodetreedump $db $zTab "" $d 1
|
||||
}
|
||||
|
||||
proc do_rtree_integrity_test {tn tbl} {
|
||||
uplevel [list do_execsql_test $tn "SELECT rtreecheck('$tbl')" ok]
|
||||
}
|
||||
|
||||
|
113
ext/rtree/rtreecheck.test
Normal file
113
ext/rtree/rtreecheck.test
Normal file
@ -0,0 +1,113 @@
|
||||
# 2017 August 17
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
set testprefix rtreecheck
|
||||
|
||||
ifcapable !rtree {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc swap_int32 {blob i0 i1} {
|
||||
binary scan $blob I* L
|
||||
|
||||
set a [lindex $L $i0]
|
||||
set b [lindex $L $i1]
|
||||
|
||||
lset L $i0 $b
|
||||
lset L $i1 $a
|
||||
|
||||
binary format I* $L
|
||||
}
|
||||
|
||||
do_catchsql_test 1.0 {
|
||||
SELECT rtreecheck();
|
||||
} {1 {wrong number of arguments to function rtreecheck()}}
|
||||
|
||||
do_catchsql_test 1.1 {
|
||||
SELECT rtreecheck(0,0,0);
|
||||
} {1 {wrong number of arguments to function rtreecheck()}}
|
||||
|
||||
|
||||
proc setup_simple_db {{module rtree}} {
|
||||
reset_db
|
||||
db func swap_int32 swap_int32
|
||||
execsql "
|
||||
CREATE VIRTUAL TABLE r1 USING $module (id, x1, x2, y1, y2);
|
||||
INSERT INTO r1 VALUES(1, 5, 5, 5, 5); -- 3
|
||||
INSERT INTO r1 VALUES(2, 6, 6, 6, 6); -- 9
|
||||
INSERT INTO r1 VALUES(3, 7, 7, 7, 7); -- 15
|
||||
INSERT INTO r1 VALUES(4, 8, 8, 8, 8); -- 21
|
||||
INSERT INTO r1 VALUES(5, 9, 9, 9, 9); -- 27
|
||||
"
|
||||
}
|
||||
|
||||
setup_simple_db
|
||||
do_execsql_test 2.1 {
|
||||
SELECT rtreecheck('r1')
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
UPDATE r1_node SET data = swap_int32(data, 3, 9);
|
||||
UPDATE r1_node SET data = swap_int32(data, 23, 29);
|
||||
}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT rtreecheck('r1')
|
||||
} {{Dimension 0 of cell 0 on node 1 is corrupt
|
||||
Dimension 1 of cell 3 on node 1 is corrupt}}
|
||||
|
||||
setup_simple_db
|
||||
do_execsql_test 2.4 {
|
||||
DELETE FROM r1_rowid WHERE rowid = 3;
|
||||
SELECT rtreecheck('r1')
|
||||
} {{Mapping (3 -> 1) missing from %_rowid table
|
||||
Wrong number of entries in %_rowid table - expected 5, actual 4}}
|
||||
|
||||
setup_simple_db
|
||||
do_execsql_test 2.5 {
|
||||
UPDATE r1_rowid SET nodeno=2 WHERE rowid=3;
|
||||
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);
|
||||
INSERT INTO r1 VALUES(1, 0x7FFFFFFF*-1, 0x7FFFFFFF);
|
||||
INSERT INTO r1 VALUES(2, 0x7FFFFFFF*-1, 5);
|
||||
INSERT INTO r1 VALUES(3, -5, 5);
|
||||
INSERT INTO r1 VALUES(4, 5, 0x11111111);
|
||||
INSERT INTO r1 VALUES(5, 5, 0x00800000);
|
||||
INSERT INTO r1 VALUES(6, 5, 0x00008000);
|
||||
INSERT INTO r1 VALUES(7, 5, 0x00000080);
|
||||
INSERT INTO r1 VALUES(8, 5, 0x40490fdb);
|
||||
INSERT INTO r1 VALUES(9, 0x7f800000, 0x7f900000);
|
||||
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}
|
||||
|
||||
|
||||
finish_test
|
||||
|
43
manifest
43
manifest
@ -1,5 +1,5 @@
|
||||
C Do\snot\sreference\sthe\sioctl()\ssystem\scall\sin\sthe\sunix\sbackend\sunless\sit\nis\sactually\sneeded\sby\sthe\sBatch\sAtomic\sWrite\sextension.\s\sThis\sshould\sallow\nthe\sbuild\sto\swork\son\sVxWorks.
|
||||
D 2017-10-25T16:14:12.910
|
||||
C Add\sSQL\sscalar\sfunction\srtreecheck()\sto\sthe\srtree\smodule.\sFor\srunning\schecks\nto\sensure\sthe\sshadow\stables\sused\sby\san\srtree\svirtual\stable\sare\sinternally\nconsistent.
|
||||
D 2017-10-25T16:38:34.144
|
||||
F Makefile.in e016061b23e60ac9ec27c65cb577292b6bde0307ca55abd874ab3487b3b1beb2
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 37740aba9c4bb359c627eadccf1cfd7be4f5f847078723777ea7763969e533b1
|
||||
@ -329,26 +329,27 @@ 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 f2fd34db37ea053798f8e66b44a473449b21301d2b92505ee576823789e909fb
|
||||
F ext/rtree/rtree.c 7941c4283bef9ecdd1b7a5c20122006b7d363836468fe7f4bef46698c55d1d93
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 4fdd60ae034e43f2fefc26492032d02e742e8b14d468b7c51d95a1e2fa47cf00
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
F ext/rtree/rtree1.test 82a353747fcab1083d114b2ac84723dfefdbf86c1a6e1df57bf588c7d4285436
|
||||
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
|
||||
F ext/rtree/rtree3.test 2cafe8265d1ff28f206fce88d114f208349df482
|
||||
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
|
||||
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
|
||||
F ext/rtree/rtree4.test 67b021858ba4334c8d49b3449476942c2ce0e5ef7123538f2e9dd508ed03a12d
|
||||
F ext/rtree/rtree5.test 8aaa4bcdc42f718fe165572f5623e4732831aca95a2bc32482d33d4d2cf1325d
|
||||
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
|
||||
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
|
||||
F ext/rtree/rtree8.test 076d9d5b783b61b7a23a5ab45fc899551dfffd821974f36ee599ff29f4de7a61
|
||||
F ext/rtree/rtree9.test 8bfa84dfaba1c897468a2448c28db0a00ad12d464225b5993c7814e907f3776f
|
||||
F ext/rtree/rtreeA.test c09ad3f76c08feac00770685ff50ca12966dc0c641bf19a982b26a80643b46d1
|
||||
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
|
||||
F ext/rtree/rtreeC.test c0a9c67f2efa98b6fae12acb8a28348d231a481d
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2
|
||||
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
|
||||
F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776
|
||||
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
|
||||
F ext/rtree/rtreeC.test d9d06dda1aee68b4dc227dfcc899f335f8b621e9d1920ee3d4e5dab8ccd71db7
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
F ext/rtree/rtreeE.test 45a147a64a76306172819562309681d8e90f94bb
|
||||
F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
|
||||
F ext/rtree/rtreeG.test 3b185719630795f38594f64cd7d1de86a33f91f1
|
||||
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
|
||||
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
|
||||
F ext/rtree/rtreeG.test fd3af1ca944a0bdb0cbb5455a4905c9f012e2fffcab6b791f07afa0dcbbcae0e
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
||||
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
|
||||
F ext/rtree/rtreecheck.test f610cb77ca1ba611e656018a7d960cd46054baecd2f12d1149bf1fec121aa230
|
||||
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
|
||||
F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
@ -1665,7 +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 1e30f4772db1e1086096f72d32e87c552923be8b264aa13cf822fae754eb083d
|
||||
R 15e40e111eafb5e48910635a49cabea3
|
||||
U drh
|
||||
Z 02638cae8d6ec29df692272f34f9ba5b
|
||||
P adfa7ed2de3e833fff65935455e71236a59602aaf7b97ece667ab300dca9f673
|
||||
R b2ab5ba3cbab5da53d273c6ee124bea0
|
||||
U dan
|
||||
Z 3064e6e3a20de6115706024077565624
|
||||
|
@ -1 +1 @@
|
||||
adfa7ed2de3e833fff65935455e71236a59602aaf7b97ece667ab300dca9f673
|
||||
dde0bb3eab1316c3247b1755594527ca70955aab4ad4907190731f7ec092b327
|
Loading…
Reference in New Issue
Block a user