]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the new interfaces to rtree, though they do not yet work. Add the
authordrh <drh@noemail.net>
Fri, 11 Apr 2014 23:14:48 +0000 (23:14 +0000)
committerdrh <drh@noemail.net>
Fri, 11 Apr 2014 23:14:48 +0000 (23:14 +0000)
"show_speedtest1_rtree.tcl" script for showing the test data used for the
R-Tree tests of speedtest1.  Change speedtest1 to generate better R-Tree
test data.

FossilOrigin-Name: 0b70275972c7a6a533566c1e50bffbf3ac531e95

ext/rtree/rtree.c
ext/rtree/sqlite3rtree.h
main.mk
manifest
manifest.uuid
test/show_speedtest1_rtree.tcl [new file with mode: 0644]
test/speedtest1.c

index 2034ff693f5d91934a5f0932df9857a7cc66df77..ddfc3d79a1cc38a9e7ed88e583bdd3f27d2ec107 100644 (file)
@@ -324,21 +324,24 @@ struct RtreeCell {
 struct RtreeMatchArg {
   u32 magic;                      /* Always RTREE_GEOMETRY_MAGIC */
   int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *);
+  int (*xQueryFunc)(sqlite3_rtree_query_info*);
   void *pContext;
   int nParam;
   RtreeDValue aParam[1];
 };
 
 /*
-** When a geometry callback is created (see sqlite3_rtree_geometry_callback),
+** When a geometry callback is created using either
+** sqlite3_rtree_geometry_callback() or sqlite3_rtree_query_callback(),
 ** a single instance of the following structure is allocated. It is used
-** as the context for the user-function created by by s_r_g_c(). The object
-** is eventually deleted by the destructor mechanism provided by
-** sqlite3_create_function_v2() (which is called by s_r_g_c() to create
-** the geometry callback function).
+** as the context for the user-function created by sqlite3_rtree_*_callback().
+** The object is eventually deleted by the destructor mechanism provided by
+** sqlite3_create_function_v2().
 */
 struct RtreeGeomCallback {
   int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
+  int (*xQueryFunc)(sqlite3_rtree_query_info*);
+  void (*xDestructor)(void*);
   void *pContext;
 };
 
@@ -3352,22 +3355,23 @@ int sqlite3RtreeInit(sqlite3 *db){
 }
 
 /*
-** A version of sqlite3_free() that can be used as a callback. This is used
-** in two places - as the destructor for the blob value returned by the
-** invocation of a geometry function, and as the destructor for the geometry
-** functions themselves.
+** This routine is called when a custom geometry function or custom query
+** function is cancelled.  The pointer is to a RtreeGeomCallback object
+** that needs to be freed.
 */
-static void doSqlite3Free(void *p){
+static void rtreeFreeCallback(void *p){
+  RtreeGeomCallback *pGeom = (RtreeGeomCallback*)p;
+  if( pGeom->xDestructor ) pGeom->xDestructor(pGeom->pContext);
   sqlite3_free(p);
 }
 
 /*
-** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite
-** scalar user function. This C function is the callback used for all such
-** registered SQL functions.
+** Each call to sqlite3_rtree_geometry_callback() or
+** sqlite3_rtree_query_callback() creates an ordinary SQLite
+** scalar user function that is implemented by this routine.
 **
-** The scalar user functions return a blob that is interpreted by r-tree
-** table MATCH operators.
+** This function returns a blob that is interpreted by r-tree
+** table MATCH operator.
 */
 static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
   RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
@@ -3391,7 +3395,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
       pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
 #endif
     }
-    sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free);
+    sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free);
   }
 }
 
