15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2001 September 15
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains code for implementations of the r-tree and r*-tree
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** algorithms packaged as an SQLite virtual table module.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Database Format of R-Tree Tables
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** --------------------------------
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The data structure for a single virtual r-tree table is stored in three
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** native SQLite tables declared as follows. In each case, the '%' character
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the table name is replaced with the user-supplied name of the r-tree
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The data for each node of the r-tree structure is stored in the %_node
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table. For each node that is not the root node of the r-tree, there is
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an entry in the %_parent table associating the node with its parent.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** And for each row of data in the table, there is an entry in the %_rowid
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table that maps from the entries rowid to the id of the node that it
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is stored on.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The root node of an r-tree always exists, even if the r-tree table is
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** empty. The nodeno of the root node is always 1. All other nodes in the
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table must be the same size as the root node. The content of each node
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is formatted as follows:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   1. If the node is the root node (node 1), then the first 2 bytes
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      of the node contain the tree depth as a big-endian integer.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      For non-root nodes, the first 2 bytes are left unused.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   2. The next 2 bytes contain the number of entries currently
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      stored in the node.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   3. The remainder of the node contains the node entries. Each entry
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      consists of a single 8-byte integer followed by an even number
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      of 4-byte coordinates. For leaf nodes the integer is the rowid
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      of a record. For internal nodes it is the node number of a
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      child page.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains an implementation of a couple of different variants
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the r-tree algorithm. See the README file for further details. The
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** same data-structure is used for all, but the algorithms for insert and
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** delete operations vary. The variants used are selected at compile time
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by defining the following symbols:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Either, both or none of the following may be set to activate
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** r*tree variant algorithms.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VARIANT_RSTARTREE_CHOOSESUBTREE 0
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VARIANT_RSTARTREE_REINSERT      1
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Exactly one of the following must be set to 1.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VARIANT_GUTTMAN_LINEAR_SPLIT    0
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VARIANT_RSTARTREE_SPLIT         1
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VARIANT_GUTTMAN_SPLIT \
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (VARIANT_GUTTMAN_LINEAR_SPLIT||VARIANT_GUTTMAN_QUADRATIC_SPLIT)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_GUTTMAN_QUADRATIC_SPLIT
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define PickNext QuadraticPickNext
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define PickSeeds QuadraticPickSeeds
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define AssignCells splitNodeGuttman
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_GUTTMAN_LINEAR_SPLIT
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define PickNext LinearPickNext
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define PickSeeds LinearPickSeeds
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define AssignCells splitNodeGuttman
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_SPLIT
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define AssignCells splitNodeStartree
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define NDEBUG 1
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_CORE
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #include "sqlite3ext.h"
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SQLITE_EXTENSION_INIT1
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #include "sqlite3.h"
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_AMALGAMATION
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqlite3rtree.h"
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef sqlite3_int64 i64;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef unsigned char u8;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef unsigned int u32;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*  The following macro is used to suppress compiler warnings.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UNUSED_PARAMETER
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define UNUSED_PARAMETER(x) (void)(x)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct Rtree Rtree;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct RtreeCursor RtreeCursor;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct RtreeNode RtreeNode;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct RtreeCell RtreeCell;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct RtreeConstraint RtreeConstraint;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct RtreeMatchArg RtreeMatchArg;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct RtreeGeomCallback RtreeGeomCallback;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef union RtreeCoord RtreeCoord;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_MAX_DIMENSIONS 5
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Size of hash table Rtree.aHash. This hash table is not expected to
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ever contain very many entries, so a fixed number of buckets is
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** used.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HASHSIZE 128
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An rtree virtual-table object.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Rtree {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab base;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db;                /* Host database connection */
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iNodeSize;              /* Size in bytes of each node in the node table */
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nDim;                   /* Number of dimensions */
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBytesPerCell;          /* Bytes consumed per cell */
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iDepth;                 /* Current depth of the r-tree structure */
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zDb;                  /* Name of database containing r-tree table */
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zName;                /* Name of r-tree table */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBusy;                  /* Current number of users of this structure */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* List of nodes removed during a CondenseTree operation. List is
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** linked together via the pointer normally used for hash chains -
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** headed by the node (leaf nodes have RtreeNode.iNode==0).
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pDeleted;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iReinsertHeight;        /* Height of sub-trees Reinsert() has run on */
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Statements to read/write/delete a record from xxx_node */
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pReadNode;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pWriteNode;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pDeleteNode;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Statements to read/write/delete a record from xxx_rowid */
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pReadRowid;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pWriteRowid;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pDeleteRowid;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Statements to read/write/delete a record from xxx_parent */
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pReadParent;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pWriteParent;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pDeleteParent;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eCoordType;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Possible values for eCoordType: */
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_COORD_REAL32 0
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_COORD_INT32  1
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The minimum number of cells allowed for a node is a third of the
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** maximum. In Gutman's notation:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     m = M/3
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If an R*-tree "Reinsert" operation is required, the same number of
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** cells are removed from the overfull node and reinserted into the tree.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_REINSERT(p) RTREE_MINCELLS(p)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_MAXCELLS 51
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The smallest possible node-size is (512-64)==448 bytes. And the largest
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Therefore all non-root nodes must contain at least 3 entries. Since
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2^40 is greater than 2^64, an r-tree structure always has a depth of
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 40 or less.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_MAX_DEPTH 40
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An rtree cursor object.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RtreeCursor {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor base;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode;                 /* Node cursor is currently pointing at */
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCell;                        /* Index of current cell in pNode */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iStrategy;                    /* Copy of idxNum search parameter */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nConstraint;                  /* Number of entries in aConstraint */
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeConstraint *aConstraint;     /* Search constraints. */
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)union RtreeCoord {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float f;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The argument is an RtreeCoord. Return the value stored within the RtreeCoord
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** formatted as a double. This macro assumes that local variable pRtree points
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to the Rtree structure associated with the RtreeCoord.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DCOORD(coord) (                           \
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (pRtree->eCoordType==RTREE_COORD_REAL32) ?      \
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((double)coord.f) :                           \
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((double)coord.i)                             \
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A search constraint.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RtreeConstraint {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCoord;                     /* Index of constrained coordinate */
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int op;                         /* Constraining operation */
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double rValue;                  /* Constraint value. */
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_rtree_geometry *pGeom;  /* Constraint callback argument for a MATCH */
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Possible values for RtreeConstraint.op */
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_EQ    0x41
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_LE    0x42
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_LT    0x43
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_GE    0x44
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_GT    0x45
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_MATCH 0x46
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An rtree structure node.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RtreeNode {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pParent;               /* Parent node */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 iNode;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRef;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDirty;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 *zData;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNext;                 /* Next node in this hash chain */
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NCELL(pNode) readInt16(&(pNode)->zData[2])
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Structure to store a deserialized rtree record.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RtreeCell {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 iRowid;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2];
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Value for the first field of every RtreeMatchArg object. The MATCH
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operator tests that the first field of a blob operand matches this
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** value to avoid operating on invalid blobs (which could cause a segfault).
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RTREE_GEOMETRY_MAGIC 0x891245AB
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An instance of this structure must be supplied as a blob argument to
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the right-hand-side of an SQL MATCH operator used to constrain an
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** r-tree query.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RtreeMatchArg {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 magic;                      /* Always RTREE_GEOMETRY_MAGIC */
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pContext;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nParam;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double aParam[1];
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When a geometry callback is created (see sqlite3_rtree_geometry_callback),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a single instance of the following structure is allocated. It is used
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as the context for the user-function created by by s_r_g_c(). The object
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is eventually deleted by the destructor mechanism provided by
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_create_function_v2() (which is called by s_r_g_c() to create
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the geometry callback function).
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RtreeGeomCallback {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pContext;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MAX
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define MAX(x,y) ((x) < (y) ? (y) : (x))
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MIN
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define MIN(x,y) ((x) > (y) ? (y) : (x))
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Functions to deserialize a 16 bit integer, 32 bit real number and
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 64 bit integer. The deserialized value is returned.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int readInt16(u8 *p){
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (p[0]<<8) + p[1];
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void readCoord(u8 *p, RtreeCoord *pCoord){
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 i = (
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((u32)p[0]) << 24) +
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((u32)p[1]) << 16) +
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((u32)p[2]) <<  8) +
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((u32)p[3]) <<  0)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *(u32 *)pCoord = i;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static i64 readInt64(u8 *p){
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[0]) << 56) +
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[1]) << 48) +
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[2]) << 40) +
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[3]) << 32) +
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[4]) << 24) +
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[5]) << 16) +
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[6]) <<  8) +
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (((i64)p[7]) <<  0)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Functions to serialize a 16 bit integer, 32 bit real number and
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 64 bit integer. The value returned is the number of bytes written
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to the argument buffer (always 2, 4 and 8 respectively).
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int writeInt16(u8 *p, int i){
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[0] = (i>> 8)&0xFF;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[1] = (i>> 0)&0xFF;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 2;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int writeCoord(u8 *p, RtreeCoord *pCoord){
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 i;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sizeof(RtreeCoord)==4 );
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sizeof(u32)==4 );
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = *(u32 *)pCoord;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[0] = (i>>24)&0xFF;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[1] = (i>>16)&0xFF;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[2] = (i>> 8)&0xFF;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[3] = (i>> 0)&0xFF;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 4;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int writeInt64(u8 *p, i64 i){
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[0] = (i>>56)&0xFF;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[1] = (i>>48)&0xFF;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[2] = (i>>40)&0xFF;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[3] = (i>>32)&0xFF;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[4] = (i>>24)&0xFF;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[5] = (i>>16)&0xFF;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[6] = (i>> 8)&0xFF;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[7] = (i>> 0)&0xFF;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 8;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Increment the reference count of node p.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeReference(RtreeNode *p){
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p ){
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->nRef++;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Clear the content of node p (set all bytes to 0x00).
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeZero(Rtree *pRtree, RtreeNode *p){
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&p->zData[2], 0, pRtree->iNodeSize-2);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->isDirty = 1;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Given a node number iNode, return the corresponding key to use
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the Rtree.aHash table.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nodeHash(i64 iNode){
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ) % HASHSIZE;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Search the node hash table for node iNode. If found, return a pointer
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to it. Otherwise, return 0.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *p;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Add node pNode to the node hash table.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHash;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pNode->pNext==0 );
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iHash = nodeHash(pNode->iNode);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode->pNext = pRtree->aHash[iHash];
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->aHash[iHash] = pNode;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Remove node pNode from the node hash table.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode **pp;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode->iNode!=0 ){
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp = &pRtree->aHash[nodeHash(pNode->iNode)];
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = pNode->pNext;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->pNext = 0;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0),
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** indicating that node has not yet been assigned a node number. It is
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** assigned a node number when nodeWrite() is called to write the
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** node contents out to the database.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode ){
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->zData = (u8 *)&pNode[1];
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->nRef = 1;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->pParent = pParent;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->isDirty = 1;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeReference(pParent);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pNode;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Obtain a reference to an r-tree node.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nodeAcquire(
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,             /* R-tree structure */
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 iNode,                 /* Node number to load */
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pParent,        /* Either the parent node or NULL */
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode **ppNode         /* OUT: Acquired node */
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc2 = SQLITE_OK;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check if the requested node is already in the hash table. If so,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** increase its reference count and return it.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (pNode = nodeHashLookup(pRtree, iNode)) ){
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pParent && !pNode->pParent ){
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeReference(pParent);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pNode->pParent = pParent;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->nRef++;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppNode = pNode;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pReadNode, 1, iNode);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_step(pRtree->pReadNode);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_ROW ){
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !pNode ){
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc2 = SQLITE_NOMEM;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode->pParent = pParent;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode->zData = (u8 *)&pNode[1];
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode->nRef = 1;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode->iNode = iNode;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode->isDirty = 0;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode->pNext = 0;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nodeReference(pParent);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_reset(pRtree->pReadNode);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ) rc = rc2;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the root node was just loaded, set pRtree->iDepth to the height
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** of the r-tree structure. A height of zero means all data is stored on
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the root node. A height of one means the children of the root node
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** are the leaves, and so on. If the depth as specified on the root node
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode && iNode==1 ){
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRtree->iDepth = readInt16(pNode->zData);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pRtree->iDepth>RTREE_MAX_DEPTH ){
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_CORRUPT;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If no error has occurred so far, check if the "number of entries"
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** field on the node is too large. If so, set the return code to
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** SQLITE_CORRUPT.
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode && rc==SQLITE_OK ){
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_CORRUPT;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pNode!=0 ){
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeHashInsert(pRtree, pNode);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_CORRUPT;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppNode = pNode;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pNode);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppNode = 0;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Overwrite cell iCell of node pNode with the contents of pCell.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeOverwriteCell(
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCell
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p += writeInt64(p, pCell->iRowid);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<(pRtree->nDim*2); ii++){
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p += writeCoord(p, &pCell->aCoord[ii]);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode->isDirty = 1;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Remove cell the cell with index iCell from node pNode.
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell];
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 *pSrc = &pDst[pRtree->nBytesPerCell];
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte = (NCELL(pNode) - iCell - 1) * pRtree->nBytesPerCell;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memmove(pDst, pSrc, nByte);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  writeInt16(&pNode->zData[2], NCELL(pNode)-1);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode->isDirty = 1;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Insert the contents of cell pCell into node pNode. If the insert
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is successful, return SQLITE_OK.
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If there is not enough free space in pNode, return SQLITE_FULL.
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nodeInsertCell(
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell;                    /* Current number of cells in pNode */
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nMaxCell;                 /* Maximum number of cells for pNode */
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nCell = NCELL(pNode);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( nCell<=nMaxCell );
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nCell<nMaxCell ){
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeOverwriteCell(pRtree, pNode, pCell, nCell);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writeInt16(&pNode->zData[2], nCell+1);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->isDirty = 1;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (nCell==nMaxCell);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the node is dirty, write it out to the database.
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nodeWrite(Rtree *pRtree, RtreeNode *pNode){
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode->isDirty ){
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_stmt *p = pRtree->pWriteNode;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pNode->iNode ){
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_bind_int64(p, 1, pNode->iNode);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_bind_null(p, 1);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_step(p);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->isDirty = 0;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_reset(p);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pNode->iNode==0 && rc==SQLITE_OK ){
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeHashInsert(pRtree, pNode);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Release a reference to a node. If the node is dirty and the reference
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** count drops to zero, the node data is written to the database.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nodeRelease(Rtree *pRtree, RtreeNode *pNode){
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode ){
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pNode->nRef>0 );
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->nRef--;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pNode->nRef==0 ){
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pNode->iNode==1 ){
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pRtree->iDepth = -1;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pNode->pParent ){
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = nodeRelease(pRtree, pNode->pParent);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = nodeWrite(pRtree, pNode);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeHashDelete(pRtree, pNode);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(pNode);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the 64-bit integer value associated with cell iCell of
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** node pNode. If pNode is a leaf node, this is a rowid. If it is
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an internal node, then the 64-bit integer is a child page number.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static i64 nodeGetRowid(
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCell
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( iCell<NCELL(pNode) );
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return readInt64(&pNode->zData[4 + pRtree->nBytesPerCell*iCell]);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return coordinate iCoord from cell iCell in node pNode.
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeGetCoord(
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCell,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCoord,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCoord *pCoord           /* Space to write result to */
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Deserialize cell iCell of node pNode. Populate the structure pointed
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to by pCell with the results.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nodeGetCell(
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCell,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<pRtree->nDim*2; ii++){
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward declaration for the function that does the work of
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the virtual table module xCreate() and xConnect() methods.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeInit(
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles));
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xCreate method.
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeCreate(
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pAux,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, const char *const*argv,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab **ppVtab,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErr
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xConnect method.
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeConnect(
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pAux,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, const char *const*argv,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab **ppVtab,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErr
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Increment the r-tree reference count.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void rtreeReference(Rtree *pRtree){
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->nBusy++;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Decrement the r-tree reference count. When the reference count reaches
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zero the structure is deleted.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void rtreeRelease(Rtree *pRtree){
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->nBusy--;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pRtree->nBusy==0 ){
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pReadNode);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pWriteNode);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pDeleteNode);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pReadRowid);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pWriteRowid);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pDeleteRowid);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pReadParent);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pWriteParent);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_finalize(pRtree->pDeleteParent);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pRtree);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xDisconnect method.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeDisconnect(sqlite3_vtab *pVtab){
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeRelease((Rtree *)pVtab);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xDestroy method.
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeDestroy(sqlite3_vtab *pVtab){
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)pVtab;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zCreate = sqlite3_mprintf(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "DROP TABLE '%q'.'%q_node';"
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "DROP TABLE '%q'.'%q_rowid';"
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "DROP TABLE '%q'.'%q_parent';",
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRtree->zDb, pRtree->zName,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRtree->zDb, pRtree->zName,
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRtree->zDb, pRtree->zName
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !zCreate ){
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_NOMEM;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(zCreate);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rtreeRelease(pRtree);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xOpen method.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCsr ){
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pCsr, 0, sizeof(RtreeCursor));
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCsr->base.pVtab = pVTab;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppCursor = (sqlite3_vtab_cursor *)pCsr;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Free the RtreeCursor.aConstraint[] array and its contents.
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void freeCursorConstraints(RtreeCursor *pCsr){
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCsr->aConstraint ){
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;                        /* Used to iterate through constraint array */
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<pCsr->nConstraint; i++){
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pGeom ){
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_free(pGeom);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pCsr->aConstraint);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCsr->aConstraint = 0;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xClose method.
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeClose(sqlite3_vtab_cursor *cur){
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)(cur->pVtab);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr = (RtreeCursor *)cur;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  freeCursorConstraints(pCsr);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = nodeRelease(pRtree, pCsr->pNode);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pCsr);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xEof method.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return non-zero if the cursor does not currently point to a valid
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** record (i.e if the scan has finished), or zero otherwise.
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeEof(sqlite3_vtab_cursor *cur){
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr = (RtreeCursor *)cur;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (pCsr->pNode==0);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The r-tree constraint passed as the second argument to this function is
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** guaranteed to be a MATCH constraint.
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int testRtreeGeom(
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,                  /* R-Tree object */
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeConstraint *pConstraint,   /* MATCH constraint to test */
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell,               /* Cell to test */
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pbRes                      /* OUT: Test result */
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double aCoord[RTREE_MAX_DIMENSIONS*2];
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCoord = pRtree->nDim*2;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pConstraint->op==RTREE_MATCH );
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pConstraint->pGeom );
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<nCoord; i++){
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aCoord[i] = DCOORD(pCell->aCoord[i]);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Cursor pCursor currently points to a cell in a non-leaf page.
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Set *pbEof to true if the sub-tree headed by the cell is filtered
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (excluded) by the constraints in the pCursor->aConstraint[]
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** array, or false otherwise.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return SQLITE_OK if successful or an SQLite error code if an error
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** occurs within a geometry callback.
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell cell;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bRes = 0;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeConstraint *p = &pCursor->aConstraint[ii];
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch( p->op ){
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_LE: case RTREE_LT:
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bRes = p->rValue<cell_min;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_GE: case RTREE_GT:
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bRes = p->rValue>cell_max;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_EQ:
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bRes = (p->rValue>cell_max || p->rValue<cell_min);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default: {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( p->op==RTREE_MATCH );
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = testRtreeGeom(pRtree, p, &cell, &bRes);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bRes = !bRes;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pbEof = bRes;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Test if the cell that cursor pCursor currently points to
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** would be filtered (excluded) by the constraints in the
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pCursor->aConstraint[] array. If so, set *pbEof to true before
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returning. If the cell is not filtered (excluded) by the constraints,
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** set pbEof to zero.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return SQLITE_OK if successful or an SQLite error code if an error
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** occurs within a geometry callback.
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function assumes that the cell is part of a leaf node.
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell cell;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pbEof = 0;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<pCursor->nConstraint; ii++){
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeConstraint *p = &pCursor->aConstraint[ii];
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double coord = DCOORD(cell.aCoord[p->iCoord]);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int res;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch( p->op ){
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_LE: res = (coord<=p->rValue); break;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_LT: res = (coord<p->rValue);  break;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_GE: res = (coord>=p->rValue); break;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_GT: res = (coord>p->rValue);  break;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case RTREE_EQ: res = (coord==p->rValue); break;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default: {
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int rc;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( p->op==RTREE_MATCH );
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = testRtreeGeom(pRtree, p, &cell, &res);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc!=SQLITE_OK ){
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return rc;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !res ){
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pbEof = 1;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Cursor pCursor currently points at a node that heads a sub-tree of
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** height iHeight (if iHeight==0, then the node is a leaf). Descend
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to point to the left-most cell of the sub-tree that matches the
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** configured constraints.
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int descendToCell(
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCursor,
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHeight,
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pEof                 /* OUT: Set to true if cannot descend */
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isEof;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pChild;
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 iRowid;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pSavedNode = pCursor->pNode;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iSavedCell = pCursor->iCell;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( iHeight>=0 );
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( iHeight==0 ){
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = testRtreeEntry(pRtree, pCursor, &isEof);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = testRtreeCell(pRtree, pCursor, &isEof);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK || isEof || iHeight==0 ){
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto descend_to_cell_out;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto descend_to_cell_out;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeRelease(pRtree, pCursor->pNode);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCursor->pNode = pChild;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  isEof = 1;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; isEof && ii<NCELL(pChild); ii++){
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCursor->iCell = ii;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto descend_to_cell_out;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isEof ){
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pCursor->pNode==pChild );
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeReference(pSavedNode);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeRelease(pRtree, pChild);
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCursor->pNode = pSavedNode;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCursor->iCell = iSavedCell;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)descend_to_cell_out:
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pEof = isEof;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** One of the cells in node pNode is guaranteed to have a 64-bit
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** integer value equal to iRowid. Return the index of this cell.
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nodeRowidIndex(
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 iRowid,
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *piIndex
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell = NCELL(pNode);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *piIndex = ii;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_CORRUPT;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the index of the cell containing a pointer to node pNode
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in its parent. If pNode is the root node, return -1.
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pParent = pNode->pParent;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pParent ){
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piIndex = -1;
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xNext method.
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** already at EOF. It is against the rules to call the xNext() method of
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a cursor that has already reached EOF.
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pCsr->pNode );
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCsr->iStrategy==1 ){
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* This "scan" is a direct lookup by rowid. There is no next entry. */
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeRelease(pRtree, pCsr->pNode);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCsr->pNode = 0;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Move to the next entry that matches the configured constraints. */
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iHeight = 0;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( pCsr->pNode ){
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RtreeNode *pNode = pCsr->pNode;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int nCell = NCELL(pNode);
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int isEof;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = descendToCell(pRtree, pCsr, iHeight, &isEof);
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc!=SQLITE_OK || !isEof ){
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return rc;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCsr->pNode = pNode->pParent;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return rc;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeReference(pCsr->pNode);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeRelease(pRtree, pNode);
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iHeight++;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xRowid method.
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(pCsr->pNode);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xColumn method.
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)cur->pVtab;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr = (RtreeCursor *)cur;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i==0 ){
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_result_int64(ctx, iRowid);
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCoord c;
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_double(ctx, c.f);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( pRtree->eCoordType==RTREE_COORD_INT32 );
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_int(ctx, c.i);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Use nodeAcquire() to obtain the leaf node containing the record with
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** rowid iRowid. If successful, set *ppLeaf to point to the node and
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** return SQLITE_OK. If there is no such record in the table, set
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to zero and return an SQLite error code.
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppLeaf = 0;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0);
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeAcquire(pRtree, iNode, 0, ppLeaf);
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_reset(pRtree->pReadRowid);
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_reset(pRtree->pReadRowid);
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to configure the RtreeConstraint object passed
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as the second argument for a MATCH constraint. The value passed as the
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** first argument to this function is the right-hand operand to the MATCH
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operator.
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeMatchArg *p;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_rtree_geometry *pGeom;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBlob;
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check that value is actually a blob. */
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check that the blob is roughly the right size. */
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nBlob = sqlite3_value_bytes(pValue);
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nBlob<(int)sizeof(RtreeMatchArg)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc(
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(sqlite3_rtree_geometry) + nBlob
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pGeom ) return SQLITE_NOMEM;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pGeom, 0, sizeof(sqlite3_rtree_geometry));
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = (RtreeMatchArg *)&pGeom[1];
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(p, sqlite3_value_blob(pValue), nBlob);
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->magic!=RTREE_GEOMETRY_MAGIC
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double))
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pGeom);
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeom->pContext = p->pContext;
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeom->nParam = p->nParam;
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeom->aParam = p->aParam;
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCons->xGeom = p->xGeom;
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCons->pGeom = pGeom;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xFilter method.
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeFilter(
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor *pVtabCursor,
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int idxNum, const char *idxStr,
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, sqlite3_value **argv
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pRoot = 0;
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeReference(pRtree);
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  freeCursorConstraints(pCsr);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr->iStrategy = idxNum;
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( idxNum==1 ){
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Special case - lookup by rowid. */
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pLeaf;        /* Leaf on which the required cell resides */
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i64 iRowid = sqlite3_value_int64(argv[0]);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = findLeafNode(pRtree, iRowid, &pLeaf);
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCsr->pNode = pLeaf;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pLeaf ){
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( rc==SQLITE_OK );
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell);
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** with the configured constraints.
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( argc>0 ){
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCsr->nConstraint = argc;
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !pCsr->aConstraint ){
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_NOMEM;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( (idxStr==0 && argc==0) || (int)strlen(idxStr)==argc*2 );
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for(ii=0; ii<argc; ii++){
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          RtreeConstraint *p = &pCsr->aConstraint[ii];
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->op = idxStr[ii*2];
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->iCoord = idxStr[ii*2+1]-'a';
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( p->op==RTREE_MATCH ){
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* A MATCH operator. The right-hand-side must be a blob that
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ** can be cast into an RtreeMatchArg object. One created using
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ** an sqlite3_rtree_geometry_callback() SQL user function.
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            */
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rc = deserializeGeometry(argv[ii], p);
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if( rc!=SQLITE_OK ){
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              break;
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }else{
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            p->rValue = sqlite3_value_double(argv[ii]);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCsr->pNode = 0;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = nodeAcquire(pRtree, 1, 0, &pRoot);
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int isEof = 1;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int nCell = NCELL(pRoot);
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCsr->pNode = pRoot;
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCell<nCell; pCsr->iCell++){
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( pCsr->pNode==pRoot );
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( !isEof ){
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK && isEof ){
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( pCsr->pNode==pRoot );
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nodeRelease(pRtree, pRoot);
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pCsr->pNode = 0;
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCell<NCELL(pCsr->pNode) );
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeRelease(pRtree);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Rtree virtual table module xBestIndex method. There are three
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table scan strategies to choose from (in order from most to
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** least desirable):
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   idxNum     idxStr        Strategy
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   ------------------------------------------------
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     1        Unused        Direct lookup by rowid.
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     2        See below     R-tree query or full-table scan.
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   ------------------------------------------------
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If strategy 1 is used, then idxStr is not meaningful. If strategy
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2 is used, idxStr is formatted to contain 2 bytes for each
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** constraint used. The first two bytes of idxStr correspond to
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the constraint in sqlite3_index_info.aConstraintUsage[] with
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (argvIndex==1) etc.
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The first of each pair of bytes in idxStr identifies the constraint
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operator as follows:
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Operator    Byte Value
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   ----------------------
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      =        0x41 ('A')
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     <=        0x42 ('B')
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      <        0x43 ('C')
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     >=        0x44 ('D')
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      >        0x45 ('E')
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   MATCH       0x46 ('F')
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   ----------------------
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The second of each pair of bytes identifies the coordinate column
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to which the constraint applies. The leftmost coordinate column
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is 'a', the second from the left 'b' etc.
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iIdx = 0;
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(zIdxStr, 0, sizeof(zIdxStr));
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(tab);
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pIdxInfo->idxStr==0 );
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* We have an equality constraint on the rowid. Use strategy 1. */
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int jj;
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(jj=0; jj<ii; jj++){
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pIdxInfo->aConstraintUsage[jj].argvIndex = 0;
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pIdxInfo->aConstraintUsage[jj].omit = 0;
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pIdxInfo->idxNum = 1;
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pIdxInfo->aConstraintUsage[ii].argvIndex = 1;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pIdxInfo->aConstraintUsage[jj].omit = 1;
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* This strategy involves a two rowid lookups on an B-Tree structures
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** and then a linear search of an R-Tree node. This should be
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** considered almost as quick as a direct rowid lookup (for which
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** sqlite uses an internal cost of 0.0).
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pIdxInfo->estimatedCost = 10.0;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u8 op;
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch( p->op ){
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          op = RTREE_MATCH;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zIdxStr[iIdx++] = op;
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zIdxStr[iIdx++] = p->iColumn - 1 + 'a';
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pIdxInfo->aConstraintUsage[ii].omit = 1;
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIdxInfo->idxNum = 2;
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIdxInfo->needToFreeIdxStr = 1;
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( iIdx>=0 );
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the N-dimensional volumn of the cell stored in *p.
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float cellArea(Rtree *pRtree, RtreeCell *p){
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float area = 1.0;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    area = area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return area;
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the margin length of cell p. The margin length is the sum
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the objects size in each dimension.
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float cellMargin(Rtree *pRtree, RtreeCell *p){
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float margin = 0.0;
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return margin;
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Store the union of cells p1 and p2 in p1.
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(ii=0; ii<(pRtree->nDim*2); ii+=2){
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return true if the area covered by p2 is a subset of the area covered
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by p1. False otherwise.
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<(pRtree->nDim*2); ii+=2){
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCoord *a1 = &p1->aCoord[ii];
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCoord *a2 = &p2->aCoord[ii];
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ){
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the amount cell p would grow by if it were unioned with pCell.
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float area;
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell cell;
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&cell, p, sizeof(RtreeCell));
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  area = cellArea(pRtree, &cell);
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cellUnion(pRtree, &cell, pCell);
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (cellArea(pRtree, &cell)-area);
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float cellOverlap(
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *p,
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iExclude
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float overlap = 0.0;
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_CHOOSESUBTREE
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( ii!=iExclude )
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( iExclude==-1 );
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNUSED_PARAMETER(iExclude);
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int jj;
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float o = 1.0;
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(jj=0; jj<(pRtree->nDim*2); jj+=2){
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double x1;
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double x2;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( x2<x1 ){
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          o = 0.0;
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          o = o * (x2-x1);
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overlap += o;
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return overlap;
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_CHOOSESUBTREE
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float cellOverlapEnlargement(
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *p,
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pInsert,
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iExclude
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float before;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float after;
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  before = cellOverlap(pRtree, p, aCell, nCell, iExclude);
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cellUnion(pRtree, p, pInsert);
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  after = cellOverlap(pRtree, p, aCell, nCell, iExclude);
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return after-before;
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function implements the ChooseLeaf algorithm from Gutman[84].
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ChooseSubTree in r*tree terminology.
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ChooseLeaf(
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,               /* Rtree table */
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell,            /* Cell to insert into rtree */
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHeight,                 /* Height of sub-tree rooted at pCell */
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode **ppLeaf           /* OUT: Selected leaf page */
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode;
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = nodeAcquire(pRtree, 1, 0, &pNode);
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iCell;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_int64 iBest;
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float fMinGrowth;
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float fMinArea;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float fMinOverlap;
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nCell = NCELL(pNode);
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell cell;
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pChild;
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell *aCell = 0;
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_CHOOSESUBTREE
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( ii==(pRtree->iDepth-1) ){
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int jj;
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell);
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !aCell ){
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_NOMEM;
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nodeRelease(pRtree, pNode);
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNode = 0;
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(jj=0; jj<nCell; jj++){
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nodeGetCell(pRtree, pNode, jj, &aCell[jj]);
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Select the child node which will be enlarged the least if pCell
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** is inserted into it. Resolve ties by choosing the entry with
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the smallest area.
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(iCell=0; iCell<nCell; iCell++){
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int bBest = 0;
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float growth;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float area;
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float overlap = 0.0;
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeGetCell(pRtree, pNode, iCell, &cell);
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      growth = cellGrowth(pRtree, &cell, pCell);
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      area = cellArea(pRtree, &cell);
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_CHOOSESUBTREE
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( ii==(pRtree->iDepth-1) ){
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell);
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (iCell==0)
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (overlap<fMinOverlap)
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (overlap==fMinOverlap && growth<fMinGrowth)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea)
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ){
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bBest = 1;
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bBest = 1;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( bBest ){
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fMinOverlap = overlap;
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fMinGrowth = growth;
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fMinArea = area;
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iBest = cell.iRowid;
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(aCell);
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeAcquire(pRtree, iBest, pNode, &pChild);
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeRelease(pRtree, pNode);
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode = pChild;
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppLeaf = pNode;
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A cell with the same content as pCell has just been inserted into
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the node pNode. This function updates the bounding box cells in
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** all ancestor elements.
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int AdjustTree(
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,                    /* Rtree table */
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,                 /* Adjust ancestry of this node. */
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell                  /* This cell was just inserted */
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *p = pNode;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( p->pParent ){
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pParent = p->pParent;
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell cell;
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iCell;
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( nodeParentIndex(pRtree, p, &iCell) ){
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_CORRUPT;
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCell(pRtree, pParent, iCell, &cell);
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !cellContains(pRtree, &cell, pCell) ){
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cellUnion(pRtree, &cell, pCell);
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeOverwriteCell(pRtree, pParent, &cell, iCell);
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p = pParent;
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write mapping (iRowid->iNode) to the <rtree>_rowid table.
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid);
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode);
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_step(pRtree->pWriteRowid);
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3_reset(pRtree->pWriteRowid);
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write mapping (iNode->iPar) to the <rtree>_parent table.
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pWriteParent, 1, iNode);
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pWriteParent, 2, iPar);
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_step(pRtree->pWriteParent);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3_reset(pRtree->pWriteParent);
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_GUTTMAN_LINEAR_SPLIT
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of the linear variant of the PickNext() function from
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Guttman[84].
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static RtreeCell *LinearPickNext(
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pLeftBox,
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pRightBox,
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aiUsed
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; aiUsed[ii]; ii++);
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aiUsed[ii] = 1;
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &aCell[ii];
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of the linear variant of the PickSeeds() function from
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Guttman[84].
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void LinearPickSeeds(
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *piLeftSeed,
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *piRightSeed
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iLeftSeed = 0;
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iRightSeed = 1;
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float maxNormalInnerWidth = 0.0;
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Pick two "seed" cells from the array of cells. The algorithm used
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** here is the LinearPickSeeds algorithm from Gutman[1984]. The
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** indices of the two seed cells in the array are stored in local
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** variables iLeftSeek and iRightSeed.
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<pRtree->nDim; i++){
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float x1 = DCOORD(aCell[0].aCoord[i*2]);
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float x2 = DCOORD(aCell[0].aCoord[i*2+1]);
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float x3 = x1;
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float x4 = x2;
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int jj;
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iCellLeft = 0;
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iCellRight = 0;
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(jj=1; jj<nCell; jj++){
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float left = DCOORD(aCell[jj].aCoord[i*2]);
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float right = DCOORD(aCell[jj].aCoord[i*2+1]);
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( left<x1 ) x1 = left;
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( right>x4 ) x4 = right;
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( left>x3 ){
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x3 = left;
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iCellRight = jj;
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( right<x2 ){
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x2 = right;
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iCellLeft = jj;
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( x4!=x1 ){
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float normalwidth = (x3 - x2) / (x4 - x1);
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( normalwidth>maxNormalInnerWidth ){
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iLeftSeed = iCellLeft;
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iRightSeed = iCellRight;
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piLeftSeed = iLeftSeed;
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piRightSeed = iRightSeed;
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_GUTTMAN_QUADRATIC_SPLIT
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of the quadratic variant of the PickNext() function from
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Guttman[84].
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static RtreeCell *QuadraticPickNext(
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pLeftBox,
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pRightBox,
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aiUsed
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define FABS(a) ((a)<0.0?-1.0*(a):(a))
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iSelect = -1;
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float fDiff;
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( aiUsed[ii]==0 ){
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float left = cellGrowth(pRtree, pLeftBox, &aCell[ii]);
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float right = cellGrowth(pRtree, pLeftBox, &aCell[ii]);
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float diff = FABS(right-left);
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( iSelect<0 || diff>fDiff ){
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fDiff = diff;
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iSelect = ii;
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aiUsed[iSelect] = 1;
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &aCell[iSelect];
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of the quadratic variant of the PickSeeds() function from
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Guttman[84].
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void QuadraticPickSeeds(
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *piLeftSeed,
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *piRightSeed
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int jj;
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iLeftSeed = 0;
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iRightSeed = 1;
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float fWaste = 0.0;
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(jj=ii+1; jj<nCell; jj++){
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float right = cellArea(pRtree, &aCell[jj]);
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]);
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float waste = growth - right;
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( waste>fWaste ){
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iLeftSeed = ii;
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iRightSeed = jj;
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fWaste = waste;
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piLeftSeed = iLeftSeed;
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piRightSeed = iRightSeed;
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT */
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Arguments aIdx, aDistance and aSpare all point to arrays of size
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** nIdx. The aIdx array contains the set of integers from 0 to
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (nIdx-1) in no particular order. This function sorts the values
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in aIdx according to the indexed values in aDistance. For
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** example, assuming the inputs:
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   aIdx      = { 0,   1,   2,   3 }
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   aDistance = { 5.0, 2.0, 7.0, 6.0 }
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this function sets the aIdx array to contain:
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   aIdx      = { 0,   1,   2,   3 }
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The aSpare array is used as temporary working space by the
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sorting algorithm.
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SortByDistance(
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aIdx,
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nIdx,
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float *aDistance,
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aSpare
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nIdx>1 ){
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iLeft = 0;
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iRight = 0;
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nLeft = nIdx/2;
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nRight = nIdx-nLeft;
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int *aLeft = aIdx;
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int *aRight = &aIdx[nLeft];
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortByDistance(aLeft, nLeft, aDistance, aSpare);
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortByDistance(aRight, nRight, aDistance, aSpare);
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(aSpare, aLeft, sizeof(int)*nLeft);
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aLeft = aSpare;
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( iLeft<nLeft || iRight<nRight ){
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( iLeft==nLeft ){
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aIdx[iLeft+iRight] = aRight[iRight];
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iRight++;
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else if( iRight==nRight ){
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aIdx[iLeft+iRight] = aLeft[iLeft];
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iLeft++;
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float fLeft = aDistance[aLeft[iLeft]];
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float fRight = aDistance[aRight[iRight]];
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( fLeft<fRight ){
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          aIdx[iLeft+iRight] = aLeft[iLeft];
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          iLeft++;
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          aIdx[iLeft+iRight] = aRight[iRight];
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          iRight++;
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Check that the sort worked */
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int jj;
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(jj=1; jj<nIdx; jj++){
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float left = aDistance[aIdx[jj-1]];
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float right = aDistance[aIdx[jj]];
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( left<=right );
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Arguments aIdx, aCell and aSpare all point to arrays of size
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** nIdx. The aIdx array contains the set of integers from 0 to
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (nIdx-1) in no particular order. This function sorts the values
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in aIdx according to dimension iDim of the cells in aCell. The
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** minimum value of dimension iDim is considered first, the
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** maximum used to break ties.
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The aSpare array is used as temporary working space by the
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sorting algorithm.
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SortByDimension(
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aIdx,
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nIdx,
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iDim,
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aSpare
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nIdx>1 ){
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iLeft = 0;
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iRight = 0;
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nLeft = nIdx/2;
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nRight = nIdx-nLeft;
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int *aLeft = aIdx;
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int *aRight = &aIdx[nLeft];
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare);
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare);
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(aSpare, aLeft, sizeof(int)*nLeft);
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aLeft = aSpare;
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( iLeft<nLeft || iRight<nRight ){
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]);
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]);
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]);
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]);
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (iLeft!=nLeft) && ((iRight==nRight)
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (xleft1<xright1)
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (xleft1==xright1 && xleft2<xright2)
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )){
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aIdx[iLeft+iRight] = aLeft[iLeft];
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iLeft++;
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aIdx[iLeft+iRight] = aRight[iRight];
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iRight++;
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Check that the sort worked */
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int jj;
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(jj=1; jj<nIdx; jj++){
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2];
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1];
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float xright1 = aCell[aIdx[jj]].aCoord[iDim*2];
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1];
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( xleft1<=xright1 && (xleft1<xright1 || xleft2<=xright2) );
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_SPLIT
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of the R*-tree variant of SplitNode from Beckman[1990].
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int splitNodeStartree(
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pLeft,
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pRight,
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pBboxLeft,
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pBboxRight
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int **aaSorted;
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aSpare;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iBestDim;
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iBestSplit;
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float fBestMargin;
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aaSorted = (int **)sqlite3_malloc(nByte);
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !aaSorted ){
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell];
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(aaSorted, 0, nByte);
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<pRtree->nDim; ii++){
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int jj;
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell];
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(jj=0; jj<nCell; jj++){
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aaSorted[ii][jj] = jj;
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare);
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<pRtree->nDim; ii++){
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float margin = 0.0;
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float fBestOverlap;
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float fBestArea;
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iBestLeft;
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nLeft;
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nLeft=RTREE_MINCELLS(pRtree);
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nLeft<=(nCell-RTREE_MINCELLS(pRtree));
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nLeft++
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ){
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RtreeCell left;
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RtreeCell right;
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int kk;
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float overlap;
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float area;
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell));
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell));
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(kk=1; kk<(nCell-1); kk++){
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( kk<nLeft ){
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cellUnion(pRtree, &left, &aCell[aaSorted[ii][kk]]);
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cellUnion(pRtree, &right, &aCell[aaSorted[ii][kk]]);
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margin += cellMargin(pRtree, &left);
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      margin += cellMargin(pRtree, &right);
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overlap = cellOverlap(pRtree, &left, &right, 1, -1);
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      area = cellArea(pRtree, &left) + cellArea(pRtree, &right);
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (nLeft==RTREE_MINCELLS(pRtree))
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (overlap<fBestOverlap)
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || (overlap==fBestOverlap && area<fBestArea)
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ){
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iBestLeft = nLeft;
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fBestOverlap = overlap;
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fBestArea = area;
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( ii==0 || margin<fBestMargin ){
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iBestDim = ii;
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fBestMargin = margin;
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iBestSplit = iBestLeft;
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pBboxLeft, &aCell[aaSorted[iBestDim][0]], sizeof(RtreeCell));
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pBboxRight, &aCell[aaSorted[iBestDim][iBestSplit]], sizeof(RtreeCell));
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pTarget = (ii<iBestSplit)?pLeft:pRight;
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell *pBbox = (ii<iBestSplit)?pBboxLeft:pBboxRight;
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell *pCell = &aCell[aaSorted[iBestDim][ii]];
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeInsertCell(pRtree, pTarget, pCell);
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cellUnion(pRtree, pBbox, pCell);
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(aaSorted);
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_GUTTMAN_SPLIT
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of the regular R-tree SplitNode from Guttman[1984].
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int splitNodeGuttman(
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell,
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell,
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pLeft,
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pRight,
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pBboxLeft,
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pBboxRight
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iLeftSeed = 0;
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iRightSeed = 1;
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aiUsed;
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aiUsed = sqlite3_malloc(sizeof(int)*nCell);
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !aiUsed ){
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(aiUsed, 0, sizeof(int)*nCell);
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed);
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell));
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell));
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]);
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]);
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aiUsed[iLeftSeed] = 1;
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aiUsed[iRightSeed] = 1;
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=nCell-2; i>0; i--){
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell *pNext;
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed);
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float diff =
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cellGrowth(pRtree, pBboxLeft, pNext) -
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cellGrowth(pRtree, pBboxRight, pNext)
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ;
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i)
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i))
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ){
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeInsertCell(pRtree, pRight, pNext);
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cellUnion(pRtree, pBboxRight, pNext);
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeInsertCell(pRtree, pLeft, pNext);
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cellUnion(pRtree, pBboxLeft, pNext);
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(aiUsed);
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int updateMapping(
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 iRowid,
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHeight
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( iHeight>0 ){
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pChild ){
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeRelease(pRtree, pChild->pParent);
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeReference(pNode);
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pChild->pParent = pNode;
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return xSetMapping(pRtree, iRowid, pNode->iNode);
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int SplitNode(
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell,
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHeight
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int newCellIsRight = 0;
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell = NCELL(pNode);
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell;
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aiUsed;
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pLeft = 0;
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pRight = 0;
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell leftbbox;
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell rightbbox;
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate an array and populate it with a copy of pCell and
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** all cells from node pLeft. Then zero the original node.
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !aCell ){
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_NOMEM;
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto splitnode_out;
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aiUsed = (int *)&aCell[nCell+1];
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(aiUsed, 0, sizeof(int)*(nCell+1));
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<nCell; i++){
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCell(pRtree, pNode, i, &aCell[i]);
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeZero(pRtree, pNode);
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&aCell[nCell], pCell, sizeof(RtreeCell));
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nCell++;
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode->iNode==1 ){
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRight = nodeNew(pRtree, pNode);
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pLeft = nodeNew(pRtree, pNode);
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRtree->iDepth++;
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->isDirty = 1;
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writeInt16(pNode->zData, pRtree->iDepth);
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pLeft = pNode;
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRight = nodeNew(pRtree, pLeft->pParent);
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeReference(pLeft);
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pLeft || !pRight ){
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_NOMEM;
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto splitnode_out;
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pLeft->zData, 0, pRtree->iNodeSize);
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pRight->zData, 0, pRtree->iNodeSize);
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox);
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto splitnode_out;
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Ensure both child nodes have node numbers assigned to them by calling
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** nodeWrite(). Node pRight always needs a node number, as it was created
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** by nodeNew() above. But node pLeft sometimes already has a node number.
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** In this case avoid the all to nodeWrite().
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight))
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft)))
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto splitnode_out;
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rightbbox.iRowid = pRight->iNode;
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  leftbbox.iRowid = pLeft->iNode;
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode->iNode==1 ){
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1);
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto splitnode_out;
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pParent = pLeft->pParent;
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iCell;
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeParentIndex(pRtree, pLeft, &iCell);
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = AdjustTree(pRtree, pParent, &leftbbox);
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto splitnode_out;
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto splitnode_out;
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<NCELL(pRight); i++){
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i64 iRowid = nodeGetRowid(pRtree, pRight, i);
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = updateMapping(pRtree, iRowid, pRight, iHeight);
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( iRowid==pCell->iRowid ){
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      newCellIsRight = 1;
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto splitnode_out;
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNode->iNode==1 ){
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<NCELL(pLeft); i++){
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i64 iRowid = nodeGetRowid(pRtree, pLeft, i);
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = updateMapping(pRtree, iRowid, pLeft, iHeight);
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto splitnode_out;
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( newCellIsRight==0 ){
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = updateMapping(pRtree, pCell->iRowid, pLeft, iHeight);
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeRelease(pRtree, pRight);
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRight = 0;
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeRelease(pRtree, pLeft);
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pLeft = 0;
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)splitnode_out:
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeRelease(pRtree, pRight);
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeRelease(pRtree, pLeft);
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(aCell);
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If node pLeaf is not the root of the r-tree and its pParent pointer is
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still NULL, load all ancestor nodes of pLeaf into memory and populate
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the pLeaf->pParent chain all the way up to the root node.
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This operation is required when a row is deleted (or updated - an update
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is implemented as a delete followed by an insert). SQLite provides the
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** rowid of the row to delete, which can be used to find the leaf on which
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the entry resides (argument pLeaf). Once the leaf is located, this
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** function is called to determine its ancestry.
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pChild = pLeaf;
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc2 = SQLITE_OK;          /* sqlite3_reset() return code */
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode);
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_step(pRtree->pReadParent);
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_ROW ){
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RtreeNode *pTest;           /* Used to test for reference loops */
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i64 iNode;                  /* Node number of parent node */
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Before setting pChild->pParent, test that we are not creating a
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** loop of references (as we would if, say, pChild==pParent). We don't
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** want to do this as it leads to a memory leak when trying to delete
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** the referenced counted node structures.
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !pTest ){
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_reset(pRtree->pReadParent);
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ) rc = rc2;
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT;
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pChild = pChild->pParent;
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int deleteCell(Rtree *, RtreeNode *, int, int);
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc2;
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pParent;
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCell;
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pNode->nRef==1 );
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove the entry in the parent cell. */
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = nodeParentIndex(pRtree, pNode, &iCell);
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pParent = pNode->pParent;
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNode->pParent = 0;
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc2 = nodeRelease(pRtree, pParent);
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = rc2;
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove the xxx_node entry. */
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode);
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_step(pRtree->pDeleteNode);
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove the xxx_parent entry. */
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode);
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_step(pRtree->pDeleteParent);
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove the node from the in-memory hash table and link it into
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the Rtree.pDeleted list. Its contents will be re-inserted later on.
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeHashDelete(pRtree, pNode);
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode->iNode = iHeight;
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode->pNext = pRtree->pDeleted;
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNode->nRef++;
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->pDeleted = pNode;
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pParent = pNode->pParent;
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pParent ){
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ii;
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nCell = NCELL(pNode);
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell box;                            /* Bounding box for pNode */
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCell(pRtree, pNode, 0, &box);
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(ii=1; ii<nCell; ii++){
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RtreeCell cell;
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeGetCell(pRtree, pNode, ii, &cell);
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cellUnion(pRtree, &box, &cell);
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    box.iRowid = pNode->iNode;
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeParentIndex(pRtree, pNode, &ii);
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeOverwriteCell(pRtree, pParent, &box, ii);
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = fixBoundingBox(pRtree, pParent);
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the cell at index iCell of node pNode. After removing the
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** cell, adjust the r-tree data structure if required.
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pParent;
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove the cell from the node. This call just moves bytes around
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the in-memory node image, so it cannot fail.
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeDeleteCell(pRtree, pNode, iCell);
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the node is not the tree root and now has less than the minimum
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** number of cells, remove it from the tree. Otherwise, update the
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** cell in the parent node so that it tightly contains the updated
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** node.
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pParent = pNode->pParent;
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pParent || pNode->iNode==1 );
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pParent ){
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( NCELL(pNode)<RTREE_MINCELLS(pRtree) ){
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = removeNode(pRtree, pNode, iHeight);
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = fixBoundingBox(pRtree, pNode);
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int Reinsert(
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell,
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHeight
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aOrder;
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *aSpare;
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *aCell;
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float *aDistance;
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell;
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float aCenterCoord[RTREE_MAX_DIMENSIONS];
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iDim;
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(aCenterCoord, 0, sizeof(float)*RTREE_MAX_DIMENSIONS);
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nCell = NCELL(pNode)+1;
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate the buffers used by this operation. The allocation is
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** relinquished before this function returns.
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aCell = (RtreeCell *)sqlite3_malloc(nCell * (
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(RtreeCell) +         /* aCell array */
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(int)       +         /* aOrder array */
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(int)       +         /* aSpare array */
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(float)               /* aDistance array */
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ));
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !aCell ){
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aOrder    = (int *)&aCell[nCell];
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aSpare    = (int *)&aOrder[nCell];
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aDistance = (float *)&aSpare[nCell];
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( ii==(nCell-1) ){
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(&aCell[ii], pCell, sizeof(RtreeCell));
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aOrder[ii] = ii;
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(iDim=0; iDim<pRtree->nDim; iDim++){
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(iDim=0; iDim<pRtree->nDim; iDim++){
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aCenterCoord[iDim] = aCenterCoord[iDim]/((float)nCell*2.0);
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<nCell; ii++){
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aDistance[ii] = 0.0;
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(iDim=0; iDim<pRtree->nDim; iDim++){
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) -
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCOORD(aCell[ii].aCoord[iDim*2]);
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortByDistance(aOrder, nCell, aDistance, aSpare);
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodeZero(pRtree, pNode);
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell *p = &aCell[aOrder[ii]];
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeInsertCell(pRtree, pNode, p);
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->iRowid==pCell->iRowid ){
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( iHeight==0 ){
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = rowidWrite(pRtree, p->iRowid, pNode->iNode);
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = parentWrite(pRtree, p->iRowid, pNode->iNode);
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = fixBoundingBox(pRtree, pNode);
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(; rc==SQLITE_OK && ii<nCell; ii++){
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Find a node to store this cell in. pNode->iNode currently contains
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the height of the sub-tree headed by the cell.
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pInsert;
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell *p = &aCell[aOrder[ii]];
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = ChooseLeaf(pRtree, p, iHeight, &pInsert);
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc2;
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = rtreeInsertCell(pRtree, pInsert, p, iHeight);
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc2 = nodeRelease(pRtree, pInsert);
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = rc2;
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(aCell);
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Insert cell pCell into node pNode. Node pNode is the head of a
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** subtree iHeight high (leaf nodes have iHeight==0).
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeInsertCell(
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode *pNode,
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeCell *pCell,
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iHeight
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( iHeight>0 ){
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid);
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pChild ){
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeRelease(pRtree, pChild->pParent);
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeReference(pNode);
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pChild->pParent = pNode;
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nodeInsertCell(pRtree, pNode, pCell) ){
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if VARIANT_RSTARTREE_REINSERT
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SplitNode(pRtree, pNode, pCell, iHeight);
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pRtree->iReinsertHeight = iHeight;
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = Reinsert(pRtree, pNode, pCell, iHeight);
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SplitNode(pRtree, pNode, pCell, iHeight);
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = AdjustTree(pRtree, pNode, pCell);
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( iHeight==0 ){
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode);
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nCell = NCELL(pNode);
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; rc==SQLITE_OK && ii<nCell; ii++){
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pInsert;
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell cell;
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCell(pRtree, pNode, ii, &cell);
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Find a node to store this cell in. pNode->iNode currently contains
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the height of the sub-tree headed by the cell.
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = ChooseLeaf(pRtree, &cell, pNode->iNode, &pInsert);
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc2;
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = rtreeInsertCell(pRtree, pInsert, &cell, pNode->iNode);
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc2 = nodeRelease(pRtree, pInsert);
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = rc2;
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Select a currently unused rowid for a new r-tree record.
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int newRowid(Rtree *pRtree, i64 *piRowid){
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_null(pRtree->pWriteRowid, 1);
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_bind_null(pRtree->pWriteRowid, 2);
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_step(pRtree->pWriteRowid);
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_reset(pRtree->pWriteRowid);
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piRowid = sqlite3_last_insert_rowid(pRtree->db);
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The xUpdate method for rtree module virtual tables.
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeUpdate(
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab *pVtab,
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nData,
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_value **azData,
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 *pRowid
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)pVtab;
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeReference(pRtree);
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(nData>=1);
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If azData[0] is not an SQL NULL value, it is the rowid of a
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** record to delete from the r-tree table. The following block does
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** just that.
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i64 iDelete;                /* The rowid to delete */
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pLeaf;           /* Leaf node containing record iDelete */
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iCell;                  /* Index of iDelete cell in pLeaf */
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pRoot;
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Obtain a reference to the root node to initialise Rtree.iDepth */
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = nodeAcquire(pRtree, 1, 0, &pRoot);
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Obtain a reference to the leaf node that contains the entry
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** about to be deleted.
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iDelete = sqlite3_value_int64(azData[0]);
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = findLeafNode(pRtree, iDelete, &pLeaf);
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Delete the cell in question from the leaf node. */
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc2;
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = deleteCell(pRtree, pLeaf, iCell, 0);
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc2 = nodeRelease(pRtree, pLeaf);
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = rc2;
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Delete the corresponding entry in the <rtree>_rowid table. */
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_step(pRtree->pDeleteRowid);
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_reset(pRtree->pDeleteRowid);
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Check if the root node now has exactly one child. If so, remove
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** it, schedule the contents of the child for reinsertion and
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** reduce the tree height by one.
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** This is equivalent to copying the contents of the child into
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the root node (the operation that Gutman's paper says to perform
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** in this scenario).
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc2;
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RtreeNode *pChild;
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc2 = nodeRelease(pRtree, pChild);
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ) rc = rc2;
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pRtree->iDepth--;
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        writeInt16(pRoot->zData, pRtree->iDepth);
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pRoot->isDirty = 1;
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Re-insert the contents of any underfull nodes removed from the tree. */
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = reinsertNodeContent(pRtree, pLeaf);
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pRtree->pDeleted = pLeaf->pNext;
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(pLeaf);
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Release the reference to the root node. */
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = nodeRelease(pRtree, pRoot);
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nodeRelease(pRtree, pRoot);
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the azData[] array contains more than one element, elements
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** (azData[2]..azData[argc-1]) contain a new record to insert into
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the r-tree structure.
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && nData>1 ){
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Insert a new record into the r-tree */
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell cell;
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ii;
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeNode *pLeaf;
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( nData==(pRtree->nDim*2 + 3) );
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(ii=0; ii<(pRtree->nDim*2); ii+=2){
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cell.aCoord[ii].f = (float)sqlite3_value_double(azData[ii+3]);
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cell.aCoord[ii+1].f = (float)sqlite3_value_double(azData[ii+4]);
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_CONSTRAINT;
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto constraint;
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(ii=0; ii<(pRtree->nDim*2); ii+=2){
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_CONSTRAINT;
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto constraint;
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Figure out the rowid of the new row. */
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( sqlite3_value_type(azData[2])==SQLITE_NULL ){
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = newRowid(pRtree, &cell.iRowid);
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cell.iRowid = sqlite3_value_int64(azData[2]);
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( SQLITE_ROW==sqlite3_step(pRtree->pReadRowid) ){
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_reset(pRtree->pReadRowid);
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_CONSTRAINT;
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto constraint;
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_reset(pRtree->pReadRowid);
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pRowid = cell.iRowid;
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc2;
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pRtree->iReinsertHeight = -1;
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc2 = nodeRelease(pRtree, pLeaf);
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = rc2;
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)constraint:
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeRelease(pRtree);
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The xRename method for rtree module virtual tables.
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree = (Rtree *)pVtab;
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zSql = sqlite3_mprintf(
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ALTER TABLE %Q.'%q_node'   RENAME TO \"%w_node\";"
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";"
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ALTER TABLE %Q.'%q_rowid'  RENAME TO \"%w_rowid\";"
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    , pRtree->zDb, pRtree->zName, zNewName
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    , pRtree->zDb, pRtree->zName, zNewName
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    , pRtree->zDb, pRtree->zName, zNewName
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zSql ){
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0);
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(zSql);
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_module rtreeModule = {
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                         /* iVersion */
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeCreate,                /* xCreate - create a table */
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeConnect,               /* xConnect - connect to an existing table */
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeBestIndex,             /* xBestIndex - Determine search strategy */
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeDisconnect,            /* xDisconnect - Disconnect from a table */
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeDestroy,               /* xDestroy - Drop a table */
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeOpen,                  /* xOpen - open a cursor */
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeClose,                 /* xClose - close a cursor */
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeFilter,                /* xFilter - configure scan constraints */
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeNext,                  /* xNext - advance a cursor */
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeEof,                   /* xEof */
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeColumn,                /* xColumn - read data */
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeRowid,                 /* xRowid - read data */
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeUpdate,                /* xUpdate - write data */
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                          /* xBegin - begin transaction */
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                          /* xSync - sync transaction */
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                          /* xCommit - commit transaction */
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                          /* xRollback - rollback transaction */
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                          /* xFindFunction - function overloading */
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rtreeRename                 /* xRename - rename the table */
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeSqlInit(
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zDb,
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPrefix,
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isCreate
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define N_STATEMENT 9
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char *azSql[N_STATEMENT] = {
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Read and write the xxx_node table */
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1",
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Read and write the xxx_rowid table */
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Read and write the xxx_parent table */
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1",
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)",
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1"
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt **appStmt[N_STATEMENT];
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->db = db;
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isCreate ){
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zCreate = sqlite3_mprintf(
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);"
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);"
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY, parentnode INTEGER);"
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))",
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !zCreate ){
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_exec(db, zCreate, 0, 0, 0);
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(zCreate);
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[0] = &pRtree->pReadNode;
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[1] = &pRtree->pWriteNode;
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[2] = &pRtree->pDeleteNode;
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[3] = &pRtree->pReadRowid;
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[4] = &pRtree->pWriteRowid;
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[5] = &pRtree->pDeleteRowid;
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[6] = &pRtree->pReadParent;
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[7] = &pRtree->pWriteParent;
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appStmt[8] = &pRtree->pDeleteParent;
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zSql ){
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0);
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(zSql);
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The second argument to this function contains the text of an SQL statement
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that returns a single integer value. The statement is compiled and executed
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** using database connection db. If successful, the integer value returned
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** code is returned and the value of *piVal after returning is not defined.
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zSql ){
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_stmt *pStmt = 0;
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( SQLITE_ROW==sqlite3_step(pStmt) ){
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *piVal = sqlite3_column_int(pStmt, 0);
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_finalize(pStmt);
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called from within the xConnect() or xCreate() method to
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** determine the node-size used by the rtree table being created or connected
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, an SQLite error code is returned.
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If this function is being called as part of an xConnect(), then the rtree
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table already exists. In this case the node-size is determined by inspecting
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the root node of the tree.
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This ensures that each node is stored on a single database page. If the
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database page-size is so large that more than RTREE_MAXCELLS entries
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** would fit in a single node, use a smaller node-size.
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getNodeSize(
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,                    /* Database handle */
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree,                  /* Rtree handle */
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isCreate                    /* True for xCreate, false for xConnect */
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zSql;
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isCreate ){
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iPageSize;
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = getIntFromStmt(db, zSql, &iPageSize);
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pRtree->iNodeSize = iPageSize-64;
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSql = sqlite3_mprintf(
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pRtree->zDb, pRtree->zName
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(zSql);
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is the implementation of both the xConnect and xCreate
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** methods of the r-tree virtual table.
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   argv[0]   -> module name
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   argv[1]   -> database name
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   argv[2]   -> table name
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   argv[...] -> column names...
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int rtreeInit(
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,                        /* Database connection */
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pAux,                         /* One of the RTREE_COORD_* constants */
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, const char *const*argv,   /* Parameters to CREATE TABLE statement */
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab **ppVtab,              /* OUT: New virtual table */
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErr,                       /* OUT: Error message, if any */
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isCreate                        /* True for xCreate, false for xConnect */
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree *pRtree;
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nDb;              /* Length of string argv[1] */
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nName;            /* Length of string argv[2] */
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *aErrMsg[] = {
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                                    /* 0 */
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Wrong number of columns for an rtree table",         /* 1 */
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Too few columns for an rtree table",                 /* 2 */
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Too many columns for an rtree table"                 /* 3 */
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( aErrMsg[iErr] ){
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate the sqlite3_vtab structure */
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nDb = strlen(argv[1]);
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nName = strlen(argv[2]);
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pRtree ){
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->nBusy = 1;
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->base.pModule = &rtreeModule;
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->zDb = (char *)&pRtree[1];
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->zName = &pRtree->zDb[nDb+1];
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->nDim = (argc-4)/2;
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2;
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pRtree->eCoordType = eCoordType;
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pRtree->zDb, argv[1], nDb);
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pRtree->zName, argv[2], nName);
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Figure out the node size to use. */
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = getNodeSize(db, pRtree, isCreate);
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create/Connect to the underlying relational database schema. If
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** that is successful, call sqlite3_declare_vtab() to configure
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the r-tree table schema.
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zTmp;
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ii;
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(ii=4; zSql && ii<argc; ii++){
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zTmp = zSql;
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_free(zTmp);
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( zSql ){
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zTmp = zSql;
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zSql = sqlite3_mprintf("%s);", zTmp);
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_free(zTmp);
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !zSql ){
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_NOMEM;
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(zSql);
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppVtab = (sqlite3_vtab *)pRtree;
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rtreeRelease(pRtree);
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation of a scalar function that decodes r-tree nodes to
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** human readable strings. This can be used for debugging and analysis.
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The scalar function takes two arguments, a blob of data containing
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an r-tree node, and the number of dimensions the r-tree indexes.
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For a two-dimensional r-tree structure called "rt", to deserialize
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** all nodes, a statement like:
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   SELECT rtreenode(2, data) FROM rt_node;
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The human readable string takes the form of a Tcl list with one
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** entry for each cell in the r-tree node. Each entry is itself a
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** list, containing the 8-byte rowid/pageno followed by the
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** <num-dimension>*2 coordinates.
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zText = 0;
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeNode node;
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rtree tree;
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nArg);
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&node, 0, sizeof(RtreeNode));
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&tree, 0, sizeof(Rtree));
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tree.nDim = sqlite3_value_int(apArg[0]);
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tree.nBytesPerCell = 8 + 8 * tree.nDim;
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=0; ii<NCELL(&node); ii++){
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char zCell[512];
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nCell = 0;
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RtreeCell cell;
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int jj;
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nodeGetCell(&tree, &node, ii, &cell);
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid);
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nCell = strlen(zCell);
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(jj=0; jj<tree.nDim*2; jj++){
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f);
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nCell = strlen(zCell);
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zText ){
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell);
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(zText);
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zText = zTextNew;
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zText = sqlite3_mprintf("{%s}", zCell);
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_result_text(ctx, zText, -1, sqlite3_free);
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nArg);
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   || sqlite3_value_bytes(apArg[0])<2
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_result_int(ctx, readInt16(zBlob));
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register the r-tree module with database handle db. This creates the
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** virtual table module "rtree" and the debugging/analysis scalar
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** function "rtreenode".
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3RtreeInit(sqlite3 *db){
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int utf8 = SQLITE_UTF8;
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0);
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *c = (void *)RTREE_COORD_REAL32;
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0);
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *c = (void *)RTREE_COORD_INT32;
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0);
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A version of sqlite3_free() that can be used as a callback. This is used
31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in two places - as the destructor for the blob value returned by the
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** invocation of a geometry function, and as the destructor for the geometry
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** functions themselves.
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void doSqlite3Free(void *p){
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** scalar user function. This C function is the callback used for all such
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** registered SQL functions.
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The scalar user functions return a blob that is interpreted by r-tree
31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** table MATCH operators.
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeMatchArg *pBlob;
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBlob;
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(double);
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pBlob ){
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_result_error_nomem(ctx);
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBlob->magic = RTREE_GEOMETRY_MAGIC;
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBlob->xGeom = pGeomCtx->xGeom;
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBlob->pContext = pGeomCtx->pContext;
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBlob->nParam = nArg;
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<nArg; i++){
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free);
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register a new geometry function for use with the r-tree MATCH operator.
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_rtree_geometry_callback(
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zGeom,
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *),
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pContext
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RtreeGeomCallback *pGeomCtx;      /* Context object for new user-function */
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate and populate the context object. */
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pGeomCtx ) return SQLITE_NOMEM;
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeomCtx->xGeom = xGeom;
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pGeomCtx->pContext = pContext;
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create the new user-function. Register a destructor function to delete
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the context object when it is no longer required.  */
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !SQLITE_CORE
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_extension_init(
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErrMsg,
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sqlite3_api_routines *pApi
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SQLITE_EXTENSION_INIT2(pApi)
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3RtreeInit(db);
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3239