Fix for [e9a9fde1f4]. When opening an existing rtree, determine the node size by inspecting the root node of the r-tree structure (instead of assuming it is a function of the page-size).
FossilOrigin-Name: ebc9433fddf78ef7b4237686951d8d79c1c98f03
This commit is contained in:
parent
9a6ffc845b
commit
5dcb3937b6
@ -423,6 +423,7 @@ nodeAcquire(
|
||||
rc = sqlite3_step(pRtree->pReadNode);
|
||||
if( rc==SQLITE_ROW ){
|
||||
const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
|
||||
assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize );
|
||||
memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
|
||||
nodeReference(pParent);
|
||||
}else{
|
||||
@ -2619,31 +2620,69 @@ static int rtreeSqlInit(
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine queries database handle db for the page-size used by
|
||||
** database zDb. If successful, the page-size in bytes is written to
|
||||
** *piPageSize and SQLITE_OK returned. Otherwise, and an SQLite error
|
||||
** code is returned.
|
||||
** The second argument to this function contains the text of an SQL statement
|
||||
** that returns a single integer value. The statement is compiled and executed
|
||||
** using database connection db. If successful, the integer value returned
|
||||
** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
|
||||
** code is returned and the value of *piVal after returning is not defined.
|
||||
*/
|
||||
static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){
|
||||
static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
|
||||
int rc = SQLITE_NOMEM;
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
*piVal = sqlite3_column_int(pStmt, 0);
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called from within the xConnect() or xCreate() method to
|
||||
** determine the node-size used by the rtree table being created or connected
|
||||
** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
|
||||
** Otherwise, an SQLite error code is returned.
|
||||
**
|
||||
** If this function is being called as part of an xConnect(), then the rtree
|
||||
** table already exists. In this case the node-size is determined by inspecting
|
||||
** the root node of the tree.
|
||||
**
|
||||
** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
|
||||
** This ensures that each node is stored on a single database page. If the
|
||||
** database page-size is so large that more than RTREE_MAXCELLS entries
|
||||
** would fit in a single node, use a smaller node-size.
|
||||
*/
|
||||
static int getNodeSize(
|
||||
sqlite3 *db, /* Database handle */
|
||||
Rtree *pRtree, /* Rtree handle */
|
||||
int isCreate /* True for xCreate, false for xConnect */
|
||||
){
|
||||
int rc;
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
|
||||
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb);
|
||||
if( !zSql ){
|
||||
return SQLITE_NOMEM;
|
||||
if( isCreate ){
|
||||
int iPageSize;
|
||||
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
|
||||
rc = getIntFromStmt(db, zSql, &iPageSize);
|
||||
if( rc==SQLITE_OK ){
|
||||
pRtree->iNodeSize = iPageSize-64;
|
||||
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
|
||||
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
|
||||
pRtree->zDb, pRtree->zName
|
||||
);
|
||||
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
|
||||
}
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
*piPageSize = sqlite3_column_int(pStmt, 0);
|
||||
}
|
||||
return sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2683,11 +2722,6 @@ static int rtreeInit(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
rc = getPageSize(db, argv[1], &iPageSize);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Allocate the sqlite3_vtab structure */
|
||||
nDb = strlen(argv[1]);
|
||||
nName = strlen(argv[2]);
|
||||
@ -2706,44 +2740,37 @@ static int rtreeInit(
|
||||
memcpy(pRtree->zDb, argv[1], nDb);
|
||||
memcpy(pRtree->zName, argv[2], nName);
|
||||
|
||||
/* Figure out the node size to use. By default, use 64 bytes less than
|
||||
** the database page-size. This ensures that each node is stored on
|
||||
** a single database page.
|
||||
**
|
||||
** If the databasd page-size is so large that more than RTREE_MAXCELLS
|
||||
** entries would fit in a single node, use a smaller node-size.
|
||||
*/
|
||||
pRtree->iNodeSize = iPageSize-64;
|
||||
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
|
||||
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
|
||||
}
|
||||
/* Figure out the node size to use. */
|
||||
rc = getNodeSize(db, pRtree, isCreate);
|
||||
|
||||
/* Create/Connect to the underlying relational database schema. If
|
||||
** that is successful, call sqlite3_declare_vtab() to configure
|
||||
** the r-tree table schema.
|
||||
*/
|
||||
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}else{
|
||||
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
|
||||
char *zTmp;
|
||||
int ii;
|
||||
for(ii=4; zSql && ii<argc; ii++){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( zSql ){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s);", zTmp);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}else{
|
||||
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
|
||||
char *zTmp;
|
||||
int ii;
|
||||
for(ii=4; zSql && ii<argc; ii++){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( zSql ){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s);", zTmp);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
58
ext/rtree/rtree7.test
Normal file
58
ext/rtree/rtree7.test
Normal file
@ -0,0 +1,58 @@
|
||||
# 2010 February 16
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test that nothing goes wrong if an rtree table is created, then the
|
||||
# database page-size is modified. At one point (3.6.22), this was causing
|
||||
# malfunctions.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !rtree||!vacuum {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_test rtree7-1.1 {
|
||||
execsql {
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2);
|
||||
INSERT INTO rt VALUES(1, 1, 2, 3, 4);
|
||||
}
|
||||
} {}
|
||||
do_test rtree7-1.2 {
|
||||
execsql { SELECT * FROM rt }
|
||||
} {1 1.0 2.0 3.0 4.0}
|
||||
do_test rtree7-1.3 {
|
||||
execsql {
|
||||
PRAGMA page_size = 2048;
|
||||
VACUUM;
|
||||
SELECT * FROM rt;
|
||||
}
|
||||
} {1 1.0 2.0 3.0 4.0}
|
||||
do_test rtree7-1.4 {
|
||||
for {set i 2} {$i <= 51} {incr i} {
|
||||
execsql { INSERT INTO rt VALUES($i, 1, 2, 3, 4) }
|
||||
}
|
||||
execsql { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt }
|
||||
} {51.0 102.0 153.0 204.0}
|
||||
do_test rtree7-1.5 {
|
||||
execsql {
|
||||
PRAGMA page_size = 512;
|
||||
VACUUM;
|
||||
SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt
|
||||
}
|
||||
} {51.0 102.0 153.0 204.0}
|
||||
|
||||
finish_test
|
25
manifest
25
manifest
@ -1,8 +1,5 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Fix\sthe\sALTER\sTABLE\sRENAME\scommand\sso\sthat\sit\sconverts\sFOREIGN\sKEY\sconstraints\nin\sATTACH-ed\sand\sin\sTEMP\stables\sas\swell\sas\sin\sthe\smain\sdatabase.\nTicket\s[13336e9c3c8c3f].
|
||||
D 2010-02-15T18:03:20
|
||||
C Fix\sfor\s[e9a9fde1f4].\sWhen\sopening\san\sexisting\srtree,\sdetermine\sthe\snode\ssize\sby\sinspecting\sthe\sroot\snode\sof\sthe\sr-tree\sstructure\s(instead\sof\sassuming\sit\sis\sa\sfunction\sof\sthe\spage-size).
|
||||
D 2010-02-16T10:59:41
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -77,7 +74,7 @@ F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
|
||||
F ext/icu/icu.c 850e9a36567bbcce6bd85a4b68243cad8e3c2de2
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 038d59b05783c2e6c927a7352bb118a76c31065a
|
||||
F ext/rtree/rtree.c b82403b0320a7278e0a0e6562c08c8bba17ee0dd
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test f72885ed80a329d6bd7991043016d74b51edf2c5
|
||||
F ext/rtree/rtree2.test 7b665c44d25e51b3098068d983a39902b2e2d7a1
|
||||
@ -85,6 +82,7 @@ F ext/rtree/rtree3.test dece988c363368af8c11862995c762071894918f
|
||||
F ext/rtree/rtree4.test 94fdd570ab5bc47244d87d4590023be43ac786bd
|
||||
F ext/rtree/rtree5.test 92508f5152a50110af6551fa5b769d1bbd7c4ef3
|
||||
F ext/rtree/rtree6.test 11aade5311789068ca659be24a47cc0d852b1971
|
||||
F ext/rtree/rtree7.test 6fd29fb8e13795c822f4ceeea92ab5d61c96976d
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
||||
F ext/rtree/tkt3363.test 2bf324f7908084a5f463de3109db9c6e607feb1b
|
||||
@ -790,14 +788,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P ec914af32675e472694270d46f3ba2214eb2fe90
|
||||
R b63197d6039614d907827a453eecec99
|
||||
U drh
|
||||
Z 49dfd565a21afaa90179ba63716c3b3a
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFLeYxroxKgR168RlERAp42AJ9eXZoQAtGar3vAWWJ+ElAji3XDgACfTqUL
|
||||
/luMg2NSLMumM1Iu2R9tVWU=
|
||||
=ahs6
|
||||
-----END PGP SIGNATURE-----
|
||||
P ab197d0aaf18016ac2dd3674f49bea5f1556451c
|
||||
R 881d2a8a41b8ae3c95eeef834233ccdb
|
||||
U dan
|
||||
Z 64c445e5b0bc8d218abafa630888b286
|
||||
|
@ -1 +1 @@
|
||||
ab197d0aaf18016ac2dd3674f49bea5f1556451c
|
||||
ebc9433fddf78ef7b4237686951d8d79c1c98f03
|
Loading…
Reference in New Issue
Block a user