@@ -3410,12 +3414,42 @@ int sqlite3_rtree_geometry_callback(
   pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
   if( !pGeomCtx ) return SQLITE_NOMEM;
   pGeomCtx->xGeom = xGeom;
+  pGeomCtx->xQueryFunc = 0;
+  pGeomCtx->xDestructor = 0;
   pGeomCtx->pContext = pContext;
 
   /* Create the new user-function. Register a destructor function to delete
   ** the context object when it is no longer required.  */
   return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, 
-      (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
+      (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
+  );
+}
+
+/*
+** Register a new 2nd-generation geometry function for use with the
+** r-tree MATCH operator.
+*/
+int sqlite3_rtree_query_callback(
+  sqlite3 *db,
+  const char *zQueryFunc,
+  int (*xQueryFunc)(sqlite3_rtree_query_info*),
+  void *pContext,
+  void (*xDestructor)(void*)
+){
+  RtreeGeomCallback *pGeomCtx;      /* Context object for new user-function */
+
+  /* Allocate and populate the context object. */
+  pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
+  if( !pGeomCtx ) return SQLITE_NOMEM;
+  pGeomCtx->xGeom = 0;
+  pGeomCtx->xQueryFunc = xQueryFunc;
+  pGeomCtx->xDestructor = xDestructor;
+  pGeomCtx->pContext = pContext;
+
+  /* Create the new user-function. Register a destructor function to delete
+  ** the context object when it is no longer required.  */
+  return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, 
+      (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
   );
 }
 
index c849091f29a895fb0a462dd4521f93f6b8417b81..79d1ffeeded502cb8057f50553cb93c30da8b22c 100644 (file)
@@ -21,6 +21,16 @@ extern "C" {
 #endif
 
 typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
+
+/* The double-precision datatype used by RTree depends on the
+** SQLITE_RTREE_INT_ONLY compile-time option.
+*/
+#ifdef SQLITE_RTREE_INT_ONLY
+  typedef sqlite3_int64 sqlite3_rtree_dbl;
+#else
+  typedef double sqlite3_rtree_dbl;
+#endif
 
 /*
 ** Register a geometry callback named zGeom that can be used as part of an
@@ -31,11 +41,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
 int sqlite3_rtree_geometry_callback(
   sqlite3 *db,
   const char *zGeom,
-#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
+  int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
   void *pContext
 );
 
@@ -47,11 +53,54 @@ int sqlite3_rtree_geometry_callback(
 struct sqlite3_rtree_geometry {
   void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
   int nParam;                     /* Size of array aParam[] */
-  double *aParam;                 /* Parameters passed to SQL geom function */
+  sqlite3_rtree_dbl *aParam;      /* Parameters passed to SQL geom function */
   void *pUser;                    /* Callback implementation user data */
   void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
 };
 
+/*
+** Register a 2nd-generation geometry callback named zScore that can be 
+** used as part of an R-Tree geometry query as follows:
+**
+**   SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
+*/
+int sqlite3_rtree_query_callback(
+  sqlite3 *db,
+  const char *zQueryFunc,
+  int (*xQueryFunc)(sqlite3_rtree_query_info*),
+  void *pContext,
+  void (*xDestructor)(void*)
+);
+
+
+/*
+** A pointer to a structure of the following type is passed as the 
+** argument to scored geometry callback registered using
+** sqlite3_rtree_query_callback().
+*/
+struct sqlite3_rtree_query_info {
+  void *pContext;                   /* pContext from when function registered */
+  int nParam;                       /* Number of function parameters */
+  sqlite3_rtree_dbl *aParam;        /* value of function parameters */
+  void *pUser;                      /* callback can use this, if desired */
+  void (*xDelUser)(void*);          /* function to free pUser */
+  sqlite3_rtree_dbl *aCoord;        /* Coordinates of node or entry to check */
+  int nCoord;                       /* Number of coordinates */
+  int iLevel;                       /* Level of current node or entry */
+  sqlite3_int64 iRowid;             /* Rowid for current entry */
+  sqlite3_rtree_dbl rParentScore;   /* Score of parent node */
+  int eParentWithin;                /* Visibility of parent node */
+  int eWithin;                      /* OUT: Visiblity */
+  sqlite3_rtree_dbl rScore;         /* OUT: Write the score here */
+};
+
+/*
+** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
+*/
+#define NOT_WITHIN       0   /* Object completely outside of query region */
+#define PARTLY_WITHIN    1   /* Object partially overlaps query region */
+#define FULLY_WITHIN     2   /* Object fully contained within query region */
+
 
 #ifdef __cplusplus
 }  /* end of the 'extern "C"' block */
