Add the "circle" test geometry callback to test_rtree.c. And tests for the same.
FossilOrigin-Name: 169b8ba4be9c3941c742eded80dbacdcd2465bc4
This commit is contained in:
parent
8c96a6eac0
commit
18ec96b3a3
@ -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
|
||||
|
26
manifest
26
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
86bcb9aab901713684f978479d29304cc9699e84
|
||||
169b8ba4be9c3941c742eded80dbacdcd2465bc4
|
163
src/test_rtree.c
163
src/test_rtree.c
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user