aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c6
-rw-r--r--src/tclsqlite.c2
-rw-r--r--src/test_rtree.c115
3 files changed, 122 insertions, 1 deletions
diff --git a/src/main.c b/src/main.c
index 9d749ea84..5dcc4dd6e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1075,13 +1075,17 @@ int sqlite3_create_function_v2(
sqlite3_mutex_enter(db->mutex);
if( xDestroy ){
pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor));
- if( !pArg ) goto out;
+ if( !pArg ){
+ xDestroy(p);
+ goto out;
+ }
pArg->xDestroy = xDestroy;
pArg->pUserData = p;
}
rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg);
if( pArg && pArg->nRef==0 ){
assert( rc!=SQLITE_OK );
+ xDestroy(p);
sqlite3DbFree(db, pArg);
}
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 141e68e55..164bc03b1 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -3576,6 +3576,7 @@ static void init_all(Tcl_Interp *interp){
extern int Sqlitetestintarray_Init(Tcl_Interp*);
extern int Sqlitetestvfs_Init(Tcl_Interp *);
extern int SqlitetestStat_Init(Tcl_Interp*);
+ extern int Sqlitetestrtree_Init(Tcl_Interp*);
Sqliteconfig_Init(interp);
Sqlitetest1_Init(interp);
@@ -3604,6 +3605,7 @@ static void init_all(Tcl_Interp *interp){
Sqlitetestintarray_Init(interp);
Sqlitetestvfs_Init(interp);
SqlitetestStat_Init(interp);
+ Sqlitetestrtree_Init(interp);
Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0);
diff --git a/src/test_rtree.c b/src/test_rtree.c
new file mode 100644
index 000000000..6cca357e1
--- /dev/null
+++ b/src/test_rtree.c
@@ -0,0 +1,115 @@
+/*
+** 2010 August 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Code for testing all sorts of SQLite interfaces. This code
+** is not included in the SQLite library.
+*/
+#include "sqlite3rtree.h"
+#include <sqlite3.h>
+#include <assert.h>
+#include "tcl.h"
+
+typedef struct Cube Cube;
+struct Cube {
+ double x;
+ double y;
+ double z;
+ double width;
+ double height;
+ double depth;
+};
+
+static void cube_context_free(void *p){
+ sqlite3_free(p);
+}
+
+static int gHere = 42;
+
+/*
+** Implementation of a simple r-tree geom callback to test for intersection
+** of r-tree rows with a "cube" shape. Cubes are defined by six scalar
+** coordinates as follows:
+**
+** cube(x, y, z, width, height, depth)
+**
+** The width, height and depth parameters must all be greater than zero.
+*/
+static int cube_geom(
+ RtreeGeometry *p,
+ int nCoord,
+ double *aCoord,
+ int *piRes
+){
+ Cube *pCube = (Cube *)p->pUser;
+
+ assert( p->pContext==(void *)&gHere );
+
+ if( pCube==0 ){
+ if( p->nParam!=6 || nCoord!=6
+ || p->aParam[3]<=0.0 || p->aParam[4]<=0.0 || p->aParam[5]<=0.0
+ ){
+ return SQLITE_ERROR;
+ }
+ pCube = (Cube *)sqlite3_malloc(sizeof(Cube));
+ if( !pCube ){
+ return SQLITE_NOMEM;
+ }
+ pCube->x = p->aParam[0];
+ pCube->y = p->aParam[1];
+ pCube->z = p->aParam[2];
+ pCube->width = p->aParam[3];
+ pCube->height = p->aParam[4];
+ pCube->depth = p->aParam[5];
+
+ p->pUser = (void *)pCube;
+ p->xDelUser = cube_context_free;
+ }
+
+ assert( nCoord==6 );
+ *piRes = 0;
+ if( aCoord[0]<=(pCube->x+pCube->width)
+ && aCoord[1]>=pCube->x
+ && aCoord[2]<=(pCube->y+pCube->height)
+ && aCoord[3]>=pCube->y
+ && aCoord[4]<=(pCube->z+pCube->depth)
+ && aCoord[5]>=pCube->z
+ ){
+ *piRes = 1;
+ }
+
+ return SQLITE_OK;
+}
+
+static int register_cube_geom(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+#ifdef SQLITE_ENABLE_RTREE
+ extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ sqlite3 *db;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ sqlite3_rtree_geometry_callback(db, "cube", cube_geom, (void *)&gHere);
+#endif
+ return TCL_OK;
+}
+
+int Sqlitetestrtree_Init(Tcl_Interp *interp){
+ Tcl_CreateObjCommand(interp, "register_cube_geom", register_cube_geom, 0, 0);
+ return TCL_OK;
+}
+