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