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