]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Have the rtree extension publish two virtual table types: "rtree" and "rtree_i32...
authordanielk1977 <danielk1977@noemail.net>
Mon, 14 Jul 2008 15:37:00 +0000 (15:37 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Mon, 14 Jul 2008 15:37:00 +0000 (15:37 +0000)
FossilOrigin-Name: c060a9a6beca455bdceee9ce6ca71a7262f98a5f

ext/rtree/rtree.c
ext/rtree/rtree1.test
ext/rtree/rtree2.test
ext/rtree/rtree5.test [new file with mode: 0644]
manifest
manifest.uuid

index 39c053de279541172b2493068ec74c40846c4803..94deaa9610def1535bc056a7c6a147eb4c0dcb77 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains code for implementations of the r-tree and r*-tree
 ** algorithms packaged as an SQLite virtual table module.
 **
-** $Id: rtree.c,v 1.5 2008/06/23 15:55:52 danielk1977 Exp $
+** $Id: rtree.c,v 1.6 2008/07/14 15:37:01 danielk1977 Exp $
 */
 
 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
@@ -75,6 +75,7 @@ typedef struct RtreeCursor RtreeCursor;
 typedef struct RtreeNode RtreeNode;
 typedef struct RtreeCell RtreeCell;
 typedef struct RtreeConstraint RtreeConstraint;
+typedef union RtreeCoord RtreeCoord;
 
 /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
 #define RTREE_MAX_DIMENSIONS 5
@@ -122,8 +123,14 @@ struct Rtree {
   sqlite3_stmt *pReadParent;
   sqlite3_stmt *pWriteParent;
   sqlite3_stmt *pDeleteParent;
+
+  int eCoordType;
 };
 
+/* Possible values for eCoordType: */
+#define RTREE_COORD_REAL32 0
+#define RTREE_COORD_INT32  1
+
 /*
 ** The minimum number of cells allowed for a node is a third of the 
 ** maximum. In Gutman's notation:
@@ -149,13 +156,29 @@ struct RtreeCursor {
   RtreeConstraint *aConstraint;     /* Search constraints. */
 };
 
+union RtreeCoord {
+  float 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.
+*/
+#define DCOORD(coord) (                           \
+  (pRtree->eCoordType==RTREE_COORD_REAL32) ?      \
+    ((double)coord.f) :                           \
+    ((double)coord.i)                             \
+)
+
 /*
 ** A search constraint.
 */
 struct RtreeConstraint {
   int iCoord;                       /* Index of constrained coordinate */
   int op;                           /* Constraining operation */
-  float rValue;                     /* Constraint value. */
+  double rValue;                    /* Constraint value. */
 };
 
 /* Possible values for RtreeConstraint.op */
@@ -198,7 +221,7 @@ struct RtreeNode {
 */
 struct RtreeCell {
   i64 iRowid;
-  float aCoord[RTREE_MAX_DIMENSIONS*2];
+  RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2];
 };
 
 #define MAX(x,y) ((x) < (y) ? (y) : (x))
