From 487e15dc239ccdb3344d1c99ce120e872bab4a74 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 20 Sep 2012 18:34:38 -0400 Subject: Imported Upstream version 2.0.6 --- ext/rtree/rtree.c | 256 +++++++++++++++++++++++++++-------------------- ext/rtree/rtree1.test | 88 +++++++++------- ext/rtree/rtree4.test | 43 +++++--- ext/rtree/rtree5.test | 8 +- ext/rtree/rtree6.test | 2 +- ext/rtree/rtree7.test | 28 ++++-- ext/rtree/rtree9.test | 1 + ext/rtree/rtreeB.test | 37 ++++--- ext/rtree/sqlite3rtree.h | 6 +- 9 files changed, 286 insertions(+), 183 deletions(-) (limited to 'ext/rtree') diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 884482e..d6cdde9 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -182,6 +182,19 @@ struct Rtree { #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 +/* +** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will +** only deal with integer coordinates. No floating point operations +** will be done. +*/ +#ifdef SQLITE_RTREE_INT_ONLY + typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ + typedef int RtreeValue; /* Low accuracy coordinate */ +#else + typedef double RtreeDValue; /* High accuracy coordinate */ + typedef float RtreeValue; /* Low accuracy coordinate */ +#endif + /* ** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: @@ -217,20 +230,25 @@ struct RtreeCursor { }; union RtreeCoord { - float f; + RtreeValue f; int i; }; /* ** The argument is an RtreeCoord. Return the value stored within the RtreeCoord -** formatted as a double. This macro assumes that local variable pRtree points -** to the Rtree structure associated with the RtreeCoord. +** formatted as a RtreeDValue (double or int64). This macro assumes that local +** variable pRtree points to the Rtree structure associated with the +** RtreeCoord. */ -#define DCOORD(coord) ( \ - (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ - ((double)coord.f) : \ - ((double)coord.i) \ -) +#ifdef SQLITE_RTREE_INT_ONLY +# define DCOORD(coord) ((RtreeDValue)coord.i) +#else +# define DCOORD(coord) ( \ + (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ + ((double)coord.f) : \ + ((double)coord.i) \ + ) +#endif /* ** A search constraint. @@ -238,8 +256,8 @@ union RtreeCoord { struct RtreeConstraint { int iCoord; /* Index of constrained coordinate */ int op; /* Constraining operation */ - double rValue; /* Constraint value. */ - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + RtreeDValue rValue; /* Constraint value. */ + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ }; @@ -287,10 +305,10 @@ struct RtreeCell { */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); void *pContext; int nParam; - double aParam[1]; + RtreeDValue aParam[1]; }; /* @@ -302,7 +320,7 @@ struct RtreeMatchArg { ** the geometry callback function). */ struct RtreeGeomCallback { - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); void *pContext; }; @@ -868,7 +886,7 @@ static int testRtreeGeom( int *pbRes /* OUT: Test result */ ){ int i; - double aCoord[RTREE_MAX_DIMENSIONS*2]; + RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; int nCoord = pRtree->nDim*2; assert( pConstraint->op==RTREE_MATCH ); @@ -898,8 +916,8 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; bRes==0 && iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); - double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); + RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); + RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -951,7 +969,7 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - double coord = DCOORD(cell.aCoord[p->iCoord]); + RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); int res; assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -1149,9 +1167,12 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ }else{ RtreeCoord c; nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); +#ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); - }else{ + }else +#endif + { assert( pRtree->eCoordType==RTREE_COORD_INT32 ); sqlite3_result_int(ctx, c.i); } @@ -1193,12 +1214,12 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ int nBlob; /* Check that value is actually a blob. */ - if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; + if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); if( nBlob<(int)sizeof(RtreeMatchArg) - || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 + || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 ){ return SQLITE_ERROR; } @@ -1212,7 +1233,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ memcpy(p, sqlite3_value_blob(pValue), nBlob); if( p->magic!=RTREE_GEOMETRY_MAGIC - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) + || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) ){ sqlite3_free(pGeom); return SQLITE_ERROR; @@ -1284,7 +1305,11 @@ static int rtreeFilter( break; } }else{ +#ifdef SQLITE_RTREE_INT_ONLY + p->rValue = sqlite3_value_int64(argv[ii]); +#else p->rValue = sqlite3_value_double(argv[ii]); +#endif } } } @@ -1418,11 +1443,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ /* ** Return the N-dimensional volumn of the cell stored in *p. */ -static float cellArea(Rtree *pRtree, RtreeCell *p){ - float area = 1.0; +static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ + RtreeDValue area = (RtreeDValue)1; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); + area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); } return area; } @@ -1431,11 +1456,11 @@ static float cellArea(Rtree *pRtree, RtreeCell *p){ ** Return the margin length of cell p. The margin length is the sum ** of the objects size in each dimension. */ -static float cellMargin(Rtree *pRtree, RtreeCell *p){ - float margin = 0.0; +static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ + RtreeDValue margin = (RtreeDValue)0; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); + margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); } return margin; } @@ -1480,8 +1505,8 @@ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ /* ** Return the amount cell p would grow by if it were unioned with pCell. */ -static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ - float area; +static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ + RtreeDValue area; RtreeCell cell; memcpy(&cell, p, sizeof(RtreeCell)); area = cellArea(pRtree, &cell); @@ -1490,7 +1515,7 @@ static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ } #if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT -static float cellOverlap( +static RtreeDValue cellOverlap( Rtree *pRtree, RtreeCell *p, RtreeCell *aCell, @@ -1498,7 +1523,7 @@ static float cellOverlap( int iExclude ){ int ii; - float overlap = 0.0; + RtreeDValue overlap = 0.0; for(ii=0; iinDim*2); jj+=2){ - double x1; - double x2; + RtreeDValue x1, x2; x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); @@ -1520,7 +1544,7 @@ static float cellOverlap( o = 0.0; break; }else{ - o = o * (float)(x2-x1); + o = o * (x2-x1); } } overlap += o; @@ -1531,7 +1555,7 @@ static float cellOverlap( #endif #if VARIANT_RSTARTREE_CHOOSESUBTREE -static float cellOverlapEnlargement( +static RtreeDValue cellOverlapEnlargement( Rtree *pRtree, RtreeCell *p, RtreeCell *pInsert, @@ -1539,12 +1563,11 @@ static float cellOverlapEnlargement( int nCell, int iExclude ){ - double before; - double after; + RtreeDValue before, after; before = cellOverlap(pRtree, p, aCell, nCell, iExclude); cellUnion(pRtree, p, pInsert); after = cellOverlap(pRtree, p, aCell, nCell, iExclude); - return (float)(after-before); + return (after-before); } #endif @@ -1568,11 +1591,11 @@ static int ChooseLeaf( int iCell; sqlite3_int64 iBest = 0; - float fMinGrowth = 0.0; - float fMinArea = 0.0; + RtreeDValue fMinGrowth = 0.0; + RtreeDValue fMinArea = 0.0; #if VARIANT_RSTARTREE_CHOOSESUBTREE - float fMinOverlap = 0.0; - float overlap; + RtreeDValue fMinOverlap = 0.0; + RtreeDValue overlap; #endif int nCell = NCELL(pNode); @@ -1603,8 +1626,8 @@ static int ChooseLeaf( */ for(iCell=0; iCellnDim; i++){ - float x1 = DCOORD(aCell[0].aCoord[i*2]); - float x2 = DCOORD(aCell[0].aCoord[i*2+1]); - float x3 = x1; - float x4 = x2; + RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); + RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); + RtreeDValue x3 = x1; + RtreeDValue x4 = x2; int jj; int iCellLeft = 0; int iCellRight = 0; for(jj=1; jjx4 ) x4 = right; @@ -1765,7 +1788,7 @@ static void LinearPickSeeds( } if( x4!=x1 ){ - float normalwidth = (x3 - x2) / (x4 - x1); + RtreeDValue normalwidth = (x3 - x2) / (x4 - x1); if( normalwidth>maxNormalInnerWidth ){ iLeftSeed = iCellLeft; iRightSeed = iCellRight; @@ -1794,13 +1817,13 @@ static RtreeCell *QuadraticPickNext( #define FABS(a) ((a)<0.0?-1.0*(a):(a)) int iSelect = -1; - float fDiff; + RtreeDValue fDiff; int ii; for(ii=0; iifDiff ){ fDiff = diff; iSelect = ii; @@ -1827,13 +1850,13 @@ static void QuadraticPickSeeds( int iLeftSeed = 0; int iRightSeed = 1; - float fWaste = 0.0; + RtreeDValue fWaste = 0.0; for(ii=0; iifWaste ){ iLeftSeed = ii; @@ -1868,7 +1891,7 @@ static void QuadraticPickSeeds( static void SortByDistance( int *aIdx, int nIdx, - float *aDistance, + RtreeDValue *aDistance, int *aSpare ){ if( nIdx>1 ){ @@ -1894,8 +1917,8 @@ static void SortByDistance( aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ - float fLeft = aDistance[aLeft[iLeft]]; - float fRight = aDistance[aRight[iRight]]; + RtreeDValue fLeft = aDistance[aLeft[iLeft]]; + RtreeDValue fRight = aDistance[aRight[iRight]]; if( fLeftnDim+1)*(sizeof(int*)+nCell*sizeof(int)); @@ -2027,9 +2050,9 @@ static int splitNodeStartree( } for(ii=0; iinDim; ii++){ - float margin = 0.0; - float fBestOverlap = 0.0; - float fBestArea = 0.0; + RtreeDValue margin = 0.0; + RtreeDValue fBestOverlap = 0.0; + RtreeDValue fBestArea = 0.0; int iBestLeft = 0; int nLeft; @@ -2041,8 +2064,8 @@ static int splitNodeStartree( RtreeCell left; RtreeCell right; int kk; - float overlap; - float area; + RtreeDValue overlap; + RtreeDValue area; memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); @@ -2125,7 +2148,7 @@ static int splitNodeGuttman( for(i=nCell-2; i>0; i--){ RtreeCell *pNext; pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); - float diff = + RtreeDValue diff = cellGrowth(pRtree, pBboxLeft, pNext) - cellGrowth(pRtree, pBboxRight, pNext) ; @@ -2458,32 +2481,34 @@ static int Reinsert( int *aOrder; int *aSpare; RtreeCell *aCell; - float *aDistance; + RtreeDValue *aDistance; int nCell; - float aCenterCoord[RTREE_MAX_DIMENSIONS]; + RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS]; int iDim; int ii; int rc = SQLITE_OK; + int n; - memset(aCenterCoord, 0, sizeof(float)*RTREE_MAX_DIMENSIONS); + memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS); nCell = NCELL(pNode)+1; + n = (nCell+1)&(~1); /* Allocate the buffers used by this operation. The allocation is ** relinquished before this function returns. */ - aCell = (RtreeCell *)sqlite3_malloc(nCell * ( - sizeof(RtreeCell) + /* aCell array */ - sizeof(int) + /* aOrder array */ - sizeof(int) + /* aSpare array */ - sizeof(float) /* aDistance array */ + aCell = (RtreeCell *)sqlite3_malloc(n * ( + sizeof(RtreeCell) + /* aCell array */ + sizeof(int) + /* aOrder array */ + sizeof(int) + /* aSpare array */ + sizeof(RtreeDValue) /* aDistance array */ )); if( !aCell ){ return SQLITE_NOMEM; } - aOrder = (int *)&aCell[nCell]; - aSpare = (int *)&aOrder[nCell]; - aDistance = (float *)&aSpare[nCell]; + aOrder = (int *)&aCell[n]; + aSpare = (int *)&aOrder[n]; + aDistance = (RtreeDValue *)&aSpare[n]; for(ii=0; iinDim; iDim++){ - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]); - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); } } for(iDim=0; iDimnDim; iDim++){ - aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0)); + aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); } for(ii=0; iinDim; iDim++){ - float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) - - DCOORD(aCell[ii].aCoord[iDim*2])); + RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - + DCOORD(aCell[ii].aCoord[iDim*2])); aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); } } @@ -2747,16 +2772,19 @@ static int rtreeUpdate( /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ assert( nData==(pRtree->nDim*2 + 3) ); +#ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - cell.aCoord[ii].f = (float)sqlite3_value_double(azData[ii+3]); - cell.aCoord[ii+1].f = (float)sqlite3_value_double(azData[ii+4]); + cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]); + cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]); if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ rc = SQLITE_CONSTRAINT; goto constraint; } } - }else{ + }else +#endif + { for(ii=0; ii<(pRtree->nDim*2); ii+=2){ cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); @@ -3056,8 +3084,8 @@ static int rtreeInit( sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); /* Allocate the sqlite3_vtab structure */ - nDb = strlen(argv[1]); - nName = strlen(argv[2]); + nDb = (int)strlen(argv[1]); + nName = (int)strlen(argv[2]); pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); if( !pRtree ){ return SQLITE_NOMEM; @@ -3152,10 +3180,16 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ nodeGetCell(&tree, &node, ii, &cell); sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); - nCell = strlen(zCell); + nCell = (int)strlen(zCell); for(jj=0; jjpContext = pGeomCtx->pContext; pBlob->nParam = nArg; for(i=0; iaParam[i] = sqlite3_value_int64(aArg[i]); +#else pBlob->aParam[i] = sqlite3_value_double(aArg[i]); +#endif } sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); } @@ -3253,7 +3295,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *), + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), void *pContext ){ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index 583b028..e3c7d68 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -104,6 +104,18 @@ for {set nCol 1} {$nCol<[llength $cols]} {incr nCol} { catchsql { DROP TABLE t1 } } +# Like execsql except display output as integer where that can be +# done without loss of information. +# +proc execsql_intout {sql} { + set out {} + foreach term [execsql $sql] { + regsub {\.0$} $term {} term + lappend out $term + } + return $out +} + # Test that it is possible to open an existing database that contains # r-tree tables. # @@ -117,8 +129,8 @@ do_test rtree-1.4.1 { do_test rtree-1.4.2 { db close sqlite3 db test.db - execsql { SELECT * FROM t1 ORDER BY ii } -} {1 5.0 10.0 2 15.0 20.0} + execsql_intout { SELECT * FROM t1 ORDER BY ii } +} {1 5 10 2 15 20} do_test rtree-1.4.3 { execsql { DROP TABLE t1 } } {} @@ -127,12 +139,12 @@ do_test rtree-1.4.3 { # column names. # do_test rtree-1.5.1 { - execsql { + execsql_intout { CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim"); INSERT INTO t1 VALUES(1, 2, 3); SELECT "the key", "x dim.", "x2'dim" FROM t1; } -} {1 2.0 3.0} +} {1 2 3} do_test rtree-1.5.1 { execsql { DROP TABLE t1 } } {} @@ -161,8 +173,8 @@ do_test rtree-2.1.1 { do_test rtree-2.1.2 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } - execsql { SELECT * FROM t1 } -} {1 1.0 3.0 2.0 4.0} + execsql_intout { SELECT * FROM t1 } +} {1 1 3 2 4} do_test rtree-2.1.3 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } execsql { SELECT rowid FROM t1 ORDER BY rowid } @@ -201,17 +213,17 @@ do_test rtree-3.1.1 { } } {} do_test rtree-3.1.2 { - execsql { + execsql_intout { INSERT INTO t1 VALUES(5, 1, 3, 2, 4); SELECT * FROM t1; } -} {5 1.0 3.0 2.0 4.0} +} {5 1 3 2 4} do_test rtree-3.1.3 { - execsql { + execsql_intout { INSERT INTO t1 VALUES(6, 2, 6, 4, 8); SELECT * FROM t1; } -} {5 1.0 3.0 2.0 4.0 6 2.0 6.0 4.0 8.0} +} {5 1 3 2 4 6 2 6 4 8} # Test the constraint on the coordinates (c[i]<=c[i+1] where (i%2==0)): do_test rtree-3.2.1 { @@ -228,25 +240,25 @@ do_test rtree-5.1.1 { execsql { CREATE VIRTUAL TABLE t2 USING rtree(ii, x1, x2) } } {} do_test rtree-5.1.2 { - execsql { + execsql_intout { INSERT INTO t2 VALUES(1, 10, 20); INSERT INTO t2 VALUES(2, 30, 40); INSERT INTO t2 VALUES(3, 50, 60); SELECT * FROM t2 ORDER BY ii; } -} {1 10.0 20.0 2 30.0 40.0 3 50.0 60.0} +} {1 10 20 2 30 40 3 50 60} do_test rtree-5.1.3 { - execsql { + execsql_intout { DELETE FROM t2 WHERE ii=2; SELECT * FROM t2 ORDER BY ii; } -} {1 10.0 20.0 3 50.0 60.0} +} {1 10 20 3 50 60} do_test rtree-5.1.4 { - execsql { + execsql_intout { DELETE FROM t2 WHERE ii=1; SELECT * FROM t2 ORDER BY ii; } -} {3 50.0 60.0} +} {3 50 60} do_test rtree-5.1.5 { execsql { DELETE FROM t2 WHERE ii=3; @@ -264,16 +276,16 @@ do_test rtree-6.1.1 { execsql { CREATE VIRTUAL TABLE t3 USING rtree(ii, x1, x2, y1, y2) } } {} do_test rtree-6.1.2 { - execsql { + execsql_intout { INSERT INTO t3 VALUES(1, 2, 3, 4, 5); UPDATE t3 SET x2=5; SELECT * FROM t3; } -} {1 2.0 5.0 4.0 5.0} +} {1 2 5 4 5} do_test rtree-6.1.3 { execsql { UPDATE t3 SET ii = 2 } - execsql { SELECT * FROM t3 } -} {2 2.0 5.0 4.0 5.0} + execsql_intout { SELECT * FROM t3 } +} {2 2 5 4 5} #---------------------------------------------------------------------------- # Test cases rtree-7.* test rename operations. @@ -286,29 +298,29 @@ do_test rtree-7.1.1 { } {} do_test rtree-7.1.2 { execsql { ALTER TABLE t4 RENAME TO t5 } - execsql { SELECT * FROM t5 } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM t5 } +} {1 2 3 4 5 6 7} do_test rtree-7.1.3 { db close sqlite3 db test.db - execsql { SELECT * FROM t5 } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM t5 } +} {1 2 3 4 5 6 7} do_test rtree-7.1.4 { execsql { ALTER TABLE t5 RENAME TO 'raisara "one"'''} - execsql { SELECT * FROM "raisara ""one""'" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "raisara ""one""'" } +} {1 2 3 4 5 6 7} do_test rtree-7.1.5 { - execsql { SELECT * FROM 'raisara "one"''' } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM 'raisara "one"''' } +} {1 2 3 4 5 6 7} do_test rtree-7.1.6 { execsql { ALTER TABLE "raisara ""one""'" RENAME TO "abc 123" } - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} do_test rtree-7.1.7 { db close sqlite3 db test.db - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} # An error midway through a rename operation. do_test rtree-7.2.1 { @@ -318,8 +330,8 @@ do_test rtree-7.2.1 { catchsql { ALTER TABLE "abc 123" RENAME TO t4 } } {1 {SQL logic error or missing database}} do_test rtree-7.2.2 { - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} do_test rtree-7.2.3 { execsql { DROP TABLE t4_node; @@ -330,13 +342,13 @@ do_test rtree-7.2.3 { do_test rtree-7.2.4 { db close sqlite3 db test.db - execsql { SELECT * FROM "abc 123" } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM "abc 123" } +} {1 2 3 4 5 6 7} do_test rtree-7.2.5 { execsql { DROP TABLE t4_rowid } execsql { ALTER TABLE "abc 123" RENAME TO t4 } - execsql { SELECT * FROM t4 } -} {1 2.0 3.0 4.0 5.0 6.0 7.0} + execsql_intout { SELECT * FROM t4 } +} {1 2 3 4 5 6 7} #---------------------------------------------------------------------------- diff --git a/ext/rtree/rtree4.test b/ext/rtree/rtree4.test index 708d335..a3872b0 100644 --- a/ext/rtree/rtree4.test +++ b/ext/rtree/rtree4.test @@ -27,21 +27,38 @@ if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 250 } -# Return a floating point number between -X and X. -# -proc rand {X} { - return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] -} - -# Return a positive floating point number less than or equal to X -# -proc randincr {X} { - while 1 { - set r [expr {int(rand()*$X*32.0)/32.0}] - if {$r>0.0} {return $r} +ifcapable !rtree_int_only { + # Return a floating point number between -X and X. + # + proc rand {X} { + return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] + } + + # Return a positive floating point number less than or equal to X + # + proc randincr {X} { + while 1 { + set r [expr {int(rand()*$X*32.0)/32.0}] + if {$r>0.0} {return $r} + } + } +} else { + # For rtree_int_only, return an number between -X and X. + # + proc rand {X} { + return [expr {int((rand()-0.5)*2*$X)}] + } + + # Return a positive integer less than or equal to X + # + proc randincr {X} { + while 1 { + set r [expr {int(rand()*$X)+1}] + if {$r>0} {return $r} + } } } - + # Scramble the $inlist into a random order. # proc scramble {inlist} { diff --git a/ext/rtree/rtree5.test b/ext/rtree/rtree5.test index ea2946f..8990772 100644 --- a/ext/rtree/rtree5.test +++ b/ext/rtree/rtree5.test @@ -49,9 +49,11 @@ do_test rtree5-1.6 { do_test rtree5-1.7 { execsql { SELECT count(*) FROM t1 WHERE x1==5 } } {1} -do_test rtree5-1.8 { - execsql { SELECT count(*) FROM t1 WHERE x1==5.2 } -} {0} +ifcapable !rtree_int_only { + do_test rtree5-1.8 { + execsql { SELECT count(*) FROM t1 WHERE x1==5.2 } + } {0} +} do_test rtree5-1.9 { execsql { SELECT count(*) FROM t1 WHERE x1==5.0 } } {1} diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test index ba0e53c..92edc8d 100644 --- a/ext/rtree/rtree6.test +++ b/ext/rtree/rtree6.test @@ -16,7 +16,7 @@ if {![info exists testdir]} { } source $testdir/tester.tcl -ifcapable !rtree { +ifcapable {!rtree || rtree_int_only} { finish_test return } diff --git a/ext/rtree/rtree7.test b/ext/rtree/rtree7.test index 31dae0c..4eee4c2 100644 --- a/ext/rtree/rtree7.test +++ b/ext/rtree/rtree7.test @@ -24,6 +24,18 @@ ifcapable !rtree||!vacuum { return } +# Like execsql except display output as integer where that can be +# done without loss of information. +# +proc execsql_intout {sql} { + set out {} + foreach term [execsql $sql] { + regsub {\.0$} $term {} term + lappend out $term + } + return $out +} + do_test rtree7-1.1 { execsql { PRAGMA page_size = 1024; @@ -32,27 +44,27 @@ do_test rtree7-1.1 { } } {} do_test rtree7-1.2 { - execsql { SELECT * FROM rt } -} {1 1.0 2.0 3.0 4.0} + execsql_intout { SELECT * FROM rt } +} {1 1 2 3 4} do_test rtree7-1.3 { - execsql { + execsql_intout { PRAGMA page_size = 2048; VACUUM; SELECT * FROM rt; } -} {1 1.0 2.0 3.0 4.0} +} {1 1 2 3 4} 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} + execsql_intout { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } +} {51 102 153 204} do_test rtree7-1.5 { - execsql { + execsql_intout { PRAGMA page_size = 512; VACUUM; SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } -} {51.0 102.0 153.0 204.0} +} {51 102 153 204} finish_test diff --git a/ext/rtree/rtree9.test b/ext/rtree/rtree9.test index ddee277..6479516 100644 --- a/ext/rtree/rtree9.test +++ b/ext/rtree/rtree9.test @@ -17,6 +17,7 @@ if {![info exists testdir]} { } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } +ifcapable rtree_int_only { finish_test; return } register_cube_geom db diff --git a/ext/rtree/rtreeB.test b/ext/rtree/rtreeB.test index 2756fce..7cb445c 100644 --- a/ext/rtree/rtreeB.test +++ b/ext/rtree/rtreeB.test @@ -18,17 +18,30 @@ if {![info exists testdir]} { source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } -do_test rtreeB-1.1 { - db eval { - CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); - INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); - INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); - INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); - INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); - INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); - SELECT rtreenode(2, data) FROM t1_node; - } -} {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}} - +ifcapable rtree_int_only { + do_test rtreeB-1.1-intonly { + db eval { + CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); + INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); + INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); + INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); + INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); + INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); + SELECT rtreenode(2, data) FROM t1_node; + } + } {{{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}}} +} else { + do_test rtreeB-1.1 { + db eval { + CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); + INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); + INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); + INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); + INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); + INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); + SELECT rtreenode(2, data) FROM t1_node; + } + } {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}} +} finish_test diff --git a/ext/rtree/sqlite3rtree.h b/ext/rtree/sqlite3rtree.h index cffb300..c849091 100644 --- a/ext/rtree/sqlite3rtree.h +++ b/ext/rtree/sqlite3rtree.h @@ -31,7 +31,11 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), +#ifdef SQLITE_RTREE_INT_ONLY + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), +#else + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), +#endif void *pContext ); -- cgit v1.2.3