# May you share freely, never taking more than you give.
#
#***********************************************************************
+# This file contains tests for the r-tree module. Specifically, it tests
+# that custom r-tree queries (geometry callbacks) work.
#
if {![info exists testdir]} {
SELECT id FROM rt WHERE id MATCH randomblob($x)
} {1 {SQL logic error or missing database}}
}
-
do_catchsql_test rtree9-4.3 {
SELECT id FROM rt WHERE id MATCH CAST(
(cube(5.5, 5.5, 5.5, 1, 1, 1) || X'1234567812345678') AS blob
} {1 {SQL logic error or missing database}}
+#-------------------------------------------------------------------------
+# Test the example 2d "circle" geometry callback.
+#
+register_circle_geom db
+
+breakpoint
+do_execsql_test rtree9-5.1 {
+ CREATE VIRTUAL TABLE rt2 USING rtree(id, xmin, xmax, ymin, ymax);
+
+ INSERT INTO rt2 VALUES(1, 1, 2, 1, 2);
+ INSERT INTO rt2 VALUES(2, 1, 2, -2, -1);
+ INSERT INTO rt2 VALUES(3, -2, -1, -2, -1);
+ INSERT INTO rt2 VALUES(4, -2, -1, 1, 2);
+
+ INSERT INTO rt2 VALUES(5, 2, 3, 2, 3);
+ INSERT INTO rt2 VALUES(6, 2, 3, -3, -2);
+ INSERT INTO rt2 VALUES(7, -3, -2, -3, -2);
+ INSERT INTO rt2 VALUES(8, -3, -2, 2, 3);
+
+ INSERT INTO rt2 VALUES(9, 1.8, 3, 1.8, 3);
+ INSERT INTO rt2 VALUES(10, 1.8, 3, -3, -1.8);
+ INSERT INTO rt2 VALUES(11, -3, -1.8, -3, -1.8);
+ INSERT INTO rt2 VALUES(12, -3, -1.8, 1.8, 3);
+
+ INSERT INTO rt2 VALUES(13, -15, 15, 1.8, 2.2);
+ INSERT INTO rt2 VALUES(14, -15, 15, -2.2, -1.8);
+ INSERT INTO rt2 VALUES(15, 1.8, 2.2, -15, 15);
+ INSERT INTO rt2 VALUES(16, -2.2, -1.8, -15, 15);
+
+ INSERT INTO rt2 VALUES(17, -100, 100, -100, 100);
+} {}
+
+do_execsql_test rtree9-5.2 {
+ SELECT id FROM rt2 WHERE id MATCH circle(0.0, 0.0, 2.0);
+} {1 2 3 4 13 14 15 16 17}
+
+do_execsql_test rtree9-5.3 {
+ UPDATE rt2 SET xmin=xmin+5, ymin=ymin+5, xmax=xmax+5, ymax=ymax+5;
+ SELECT id FROM rt2 WHERE id MATCH circle(5.0, 5.0, 2.0);
+} {1 2 3 4 13 14 15 16 17}
+
finish_test
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Remove\sunreachable\sbranches\sto\sfacilitate\stest\scoverage.
-D 2010-08-31T01:09:16
+C Add\sthe\s"circle"\stest\sgeometry\scallback\sto\stest_rtree.c.\sAnd\stests\sfor\sthe\ssame.
+D 2010-08-31T15:02:01
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/rtree/rtree6.test 1ebe0d632a7501cc80ba5a225f028fd4f0fdda08
F ext/rtree/rtree7.test bcb647b42920b3b5d025846689147778485cc318
F ext/rtree/rtree8.test 9772e16da71e17e02bdebf0a5188590f289ab37d
-F ext/rtree/rtree9.test c3ab7efd3617bc4d3da1d96265fdb8a28e5a3d55
+F ext/rtree/rtree9.test df9843d1a9195249c8d3b4ea6aedda2d5c73e9c2
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
-F src/test_rtree.c 85b550f364c3694e6844bc5d41829d9c1f354e17
+F src/test_rtree.c f0476682986e7d3b04919432020b91bde4aaa925
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 4fead8e714c7e50a9d246467e62bc846ef6180a0
-R 2a554c21e54c6c6b8cf219133e4b794c
-U drh
-Z 1f84fd2f1fe3fdabeee2241cc9429c00
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFMfFY/oxKgR168RlERAmjVAJ9LLyOmGxhu/yZZZmudXyMu4QPOdQCdEH6H
-g2BR3lfdwre9DKrRofma7OY=
-=SZjz
------END PGP SIGNATURE-----
+P 86bcb9aab901713684f978479d29304cc9699e84
+R 5c25e19d785d39dcca465a202d21adcc
+U dan
+Z 0dfc99dba1561d16d8cd1c933b53fac9
-86bcb9aab901713684f978479d29304cc9699e84
\ No newline at end of file
+169b8ba4be9c3941c742eded80dbacdcd2465bc4
\ No newline at end of file
** Code for testing all sorts of SQLite interfaces. This code
** is not included in the SQLite library.
*/
-#include "sqlite3rtree.h"
+
#include <sqlite3.h>
+
+/*
+** Type used to cache parameter information for the "circle" r-tree geometry
+** callback.
+*/
+typedef struct Circle Circle;
+struct Circle {
+ struct Box {
+ double xmin;
+ double xmax;
+ double ymin;
+ double ymax;
+ } aBox[2];
+ double centerx;
+ double centery;
+ double radius;
+};
+
+/*
+** Destructor function for Circle objects allocated by circle_geom().
+*/
+static void circle_del(void *p){
+ sqlite3_free(p);
+}
+
+/*
+** Implementation of "circle" r-tree geometry callback.
+*/
+static int circle_geom(
+ sqlite3_rtree_geometry *p,
+ int nCoord,
+ double *aCoord,
+ int *pRes
+){
+ int i; /* Iterator variable */
+ Circle *pCircle; /* Structure defining circular region */
+ double xmin, xmax; /* X dimensions of box being tested */
+ double ymin, ymax; /* X dimensions of box being tested */
+
+ if( p->pUser==0 ){
+ /* If pUser is still 0, then the parameter values have not been tested
+ ** for correctness or stored into a Circle structure yet. Do this now. */
+
+ /* This geometry callback is for use with a 2-dimensional r-tree table.
+ ** Return an error if the table does not have exactly 2 dimensions. */
+ if( nCoord!=4 ) return SQLITE_ERROR;
+
+ /* Test that the correct number of parameters (3) have been supplied,
+ ** and that the parameters are in range (that the radius of the circle
+ ** radius is greater than zero). */
+ if( p->nParam!=3 || p->aParam[2]<0.0 ) return SQLITE_ERROR;
+
+ /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM
+ ** if the allocation fails. */
+ pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle)));
+ if( !pCircle ) return SQLITE_NOMEM;
+ p->xDelUser = circle_del;
+
+ /* Record the center and radius of the circular region. One way that
+ ** tested bounding boxes that intersect the circular region are detected
+ ** is by testing if each corner of the bounding box likes within radius
+ ** units of the center of the circle. */
+ pCircle->centerx = p->aParam[0];
+ pCircle->centery = p->aParam[1];
+ pCircle->radius = p->aParam[2];
+
+ /* Define two bounding box regions. The first, aBox[0], extends to
+ ** infinity in the X dimension. It covers the same range of the Y dimension
+ ** as the circular region. The second, aBox[1], extends to infinity in
+ ** the Y dimension and is constrained to the range of the circle in the
+ ** X dimension.
+ **
+ ** Then imagine each box is split in half along its short axis by a line
+ ** that intersects the center of the circular region. A bounding box
+ ** being tested can be said to intersect the circular region if it contains
+ ** points from each half of either of the two infinite bounding boxes.
+ */
+ pCircle->aBox[0].xmin = pCircle->centerx;
+ pCircle->aBox[0].xmax = pCircle->centerx;
+ pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius;
+ pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius;
+ pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius;
+ pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
+ pCircle->aBox[1].ymin = pCircle->centery;
+ pCircle->aBox[1].ymax = pCircle->centery;
+ }
+
+ pCircle = (Circle *)p->pUser;
+ xmin = aCoord[0];
+ xmax = aCoord[1];
+ ymin = aCoord[2];
+ ymax = aCoord[3];
+
+ /* Check if any of the 4 corners of the bounding-box being tested lie
+ ** inside the circular region. If they do, then the bounding-box does
+ ** intersect the region of interest. Set the output variable to true and
+ ** return SQLITE_OK in this case. */
+ for(i=0; i<4; i++){
+ double x = (i&0x01) ? xmax : xmin;
+ double y = (i&0x02) ? ymax : ymin;
+ double d2;
+
+ d2 = (x-pCircle->centerx)*(x-pCircle->centerx);
+ d2 += (y-pCircle->centery)*(y-pCircle->centery);
+ if( d2<(pCircle->radius*pCircle->radius) ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ }
+
+ /* Check if the bounding box covers any other part of the circular region.
+ ** See comments above for a description of how this test works. If it does
+ ** cover part of the circular region, set the output variable to true
+ ** and return SQLITE_OK. */
+ for(i=0; i<2; i++){
+ if( xmin<=pCircle->aBox[i].xmin
+ && xmax>=pCircle->aBox[i].xmax
+ && ymin<=pCircle->aBox[i].ymin
+ && ymax>=pCircle->aBox[i].ymax
+ ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ }
+
+ /* The specified bounding box does not intersect the circular region. Set
+ ** the output variable to zero and return SQLITE_OK. */
+ *pRes = 0;
+ return SQLITE_OK;
+}
+
+/* END of implementation of "circle" geometry callback.
+**************************************************************************
+*************************************************************************/
+
#include <assert.h>
#include "tcl.h"
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
rc = sqlite3_rtree_geometry_callback(db, "cube", cube_geom, (void *)&gHere);
- Tcl_SetResult(interp, sqlite3TestErrorName(rc), TCL_STATIC);
+ Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
+#endif
+ return TCL_OK;
+}
+
+static int register_circle_geom(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+#ifdef SQLITE_ENABLE_RTREE
+ extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ extern const char *sqlite3TestErrorName(int);
+ sqlite3 *db;
+ int rc;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ rc = sqlite3_rtree_geometry_callback(db, "circle", circle_geom, 0);
+ Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
#endif
return TCL_OK;
}
int Sqlitetestrtree_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "register_cube_geom", register_cube_geom, 0, 0);
+ Tcl_CreateObjCommand(interp, "register_circle_geom",register_circle_geom,0,0);
return TCL_OK;
}