Add the "circle" test geometry callback to test_rtree.c. And tests for the same.

FossilOrigin-Name: 169b8ba4be9c3941c742eded80dbacdcd2465bc4
This commit is contained in:
dan 2010-08-31 15:02:00 +00:00
parent 8c96a6eac0
commit 18ec96b3a3
4 changed files with 213 additions and 22 deletions

View File

@ -8,6 +8,8 @@
# 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]} {
@ -72,7 +74,6 @@ for {set x 2} {$x<200} {incr x 2} {
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
@ -80,4 +81,45 @@ do_catchsql_test rtree9-4.3 {
} {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

View File

@ -1,8 +1,5 @@
-----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
@ -91,7 +88,7 @@ F ext/rtree/rtree5.test ce3d7ccae2cfd9d2e1052b462424964c9bdcda12
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
@ -211,7 +208,7 @@ F src/test_mutex.c ce06b59aca168cd8c520b77159a24352a7469bd3
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
@ -854,14 +851,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
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

View File

@ -1 +1 @@
86bcb9aab901713684f978479d29304cc9699e84
169b8ba4be9c3941c742eded80dbacdcd2465bc4

View File

@ -12,8 +12,143 @@
** 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"
@ -111,13 +246,37 @@ static int register_cube_geom(
}
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;
}