xref: /sqlite-3.40.0/src/test_rtree.c (revision 7bddb755)
1 /*
2 ** 2010 August 28
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 ** Code for testing all sorts of SQLite interfaces. This code
13 ** is not included in the SQLite library.
14 */
15 #include "sqlite3rtree.h"
16 #include <sqlite3.h>
17 #include <assert.h>
18 #include "tcl.h"
19 
20 typedef struct Cube Cube;
21 struct Cube {
22   double x;
23   double y;
24   double z;
25   double width;
26   double height;
27   double depth;
28 };
29 
30 static void cube_context_free(void *p){
31   sqlite3_free(p);
32 }
33 
34 /*
35 ** The context pointer registered along with the 'cube' callback is
36 ** always ((void *)&gHere). This is just to facilitate testing, it is not
37 ** actually used for anything.
38 */
39 static int gHere = 42;
40 
41 /*
42 ** Implementation of a simple r-tree geom callback to test for intersection
43 ** of r-tree rows with a "cube" shape. Cubes are defined by six scalar
44 ** coordinates as follows:
45 **
46 **   cube(x, y, z, width, height, depth)
47 **
48 ** The width, height and depth parameters must all be greater than zero.
49 */
50 static int cube_geom(
51   RtreeGeometry *p,
52   int nCoord,
53   double *aCoord,
54   int *piRes
55 ){
56   Cube *pCube = (Cube *)p->pUser;
57 
58   assert( p->pContext==(void *)&gHere );
59 
60   if( pCube==0 ){
61     if( p->nParam!=6 || nCoord!=6
62      || p->aParam[3]<=0.0 || p->aParam[4]<=0.0 || p->aParam[5]<=0.0
63     ){
64       return SQLITE_ERROR;
65     }
66     pCube = (Cube *)sqlite3_malloc(sizeof(Cube));
67     if( !pCube ){
68       return SQLITE_NOMEM;
69     }
70     pCube->x = p->aParam[0];
71     pCube->y = p->aParam[1];
72     pCube->z = p->aParam[2];
73     pCube->width = p->aParam[3];
74     pCube->height = p->aParam[4];
75     pCube->depth = p->aParam[5];
76 
77     p->pUser = (void *)pCube;
78     p->xDelUser = cube_context_free;
79   }
80 
81   assert( nCoord==6 );
82   *piRes = 0;
83   if( aCoord[0]<=(pCube->x+pCube->width)
84    && aCoord[1]>=pCube->x
85    && aCoord[2]<=(pCube->y+pCube->height)
86    && aCoord[3]>=pCube->y
87    && aCoord[4]<=(pCube->z+pCube->depth)
88    && aCoord[5]>=pCube->z
89   ){
90     *piRes = 1;
91   }
92 
93   return SQLITE_OK;
94 }
95 
96 static int register_cube_geom(
97   void * clientData,
98   Tcl_Interp *interp,
99   int objc,
100   Tcl_Obj *CONST objv[]
101 ){
102 #ifdef SQLITE_ENABLE_RTREE
103   extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
104   extern const char *sqlite3TestErrorName(int);
105   sqlite3 *db;
106   int rc;
107 
108   if( objc!=2 ){
109     Tcl_WrongNumArgs(interp, 1, objv, "DB");
110     return TCL_ERROR;
111   }
112   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
113   rc = sqlite3_rtree_geometry_callback(db, "cube", cube_geom, (void *)&gHere);
114   Tcl_SetResult(interp, sqlite3TestErrorName(rc), TCL_STATIC);
115 #endif
116   return TCL_OK;
117 }
118 
119 int Sqlitetestrtree_Init(Tcl_Interp *interp){
120   Tcl_CreateObjCommand(interp, "register_cube_geom", register_cube_geom, 0, 0);
121   return TCL_OK;
122 }
123 
124