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;
};
}
/*
-** 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);
pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
#endif
}
- sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free);
+ sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free);
}
}
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
);
}
#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
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
);
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 */
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
-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
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
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
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
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
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
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
-9d485c4207a81f32334857d4a608c5c511dd2b83
\ No newline at end of file
+0b70275972c7a6a533566c1e50bffbf3ac531e95
\ No newline at end of file
--- /dev/null
+#!/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
** 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;
/*
** 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");
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);
}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);