@@ -211,14 +234,14 @@ struct RtreeCell {
 static int readInt16(u8 *p){
   return (p[0]<<8) + p[1];
 }
-static float readReal32(u8 *p){
+static void readCoord(u8 *p, RtreeCoord *pCoord){
   u32 i = (
     (((u32)p[0]) << 24) + 
     (((u32)p[1]) << 16) + 
     (((u32)p[2]) <<  8) + 
     (((u32)p[3]) <<  0)
   );
-  return *(float *)&i;
+  *(u32 *)pCoord = i;
 }
 static i64 readInt64(u8 *p){
   return (
@@ -243,11 +266,11 @@ static int writeInt16(u8 *p, int i){
   p[1] = (i>> 0)&0xFF;
   return 2;
 }
-static int writeReal32(u8 *p, float f){
+static int writeCoord(u8 *p, RtreeCoord *pCoord){
   u32 i;
-  assert( sizeof(float)==4 );
+  assert( sizeof(RtreeCoord)==4 );
   assert( sizeof(u32)==4 );
-  i = *(u32 *)&f;
+  i = *(u32 *)pCoord;
   p[0] = (i>>24)&0xFF;
   p[1] = (i>>16)&0xFF;
   p[2] = (i>> 8)&0xFF;
@@ -428,7 +451,7 @@ static void nodeOverwriteCell(
   u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
   p += writeInt64(p, pCell->iRowid);
   for(ii=0; ii<(pRtree->nDim*2); ii++){
-    p += writeReal32(p, pCell->aCoord[ii]);
+    p += writeCoord(p, &pCell->aCoord[ii]);
   }
   pNode->isDirty = 1;
 }
@@ -543,13 +566,14 @@ static i64 nodeGetRowid(
 /*
 ** Return coordinate iCoord from cell iCell in node pNode.
 */
-static float nodeGetCoord(
+static void nodeGetCoord(
   Rtree *pRtree, 
   RtreeNode *pNode, 
   int iCell,
-  int iCoord
+  int iCoord,
+  RtreeCoord *pCoord           /* Space to write result to */
 ){
-  return readReal32(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord]);
+  readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
 }
 
 /*
@@ -565,16 +589,16 @@ static void nodeGetCell(
   int ii;
   pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
   for(ii=0; ii<pRtree->nDim*2; ii++){
-    pCell->aCoord[ii] = nodeGetCoord(pRtree, pNode, iCell, ii);
+    nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]);
   }
 }
 
 
-/* Forward declaration for the function that does the work of 
+/* Forward declaration for the function that does the work of
 ** the virtual table module xCreate() and xConnect() methods.
 */
 static int rtreeInit(
-  sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
+  sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int, int
 );
 
 /* 
@@ -587,7 +611,7 @@ static int rtreeCreate(
   sqlite3_vtab **ppVtab,
   char **pzErr
 ){
-  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
+  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1, (int)pAux);
 }
 
 /* 
@@ -600,7 +624,7 @@ static int rtreeConnect(
   sqlite3_vtab **ppVtab,
   char **pzErr
 ){
-  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
+  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0, (int)pAux);
 }
 
 /*
@@ -716,43 +740,28 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
 static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){
   RtreeCell cell;
   int ii;
+  int bRes = 0;
 
   nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
-  for(ii=0; ii<pCursor->nConstraint; ii++){
+  for(ii=0; bRes==0 && ii<pCursor->nConstraint; 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]);
 
-    float cell_min = cell.aCoord[(p->iCoord>>1)*2];
-    float cell_max = cell.aCoord[(p->iCoord>>1)*2+1];
-    assert( cell_min<=cell_max );
+    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE 
+        || p->op==RTREE_GT || p->op==RTREE_EQ
+    );
 
     switch( p->op ){
-      case RTREE_LE: case RTREE_LT: {
-        if( p->rValue<cell_min ){
-          return 1;
-        }
+      case RTREE_LE: case RTREE_LT: bRes = p->rValue<cell_min; break;
+      case RTREE_GE: case RTREE_GT: bRes = p->rValue>cell_max; break;
+      case RTREE_EQ: 
+        bRes = (p->rValue>cell_max || p->rValue<cell_min);
         break;
-      }
-
-      case RTREE_GE: case RTREE_GT: {
-        if( p->rValue>cell_max ){
-          return 1;
-        }
-        break;
-      }
-
-      case RTREE_EQ: {
-        if( p->rValue>cell_max || p->rValue<cell_min ){
-          return 1;
-        }
-        break;
-      }
-#ifndef NDEBUG
-      default: assert(!"Internal error");
-#endif
     }
   }
 
-  return 0;
+  return bRes;
 }
 
 /* 
@@ -769,18 +778,19 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor){
   nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
   for(ii=0; ii<pCursor->nConstraint; ii++){
     RtreeConstraint *p = &pCursor->aConstraint[ii];
-    float cell_val = cell.aCoord[p->iCoord];
+    double 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
+    );
     switch( p->op ){
-      case RTREE_LE: res = (cell_val<=p->rValue); break;
-      case RTREE_LT: res = (cell_val<p->rValue);  break;
-      case RTREE_GE: res = (cell_val>=p->rValue); break;
-      case RTREE_GT: res = (cell_val>p->rValue);  break;
-      case RTREE_EQ: res = (cell_val==p->rValue); break;
-#ifndef NDEBUG
-      default: assert(!"Internal error");
-#endif
+      case RTREE_LE: res = (coord<=p->rValue); break;
+      case RTREE_LT: res = (coord<p->rValue);  break;
+      case RTREE_GE: res = (coord>=p->rValue); break;
+      case RTREE_GT: res = (coord>p->rValue);  break;
+      case RTREE_EQ: res = (coord==p->rValue); break;
     }
+
     if( !res ) return 1;
   }
 
@@ -935,8 +945,14 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
     i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
     sqlite3_result_int64(ctx, iRowid);
   }else{
-    float fCoord = nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1);
-    sqlite3_result_double(ctx, fCoord);
+    RtreeCoord c;
+    nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c);
+    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
+      sqlite3_result_double(ctx, c.f);
+    }else{
+      assert( pRtree->eCoordType==RTREE_COORD_INT32 );
+      sqlite3_result_int(ctx, c.i);
+    }
   }
 
   return SQLITE_OK;
@@ -1161,7 +1177,7 @@ static float cellArea(Rtree *pRtree, RtreeCell *p){
   float area = 1.0;
   int ii;
   for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-    area = area * (p->aCoord[ii+1] - p->aCoord[ii]);
+    area = area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
   }
   return area;
 }
@@ -1174,7 +1190,7 @@ static float cellMargin(Rtree *pRtree, RtreeCell *p){
   float margin = 0.0;
   int ii;
   for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-    margin += (p->aCoord[ii+1] - p->aCoord[ii]);
+    margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
   }
   return margin;
 }
@@ -1184,9 +1200,16 @@ static float cellMargin(Rtree *pRtree, RtreeCell *p){
 */
 static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
   int ii;
-  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-    p1->aCoord[ii] = MIN(p1->aCoord[ii], p2->aCoord[ii]);
-    p1->aCoord[ii+1] = MAX(p1->aCoord[ii+1], p2->aCoord[ii+1]);
+  if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
+    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+      p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
+      p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
+    }
+  }else{
+    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+      p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
+      p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
+    }
   }
 }
 
@@ -1217,9 +1240,11 @@ static float cellOverlap(
       int jj;
       float o = 1.0;
       for(jj=0; jj<(pRtree->nDim*2); jj+=2){
+        double x1;
+        double x2;
 
-        float x1 = MAX(p->aCoord[jj], aCell[ii].aCoord[jj]);
-        float x2 = MIN(p->aCoord[jj+1], aCell[ii].aCoord[jj+1]);
+        x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
+        x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
 
         if( x2<x1 ){
           o = 0.0;
@@ -1619,6 +1644,7 @@ static void SortByDistance(
 ** sorting algorithm.
 */
 static void SortByDimension(
+  Rtree *pRtree,
   int *aIdx, 
   int nIdx, 
   int iDim, 
@@ -1635,17 +1661,16 @@ static void SortByDimension(
     int *aLeft = aIdx;
     int *aRight = &aIdx[nLeft];
 
-    SortByDimension(aLeft, nLeft, iDim, aCell, aSpare);
-    SortByDimension(aRight, nRight, iDim, aCell, aSpare);
+    SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare);
+    SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare);
 
     memcpy(aSpare, aLeft, sizeof(int)*nLeft);
     aLeft = aSpare;
     while( iLeft<nLeft || iRight<nRight ){
-      float xleft1 = aCell[aLeft[iLeft]].aCoord[iDim*2];
-      float xleft2 = aCell[aLeft[iLeft]].aCoord[iDim*2+1];
-      float xright1 = aCell[aRight[iRight]].aCoord[iDim*2];
-      float xright2 = aCell[aRight[iRight]].aCoord[iDim*2+1];
-
+      double xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]);
+      double xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]);
+      double xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]);
+      double xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]);
       if( (iLeft!=nLeft) && ((iRight==nRight)
        || (xleft1<xright1)
        || (xleft1==xright1 && xleft2<xright2)
@@ -1710,7 +1735,7 @@ static int splitNodeStartree(
     for(jj=0; jj<nCell; jj++){
       aaSorted[ii][jj] = jj;
     }
-    SortByDimension(aaSorted[ii], nCell, ii, aCell, aSpare);
+    SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
   }
 
   for(ii=0; ii<pRtree->nDim; ii++){
@@ -2134,8 +2159,8 @@ static int Reinsert(
     }
     aOrder[ii] = ii;
     for(iDim=0; iDim<pRtree->nDim; iDim++){
-      aCenterCoord[iDim] += aCell[ii].aCoord[iDim*2];
-      aCenterCoord[iDim] += 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; iDim<pRtree->nDim; iDim++){
@@ -2145,7 +2170,8 @@ static int Reinsert(
   for(ii=0; ii<nCell; ii++){
     aDistance[ii] = 0.0;
     for(iDim=0; iDim<pRtree->nDim; iDim++){
-      float coord = aCell[ii].aCoord[iDim*2+1] - aCell[ii].aCoord[iDim*2];
+      float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) - 
+          DCOORD(aCell[ii].aCoord[iDim*2]);
       aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
     }
   }
@@ -2387,12 +2413,23 @@ int rtreeUpdate(
 
     /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
     assert( nData==(pRtree->nDim*2 + 3) );
-    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
-      cell.aCoord[ii] = (float)sqlite3_value_double(azData[ii+3]);
-      cell.aCoord[ii+1] = (float)sqlite3_value_double(azData[ii+4]);
-      if( cell.aCoord[ii]>cell.aCoord[ii+1] ){
-        rc = SQLITE_CONSTRAINT;
-        goto constraint;
+    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]);
+        if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
+          rc = SQLITE_CONSTRAINT;
+          goto constraint;
+        }
+      }
+    }else{
+      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]);
+        if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
+          rc = SQLITE_CONSTRAINT;
+          goto constraint;
+        }
       }
     }
 