diff --git a/main.mk b/main.mk
index d7f8aaa3ddf13817428e8525746cbdfb60d07407..57757ccc6a1e86303b5c9d0efb7e4db2f0a8112a 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -483,7 +483,7 @@ parse.c:    $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk
        mv parse.h parse.h.temp
        $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
 
-sqlite3.h:     $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
+sqlite3.h:     $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
        tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
 
 keywordhash.h: $(TOP)/tool/mkkeywordhash.c
index 12cad8c970d17c5df7abb1c5440739f44fcced58..af46986305cc75be89b3ea7f0fbc5e01f4ec157d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\s--verify\soption\sto\sspeedtest1.\s\sAdd\sverification\stest\scases\sto\nthe\s"rtree"\stestset\sand\sa\scase\sthat\suses\sa\scustom\sgeometry\scallback.
-D 2014-04-11T17:41:08.614
+C Add\sthe\snew\sinterfaces\sto\srtree,\sthough\sthey\sdo\snot\syet\swork.\s\sAdd\sthe\n"show_speedtest1_rtree.tcl"\sscript\sfor\sshowing\sthe\stest\sdata\sused\sfor\sthe\nR-Tree\stests\sof\sspeedtest1.\s\sChange\sspeedtest1\sto\sgenerate\sbetter\sR-Tree\ntest\sdata.
+D 2014-04-11T23:14:48.914
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -120,7 +120,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c 043f16a6c3f823c760657b975f2ff1de7fe5c197
+F ext/rtree/rtree.c 541016f8a53bbedda4dc2deb0067f6955b0accb9
 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
 F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290
 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -137,7 +137,7 @@ F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d
 F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
-F ext/rtree/sqlite3rtree.h c34c1e41d1ab80bb8ad09aae402c9c956871a765
+F ext/rtree/sqlite3rtree.h f93a466456ed25a9dadf90ad050e2945a2c49cff
 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 F ext/session/session1.test 894e3bc9f497c4fa07a2aa3271e3911f3670c3d8
@@ -157,7 +157,7 @@ F ext/session/test_session.c 7878ac0e2fe9675e8ec24d54f6a538ccc105977f
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
-F main.mk a3028a846754a96c8841d1a7227890c471c65ec2
+F main.mk 82b154dd823b75c2f1247f1bb98893bf94a5af57
 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
 F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -825,6 +825,7 @@ F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
 F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
 F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1
 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
+F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
 F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
 F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
 F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f
@@ -840,7 +841,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
 F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
-F test/speedtest1.c 017473605f9df5f4770dd60ddb4038e6d6829916
+F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920
 F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
 F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
@@ -1174,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 20a73ec0b2f56609a4504052e198e32803d30207
-R 47999e8bbddb67bbaef79a4f5741e58b
+P 9d485c4207a81f32334857d4a608c5c511dd2b83
+R 0017d933bc77106350e8e33449b1c08c
 U drh