@@ -2588,7 +2625,8 @@ static int rtreeInit(
   int argc, const char *const*argv,   /* Parameters to CREATE TABLE statement */
   sqlite3_vtab **ppVtab,              /* OUT: New virtual table */
   char **pzErr,                       /* OUT: Error message, if any */
-  int isCreate                        /* True for xCreate, false for xConnect */
+  int isCreate,                       /* True for xCreate, false for xConnect */
+  int eCoordType                      /* One of the RTREE_COORD_* constants */
 ){
   int rc = SQLITE_OK;
   int iPageSize = 0;
@@ -2628,6 +2666,7 @@ static int rtreeInit(
   pRtree->zName = &pRtree->zDb[nDb+1];
   pRtree->nDim = (argc-4)/2;
   pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
+  pRtree->eCoordType = eCoordType;
   memcpy(pRtree->zDb, argv[1], nDb);
   memcpy(pRtree->zName, argv[2], nName);
 
@@ -2716,7 +2755,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
     sqlite3_snprintf(512-nCell,&zCell[nCell],"%d", cell.iRowid);
     nCell = strlen(zCell);
     for(jj=0; jj<tree.nDim*2; jj++){
-      sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj]);
+      sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);
       nCell = strlen(zCell);
     }
 
@@ -2760,7 +2799,12 @@ int sqlite3RtreeInit(sqlite3 *db){
     rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
   }
   if( rc==SQLITE_OK ){
-    rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, 0, 0);
+    void *c = (void *)RTREE_COORD_REAL32;
+    rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0);
+  }
+  if( rc==SQLITE_OK ){
+    void *c = (void *)RTREE_COORD_INT32;
+    rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0);
   }
 
   return rc;
index bb759af1e2508c37b1926408058d2da35c877a20..ee9866f9cc0787be66942ddb6bb6d8d263b12020 100644 (file)
 #
 # The focus of this file is testing the r-tree extension.
 #
-# $Id: rtree1.test,v 1.4 2008/06/23 16:53:47 danielk1977 Exp $
+# $Id: rtree1.test,v 1.5 2008/07/14 15:37:01 danielk1977 Exp $
 #
 
 if {![info exists testdir]} {
   set testdir [file join [file dirname $argv0] .. .. test]
 }
+source [file join [file dirname [info script]] rtree_util.tcl]
 source $testdir/tester.tcl
 
 # Test plan:
index 018e5ab2fa1a90babfe08f0134b5b23b07a51ac2..7e38c8f5f5bcee33f7615f578ff0b1096847d172 100644 (file)
@@ -11,7 +11,7 @@
 #
 # The focus of this file is testing the r-tree extension.
 #
-# $Id: rtree2.test,v 1.3 2008/06/23 15:55:52 danielk1977 Exp $
+# $Id: rtree2.test,v 1.4 2008/07/14 15:37:01 danielk1977 Exp $
 #
 
 if {![info exists testdir]} {
@@ -34,97 +34,45 @@ if {[info exists ISQUICK] && $ISQUICK} {
   set ::NSELECT 10
 }
 
-for {set nDim 1} {$nDim <= 5} {incr nDim} {
-
-  do_test rtree2-$nDim.1 {
-    set cols [list]
-    foreach c [list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9] {
-      lappend cols "$c REAL"
-    }
-    set cols [join [lrange $cols 0 [expr {$nDim*2-1}]] ", "]
-    execsql " 
-      CREATE VIRTUAL TABLE t1 USING rtree(ii, $cols);
-      CREATE TABLE t2 (ii, $cols);
-    "
-  } {}
-
-  do_test rtree2-$nDim.2 {
-    db transaction {
-      for {set ii 0} {$ii < $::NROW} {incr ii} {
-        #puts "Row $ii"
-        set values [list]
-        for {set jj 0} {$jj<$nDim*2} {incr jj} {
-          lappend values [expr int(rand()*1000)]
-        }
-        set values [join $values ,]
-        #puts [rtree_treedump db t1]
-        #puts "INSERT INTO t2 VALUES($ii, $values)"
-        set rc [catch {db eval "INSERT INTO t1 VALUES($ii, $values)"}]
-        if {$rc} {
-          incr ii -1
-        } else {
-          db eval "INSERT INTO t2 VALUES($ii, $values)"
-        }
-        #if {[rtree_check db t1]} {
-          #puts [rtree_treedump db t1]
-          #exit
-        #}
+foreach module {rtree_i32 rtree} {
+  for {set nDim 1} {$nDim <= 5} {incr nDim} {
+  
+    do_test rtree2-$module.$nDim.1 {
+      set cols [list]
+      foreach c [list c0 c1 c2 c3 c4 c5 c6 c7 c8 c9] {
+        lappend cols "$c REAL"
       }
-    }
-
-    set t1 [execsql {SELECT * FROM t1 ORDER BY ii}]
-    set t2 [execsql {SELECT * FROM t2 ORDER BY ii}]
-    set rc [expr {$t1 eq $t2}]
-    if {$rc != 1} {
-      puts $t1
-      puts $t2
-    }
-    set rc
-  } {1}
-
-  do_test rtree2-$nDim.3 {
-    rtree_check db t1
-  } 0
-
-  set OPS [list < > <= >= =]
-  for {set ii 0} {$ii < $::NSELECT} {incr ii} {
-    do_test rtree2-$nDim.4.$ii.1 {
-      set where [list]
-      foreach look_three_dots! {. . .} {
-        set colidx [expr int(rand()*($nDim*2+1))-1]
-        if {$colidx<0} {
-          set col ii
-        } else {
-          set col "c$colidx"
+      set cols [join [lrange $cols 0 [expr {$nDim*2-1}]] ", "]
+      execsql " 
+        CREATE VIRTUAL TABLE t1 USING ${module}(ii, $cols);
+        CREATE TABLE t2 (ii, $cols);
+      "
+    } {}
+  
+    do_test rtree2-$module.$nDim.2 {
+      db transaction {
+        for {set ii 0} {$ii < $::NROW} {incr ii} {
+          #puts "Row $ii"
+          set values [list]
+          for {set jj 0} {$jj<$nDim*2} {incr jj} {
+            lappend values [expr int(rand()*1000)]
+          }
+          set values [join $values ,]
+          #puts [rtree_treedump db t1]
+          #puts "INSERT INTO t2 VALUES($ii, $values)"
+          set rc [catch {db eval "INSERT INTO t1 VALUES($ii, $values)"}]
+          if {$rc} {
+            incr ii -1
+          } else {
+            db eval "INSERT INTO t2 VALUES($ii, $values)"
+          }
+          #if {[rtree_check db t1]} {
+            #puts [rtree_treedump db t1]
+            #exit
+          #}
         }
-        set op  [lindex $OPS [expr int(rand()*[llength $OPS])]]
-        set val [expr int(rand()*1000)]
-        lappend where "$col $op $val"
-      }
-      set where [join $where " AND "]
-
-      set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"]
-      set t2 [execsql "SELECT * FROM t2 WHERE $where ORDER BY ii"]
-      set rc [expr {$t1 eq $t2}]
-      if {$rc != 1} {
-        #puts $where
-        puts $t1
-        puts $t2
-        #puts [rtree_treedump db t1]
-        #breakpoint
-        #set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"]
-        #exit
       }
-      set rc
-    } {1}
-  }
-
-  for {set ii 0} {$ii < $::NROW} {incr ii $::NDEL} {
-    #puts [rtree_treedump db t1]
-    do_test rtree2-$nDim.5.$ii.1 {
-      execsql "DELETE FROM t2 WHERE ii <= $::ii"
-      execsql "DELETE FROM t1 WHERE ii <= $::ii"
-
+  
       set t1 [execsql {SELECT * FROM t1 ORDER BY ii}]
       set t2 [execsql {SELECT * FROM t2 ORDER BY ii}]
       set rc [expr {$t1 eq $t2}]
@@ -134,17 +82,71 @@ for {set nDim 1} {$nDim <= 5} {incr nDim} {
       }
       set rc
     } {1}
-    do_test rtree2-$nDim.5.$ii.2 {
+  
+    do_test rtree2-$module.$nDim.3 {
       rtree_check db t1
-    } {0}
-  }
-
-  do_test rtree2-$nDim.6 {
-    execsql {
-      DROP TABLE t1;
-      DROP TABLE t2;
+    } 0
+  
+    set OPS [list < > <= >= =]
+    for {set ii 0} {$ii < $::NSELECT} {incr ii} {
+      do_test rtree2-$module.$nDim.4.$ii.1 {
+        set where [list]
+        foreach look_three_dots! {. . .} {
+          set colidx [expr int(rand()*($nDim*2+1))-1]
+          if {$colidx<0} {
+            set col ii
+          } else {
+            set col "c$colidx"
+          }
+          set op  [lindex $OPS [expr int(rand()*[llength $OPS])]]
+          set val [expr int(rand()*1000)]
+          lappend where "$col $op $val"
+        }
+        set where [join $where " AND "]
+  
+        set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"]
+        set t2 [execsql "SELECT * FROM t2 WHERE $where ORDER BY ii"]
+        set rc [expr {$t1 eq $t2}]
+        if {$rc != 1} {
+          #puts $where
+          puts $t1
+          puts $t2
+          #puts [rtree_treedump db t1]
+          #breakpoint
+          #set t1 [execsql "SELECT * FROM t1 WHERE $where ORDER BY ii"]
+          #exit
+        }
+        set rc
+      } {1}
     }
-  } {}
+  
+    for {set ii 0} {$ii < $::NROW} {incr ii $::NDEL} {
+      #puts [rtree_treedump db t1]
+      do_test rtree2-$module.$nDim.5.$ii.1 {
+        execsql "DELETE FROM t2 WHERE ii <= $::ii"
+        execsql "DELETE FROM t1 WHERE ii <= $::ii"
+  
+        set t1 [execsql {SELECT * FROM t1 ORDER BY ii}]
+        set t2 [execsql {SELECT * FROM t2 ORDER BY ii}]
+        set rc [expr {$t1 eq $t2}]
+        if {$rc != 1} {
+          puts $t1
+          puts $t2
+        }
+        set rc
+      } {1}
+      do_test rtree2-$module.$nDim.5.$ii.2 {
+        rtree_check db t1
+      } {0}
+    }
+  
+    do_test rtree2-$module.$nDim.6 {
+      execsql {
+        DROP TABLE t1;
+        DROP TABLE t2;
+      }
+    } {}
+  }
 }
 
 finish_test
diff --git a/ext/rtree/rtree5.test b/ext/rtree/rtree5.test
new file mode 100644 (file)
index 0000000..4fa007f
--- /dev/null
@@ -0,0 +1,80 @@
+# 2008 Jul 14
+#
+# 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.
+#
+#***********************************************************************
+#
+# The focus of this file is testing the r-tree extension when it is
+# configured to store values as 32 bit integers.
+#
+# $Id: rtree5.test,v 1.1 2008/07/14 15:37:01 danielk1977 Exp $
+#
+
+if {![info exists testdir]} {
+  set testdir [file join [file dirname $argv0] .. .. test]
+} 
+source $testdir/tester.tcl
+
+ifcapable !rtree {
+  finish_test
+  return
+}
+
+do_test rtree5-1.0 {
+  execsql { CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2, y1, y2) }
+} {}
+do_test rtree5-1.1 {
+  execsql { INSERT INTO t1 VALUES(1, 5, 10, 4, 11.2) }
+} {}
+do_test rtree5-1.2 { 
+  execsql { SELECT * FROM t1 }
+} {1 5 10 4 11}
+do_test rtree5-1.3 { 
+  execsql { SELECT typeof(x1) FROM t1 }
+} {integer}
+
+do_test rtree5-1.4 { 
+  execsql { SELECT x1==5 FROM t1 }
+} {1}
+do_test rtree5-1.5 { 
+  execsql { SELECT x1==5.2 FROM t1 }
+} {0}
+do_test rtree5-1.6 { 
+  execsql { SELECT x1==5.0 FROM t1 }
+} {1}
+
+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}
+do_test rtree5-1.9 { 
+  execsql { SELECT count(*) FROM t1 WHERE x1==5.0 }
+} {1}
+
+do_test rtree5-1.10 { 
+  execsql { SELECT (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5 }
+} {2147483643 2147483647 -2147483648 -2147483643}
+do_test rtree5-1.10 { 
+  execsql { 
+    INSERT INTO t1 VALUES(2, (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5) 
+  }
+} {}
+do_test rtree5-1.12 { 
+  execsql { SELECT * FROM t1 WHERE id=2 }
+} {2 2147483643 2147483647 -2147483648 -2147483643}
+do_test rtree5-1.13 { 
+  execsql { 
+    SELECT * FROM t1 WHERE 
+        x1=2147483643 AND x2=2147483647 AND 
+        y1=-2147483648 AND y2=-2147483643
+  }
+} {2 2147483643 2147483647 -2147483648 -2147483643}
+
+finish_test
index 3cdb89ff4d9879287f1c7987f085aa620283fd22..f0c9cbcf3be86330f9e0d05d984a1ba7726e7d35 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\sthe\smalloc2.test\sscript\ssince\sit\swas\sdesigned\sfor\suse\sin\sversions\nof\sSQLite\sthat\spredate\sSQLite's\sability\sto\srecover\sfrom\sout-of-memory\nerrors\sautomatically.\s\sRemoving\sthis\sscript\scauses\sno\sreduction\sin\ntest\scoverage\sand\sremoves\spotential\sproblems\sreported\sby\sticket\s#3213.\s(CVS\s5409)
-D 2008-07-14T15:11:20
+C Have\sthe\srtree\sextension\spublish\stwo\svirtual\stable\stypes:\s"rtree"\sand\s"rtree_i32".\srtree_i32\sstores\scoordinate\sdata\sas\s32-bit\ssigned\sintegers.\srtree\suses\s32-bit\sreal\s(floating\spoint)\svalues.\s(CVS\s5410)
+D 2008-07-14T15:37:01
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in a03f7cb4f7ad50bc53a788c6c544430e81f95de4
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -64,12 +64,13 @@ F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
 F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
 F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c 20b87410e55f33a03e0f7cc58c0f1908faf91858
+F ext/rtree/rtree.c f00cabbe00326c9138155c497b1d9b5621ac5089
 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
-F ext/rtree/rtree1.test 994da7f85328cf499cdf149c6caa32547ea75dbf
-F ext/rtree/rtree2.test 07aea32287ce3f7717fe285e6172e5418ce3fd52
+F ext/rtree/rtree1.test 620223886bf1a319317e63235aac20790375c544
+F ext/rtree/rtree2.test 9ac9d28fa948779df66916c67a5dcf9704c3cb74
 F ext/rtree/rtree3.test 877a09c1a0c2b87af0f94f3a286e7dd3b65adf22
 F ext/rtree/rtree4.test 11724f766a74f48710998cdd7552cec140c55bf9
+F ext/rtree/rtree5.test 7d0643482829038f0263881ddf7e2d51bff1d60f
 F ext/rtree/rtree_perf.tcl 0fabb6d5c48cb8024e042ce5d4bb88998b6ec1cb
 F ext/rtree/rtree_util.tcl ee0a0311eb12175319d78bfb37302320496cee6e
 F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
@@ -604,7 +605,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 4961b0bbe8b9cf5fb27de7f2514e8ab399a00134
-R 65a91dac815025c38b80c9e74c9e131b
-U drh
-Z a7a9dcd0eb2d9135eecea29892bd5027
+P 5bfc962533995530a0ef0875556f9f46e8dbf68b
+R 39404ee872afb35ff09c42f055604afd
+U danielk1977
+Z 2a93a0c5a03fb958f7f8abea1f4df604
index d50a3ca8f839b93fddff0a6c4dd733c50c68944a..af79c00e1979a8239ea5e7a547f7d5a9ab01e65e 100644 (file)
@@ -1 +1 @@
-5bfc962533995530a0ef0875556f9f46e8dbf68b
\ No newline at end of file
+c060a9a6beca455bdceee9ce6ca71a7262f98a5f
\ No newline at end of file