-Z 73dffdddfd99e7f86f5cf9f646a8ff0c
+Z 0d8113e9fad970081c8175cf29f2569d
index 0d054cdd301865c810b1934ca5bfb75a510c1663..1c530a4dc894ea5acfc9d59c23fef2b588bab66a 100644 (file)
@@ -1 +1 @@
-9d485c4207a81f32334857d4a608c5c511dd2b83
\ No newline at end of file
+0b70275972c7a6a533566c1e50bffbf3ac531e95
\ No newline at end of file
diff --git a/test/show_speedtest1_rtree.tcl b/test/show_speedtest1_rtree.tcl
new file mode 100644 (file)
index 0000000..3faa168
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/tclsh
+#
+# This script displays the field of rectangles used by --testset rtree
+# of speedtest1.  Run this script as follows:
+#
+#      rm test.db
+#      ./speedtest1 --testset rtree --size 25 test.db
+#      sqlite3 --separator ' ' test.db 'SELECT * FROM rt1' >data.txt
+#      wish show_speedtest1_rtree.tcl
+#
+# The filename "data.txt" is hard coded into this script and so that name
+# must be used on lines 3 and 4 above.  Elsewhere, different filenames can
+# be used.  The --size N parameter can be adjusted as desired.
+#
+package require Tk
+set f [open data.txt rb]
+set data [read $f]
+close $f
+canvas .c
+frame .b
+button .b.b1 -text X-Y -command refill-xy
+button .b.b2 -text X-Z -command refill-xz
+button .b.b3 -text Y-Z -command refill-yz
+pack .b.b1 .b.b2 .b.b3 -side left
+pack .c -side top -fill both -expand 1
+pack .b -side top
+proc resize_canvas_to_fit {} {
+  foreach {x0 y0 x1 y1} [.c bbox all] break
+  set w [expr {$x1-$x0}]
+  set h [expr {$y1-$y0}]
+  .c config -width $w -height $h
+}
+proc refill-xy {} {
+  .c delete all
+  foreach {id x0 x1 y0 y1 z0 z1} $::data {
+    .c create rectangle $x0 $y0 $x1 $y1
+  }
+  .c scale all 0 0 0.05 0.05
+  resize_canvas_to_fit
+}
+proc refill-xz {} {
+  .c delete all
+  foreach {id x0 x1 y0 y1 z0 z1} $::data {
+    .c create rectangle $x0 $z0 $x1 $z1
+  }
+  .c scale all 0 0 0.05 0.05
+  resize_canvas_to_fit
+}
+proc refill-yz {} {
+  .c delete all
+  foreach {id x0 x1 y0 y1 z0 z1} $::data {
+    .c create rectangle $y0 $z0 $y1 $z1
+  }
+  .c scale all 0 0 0.05 0.05
+  resize_canvas_to_fit
+}
+refill-xy
index 0680e9599f55d24ca04bfa64b7a5a4e5fa19ad2a..383f5809a98583817271b1849c46178f01667b1d 100644 (file)
@@ -938,14 +938,15 @@ void testset_cte(void){
 ** be far apart.
 */
 static void twoCoords(
+  int p1, int p2,                   /* Parameters adjusting sizes */
   unsigned mx,                      /* Range of 1..mx */
   unsigned *pX0, unsigned *pX1      /* OUT: write results here */
 ){
   unsigned d, x0, x1, span;
 
   span = mx/100 + 1;
-  if( speedtest1_random()%3==0 ) span *= 3;
-  if( speedtest1_random()%17==0 ) span = mx - 5;
+  if( speedtest1_random()%3==0 ) span *= p1;
+  if( speedtest1_random()%p2==0 ) span = mx/2;
   d = speedtest1_random()%span + 1;
   x0 = speedtest1_random()%(mx-d) + 1;
   x1 = x0 + d;
@@ -976,14 +977,14 @@ static int xsliceGeometryCallback(
 /*
 ** A testset for the R-Tree virtual table
 */
-void testset_rtree(void){
+void testset_rtree(int p1, int p2){
   unsigned i, n;
   unsigned mxCoord;
   unsigned x0, x1, y0, y1, z0, z1;
   unsigned iStep;
   int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 );
 
-  mxCoord = g.szTest*600;
+  mxCoord = 15000;
   n = g.szTest*100;
   speedtest1_begin_test(100, "%d INSERTs into an r-tree", n);
   speedtest1_exec("BEGIN");
@@ -991,9 +992,9 @@ void testset_rtree(void){
   speedtest1_prepare("INSERT INTO rt1(id,x0,x1,y0,y1,z0,z1)"
                      "VALUES(?1,?2,?3,?4,?5,?6,?7)");
   for(i=1; i<=n; i++){
-    twoCoords(mxCoord, &x0, &x1);
-    twoCoords(mxCoord, &y0, &y1);
-    twoCoords(mxCoord, &z0, &z1);
+    twoCoords(p1, p2, mxCoord, &x0, &x1);
+    twoCoords(p1, p2, mxCoord, &y0, &y1);
+    twoCoords(p1, p2, mxCoord, &z0, &z1);
     sqlite3_bind_int(g.pStmt, 1, i);
     sqlite3_bind_int(g.pStmt, 2, x0);
     sqlite3_bind_int(g.pStmt, 3, x1);
@@ -1322,7 +1323,7 @@ int main(int argc, char **argv){
   }else if( strcmp(zTSet,"cte")==0 ){
     testset_cte();
   }else if( strcmp(zTSet,"rtree")==0 ){
-    testset_rtree();
+    testset_rtree(6, 147);
   }else{
     fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n",
                  zTSet);