OLD | NEW |
1 /* | 1 /* |
2 ** 2001 September 15 | 2 ** 2001 September 15 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** This file contains code for implementations of the r-tree and r*-tree | 12 ** This file contains code for implementations of the r-tree and r*-tree |
13 ** algorithms packaged as an SQLite virtual table module. | 13 ** algorithms packaged as an SQLite virtual table module. |
| 14 */ |
| 15 |
| 16 /* |
| 17 ** Database Format of R-Tree Tables |
| 18 ** -------------------------------- |
14 ** | 19 ** |
15 ** $Id: rtree.c,v 1.14 2009/08/06 18:36:47 danielk1977 Exp $ | 20 ** The data structure for a single virtual r-tree table is stored in three |
| 21 ** native SQLite tables declared as follows. In each case, the '%' character |
| 22 ** in the table name is replaced with the user-supplied name of the r-tree |
| 23 ** table. |
| 24 ** |
| 25 ** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB) |
| 26 ** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) |
| 27 ** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) |
| 28 ** |
| 29 ** The data for each node of the r-tree structure is stored in the %_node |
| 30 ** table. For each node that is not the root node of the r-tree, there is |
| 31 ** an entry in the %_parent table associating the node with its parent. |
| 32 ** And for each row of data in the table, there is an entry in the %_rowid |
| 33 ** table that maps from the entries rowid to the id of the node that it |
| 34 ** is stored on. |
| 35 ** |
| 36 ** The root node of an r-tree always exists, even if the r-tree table is |
| 37 ** empty. The nodeno of the root node is always 1. All other nodes in the |
| 38 ** table must be the same size as the root node. The content of each node |
| 39 ** is formatted as follows: |
| 40 ** |
| 41 ** 1. If the node is the root node (node 1), then the first 2 bytes |
| 42 ** of the node contain the tree depth as a big-endian integer. |
| 43 ** For non-root nodes, the first 2 bytes are left unused. |
| 44 ** |
| 45 ** 2. The next 2 bytes contain the number of entries currently |
| 46 ** stored in the node. |
| 47 ** |
| 48 ** 3. The remainder of the node contains the node entries. Each entry |
| 49 ** consists of a single 8-byte integer followed by an even number |
| 50 ** of 4-byte coordinates. For leaf nodes the integer is the rowid |
| 51 ** of a record. For internal nodes it is the node number of a |
| 52 ** child page. |
16 */ | 53 */ |
17 | 54 |
18 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) | 55 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) |
19 | 56 |
20 /* | 57 /* |
21 ** This file contains an implementation of a couple of different variants | 58 ** This file contains an implementation of a couple of different variants |
22 ** of the r-tree algorithm. See the README file for further details. The | 59 ** of the r-tree algorithm. See the README file for further details. The |
23 ** same data-structure is used for all, but the algorithms for insert and | 60 ** same data-structure is used for all, but the algorithms for insert and |
24 ** delete operations vary. The variants used are selected at compile time | 61 ** delete operations vary. The variants used are selected at compile time |
25 ** by defining the following symbols: | 62 ** by defining the following symbols: |
(...skipping 22 matching lines...) Expand all Loading... |
48 #endif | 85 #endif |
49 #if VARIANT_GUTTMAN_LINEAR_SPLIT | 86 #if VARIANT_GUTTMAN_LINEAR_SPLIT |
50 #define PickNext LinearPickNext | 87 #define PickNext LinearPickNext |
51 #define PickSeeds LinearPickSeeds | 88 #define PickSeeds LinearPickSeeds |
52 #define AssignCells splitNodeGuttman | 89 #define AssignCells splitNodeGuttman |
53 #endif | 90 #endif |
54 #if VARIANT_RSTARTREE_SPLIT | 91 #if VARIANT_RSTARTREE_SPLIT |
55 #define AssignCells splitNodeStartree | 92 #define AssignCells splitNodeStartree |
56 #endif | 93 #endif |
57 | 94 |
| 95 #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 96 # define NDEBUG 1 |
| 97 #endif |
58 | 98 |
59 #ifndef SQLITE_CORE | 99 #ifndef SQLITE_CORE |
60 #include "sqlite3ext.h" | 100 #include "sqlite3ext.h" |
61 SQLITE_EXTENSION_INIT1 | 101 SQLITE_EXTENSION_INIT1 |
62 #else | 102 #else |
63 #include "sqlite3.h" | 103 #include "sqlite3.h" |
64 #endif | 104 #endif |
65 | 105 |
66 #include <string.h> | 106 #include <string.h> |
67 #include <assert.h> | 107 #include <assert.h> |
68 | 108 |
69 #ifndef SQLITE_AMALGAMATION | 109 #ifndef SQLITE_AMALGAMATION |
| 110 #include "sqlite3rtree.h" |
70 typedef sqlite3_int64 i64; | 111 typedef sqlite3_int64 i64; |
71 typedef unsigned char u8; | 112 typedef unsigned char u8; |
72 typedef unsigned int u32; | 113 typedef unsigned int u32; |
73 #endif | 114 #endif |
74 | 115 |
| 116 /* The following macro is used to suppress compiler warnings. |
| 117 */ |
| 118 #ifndef UNUSED_PARAMETER |
| 119 # define UNUSED_PARAMETER(x) (void)(x) |
| 120 #endif |
| 121 |
75 typedef struct Rtree Rtree; | 122 typedef struct Rtree Rtree; |
76 typedef struct RtreeCursor RtreeCursor; | 123 typedef struct RtreeCursor RtreeCursor; |
77 typedef struct RtreeNode RtreeNode; | 124 typedef struct RtreeNode RtreeNode; |
78 typedef struct RtreeCell RtreeCell; | 125 typedef struct RtreeCell RtreeCell; |
79 typedef struct RtreeConstraint RtreeConstraint; | 126 typedef struct RtreeConstraint RtreeConstraint; |
| 127 typedef struct RtreeMatchArg RtreeMatchArg; |
| 128 typedef struct RtreeGeomCallback RtreeGeomCallback; |
80 typedef union RtreeCoord RtreeCoord; | 129 typedef union RtreeCoord RtreeCoord; |
81 | 130 |
82 /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ | 131 /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ |
83 #define RTREE_MAX_DIMENSIONS 5 | 132 #define RTREE_MAX_DIMENSIONS 5 |
84 | 133 |
85 /* Size of hash table Rtree.aHash. This hash table is not expected to | 134 /* Size of hash table Rtree.aHash. This hash table is not expected to |
86 ** ever contain very many entries, so a fixed number of buckets is | 135 ** ever contain very many entries, so a fixed number of buckets is |
87 ** used. | 136 ** used. |
88 */ | 137 */ |
89 #define HASHSIZE 128 | 138 #define HASHSIZE 128 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 ** | 188 ** |
140 ** m = M/3 | 189 ** m = M/3 |
141 ** | 190 ** |
142 ** If an R*-tree "Reinsert" operation is required, the same number of | 191 ** If an R*-tree "Reinsert" operation is required, the same number of |
143 ** cells are removed from the overfull node and reinserted into the tree. | 192 ** cells are removed from the overfull node and reinserted into the tree. |
144 */ | 193 */ |
145 #define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3) | 194 #define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3) |
146 #define RTREE_REINSERT(p) RTREE_MINCELLS(p) | 195 #define RTREE_REINSERT(p) RTREE_MINCELLS(p) |
147 #define RTREE_MAXCELLS 51 | 196 #define RTREE_MAXCELLS 51 |
148 | 197 |
| 198 /* |
| 199 ** The smallest possible node-size is (512-64)==448 bytes. And the largest |
| 200 ** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). |
| 201 ** Therefore all non-root nodes must contain at least 3 entries. Since |
| 202 ** 2^40 is greater than 2^64, an r-tree structure always has a depth of |
| 203 ** 40 or less. |
| 204 */ |
| 205 #define RTREE_MAX_DEPTH 40 |
| 206 |
149 /* | 207 /* |
150 ** An rtree cursor object. | 208 ** An rtree cursor object. |
151 */ | 209 */ |
152 struct RtreeCursor { | 210 struct RtreeCursor { |
153 sqlite3_vtab_cursor base; | 211 sqlite3_vtab_cursor base; |
154 RtreeNode *pNode; /* Node cursor is currently pointing at */ | 212 RtreeNode *pNode; /* Node cursor is currently pointing at */ |
155 int iCell; /* Index of current cell in pNode */ | 213 int iCell; /* Index of current cell in pNode */ |
156 int iStrategy; /* Copy of idxNum search parameter */ | 214 int iStrategy; /* Copy of idxNum search parameter */ |
157 int nConstraint; /* Number of entries in aConstraint */ | 215 int nConstraint; /* Number of entries in aConstraint */ |
158 RtreeConstraint *aConstraint; /* Search constraints. */ | 216 RtreeConstraint *aConstraint; /* Search constraints. */ |
(...skipping 12 matching lines...) Expand all Loading... |
171 #define DCOORD(coord) ( \ | 229 #define DCOORD(coord) ( \ |
172 (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ | 230 (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ |
173 ((double)coord.f) : \ | 231 ((double)coord.f) : \ |
174 ((double)coord.i) \ | 232 ((double)coord.i) \ |
175 ) | 233 ) |
176 | 234 |
177 /* | 235 /* |
178 ** A search constraint. | 236 ** A search constraint. |
179 */ | 237 */ |
180 struct RtreeConstraint { | 238 struct RtreeConstraint { |
181 int iCoord; /* Index of constrained coordinate */ | 239 int iCoord; /* Index of constrained coordinate */ |
182 int op; /* Constraining operation */ | 240 int op; /* Constraining operation */ |
183 double rValue; /* Constraint value. */ | 241 double rValue; /* Constraint value. */ |
| 242 int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); |
| 243 sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ |
184 }; | 244 }; |
185 | 245 |
186 /* Possible values for RtreeConstraint.op */ | 246 /* Possible values for RtreeConstraint.op */ |
187 #define RTREE_EQ 0x41 | 247 #define RTREE_EQ 0x41 |
188 #define RTREE_LE 0x42 | 248 #define RTREE_LE 0x42 |
189 #define RTREE_LT 0x43 | 249 #define RTREE_LT 0x43 |
190 #define RTREE_GE 0x44 | 250 #define RTREE_GE 0x44 |
191 #define RTREE_GT 0x45 | 251 #define RTREE_GT 0x45 |
| 252 #define RTREE_MATCH 0x46 |
192 | 253 |
193 /* | 254 /* |
194 ** An rtree structure node. | 255 ** An rtree structure node. |
195 ** | |
196 ** Data format (RtreeNode.zData): | |
197 ** | |
198 ** 1. If the node is the root node (node 1), then the first 2 bytes | |
199 ** of the node contain the tree depth as a big-endian integer. | |
200 ** For non-root nodes, the first 2 bytes are left unused. | |
201 ** | |
202 ** 2. The next 2 bytes contain the number of entries currently | |
203 ** stored in the node. | |
204 ** | |
205 ** 3. The remainder of the node contains the node entries. Each entry | |
206 ** consists of a single 8-byte integer followed by an even number | |
207 ** of 4-byte coordinates. For leaf nodes the integer is the rowid | |
208 ** of a record. For internal nodes it is the node number of a | |
209 ** child page. | |
210 */ | 256 */ |
211 struct RtreeNode { | 257 struct RtreeNode { |
212 RtreeNode *pParent; /* Parent node */ | 258 RtreeNode *pParent; /* Parent node */ |
213 i64 iNode; | 259 i64 iNode; |
214 int nRef; | 260 int nRef; |
215 int isDirty; | 261 int isDirty; |
216 u8 *zData; | 262 u8 *zData; |
217 RtreeNode *pNext; /* Next node in this hash chain */ | 263 RtreeNode *pNext; /* Next node in this hash chain */ |
218 }; | 264 }; |
219 #define NCELL(pNode) readInt16(&(pNode)->zData[2]) | 265 #define NCELL(pNode) readInt16(&(pNode)->zData[2]) |
220 | 266 |
221 /* | 267 /* |
222 ** Structure to store a deserialized rtree record. | 268 ** Structure to store a deserialized rtree record. |
223 */ | 269 */ |
224 struct RtreeCell { | 270 struct RtreeCell { |
225 i64 iRowid; | 271 i64 iRowid; |
226 RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; | 272 RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; |
227 }; | 273 }; |
228 | 274 |
| 275 |
| 276 /* |
| 277 ** Value for the first field of every RtreeMatchArg object. The MATCH |
| 278 ** operator tests that the first field of a blob operand matches this |
| 279 ** value to avoid operating on invalid blobs (which could cause a segfault). |
| 280 */ |
| 281 #define RTREE_GEOMETRY_MAGIC 0x891245AB |
| 282 |
| 283 /* |
| 284 ** An instance of this structure must be supplied as a blob argument to |
| 285 ** the right-hand-side of an SQL MATCH operator used to constrain an |
| 286 ** r-tree query. |
| 287 */ |
| 288 struct RtreeMatchArg { |
| 289 u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ |
| 290 int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); |
| 291 void *pContext; |
| 292 int nParam; |
| 293 double aParam[1]; |
| 294 }; |
| 295 |
| 296 /* |
| 297 ** When a geometry callback is created (see sqlite3_rtree_geometry_callback), |
| 298 ** a single instance of the following structure is allocated. It is used |
| 299 ** as the context for the user-function created by by s_r_g_c(). The object |
| 300 ** is eventually deleted by the destructor mechanism provided by |
| 301 ** sqlite3_create_function_v2() (which is called by s_r_g_c() to create |
| 302 ** the geometry callback function). |
| 303 */ |
| 304 struct RtreeGeomCallback { |
| 305 int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); |
| 306 void *pContext; |
| 307 }; |
| 308 |
229 #ifndef MAX | 309 #ifndef MAX |
230 # define MAX(x,y) ((x) < (y) ? (y) : (x)) | 310 # define MAX(x,y) ((x) < (y) ? (y) : (x)) |
231 #endif | 311 #endif |
232 #ifndef MIN | 312 #ifndef MIN |
233 # define MIN(x,y) ((x) > (y) ? (y) : (x)) | 313 # define MIN(x,y) ((x) > (y) ? (y) : (x)) |
234 #endif | 314 #endif |
235 | 315 |
236 /* | 316 /* |
237 ** Functions to deserialize a 16 bit integer, 32 bit real number and | 317 ** Functions to deserialize a 16 bit integer, 32 bit real number and |
238 ** 64 bit integer. The deserialized value is returned. | 318 ** 64 bit integer. The deserialized value is returned. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 static void nodeReference(RtreeNode *p){ | 381 static void nodeReference(RtreeNode *p){ |
302 if( p ){ | 382 if( p ){ |
303 p->nRef++; | 383 p->nRef++; |
304 } | 384 } |
305 } | 385 } |
306 | 386 |
307 /* | 387 /* |
308 ** Clear the content of node p (set all bytes to 0x00). | 388 ** Clear the content of node p (set all bytes to 0x00). |
309 */ | 389 */ |
310 static void nodeZero(Rtree *pRtree, RtreeNode *p){ | 390 static void nodeZero(Rtree *pRtree, RtreeNode *p){ |
311 if( p ){ | 391 memset(&p->zData[2], 0, pRtree->iNodeSize-2); |
312 memset(&p->zData[2], 0, pRtree->iNodeSize-2); | 392 p->isDirty = 1; |
313 p->isDirty = 1; | |
314 } | |
315 } | 393 } |
316 | 394 |
317 /* | 395 /* |
318 ** Given a node number iNode, return the corresponding key to use | 396 ** Given a node number iNode, return the corresponding key to use |
319 ** in the Rtree.aHash table. | 397 ** in the Rtree.aHash table. |
320 */ | 398 */ |
321 static int nodeHash(i64 iNode){ | 399 static int nodeHash(i64 iNode){ |
322 return ( | 400 return ( |
323 (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^ | 401 (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^ |
324 (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0) | 402 (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0) |
325 ) % HASHSIZE; | 403 ) % HASHSIZE; |
326 } | 404 } |
327 | 405 |
328 /* | 406 /* |
329 ** Search the node hash table for node iNode. If found, return a pointer | 407 ** Search the node hash table for node iNode. If found, return a pointer |
330 ** to it. Otherwise, return 0. | 408 ** to it. Otherwise, return 0. |
331 */ | 409 */ |
332 static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){ | 410 static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){ |
333 RtreeNode *p; | 411 RtreeNode *p; |
334 assert( iNode!=0 ); | |
335 for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext); | 412 for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext); |
336 return p; | 413 return p; |
337 } | 414 } |
338 | 415 |
339 /* | 416 /* |
340 ** Add node pNode to the node hash table. | 417 ** Add node pNode to the node hash table. |
341 */ | 418 */ |
342 static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){ | 419 static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){ |
343 if( pNode ){ | 420 int iHash; |
344 int iHash; | 421 assert( pNode->pNext==0 ); |
345 assert( pNode->pNext==0 ); | 422 iHash = nodeHash(pNode->iNode); |
346 iHash = nodeHash(pNode->iNode); | 423 pNode->pNext = pRtree->aHash[iHash]; |
347 pNode->pNext = pRtree->aHash[iHash]; | 424 pRtree->aHash[iHash] = pNode; |
348 pRtree->aHash[iHash] = pNode; | |
349 } | |
350 } | 425 } |
351 | 426 |
352 /* | 427 /* |
353 ** Remove node pNode from the node hash table. | 428 ** Remove node pNode from the node hash table. |
354 */ | 429 */ |
355 static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){ | 430 static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){ |
356 RtreeNode **pp; | 431 RtreeNode **pp; |
357 if( pNode->iNode!=0 ){ | 432 if( pNode->iNode!=0 ){ |
358 pp = &pRtree->aHash[nodeHash(pNode->iNode)]; | 433 pp = &pRtree->aHash[nodeHash(pNode->iNode)]; |
359 for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); } | 434 for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); } |
360 *pp = pNode->pNext; | 435 *pp = pNode->pNext; |
361 pNode->pNext = 0; | 436 pNode->pNext = 0; |
362 } | 437 } |
363 } | 438 } |
364 | 439 |
365 /* | 440 /* |
366 ** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0), | 441 ** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0), |
367 ** indicating that node has not yet been assigned a node number. It is | 442 ** indicating that node has not yet been assigned a node number. It is |
368 ** assigned a node number when nodeWrite() is called to write the | 443 ** assigned a node number when nodeWrite() is called to write the |
369 ** node contents out to the database. | 444 ** node contents out to the database. |
370 */ | 445 */ |
371 static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent, int zero){ | 446 static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ |
372 RtreeNode *pNode; | 447 RtreeNode *pNode; |
373 pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); | 448 pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); |
374 if( pNode ){ | 449 if( pNode ){ |
375 memset(pNode, 0, sizeof(RtreeNode) + (zero?pRtree->iNodeSize:0)); | 450 memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); |
376 pNode->zData = (u8 *)&pNode[1]; | 451 pNode->zData = (u8 *)&pNode[1]; |
377 pNode->nRef = 1; | 452 pNode->nRef = 1; |
378 pNode->pParent = pParent; | 453 pNode->pParent = pParent; |
379 pNode->isDirty = 1; | 454 pNode->isDirty = 1; |
380 nodeReference(pParent); | 455 nodeReference(pParent); |
381 } | 456 } |
382 return pNode; | 457 return pNode; |
383 } | 458 } |
384 | 459 |
385 /* | 460 /* |
386 ** Obtain a reference to an r-tree node. | 461 ** Obtain a reference to an r-tree node. |
387 */ | 462 */ |
388 static int | 463 static int |
389 nodeAcquire( | 464 nodeAcquire( |
390 Rtree *pRtree, /* R-tree structure */ | 465 Rtree *pRtree, /* R-tree structure */ |
391 i64 iNode, /* Node number to load */ | 466 i64 iNode, /* Node number to load */ |
392 RtreeNode *pParent, /* Either the parent node or NULL */ | 467 RtreeNode *pParent, /* Either the parent node or NULL */ |
393 RtreeNode **ppNode /* OUT: Acquired node */ | 468 RtreeNode **ppNode /* OUT: Acquired node */ |
394 ){ | 469 ){ |
395 int rc; | 470 int rc; |
| 471 int rc2 = SQLITE_OK; |
396 RtreeNode *pNode; | 472 RtreeNode *pNode; |
397 | 473 |
398 /* Check if the requested node is already in the hash table. If so, | 474 /* Check if the requested node is already in the hash table. If so, |
399 ** increase its reference count and return it. | 475 ** increase its reference count and return it. |
400 */ | 476 */ |
401 if( (pNode = nodeHashLookup(pRtree, iNode)) ){ | 477 if( (pNode = nodeHashLookup(pRtree, iNode)) ){ |
402 assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); | 478 assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); |
403 if( pParent && !pNode->pParent ){ | 479 if( pParent && !pNode->pParent ){ |
404 nodeReference(pParent); | 480 nodeReference(pParent); |
405 pNode->pParent = pParent; | 481 pNode->pParent = pParent; |
406 } | 482 } |
407 pNode->nRef++; | 483 pNode->nRef++; |
408 *ppNode = pNode; | 484 *ppNode = pNode; |
409 return SQLITE_OK; | 485 return SQLITE_OK; |
410 } | 486 } |
411 | 487 |
412 pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); | |
413 if( !pNode ){ | |
414 *ppNode = 0; | |
415 return SQLITE_NOMEM; | |
416 } | |
417 pNode->pParent = pParent; | |
418 pNode->zData = (u8 *)&pNode[1]; | |
419 pNode->nRef = 1; | |
420 pNode->iNode = iNode; | |
421 pNode->isDirty = 0; | |
422 pNode->pNext = 0; | |
423 | |
424 sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); | 488 sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); |
425 rc = sqlite3_step(pRtree->pReadNode); | 489 rc = sqlite3_step(pRtree->pReadNode); |
426 if( rc==SQLITE_ROW ){ | 490 if( rc==SQLITE_ROW ){ |
427 const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); | 491 const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); |
428 memcpy(pNode->zData, zBlob, pRtree->iNodeSize); | 492 if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){ |
429 nodeReference(pParent); | 493 pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize); |
| 494 if( !pNode ){ |
| 495 rc2 = SQLITE_NOMEM; |
| 496 }else{ |
| 497 pNode->pParent = pParent; |
| 498 pNode->zData = (u8 *)&pNode[1]; |
| 499 pNode->nRef = 1; |
| 500 pNode->iNode = iNode; |
| 501 pNode->isDirty = 0; |
| 502 pNode->pNext = 0; |
| 503 memcpy(pNode->zData, zBlob, pRtree->iNodeSize); |
| 504 nodeReference(pParent); |
| 505 } |
| 506 } |
| 507 } |
| 508 rc = sqlite3_reset(pRtree->pReadNode); |
| 509 if( rc==SQLITE_OK ) rc = rc2; |
| 510 |
| 511 /* If the root node was just loaded, set pRtree->iDepth to the height |
| 512 ** of the r-tree structure. A height of zero means all data is stored on |
| 513 ** the root node. A height of one means the children of the root node |
| 514 ** are the leaves, and so on. If the depth as specified on the root node |
| 515 ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt. |
| 516 */ |
| 517 if( pNode && iNode==1 ){ |
| 518 pRtree->iDepth = readInt16(pNode->zData); |
| 519 if( pRtree->iDepth>RTREE_MAX_DEPTH ){ |
| 520 rc = SQLITE_CORRUPT; |
| 521 } |
| 522 } |
| 523 |
| 524 /* If no error has occurred so far, check if the "number of entries" |
| 525 ** field on the node is too large. If so, set the return code to |
| 526 ** SQLITE_CORRUPT. |
| 527 */ |
| 528 if( pNode && rc==SQLITE_OK ){ |
| 529 if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){ |
| 530 rc = SQLITE_CORRUPT; |
| 531 } |
| 532 } |
| 533 |
| 534 if( rc==SQLITE_OK ){ |
| 535 if( pNode!=0 ){ |
| 536 nodeHashInsert(pRtree, pNode); |
| 537 }else{ |
| 538 rc = SQLITE_CORRUPT; |
| 539 } |
| 540 *ppNode = pNode; |
430 }else{ | 541 }else{ |
431 sqlite3_free(pNode); | 542 sqlite3_free(pNode); |
432 pNode = 0; | 543 *ppNode = 0; |
433 } | 544 } |
434 | 545 |
435 *ppNode = pNode; | |
436 rc = sqlite3_reset(pRtree->pReadNode); | |
437 | |
438 if( rc==SQLITE_OK && iNode==1 ){ | |
439 pRtree->iDepth = readInt16(pNode->zData); | |
440 } | |
441 | |
442 assert( (rc==SQLITE_OK && pNode) || (pNode==0 && rc!=SQLITE_OK) ); | |
443 nodeHashInsert(pRtree, pNode); | |
444 | |
445 return rc; | 546 return rc; |
446 } | 547 } |
447 | 548 |
448 /* | 549 /* |
449 ** Overwrite cell iCell of node pNode with the contents of pCell. | 550 ** Overwrite cell iCell of node pNode with the contents of pCell. |
450 */ | 551 */ |
451 static void nodeOverwriteCell( | 552 static void nodeOverwriteCell( |
452 Rtree *pRtree, | 553 Rtree *pRtree, |
453 RtreeNode *pNode, | 554 RtreeNode *pNode, |
454 RtreeCell *pCell, | 555 RtreeCell *pCell, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 Rtree *pRtree, | 587 Rtree *pRtree, |
487 RtreeNode *pNode, | 588 RtreeNode *pNode, |
488 RtreeCell *pCell | 589 RtreeCell *pCell |
489 ){ | 590 ){ |
490 int nCell; /* Current number of cells in pNode */ | 591 int nCell; /* Current number of cells in pNode */ |
491 int nMaxCell; /* Maximum number of cells for pNode */ | 592 int nMaxCell; /* Maximum number of cells for pNode */ |
492 | 593 |
493 nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell; | 594 nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell; |
494 nCell = NCELL(pNode); | 595 nCell = NCELL(pNode); |
495 | 596 |
496 assert(nCell<=nMaxCell); | 597 assert( nCell<=nMaxCell ); |
497 | |
498 if( nCell<nMaxCell ){ | 598 if( nCell<nMaxCell ){ |
499 nodeOverwriteCell(pRtree, pNode, pCell, nCell); | 599 nodeOverwriteCell(pRtree, pNode, pCell, nCell); |
500 writeInt16(&pNode->zData[2], nCell+1); | 600 writeInt16(&pNode->zData[2], nCell+1); |
501 pNode->isDirty = 1; | 601 pNode->isDirty = 1; |
502 } | 602 } |
503 | 603 |
504 return (nCell==nMaxCell); | 604 return (nCell==nMaxCell); |
505 } | 605 } |
506 | 606 |
507 /* | 607 /* |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 if( pCsr ){ | 807 if( pCsr ){ |
708 memset(pCsr, 0, sizeof(RtreeCursor)); | 808 memset(pCsr, 0, sizeof(RtreeCursor)); |
709 pCsr->base.pVtab = pVTab; | 809 pCsr->base.pVtab = pVTab; |
710 rc = SQLITE_OK; | 810 rc = SQLITE_OK; |
711 } | 811 } |
712 *ppCursor = (sqlite3_vtab_cursor *)pCsr; | 812 *ppCursor = (sqlite3_vtab_cursor *)pCsr; |
713 | 813 |
714 return rc; | 814 return rc; |
715 } | 815 } |
716 | 816 |
| 817 |
| 818 /* |
| 819 ** Free the RtreeCursor.aConstraint[] array and its contents. |
| 820 */ |
| 821 static void freeCursorConstraints(RtreeCursor *pCsr){ |
| 822 if( pCsr->aConstraint ){ |
| 823 int i; /* Used to iterate through constraint array */ |
| 824 for(i=0; i<pCsr->nConstraint; i++){ |
| 825 sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom; |
| 826 if( pGeom ){ |
| 827 if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser); |
| 828 sqlite3_free(pGeom); |
| 829 } |
| 830 } |
| 831 sqlite3_free(pCsr->aConstraint); |
| 832 pCsr->aConstraint = 0; |
| 833 } |
| 834 } |
| 835 |
717 /* | 836 /* |
718 ** Rtree virtual table module xClose method. | 837 ** Rtree virtual table module xClose method. |
719 */ | 838 */ |
720 static int rtreeClose(sqlite3_vtab_cursor *cur){ | 839 static int rtreeClose(sqlite3_vtab_cursor *cur){ |
721 Rtree *pRtree = (Rtree *)(cur->pVtab); | 840 Rtree *pRtree = (Rtree *)(cur->pVtab); |
722 int rc; | 841 int rc; |
723 RtreeCursor *pCsr = (RtreeCursor *)cur; | 842 RtreeCursor *pCsr = (RtreeCursor *)cur; |
724 sqlite3_free(pCsr->aConstraint); | 843 freeCursorConstraints(pCsr); |
725 rc = nodeRelease(pRtree, pCsr->pNode); | 844 rc = nodeRelease(pRtree, pCsr->pNode); |
726 sqlite3_free(pCsr); | 845 sqlite3_free(pCsr); |
727 return rc; | 846 return rc; |
728 } | 847 } |
729 | 848 |
730 /* | 849 /* |
731 ** Rtree virtual table module xEof method. | 850 ** Rtree virtual table module xEof method. |
732 ** | 851 ** |
733 ** Return non-zero if the cursor does not currently point to a valid | 852 ** Return non-zero if the cursor does not currently point to a valid |
734 ** record (i.e if the scan has finished), or zero otherwise. | 853 ** record (i.e if the scan has finished), or zero otherwise. |
735 */ | 854 */ |
736 static int rtreeEof(sqlite3_vtab_cursor *cur){ | 855 static int rtreeEof(sqlite3_vtab_cursor *cur){ |
737 RtreeCursor *pCsr = (RtreeCursor *)cur; | 856 RtreeCursor *pCsr = (RtreeCursor *)cur; |
738 return (pCsr->pNode==0); | 857 return (pCsr->pNode==0); |
739 } | 858 } |
740 | 859 |
| 860 /* |
| 861 ** The r-tree constraint passed as the second argument to this function is |
| 862 ** guaranteed to be a MATCH constraint. |
| 863 */ |
| 864 static int testRtreeGeom( |
| 865 Rtree *pRtree, /* R-Tree object */ |
| 866 RtreeConstraint *pConstraint, /* MATCH constraint to test */ |
| 867 RtreeCell *pCell, /* Cell to test */ |
| 868 int *pbRes /* OUT: Test result */ |
| 869 ){ |
| 870 int i; |
| 871 double aCoord[RTREE_MAX_DIMENSIONS*2]; |
| 872 int nCoord = pRtree->nDim*2; |
| 873 |
| 874 assert( pConstraint->op==RTREE_MATCH ); |
| 875 assert( pConstraint->pGeom ); |
| 876 |
| 877 for(i=0; i<nCoord; i++){ |
| 878 aCoord[i] = DCOORD(pCell->aCoord[i]); |
| 879 } |
| 880 return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes); |
| 881 } |
| 882 |
741 /* | 883 /* |
742 ** Cursor pCursor currently points to a cell in a non-leaf page. | 884 ** Cursor pCursor currently points to a cell in a non-leaf page. |
743 ** Return true if the sub-tree headed by the cell is filtered | 885 ** Set *pbEof to true if the sub-tree headed by the cell is filtered |
744 ** (excluded) by the constraints in the pCursor->aConstraint[] | 886 ** (excluded) by the constraints in the pCursor->aConstraint[] |
745 ** array, or false otherwise. | 887 ** array, or false otherwise. |
| 888 ** |
| 889 ** Return SQLITE_OK if successful or an SQLite error code if an error |
| 890 ** occurs within a geometry callback. |
746 */ | 891 */ |
747 static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){ | 892 static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ |
748 RtreeCell cell; | 893 RtreeCell cell; |
749 int ii; | 894 int ii; |
750 int bRes = 0; | 895 int bRes = 0; |
| 896 int rc = SQLITE_OK; |
751 | 897 |
752 nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); | 898 nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); |
753 for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ | 899 for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ |
754 RtreeConstraint *p = &pCursor->aConstraint[ii]; | 900 RtreeConstraint *p = &pCursor->aConstraint[ii]; |
755 double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); | 901 double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); |
756 double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); | 902 double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); |
757 | 903 |
758 assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE | 904 assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
759 || p->op==RTREE_GT || p->op==RTREE_EQ | 905 || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH |
760 ); | 906 ); |
761 | 907 |
762 switch( p->op ){ | 908 switch( p->op ){ |
763 case RTREE_LE: case RTREE_LT: bRes = p->rValue<cell_min; break; | 909 case RTREE_LE: case RTREE_LT: |
764 case RTREE_GE: case RTREE_GT: bRes = p->rValue>cell_max; break; | 910 bRes = p->rValue<cell_min; |
765 case RTREE_EQ: | 911 break; |
| 912 |
| 913 case RTREE_GE: case RTREE_GT: |
| 914 bRes = p->rValue>cell_max; |
| 915 break; |
| 916 |
| 917 case RTREE_EQ: |
766 bRes = (p->rValue>cell_max || p->rValue<cell_min); | 918 bRes = (p->rValue>cell_max || p->rValue<cell_min); |
767 break; | 919 break; |
| 920 |
| 921 default: { |
| 922 assert( p->op==RTREE_MATCH ); |
| 923 rc = testRtreeGeom(pRtree, p, &cell, &bRes); |
| 924 bRes = !bRes; |
| 925 break; |
| 926 } |
768 } | 927 } |
769 } | 928 } |
770 | 929 |
771 return bRes; | 930 *pbEof = bRes; |
| 931 return rc; |
772 } | 932 } |
773 | 933 |
774 /* | 934 /* |
775 ** Return true if the cell that cursor pCursor currently points to | 935 ** Test if the cell that cursor pCursor currently points to |
776 ** would be filtered (excluded) by the constraints in the | 936 ** would be filtered (excluded) by the constraints in the |
777 ** pCursor->aConstraint[] array, or false otherwise. | 937 ** pCursor->aConstraint[] array. If so, set *pbEof to true before |
| 938 ** returning. If the cell is not filtered (excluded) by the constraints, |
| 939 ** set pbEof to zero. |
| 940 ** |
| 941 ** Return SQLITE_OK if successful or an SQLite error code if an error |
| 942 ** occurs within a geometry callback. |
778 ** | 943 ** |
779 ** This function assumes that the cell is part of a leaf node. | 944 ** This function assumes that the cell is part of a leaf node. |
780 */ | 945 */ |
781 static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor){ | 946 static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ |
782 RtreeCell cell; | 947 RtreeCell cell; |
783 int ii; | 948 int ii; |
| 949 *pbEof = 0; |
784 | 950 |
785 nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); | 951 nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); |
786 for(ii=0; ii<pCursor->nConstraint; ii++){ | 952 for(ii=0; ii<pCursor->nConstraint; ii++){ |
787 RtreeConstraint *p = &pCursor->aConstraint[ii]; | 953 RtreeConstraint *p = &pCursor->aConstraint[ii]; |
788 double coord = DCOORD(cell.aCoord[p->iCoord]); | 954 double coord = DCOORD(cell.aCoord[p->iCoord]); |
789 int res; | 955 int res; |
790 assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE | 956 assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
791 || p->op==RTREE_GT || p->op==RTREE_EQ | 957 || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH |
792 ); | 958 ); |
793 switch( p->op ){ | 959 switch( p->op ){ |
794 case RTREE_LE: res = (coord<=p->rValue); break; | 960 case RTREE_LE: res = (coord<=p->rValue); break; |
795 case RTREE_LT: res = (coord<p->rValue); break; | 961 case RTREE_LT: res = (coord<p->rValue); break; |
796 case RTREE_GE: res = (coord>=p->rValue); break; | 962 case RTREE_GE: res = (coord>=p->rValue); break; |
797 case RTREE_GT: res = (coord>p->rValue); break; | 963 case RTREE_GT: res = (coord>p->rValue); break; |
798 case RTREE_EQ: res = (coord==p->rValue); break; | 964 case RTREE_EQ: res = (coord==p->rValue); break; |
| 965 default: { |
| 966 int rc; |
| 967 assert( p->op==RTREE_MATCH ); |
| 968 rc = testRtreeGeom(pRtree, p, &cell, &res); |
| 969 if( rc!=SQLITE_OK ){ |
| 970 return rc; |
| 971 } |
| 972 break; |
| 973 } |
799 } | 974 } |
800 | 975 |
801 if( !res ) return 1; | 976 if( !res ){ |
| 977 *pbEof = 1; |
| 978 return SQLITE_OK; |
| 979 } |
802 } | 980 } |
803 | 981 |
804 return 0; | 982 return SQLITE_OK; |
805 } | 983 } |
806 | 984 |
807 /* | 985 /* |
808 ** Cursor pCursor currently points at a node that heads a sub-tree of | 986 ** Cursor pCursor currently points at a node that heads a sub-tree of |
809 ** height iHeight (if iHeight==0, then the node is a leaf). Descend | 987 ** height iHeight (if iHeight==0, then the node is a leaf). Descend |
810 ** to point to the left-most cell of the sub-tree that matches the | 988 ** to point to the left-most cell of the sub-tree that matches the |
811 ** configured constraints. | 989 ** configured constraints. |
812 */ | 990 */ |
813 static int descendToCell( | 991 static int descendToCell( |
814 Rtree *pRtree, | 992 Rtree *pRtree, |
815 RtreeCursor *pCursor, | 993 RtreeCursor *pCursor, |
816 int iHeight, | 994 int iHeight, |
817 int *pEof /* OUT: Set to true if cannot descend */ | 995 int *pEof /* OUT: Set to true if cannot descend */ |
818 ){ | 996 ){ |
819 int isEof; | 997 int isEof; |
820 int rc; | 998 int rc; |
821 int ii; | 999 int ii; |
822 RtreeNode *pChild; | 1000 RtreeNode *pChild; |
823 sqlite3_int64 iRowid; | 1001 sqlite3_int64 iRowid; |
824 | 1002 |
825 RtreeNode *pSavedNode = pCursor->pNode; | 1003 RtreeNode *pSavedNode = pCursor->pNode; |
826 int iSavedCell = pCursor->iCell; | 1004 int iSavedCell = pCursor->iCell; |
827 | 1005 |
828 assert( iHeight>=0 ); | 1006 assert( iHeight>=0 ); |
829 | 1007 |
830 if( iHeight==0 ){ | 1008 if( iHeight==0 ){ |
831 isEof = testRtreeEntry(pRtree, pCursor); | 1009 rc = testRtreeEntry(pRtree, pCursor, &isEof); |
832 }else{ | 1010 }else{ |
833 isEof = testRtreeCell(pRtree, pCursor); | 1011 rc = testRtreeCell(pRtree, pCursor, &isEof); |
834 } | 1012 } |
835 if( isEof || iHeight==0 ){ | 1013 if( rc!=SQLITE_OK || isEof || iHeight==0 ){ |
836 *pEof = isEof; | 1014 goto descend_to_cell_out; |
837 return SQLITE_OK; | |
838 } | 1015 } |
839 | 1016 |
840 iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell); | 1017 iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell); |
841 rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild); | 1018 rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild); |
842 if( rc!=SQLITE_OK ){ | 1019 if( rc!=SQLITE_OK ){ |
843 return rc; | 1020 goto descend_to_cell_out; |
844 } | 1021 } |
845 | 1022 |
846 nodeRelease(pRtree, pCursor->pNode); | 1023 nodeRelease(pRtree, pCursor->pNode); |
847 pCursor->pNode = pChild; | 1024 pCursor->pNode = pChild; |
848 isEof = 1; | 1025 isEof = 1; |
849 for(ii=0; isEof && ii<NCELL(pChild); ii++){ | 1026 for(ii=0; isEof && ii<NCELL(pChild); ii++){ |
850 pCursor->iCell = ii; | 1027 pCursor->iCell = ii; |
851 rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof); | 1028 rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof); |
852 if( rc!=SQLITE_OK ){ | 1029 if( rc!=SQLITE_OK ){ |
853 return rc; | 1030 goto descend_to_cell_out; |
854 } | 1031 } |
855 } | 1032 } |
856 | 1033 |
857 if( isEof ){ | 1034 if( isEof ){ |
858 assert( pCursor->pNode==pChild ); | 1035 assert( pCursor->pNode==pChild ); |
859 nodeReference(pSavedNode); | 1036 nodeReference(pSavedNode); |
860 nodeRelease(pRtree, pChild); | 1037 nodeRelease(pRtree, pChild); |
861 pCursor->pNode = pSavedNode; | 1038 pCursor->pNode = pSavedNode; |
862 pCursor->iCell = iSavedCell; | 1039 pCursor->iCell = iSavedCell; |
863 } | 1040 } |
864 | 1041 |
| 1042 descend_to_cell_out: |
865 *pEof = isEof; | 1043 *pEof = isEof; |
866 return SQLITE_OK; | 1044 return rc; |
867 } | 1045 } |
868 | 1046 |
869 /* | 1047 /* |
870 ** One of the cells in node pNode is guaranteed to have a 64-bit | 1048 ** One of the cells in node pNode is guaranteed to have a 64-bit |
871 ** integer value equal to iRowid. Return the index of this cell. | 1049 ** integer value equal to iRowid. Return the index of this cell. |
872 */ | 1050 */ |
873 static int nodeRowidIndex(Rtree *pRtree, RtreeNode *pNode, i64 iRowid){ | 1051 static int nodeRowidIndex( |
| 1052 Rtree *pRtree, |
| 1053 RtreeNode *pNode, |
| 1054 i64 iRowid, |
| 1055 int *piIndex |
| 1056 ){ |
874 int ii; | 1057 int ii; |
875 for(ii=0; nodeGetRowid(pRtree, pNode, ii)!=iRowid; ii++){ | 1058 int nCell = NCELL(pNode); |
876 assert( ii<(NCELL(pNode)-1) ); | 1059 for(ii=0; ii<nCell; ii++){ |
| 1060 if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){ |
| 1061 *piIndex = ii; |
| 1062 return SQLITE_OK; |
| 1063 } |
877 } | 1064 } |
878 return ii; | 1065 return SQLITE_CORRUPT; |
879 } | 1066 } |
880 | 1067 |
881 /* | 1068 /* |
882 ** Return the index of the cell containing a pointer to node pNode | 1069 ** Return the index of the cell containing a pointer to node pNode |
883 ** in its parent. If pNode is the root node, return -1. | 1070 ** in its parent. If pNode is the root node, return -1. |
884 */ | 1071 */ |
885 static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode){ | 1072 static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){ |
886 RtreeNode *pParent = pNode->pParent; | 1073 RtreeNode *pParent = pNode->pParent; |
887 if( pParent ){ | 1074 if( pParent ){ |
888 return nodeRowidIndex(pRtree, pParent, pNode->iNode); | 1075 return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex); |
889 } | 1076 } |
890 return -1; | 1077 *piIndex = -1; |
| 1078 return SQLITE_OK; |
891 } | 1079 } |
892 | 1080 |
893 /* | 1081 /* |
894 ** Rtree virtual table module xNext method. | 1082 ** Rtree virtual table module xNext method. |
895 */ | 1083 */ |
896 static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ | 1084 static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ |
897 Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab); | 1085 Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab); |
898 RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; | 1086 RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; |
899 int rc = SQLITE_OK; | 1087 int rc = SQLITE_OK; |
900 | 1088 |
| 1089 /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is |
| 1090 ** already at EOF. It is against the rules to call the xNext() method of |
| 1091 ** a cursor that has already reached EOF. |
| 1092 */ |
| 1093 assert( pCsr->pNode ); |
| 1094 |
901 if( pCsr->iStrategy==1 ){ | 1095 if( pCsr->iStrategy==1 ){ |
902 /* This "scan" is a direct lookup by rowid. There is no next entry. */ | 1096 /* This "scan" is a direct lookup by rowid. There is no next entry. */ |
903 nodeRelease(pRtree, pCsr->pNode); | 1097 nodeRelease(pRtree, pCsr->pNode); |
904 pCsr->pNode = 0; | 1098 pCsr->pNode = 0; |
905 } | 1099 }else{ |
906 | |
907 else if( pCsr->pNode ){ | |
908 /* Move to the next entry that matches the configured constraints. */ | 1100 /* Move to the next entry that matches the configured constraints. */ |
909 int iHeight = 0; | 1101 int iHeight = 0; |
910 while( pCsr->pNode ){ | 1102 while( pCsr->pNode ){ |
911 RtreeNode *pNode = pCsr->pNode; | 1103 RtreeNode *pNode = pCsr->pNode; |
912 int nCell = NCELL(pNode); | 1104 int nCell = NCELL(pNode); |
913 for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){ | 1105 for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){ |
914 int isEof; | 1106 int isEof; |
915 rc = descendToCell(pRtree, pCsr, iHeight, &isEof); | 1107 rc = descendToCell(pRtree, pCsr, iHeight, &isEof); |
916 if( rc!=SQLITE_OK || !isEof ){ | 1108 if( rc!=SQLITE_OK || !isEof ){ |
917 return rc; | 1109 return rc; |
918 } | 1110 } |
919 } | 1111 } |
920 pCsr->pNode = pNode->pParent; | 1112 pCsr->pNode = pNode->pParent; |
921 pCsr->iCell = nodeParentIndex(pRtree, pNode); | 1113 rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell); |
| 1114 if( rc!=SQLITE_OK ){ |
| 1115 return rc; |
| 1116 } |
922 nodeReference(pCsr->pNode); | 1117 nodeReference(pCsr->pNode); |
923 nodeRelease(pRtree, pNode); | 1118 nodeRelease(pRtree, pNode); |
924 iHeight++; | 1119 iHeight++; |
925 } | 1120 } |
926 } | 1121 } |
927 | 1122 |
928 return rc; | 1123 return rc; |
929 } | 1124 } |
930 | 1125 |
931 /* | 1126 /* |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){ | 1174 if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){ |
980 i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0); | 1175 i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0); |
981 rc = nodeAcquire(pRtree, iNode, 0, ppLeaf); | 1176 rc = nodeAcquire(pRtree, iNode, 0, ppLeaf); |
982 sqlite3_reset(pRtree->pReadRowid); | 1177 sqlite3_reset(pRtree->pReadRowid); |
983 }else{ | 1178 }else{ |
984 rc = sqlite3_reset(pRtree->pReadRowid); | 1179 rc = sqlite3_reset(pRtree->pReadRowid); |
985 } | 1180 } |
986 return rc; | 1181 return rc; |
987 } | 1182 } |
988 | 1183 |
| 1184 /* |
| 1185 ** This function is called to configure the RtreeConstraint object passed |
| 1186 ** as the second argument for a MATCH constraint. The value passed as the |
| 1187 ** first argument to this function is the right-hand operand to the MATCH |
| 1188 ** operator. |
| 1189 */ |
| 1190 static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ |
| 1191 RtreeMatchArg *p; |
| 1192 sqlite3_rtree_geometry *pGeom; |
| 1193 int nBlob; |
| 1194 |
| 1195 /* Check that value is actually a blob. */ |
| 1196 if( !sqlite3_value_type(pValue)==SQLITE_BLOB ) return SQLITE_ERROR; |
| 1197 |
| 1198 /* Check that the blob is roughly the right size. */ |
| 1199 nBlob = sqlite3_value_bytes(pValue); |
| 1200 if( nBlob<(int)sizeof(RtreeMatchArg) |
| 1201 || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 |
| 1202 ){ |
| 1203 return SQLITE_ERROR; |
| 1204 } |
| 1205 |
| 1206 pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( |
| 1207 sizeof(sqlite3_rtree_geometry) + nBlob |
| 1208 ); |
| 1209 if( !pGeom ) return SQLITE_NOMEM; |
| 1210 memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); |
| 1211 p = (RtreeMatchArg *)&pGeom[1]; |
| 1212 |
| 1213 memcpy(p, sqlite3_value_blob(pValue), nBlob); |
| 1214 if( p->magic!=RTREE_GEOMETRY_MAGIC |
| 1215 || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) |
| 1216 ){ |
| 1217 sqlite3_free(pGeom); |
| 1218 return SQLITE_ERROR; |
| 1219 } |
| 1220 |
| 1221 pGeom->pContext = p->pContext; |
| 1222 pGeom->nParam = p->nParam; |
| 1223 pGeom->aParam = p->aParam; |
| 1224 |
| 1225 pCons->xGeom = p->xGeom; |
| 1226 pCons->pGeom = pGeom; |
| 1227 return SQLITE_OK; |
| 1228 } |
989 | 1229 |
990 /* | 1230 /* |
991 ** Rtree virtual table module xFilter method. | 1231 ** Rtree virtual table module xFilter method. |
992 */ | 1232 */ |
993 static int rtreeFilter( | 1233 static int rtreeFilter( |
994 sqlite3_vtab_cursor *pVtabCursor, | 1234 sqlite3_vtab_cursor *pVtabCursor, |
995 int idxNum, const char *idxStr, | 1235 int idxNum, const char *idxStr, |
996 int argc, sqlite3_value **argv | 1236 int argc, sqlite3_value **argv |
997 ){ | 1237 ){ |
998 Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; | 1238 Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; |
999 RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; | 1239 RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; |
1000 | 1240 |
1001 RtreeNode *pRoot = 0; | 1241 RtreeNode *pRoot = 0; |
1002 int ii; | 1242 int ii; |
1003 int rc = SQLITE_OK; | 1243 int rc = SQLITE_OK; |
1004 | 1244 |
1005 rtreeReference(pRtree); | 1245 rtreeReference(pRtree); |
1006 | 1246 |
1007 sqlite3_free(pCsr->aConstraint); | 1247 freeCursorConstraints(pCsr); |
1008 pCsr->aConstraint = 0; | |
1009 pCsr->iStrategy = idxNum; | 1248 pCsr->iStrategy = idxNum; |
1010 | 1249 |
1011 if( idxNum==1 ){ | 1250 if( idxNum==1 ){ |
1012 /* Special case - lookup by rowid. */ | 1251 /* Special case - lookup by rowid. */ |
1013 RtreeNode *pLeaf; /* Leaf on which the required cell resides */ | 1252 RtreeNode *pLeaf; /* Leaf on which the required cell resides */ |
1014 i64 iRowid = sqlite3_value_int64(argv[0]); | 1253 i64 iRowid = sqlite3_value_int64(argv[0]); |
1015 rc = findLeafNode(pRtree, iRowid, &pLeaf); | 1254 rc = findLeafNode(pRtree, iRowid, &pLeaf); |
1016 pCsr->pNode = pLeaf; | 1255 pCsr->pNode = pLeaf; |
1017 if( pLeaf && rc==SQLITE_OK ){ | 1256 if( pLeaf ){ |
1018 pCsr->iCell = nodeRowidIndex(pRtree, pLeaf, iRowid); | 1257 assert( rc==SQLITE_OK ); |
| 1258 rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell); |
1019 } | 1259 } |
1020 }else{ | 1260 }else{ |
1021 /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array | 1261 /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array |
1022 ** with the configured constraints. | 1262 ** with the configured constraints. |
1023 */ | 1263 */ |
1024 if( argc>0 ){ | 1264 if( argc>0 ){ |
1025 pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); | 1265 pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); |
1026 pCsr->nConstraint = argc; | 1266 pCsr->nConstraint = argc; |
1027 if( !pCsr->aConstraint ){ | 1267 if( !pCsr->aConstraint ){ |
1028 rc = SQLITE_NOMEM; | 1268 rc = SQLITE_NOMEM; |
1029 }else{ | 1269 }else{ |
1030 assert( (idxStr==0 && argc==0) || strlen(idxStr)==argc*2 ); | 1270 memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); |
| 1271 assert( (idxStr==0 && argc==0) || (int)strlen(idxStr)==argc*2 ); |
1031 for(ii=0; ii<argc; ii++){ | 1272 for(ii=0; ii<argc; ii++){ |
1032 RtreeConstraint *p = &pCsr->aConstraint[ii]; | 1273 RtreeConstraint *p = &pCsr->aConstraint[ii]; |
1033 p->op = idxStr[ii*2]; | 1274 p->op = idxStr[ii*2]; |
1034 p->iCoord = idxStr[ii*2+1]-'a'; | 1275 p->iCoord = idxStr[ii*2+1]-'a'; |
1035 p->rValue = sqlite3_value_double(argv[ii]); | 1276 if( p->op==RTREE_MATCH ){ |
| 1277 /* A MATCH operator. The right-hand-side must be a blob that |
| 1278 ** can be cast into an RtreeMatchArg object. One created using |
| 1279 ** an sqlite3_rtree_geometry_callback() SQL user function. |
| 1280 */ |
| 1281 rc = deserializeGeometry(argv[ii], p); |
| 1282 if( rc!=SQLITE_OK ){ |
| 1283 break; |
| 1284 } |
| 1285 }else{ |
| 1286 p->rValue = sqlite3_value_double(argv[ii]); |
| 1287 } |
1036 } | 1288 } |
1037 } | 1289 } |
1038 } | 1290 } |
1039 | 1291 |
1040 if( rc==SQLITE_OK ){ | 1292 if( rc==SQLITE_OK ){ |
1041 pCsr->pNode = 0; | 1293 pCsr->pNode = 0; |
1042 rc = nodeAcquire(pRtree, 1, 0, &pRoot); | 1294 rc = nodeAcquire(pRtree, 1, 0, &pRoot); |
1043 } | 1295 } |
1044 if( rc==SQLITE_OK ){ | 1296 if( rc==SQLITE_OK ){ |
1045 int isEof = 1; | 1297 int isEof = 1; |
(...skipping 20 matching lines...) Expand all Loading... |
1066 } | 1318 } |
1067 | 1319 |
1068 /* | 1320 /* |
1069 ** Rtree virtual table module xBestIndex method. There are three | 1321 ** Rtree virtual table module xBestIndex method. There are three |
1070 ** table scan strategies to choose from (in order from most to | 1322 ** table scan strategies to choose from (in order from most to |
1071 ** least desirable): | 1323 ** least desirable): |
1072 ** | 1324 ** |
1073 ** idxNum idxStr Strategy | 1325 ** idxNum idxStr Strategy |
1074 ** ------------------------------------------------ | 1326 ** ------------------------------------------------ |
1075 ** 1 Unused Direct lookup by rowid. | 1327 ** 1 Unused Direct lookup by rowid. |
1076 ** 2 See below R-tree query. | 1328 ** 2 See below R-tree query or full-table scan. |
1077 ** 3 Unused Full table scan. | |
1078 ** ------------------------------------------------ | 1329 ** ------------------------------------------------ |
1079 ** | 1330 ** |
1080 ** If strategy 1 or 3 is used, then idxStr is not meaningful. If strategy | 1331 ** If strategy 1 is used, then idxStr is not meaningful. If strategy |
1081 ** 2 is used, idxStr is formatted to contain 2 bytes for each | 1332 ** 2 is used, idxStr is formatted to contain 2 bytes for each |
1082 ** constraint used. The first two bytes of idxStr correspond to | 1333 ** constraint used. The first two bytes of idxStr correspond to |
1083 ** the constraint in sqlite3_index_info.aConstraintUsage[] with | 1334 ** the constraint in sqlite3_index_info.aConstraintUsage[] with |
1084 ** (argvIndex==1) etc. | 1335 ** (argvIndex==1) etc. |
1085 ** | 1336 ** |
1086 ** The first of each pair of bytes in idxStr identifies the constraint | 1337 ** The first of each pair of bytes in idxStr identifies the constraint |
1087 ** operator as follows: | 1338 ** operator as follows: |
1088 ** | 1339 ** |
1089 ** Operator Byte Value | 1340 ** Operator Byte Value |
1090 ** ---------------------- | 1341 ** ---------------------- |
1091 ** = 0x41 ('A') | 1342 ** = 0x41 ('A') |
1092 ** <= 0x42 ('B') | 1343 ** <= 0x42 ('B') |
1093 ** < 0x43 ('C') | 1344 ** < 0x43 ('C') |
1094 ** >= 0x44 ('D') | 1345 ** >= 0x44 ('D') |
1095 ** > 0x45 ('E') | 1346 ** > 0x45 ('E') |
| 1347 ** MATCH 0x46 ('F') |
1096 ** ---------------------- | 1348 ** ---------------------- |
1097 ** | 1349 ** |
1098 ** The second of each pair of bytes identifies the coordinate column | 1350 ** The second of each pair of bytes identifies the coordinate column |
1099 ** to which the constraint applies. The leftmost coordinate column | 1351 ** to which the constraint applies. The leftmost coordinate column |
1100 ** is 'a', the second from the left 'b' etc. | 1352 ** is 'a', the second from the left 'b' etc. |
1101 */ | 1353 */ |
1102 static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ | 1354 static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
1103 int rc = SQLITE_OK; | 1355 int rc = SQLITE_OK; |
1104 int ii, cCol; | 1356 int ii; |
1105 | 1357 |
1106 int iIdx = 0; | 1358 int iIdx = 0; |
1107 char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; | 1359 char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; |
1108 memset(zIdxStr, 0, sizeof(zIdxStr)); | 1360 memset(zIdxStr, 0, sizeof(zIdxStr)); |
| 1361 UNUSED_PARAMETER(tab); |
1109 | 1362 |
1110 assert( pIdxInfo->idxStr==0 ); | 1363 assert( pIdxInfo->idxStr==0 ); |
1111 for(ii=0; ii<pIdxInfo->nConstraint; ii++){ | 1364 for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ |
1112 struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; | 1365 struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; |
1113 | 1366 |
1114 if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ | 1367 if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ |
1115 /* We have an equality constraint on the rowid. Use strategy 1. */ | 1368 /* We have an equality constraint on the rowid. Use strategy 1. */ |
1116 int jj; | 1369 int jj; |
1117 for(jj=0; jj<ii; jj++){ | 1370 for(jj=0; jj<ii; jj++){ |
1118 pIdxInfo->aConstraintUsage[jj].argvIndex = 0; | 1371 pIdxInfo->aConstraintUsage[jj].argvIndex = 0; |
1119 pIdxInfo->aConstraintUsage[jj].omit = 0; | 1372 pIdxInfo->aConstraintUsage[jj].omit = 0; |
1120 } | 1373 } |
1121 pIdxInfo->idxNum = 1; | 1374 pIdxInfo->idxNum = 1; |
1122 pIdxInfo->aConstraintUsage[ii].argvIndex = 1; | 1375 pIdxInfo->aConstraintUsage[ii].argvIndex = 1; |
1123 pIdxInfo->aConstraintUsage[jj].omit = 1; | 1376 pIdxInfo->aConstraintUsage[jj].omit = 1; |
1124 | 1377 |
1125 /* This strategy involves a two rowid lookups on an B-Tree structures | 1378 /* This strategy involves a two rowid lookups on an B-Tree structures |
1126 ** and then a linear search of an R-Tree node. This should be | 1379 ** and then a linear search of an R-Tree node. This should be |
1127 ** considered almost as quick as a direct rowid lookup (for which | 1380 ** considered almost as quick as a direct rowid lookup (for which |
1128 ** sqlite uses an internal cost of 0.0). | 1381 ** sqlite uses an internal cost of 0.0). |
1129 */ | 1382 */ |
1130 pIdxInfo->estimatedCost = 10.0; | 1383 pIdxInfo->estimatedCost = 10.0; |
1131 return SQLITE_OK; | 1384 return SQLITE_OK; |
1132 } | 1385 } |
1133 | 1386 |
1134 if( p->usable && p->iColumn>0 ){ | 1387 if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ |
1135 u8 op = 0; | 1388 u8 op; |
1136 switch( p->op ){ | 1389 switch( p->op ){ |
1137 case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; | 1390 case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; |
1138 case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; | 1391 case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; |
1139 case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; | 1392 case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; |
1140 case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; | 1393 case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; |
1141 case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; | 1394 case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; |
| 1395 default: |
| 1396 assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 1397 op = RTREE_MATCH; |
| 1398 break; |
1142 } | 1399 } |
1143 if( op ){ | 1400 zIdxStr[iIdx++] = op; |
1144 /* Make sure this particular constraint has not been used before. | 1401 zIdxStr[iIdx++] = p->iColumn - 1 + 'a'; |
1145 ** If it has been used before, ignore it. | 1402 pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); |
1146 ** | 1403 pIdxInfo->aConstraintUsage[ii].omit = 1; |
1147 ** A <= or < can be used if there is a prior >= or >. | |
1148 ** A >= or > can be used if there is a prior < or <=. | |
1149 ** A <= or < is disqualified if there is a prior <=, <, or ==. | |
1150 ** A >= or > is disqualified if there is a prior >=, >, or ==. | |
1151 ** A == is disqualifed if there is any prior constraint. | |
1152 */ | |
1153 int j, opmsk; | |
1154 static const unsigned char compatible[] = { 0, 0, 1, 1, 2, 2 }; | |
1155 assert( compatible[RTREE_EQ & 7]==0 ); | |
1156 assert( compatible[RTREE_LT & 7]==1 ); | |
1157 assert( compatible[RTREE_LE & 7]==1 ); | |
1158 assert( compatible[RTREE_GT & 7]==2 ); | |
1159 assert( compatible[RTREE_GE & 7]==2 ); | |
1160 cCol = p->iColumn - 1 + 'a'; | |
1161 opmsk = compatible[op & 7]; | |
1162 for(j=0; j<iIdx; j+=2){ | |
1163 if( zIdxStr[j+1]==cCol && (compatible[zIdxStr[j] & 7] & opmsk)!=0 ){ | |
1164 op = 0; | |
1165 break; | |
1166 } | |
1167 } | |
1168 } | |
1169 if( op ){ | |
1170 assert( iIdx<sizeof(zIdxStr)-1 ); | |
1171 zIdxStr[iIdx++] = op; | |
1172 zIdxStr[iIdx++] = cCol; | |
1173 pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); | |
1174 pIdxInfo->aConstraintUsage[ii].omit = 1; | |
1175 } | |
1176 } | 1404 } |
1177 } | 1405 } |
1178 | 1406 |
1179 pIdxInfo->idxNum = 2; | 1407 pIdxInfo->idxNum = 2; |
1180 pIdxInfo->needToFreeIdxStr = 1; | 1408 pIdxInfo->needToFreeIdxStr = 1; |
1181 if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ | 1409 if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ |
1182 return SQLITE_NOMEM; | 1410 return SQLITE_NOMEM; |
1183 } | 1411 } |
1184 assert( iIdx>=0 ); | 1412 assert( iIdx>=0 ); |
1185 pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1)); | 1413 pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1)); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 static float cellOverlap( | 1492 static float cellOverlap( |
1265 Rtree *pRtree, | 1493 Rtree *pRtree, |
1266 RtreeCell *p, | 1494 RtreeCell *p, |
1267 RtreeCell *aCell, | 1495 RtreeCell *aCell, |
1268 int nCell, | 1496 int nCell, |
1269 int iExclude | 1497 int iExclude |
1270 ){ | 1498 ){ |
1271 int ii; | 1499 int ii; |
1272 float overlap = 0.0; | 1500 float overlap = 0.0; |
1273 for(ii=0; ii<nCell; ii++){ | 1501 for(ii=0; ii<nCell; ii++){ |
1274 if( ii!=iExclude ){ | 1502 #if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 1503 if( ii!=iExclude ) |
| 1504 #else |
| 1505 assert( iExclude==-1 ); |
| 1506 UNUSED_PARAMETER(iExclude); |
| 1507 #endif |
| 1508 { |
1275 int jj; | 1509 int jj; |
1276 float o = 1.0; | 1510 float o = 1.0; |
1277 for(jj=0; jj<(pRtree->nDim*2); jj+=2){ | 1511 for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
1278 double x1; | 1512 double x1; |
1279 double x2; | 1513 double x2; |
1280 | 1514 |
1281 x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); | 1515 x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); |
1282 x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); | 1516 x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); |
1283 | 1517 |
1284 if( x2<x1 ){ | 1518 if( x2<x1 ){ |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 nodeGetCell(pRtree, pNode, jj, &aCell[jj]); | 1591 nodeGetCell(pRtree, pNode, jj, &aCell[jj]); |
1358 } | 1592 } |
1359 } | 1593 } |
1360 #endif | 1594 #endif |
1361 | 1595 |
1362 /* Select the child node which will be enlarged the least if pCell | 1596 /* Select the child node which will be enlarged the least if pCell |
1363 ** is inserted into it. Resolve ties by choosing the entry with | 1597 ** is inserted into it. Resolve ties by choosing the entry with |
1364 ** the smallest area. | 1598 ** the smallest area. |
1365 */ | 1599 */ |
1366 for(iCell=0; iCell<nCell; iCell++){ | 1600 for(iCell=0; iCell<nCell; iCell++){ |
| 1601 int bBest = 0; |
1367 float growth; | 1602 float growth; |
1368 float area; | 1603 float area; |
1369 float overlap = 0.0; | 1604 float overlap = 0.0; |
1370 nodeGetCell(pRtree, pNode, iCell, &cell); | 1605 nodeGetCell(pRtree, pNode, iCell, &cell); |
1371 growth = cellGrowth(pRtree, &cell, pCell); | 1606 growth = cellGrowth(pRtree, &cell, pCell); |
1372 area = cellArea(pRtree, &cell); | 1607 area = cellArea(pRtree, &cell); |
| 1608 |
1373 #if VARIANT_RSTARTREE_CHOOSESUBTREE | 1609 #if VARIANT_RSTARTREE_CHOOSESUBTREE |
1374 if( ii==(pRtree->iDepth-1) ){ | 1610 if( ii==(pRtree->iDepth-1) ){ |
1375 overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); | 1611 overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); |
1376 } | 1612 } |
1377 #endif | |
1378 if( (iCell==0) | 1613 if( (iCell==0) |
1379 || (overlap<fMinOverlap) | 1614 || (overlap<fMinOverlap) |
1380 || (overlap==fMinOverlap && growth<fMinGrowth) | 1615 || (overlap==fMinOverlap && growth<fMinGrowth) |
1381 || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea) | 1616 || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea) |
1382 ){ | 1617 ){ |
| 1618 bBest = 1; |
| 1619 } |
| 1620 #else |
| 1621 if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){ |
| 1622 bBest = 1; |
| 1623 } |
| 1624 #endif |
| 1625 if( bBest ){ |
1383 fMinOverlap = overlap; | 1626 fMinOverlap = overlap; |
1384 fMinGrowth = growth; | 1627 fMinGrowth = growth; |
1385 fMinArea = area; | 1628 fMinArea = area; |
1386 iBest = cell.iRowid; | 1629 iBest = cell.iRowid; |
1387 } | 1630 } |
1388 } | 1631 } |
1389 | 1632 |
1390 sqlite3_free(aCell); | 1633 sqlite3_free(aCell); |
1391 rc = nodeAcquire(pRtree, iBest, pNode, &pChild); | 1634 rc = nodeAcquire(pRtree, iBest, pNode, &pChild); |
1392 nodeRelease(pRtree, pNode); | 1635 nodeRelease(pRtree, pNode); |
1393 pNode = pChild; | 1636 pNode = pChild; |
1394 } | 1637 } |
1395 | 1638 |
1396 *ppLeaf = pNode; | 1639 *ppLeaf = pNode; |
1397 return rc; | 1640 return rc; |
1398 } | 1641 } |
1399 | 1642 |
1400 /* | 1643 /* |
1401 ** A cell with the same content as pCell has just been inserted into | 1644 ** A cell with the same content as pCell has just been inserted into |
1402 ** the node pNode. This function updates the bounding box cells in | 1645 ** the node pNode. This function updates the bounding box cells in |
1403 ** all ancestor elements. | 1646 ** all ancestor elements. |
1404 */ | 1647 */ |
1405 static void AdjustTree( | 1648 static int AdjustTree( |
1406 Rtree *pRtree, /* Rtree table */ | 1649 Rtree *pRtree, /* Rtree table */ |
1407 RtreeNode *pNode, /* Adjust ancestry of this node. */ | 1650 RtreeNode *pNode, /* Adjust ancestry of this node. */ |
1408 RtreeCell *pCell /* This cell was just inserted */ | 1651 RtreeCell *pCell /* This cell was just inserted */ |
1409 ){ | 1652 ){ |
1410 RtreeNode *p = pNode; | 1653 RtreeNode *p = pNode; |
1411 while( p->pParent ){ | 1654 while( p->pParent ){ |
| 1655 RtreeNode *pParent = p->pParent; |
1412 RtreeCell cell; | 1656 RtreeCell cell; |
1413 RtreeNode *pParent = p->pParent; | 1657 int iCell; |
1414 int iCell = nodeParentIndex(pRtree, p); | 1658 |
| 1659 if( nodeParentIndex(pRtree, p, &iCell) ){ |
| 1660 return SQLITE_CORRUPT; |
| 1661 } |
1415 | 1662 |
1416 nodeGetCell(pRtree, pParent, iCell, &cell); | 1663 nodeGetCell(pRtree, pParent, iCell, &cell); |
1417 if( !cellContains(pRtree, &cell, pCell) ){ | 1664 if( !cellContains(pRtree, &cell, pCell) ){ |
1418 cellUnion(pRtree, &cell, pCell); | 1665 cellUnion(pRtree, &cell, pCell); |
1419 nodeOverwriteCell(pRtree, pParent, &cell, iCell); | 1666 nodeOverwriteCell(pRtree, pParent, &cell, iCell); |
1420 } | 1667 } |
1421 | 1668 |
1422 p = pParent; | 1669 p = pParent; |
1423 } | 1670 } |
| 1671 return SQLITE_OK; |
1424 } | 1672 } |
1425 | 1673 |
1426 /* | 1674 /* |
1427 ** Write mapping (iRowid->iNode) to the <rtree>_rowid table. | 1675 ** Write mapping (iRowid->iNode) to the <rtree>_rowid table. |
1428 */ | 1676 */ |
1429 static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){ | 1677 static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){ |
1430 sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid); | 1678 sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid); |
1431 sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode); | 1679 sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode); |
1432 sqlite3_step(pRtree->pWriteRowid); | 1680 sqlite3_step(pRtree->pWriteRowid); |
1433 return sqlite3_reset(pRtree->pWriteRowid); | 1681 return sqlite3_reset(pRtree->pWriteRowid); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1479 int iLeftSeed = 0; | 1727 int iLeftSeed = 0; |
1480 int iRightSeed = 1; | 1728 int iRightSeed = 1; |
1481 float maxNormalInnerWidth = 0.0; | 1729 float maxNormalInnerWidth = 0.0; |
1482 | 1730 |
1483 /* Pick two "seed" cells from the array of cells. The algorithm used | 1731 /* Pick two "seed" cells from the array of cells. The algorithm used |
1484 ** here is the LinearPickSeeds algorithm from Gutman[1984]. The | 1732 ** here is the LinearPickSeeds algorithm from Gutman[1984]. The |
1485 ** indices of the two seed cells in the array are stored in local | 1733 ** indices of the two seed cells in the array are stored in local |
1486 ** variables iLeftSeek and iRightSeed. | 1734 ** variables iLeftSeek and iRightSeed. |
1487 */ | 1735 */ |
1488 for(i=0; i<pRtree->nDim; i++){ | 1736 for(i=0; i<pRtree->nDim; i++){ |
1489 float x1 = aCell[0].aCoord[i*2]; | 1737 float x1 = DCOORD(aCell[0].aCoord[i*2]); |
1490 float x2 = aCell[0].aCoord[i*2+1]; | 1738 float x2 = DCOORD(aCell[0].aCoord[i*2+1]); |
1491 float x3 = x1; | 1739 float x3 = x1; |
1492 float x4 = x2; | 1740 float x4 = x2; |
1493 int jj; | 1741 int jj; |
1494 | 1742 |
1495 int iCellLeft = 0; | 1743 int iCellLeft = 0; |
1496 int iCellRight = 0; | 1744 int iCellRight = 0; |
1497 | 1745 |
1498 for(jj=1; jj<nCell; jj++){ | 1746 for(jj=1; jj<nCell; jj++){ |
1499 float left = aCell[jj].aCoord[i*2]; | 1747 float left = DCOORD(aCell[jj].aCoord[i*2]); |
1500 float right = aCell[jj].aCoord[i*2+1]; | 1748 float right = DCOORD(aCell[jj].aCoord[i*2+1]); |
1501 | 1749 |
1502 if( left<x1 ) x1 = left; | 1750 if( left<x1 ) x1 = left; |
1503 if( right>x4 ) x4 = right; | 1751 if( right>x4 ) x4 = right; |
1504 if( left>x3 ){ | 1752 if( left>x3 ){ |
1505 x3 = left; | 1753 x3 = left; |
1506 iCellRight = jj; | 1754 iCellRight = jj; |
1507 } | 1755 } |
1508 if( right<x2 ){ | 1756 if( right<x2 ){ |
1509 x2 = right; | 1757 x2 = right; |
1510 iCellLeft = jj; | 1758 iCellLeft = jj; |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 RtreeNode *pRight, | 2096 RtreeNode *pRight, |
1849 RtreeCell *pBboxLeft, | 2097 RtreeCell *pBboxLeft, |
1850 RtreeCell *pBboxRight | 2098 RtreeCell *pBboxRight |
1851 ){ | 2099 ){ |
1852 int iLeftSeed = 0; | 2100 int iLeftSeed = 0; |
1853 int iRightSeed = 1; | 2101 int iRightSeed = 1; |
1854 int *aiUsed; | 2102 int *aiUsed; |
1855 int i; | 2103 int i; |
1856 | 2104 |
1857 aiUsed = sqlite3_malloc(sizeof(int)*nCell); | 2105 aiUsed = sqlite3_malloc(sizeof(int)*nCell); |
| 2106 if( !aiUsed ){ |
| 2107 return SQLITE_NOMEM; |
| 2108 } |
1858 memset(aiUsed, 0, sizeof(int)*nCell); | 2109 memset(aiUsed, 0, sizeof(int)*nCell); |
1859 | 2110 |
1860 PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed); | 2111 PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed); |
1861 | 2112 |
1862 memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell)); | 2113 memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell)); |
1863 memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell)); | 2114 memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell)); |
1864 nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]); | 2115 nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]); |
1865 nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]); | 2116 nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]); |
1866 aiUsed[iLeftSeed] = 1; | 2117 aiUsed[iLeftSeed] = 1; |
1867 aiUsed[iRightSeed] = 1; | 2118 aiUsed[iRightSeed] = 1; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1939 aiUsed = (int *)&aCell[nCell+1]; | 2190 aiUsed = (int *)&aCell[nCell+1]; |
1940 memset(aiUsed, 0, sizeof(int)*(nCell+1)); | 2191 memset(aiUsed, 0, sizeof(int)*(nCell+1)); |
1941 for(i=0; i<nCell; i++){ | 2192 for(i=0; i<nCell; i++){ |
1942 nodeGetCell(pRtree, pNode, i, &aCell[i]); | 2193 nodeGetCell(pRtree, pNode, i, &aCell[i]); |
1943 } | 2194 } |
1944 nodeZero(pRtree, pNode); | 2195 nodeZero(pRtree, pNode); |
1945 memcpy(&aCell[nCell], pCell, sizeof(RtreeCell)); | 2196 memcpy(&aCell[nCell], pCell, sizeof(RtreeCell)); |
1946 nCell++; | 2197 nCell++; |
1947 | 2198 |
1948 if( pNode->iNode==1 ){ | 2199 if( pNode->iNode==1 ){ |
1949 pRight = nodeNew(pRtree, pNode, 1); | 2200 pRight = nodeNew(pRtree, pNode); |
1950 pLeft = nodeNew(pRtree, pNode, 1); | 2201 pLeft = nodeNew(pRtree, pNode); |
1951 pRtree->iDepth++; | 2202 pRtree->iDepth++; |
1952 pNode->isDirty = 1; | 2203 pNode->isDirty = 1; |
1953 writeInt16(pNode->zData, pRtree->iDepth); | 2204 writeInt16(pNode->zData, pRtree->iDepth); |
1954 }else{ | 2205 }else{ |
1955 pLeft = pNode; | 2206 pLeft = pNode; |
1956 pRight = nodeNew(pRtree, pLeft->pParent, 1); | 2207 pRight = nodeNew(pRtree, pLeft->pParent); |
1957 nodeReference(pLeft); | 2208 nodeReference(pLeft); |
1958 } | 2209 } |
1959 | 2210 |
1960 if( !pLeft || !pRight ){ | 2211 if( !pLeft || !pRight ){ |
1961 rc = SQLITE_NOMEM; | 2212 rc = SQLITE_NOMEM; |
1962 goto splitnode_out; | 2213 goto splitnode_out; |
1963 } | 2214 } |
1964 | 2215 |
1965 memset(pLeft->zData, 0, pRtree->iNodeSize); | 2216 memset(pLeft->zData, 0, pRtree->iNodeSize); |
1966 memset(pRight->zData, 0, pRtree->iNodeSize); | 2217 memset(pRight->zData, 0, pRtree->iNodeSize); |
1967 | 2218 |
1968 rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox); | 2219 rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox); |
1969 if( rc!=SQLITE_OK ){ | 2220 if( rc!=SQLITE_OK ){ |
1970 goto splitnode_out; | 2221 goto splitnode_out; |
1971 } | 2222 } |
1972 | 2223 |
1973 /* Ensure both child nodes have node numbers assigned to them. */ | 2224 /* Ensure both child nodes have node numbers assigned to them by calling |
1974 if( (0==pRight->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pRight))) | 2225 ** nodeWrite(). Node pRight always needs a node number, as it was created |
| 2226 ** by nodeNew() above. But node pLeft sometimes already has a node number. |
| 2227 ** In this case avoid the all to nodeWrite(). |
| 2228 */ |
| 2229 if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight)) |
1975 || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft))) | 2230 || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft))) |
1976 ){ | 2231 ){ |
1977 goto splitnode_out; | 2232 goto splitnode_out; |
1978 } | 2233 } |
1979 | 2234 |
1980 rightbbox.iRowid = pRight->iNode; | 2235 rightbbox.iRowid = pRight->iNode; |
1981 leftbbox.iRowid = pLeft->iNode; | 2236 leftbbox.iRowid = pLeft->iNode; |
1982 | 2237 |
1983 if( pNode->iNode==1 ){ | 2238 if( pNode->iNode==1 ){ |
1984 rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1); | 2239 rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1); |
1985 if( rc!=SQLITE_OK ){ | 2240 if( rc!=SQLITE_OK ){ |
1986 goto splitnode_out; | 2241 goto splitnode_out; |
1987 } | 2242 } |
1988 }else{ | 2243 }else{ |
1989 RtreeNode *pParent = pLeft->pParent; | 2244 RtreeNode *pParent = pLeft->pParent; |
1990 int iCell = nodeParentIndex(pRtree, pLeft); | 2245 int iCell; |
1991 nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); | 2246 rc = nodeParentIndex(pRtree, pLeft, &iCell); |
1992 AdjustTree(pRtree, pParent, &leftbbox); | 2247 if( rc==SQLITE_OK ){ |
| 2248 nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); |
| 2249 rc = AdjustTree(pRtree, pParent, &leftbbox); |
| 2250 } |
| 2251 if( rc!=SQLITE_OK ){ |
| 2252 goto splitnode_out; |
| 2253 } |
1993 } | 2254 } |
1994 if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){ | 2255 if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){ |
1995 goto splitnode_out; | 2256 goto splitnode_out; |
1996 } | 2257 } |
1997 | 2258 |
1998 for(i=0; i<NCELL(pRight); i++){ | 2259 for(i=0; i<NCELL(pRight); i++){ |
1999 i64 iRowid = nodeGetRowid(pRtree, pRight, i); | 2260 i64 iRowid = nodeGetRowid(pRtree, pRight, i); |
2000 rc = updateMapping(pRtree, iRowid, pRight, iHeight); | 2261 rc = updateMapping(pRtree, iRowid, pRight, iHeight); |
2001 if( iRowid==pCell->iRowid ){ | 2262 if( iRowid==pCell->iRowid ){ |
2002 newCellIsRight = 1; | 2263 newCellIsRight = 1; |
(...skipping 23 matching lines...) Expand all Loading... |
2026 pLeft = 0; | 2287 pLeft = 0; |
2027 } | 2288 } |
2028 | 2289 |
2029 splitnode_out: | 2290 splitnode_out: |
2030 nodeRelease(pRtree, pRight); | 2291 nodeRelease(pRtree, pRight); |
2031 nodeRelease(pRtree, pLeft); | 2292 nodeRelease(pRtree, pLeft); |
2032 sqlite3_free(aCell); | 2293 sqlite3_free(aCell); |
2033 return rc; | 2294 return rc; |
2034 } | 2295 } |
2035 | 2296 |
| 2297 /* |
| 2298 ** If node pLeaf is not the root of the r-tree and its pParent pointer is |
| 2299 ** still NULL, load all ancestor nodes of pLeaf into memory and populate |
| 2300 ** the pLeaf->pParent chain all the way up to the root node. |
| 2301 ** |
| 2302 ** This operation is required when a row is deleted (or updated - an update |
| 2303 ** is implemented as a delete followed by an insert). SQLite provides the |
| 2304 ** rowid of the row to delete, which can be used to find the leaf on which |
| 2305 ** the entry resides (argument pLeaf). Once the leaf is located, this |
| 2306 ** function is called to determine its ancestry. |
| 2307 */ |
2036 static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){ | 2308 static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){ |
2037 int rc = SQLITE_OK; | 2309 int rc = SQLITE_OK; |
2038 if( pLeaf->iNode!=1 && pLeaf->pParent==0 ){ | 2310 RtreeNode *pChild = pLeaf; |
2039 sqlite3_bind_int64(pRtree->pReadParent, 1, pLeaf->iNode); | 2311 while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){ |
2040 if( sqlite3_step(pRtree->pReadParent)==SQLITE_ROW ){ | 2312 int rc2 = SQLITE_OK; /* sqlite3_reset() return code */ |
2041 i64 iNode = sqlite3_column_int64(pRtree->pReadParent, 0); | 2313 sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode); |
2042 rc = nodeAcquire(pRtree, iNode, 0, &pLeaf->pParent); | 2314 rc = sqlite3_step(pRtree->pReadParent); |
2043 }else{ | 2315 if( rc==SQLITE_ROW ){ |
2044 rc = SQLITE_ERROR; | 2316 RtreeNode *pTest; /* Used to test for reference loops */ |
| 2317 i64 iNode; /* Node number of parent node */ |
| 2318 |
| 2319 /* Before setting pChild->pParent, test that we are not creating a |
| 2320 ** loop of references (as we would if, say, pChild==pParent). We don't |
| 2321 ** want to do this as it leads to a memory leak when trying to delete |
| 2322 ** the referenced counted node structures. |
| 2323 */ |
| 2324 iNode = sqlite3_column_int64(pRtree->pReadParent, 0); |
| 2325 for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent); |
| 2326 if( !pTest ){ |
| 2327 rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent); |
| 2328 } |
2045 } | 2329 } |
2046 sqlite3_reset(pRtree->pReadParent); | 2330 rc = sqlite3_reset(pRtree->pReadParent); |
2047 if( rc==SQLITE_OK ){ | 2331 if( rc==SQLITE_OK ) rc = rc2; |
2048 rc = fixLeafParent(pRtree, pLeaf->pParent); | 2332 if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT; |
2049 } | 2333 pChild = pChild->pParent; |
2050 } | 2334 } |
2051 return rc; | 2335 return rc; |
2052 } | 2336 } |
2053 | 2337 |
2054 static int deleteCell(Rtree *, RtreeNode *, int, int); | 2338 static int deleteCell(Rtree *, RtreeNode *, int, int); |
2055 | 2339 |
2056 static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ | 2340 static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ |
2057 int rc; | 2341 int rc; |
| 2342 int rc2; |
2058 RtreeNode *pParent; | 2343 RtreeNode *pParent; |
2059 int iCell; | 2344 int iCell; |
2060 | 2345 |
2061 assert( pNode->nRef==1 ); | 2346 assert( pNode->nRef==1 ); |
2062 | 2347 |
2063 /* Remove the entry in the parent cell. */ | 2348 /* Remove the entry in the parent cell. */ |
2064 iCell = nodeParentIndex(pRtree, pNode); | 2349 rc = nodeParentIndex(pRtree, pNode, &iCell); |
2065 pParent = pNode->pParent; | 2350 if( rc==SQLITE_OK ){ |
2066 pNode->pParent = 0; | 2351 pParent = pNode->pParent; |
2067 if( SQLITE_OK!=(rc = deleteCell(pRtree, pParent, iCell, iHeight+1)) | 2352 pNode->pParent = 0; |
2068 || SQLITE_OK!=(rc = nodeRelease(pRtree, pParent)) | 2353 rc = deleteCell(pRtree, pParent, iCell, iHeight+1); |
2069 ){ | 2354 } |
| 2355 rc2 = nodeRelease(pRtree, pParent); |
| 2356 if( rc==SQLITE_OK ){ |
| 2357 rc = rc2; |
| 2358 } |
| 2359 if( rc!=SQLITE_OK ){ |
2070 return rc; | 2360 return rc; |
2071 } | 2361 } |
2072 | 2362 |
2073 /* Remove the xxx_node entry. */ | 2363 /* Remove the xxx_node entry. */ |
2074 sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode); | 2364 sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode); |
2075 sqlite3_step(pRtree->pDeleteNode); | 2365 sqlite3_step(pRtree->pDeleteNode); |
2076 if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){ | 2366 if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){ |
2077 return rc; | 2367 return rc; |
2078 } | 2368 } |
2079 | 2369 |
2080 /* Remove the xxx_parent entry. */ | 2370 /* Remove the xxx_parent entry. */ |
2081 sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode); | 2371 sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode); |
2082 sqlite3_step(pRtree->pDeleteParent); | 2372 sqlite3_step(pRtree->pDeleteParent); |
2083 if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){ | 2373 if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){ |
2084 return rc; | 2374 return rc; |
2085 } | 2375 } |
2086 | 2376 |
2087 /* Remove the node from the in-memory hash table and link it into | 2377 /* Remove the node from the in-memory hash table and link it into |
2088 ** the Rtree.pDeleted list. Its contents will be re-inserted later on. | 2378 ** the Rtree.pDeleted list. Its contents will be re-inserted later on. |
2089 */ | 2379 */ |
2090 nodeHashDelete(pRtree, pNode); | 2380 nodeHashDelete(pRtree, pNode); |
2091 pNode->iNode = iHeight; | 2381 pNode->iNode = iHeight; |
2092 pNode->pNext = pRtree->pDeleted; | 2382 pNode->pNext = pRtree->pDeleted; |
2093 pNode->nRef++; | 2383 pNode->nRef++; |
2094 pRtree->pDeleted = pNode; | 2384 pRtree->pDeleted = pNode; |
2095 | 2385 |
2096 return SQLITE_OK; | 2386 return SQLITE_OK; |
2097 } | 2387 } |
2098 | 2388 |
2099 static void fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ | 2389 static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ |
2100 RtreeNode *pParent = pNode->pParent; | 2390 RtreeNode *pParent = pNode->pParent; |
| 2391 int rc = SQLITE_OK; |
2101 if( pParent ){ | 2392 if( pParent ){ |
2102 int ii; | 2393 int ii; |
2103 int nCell = NCELL(pNode); | 2394 int nCell = NCELL(pNode); |
2104 RtreeCell box; /* Bounding box for pNode */ | 2395 RtreeCell box; /* Bounding box for pNode */ |
2105 nodeGetCell(pRtree, pNode, 0, &box); | 2396 nodeGetCell(pRtree, pNode, 0, &box); |
2106 for(ii=1; ii<nCell; ii++){ | 2397 for(ii=1; ii<nCell; ii++){ |
2107 RtreeCell cell; | 2398 RtreeCell cell; |
2108 nodeGetCell(pRtree, pNode, ii, &cell); | 2399 nodeGetCell(pRtree, pNode, ii, &cell); |
2109 cellUnion(pRtree, &box, &cell); | 2400 cellUnion(pRtree, &box, &cell); |
2110 } | 2401 } |
2111 box.iRowid = pNode->iNode; | 2402 box.iRowid = pNode->iNode; |
2112 ii = nodeParentIndex(pRtree, pNode); | 2403 rc = nodeParentIndex(pRtree, pNode, &ii); |
2113 nodeOverwriteCell(pRtree, pParent, &box, ii); | 2404 if( rc==SQLITE_OK ){ |
2114 fixBoundingBox(pRtree, pParent); | 2405 nodeOverwriteCell(pRtree, pParent, &box, ii); |
| 2406 rc = fixBoundingBox(pRtree, pParent); |
| 2407 } |
2115 } | 2408 } |
| 2409 return rc; |
2116 } | 2410 } |
2117 | 2411 |
2118 /* | 2412 /* |
2119 ** Delete the cell at index iCell of node pNode. After removing the | 2413 ** Delete the cell at index iCell of node pNode. After removing the |
2120 ** cell, adjust the r-tree data structure if required. | 2414 ** cell, adjust the r-tree data structure if required. |
2121 */ | 2415 */ |
2122 static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){ | 2416 static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){ |
| 2417 RtreeNode *pParent; |
2123 int rc; | 2418 int rc; |
2124 | 2419 |
2125 if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){ | 2420 if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){ |
2126 return rc; | 2421 return rc; |
2127 } | 2422 } |
2128 | 2423 |
2129 /* Remove the cell from the node. This call just moves bytes around | 2424 /* Remove the cell from the node. This call just moves bytes around |
2130 ** the in-memory node image, so it cannot fail. | 2425 ** the in-memory node image, so it cannot fail. |
2131 */ | 2426 */ |
2132 nodeDeleteCell(pRtree, pNode, iCell); | 2427 nodeDeleteCell(pRtree, pNode, iCell); |
2133 | 2428 |
2134 /* If the node is not the tree root and now has less than the minimum | 2429 /* If the node is not the tree root and now has less than the minimum |
2135 ** number of cells, remove it from the tree. Otherwise, update the | 2430 ** number of cells, remove it from the tree. Otherwise, update the |
2136 ** cell in the parent node so that it tightly contains the updated | 2431 ** cell in the parent node so that it tightly contains the updated |
2137 ** node. | 2432 ** node. |
2138 */ | 2433 */ |
2139 if( pNode->iNode!=1 ){ | 2434 pParent = pNode->pParent; |
2140 RtreeNode *pParent = pNode->pParent; | 2435 assert( pParent || pNode->iNode==1 ); |
2141 if( (pParent->iNode!=1 || NCELL(pParent)!=1) | 2436 if( pParent ){ |
2142 && (NCELL(pNode)<RTREE_MINCELLS(pRtree)) | 2437 if( NCELL(pNode)<RTREE_MINCELLS(pRtree) ){ |
2143 ){ | |
2144 rc = removeNode(pRtree, pNode, iHeight); | 2438 rc = removeNode(pRtree, pNode, iHeight); |
2145 }else{ | 2439 }else{ |
2146 fixBoundingBox(pRtree, pNode); | 2440 rc = fixBoundingBox(pRtree, pNode); |
2147 } | 2441 } |
2148 } | 2442 } |
2149 | 2443 |
2150 return rc; | 2444 return rc; |
2151 } | 2445 } |
2152 | 2446 |
2153 static int Reinsert( | 2447 static int Reinsert( |
2154 Rtree *pRtree, | 2448 Rtree *pRtree, |
2155 RtreeNode *pNode, | 2449 RtreeNode *pNode, |
2156 RtreeCell *pCell, | 2450 RtreeCell *pCell, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2219 nodeInsertCell(pRtree, pNode, p); | 2513 nodeInsertCell(pRtree, pNode, p); |
2220 if( p->iRowid==pCell->iRowid ){ | 2514 if( p->iRowid==pCell->iRowid ){ |
2221 if( iHeight==0 ){ | 2515 if( iHeight==0 ){ |
2222 rc = rowidWrite(pRtree, p->iRowid, pNode->iNode); | 2516 rc = rowidWrite(pRtree, p->iRowid, pNode->iNode); |
2223 }else{ | 2517 }else{ |
2224 rc = parentWrite(pRtree, p->iRowid, pNode->iNode); | 2518 rc = parentWrite(pRtree, p->iRowid, pNode->iNode); |
2225 } | 2519 } |
2226 } | 2520 } |
2227 } | 2521 } |
2228 if( rc==SQLITE_OK ){ | 2522 if( rc==SQLITE_OK ){ |
2229 fixBoundingBox(pRtree, pNode); | 2523 rc = fixBoundingBox(pRtree, pNode); |
2230 } | 2524 } |
2231 for(; rc==SQLITE_OK && ii<nCell; ii++){ | 2525 for(; rc==SQLITE_OK && ii<nCell; ii++){ |
2232 /* Find a node to store this cell in. pNode->iNode currently contains | 2526 /* Find a node to store this cell in. pNode->iNode currently contains |
2233 ** the height of the sub-tree headed by the cell. | 2527 ** the height of the sub-tree headed by the cell. |
2234 */ | 2528 */ |
2235 RtreeNode *pInsert; | 2529 RtreeNode *pInsert; |
2236 RtreeCell *p = &aCell[aOrder[ii]]; | 2530 RtreeCell *p = &aCell[aOrder[ii]]; |
2237 rc = ChooseLeaf(pRtree, p, iHeight, &pInsert); | 2531 rc = ChooseLeaf(pRtree, p, iHeight, &pInsert); |
2238 if( rc==SQLITE_OK ){ | 2532 if( rc==SQLITE_OK ){ |
2239 int rc2; | 2533 int rc2; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2273 if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ | 2567 if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ |
2274 rc = SplitNode(pRtree, pNode, pCell, iHeight); | 2568 rc = SplitNode(pRtree, pNode, pCell, iHeight); |
2275 }else{ | 2569 }else{ |
2276 pRtree->iReinsertHeight = iHeight; | 2570 pRtree->iReinsertHeight = iHeight; |
2277 rc = Reinsert(pRtree, pNode, pCell, iHeight); | 2571 rc = Reinsert(pRtree, pNode, pCell, iHeight); |
2278 } | 2572 } |
2279 #else | 2573 #else |
2280 rc = SplitNode(pRtree, pNode, pCell, iHeight); | 2574 rc = SplitNode(pRtree, pNode, pCell, iHeight); |
2281 #endif | 2575 #endif |
2282 }else{ | 2576 }else{ |
2283 AdjustTree(pRtree, pNode, pCell); | 2577 rc = AdjustTree(pRtree, pNode, pCell); |
2284 if( iHeight==0 ){ | 2578 if( rc==SQLITE_OK ){ |
2285 rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); | 2579 if( iHeight==0 ){ |
2286 }else{ | 2580 rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); |
2287 rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); | 2581 }else{ |
| 2582 rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); |
| 2583 } |
2288 } | 2584 } |
2289 } | 2585 } |
2290 return rc; | 2586 return rc; |
2291 } | 2587 } |
2292 | 2588 |
2293 static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){ | 2589 static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){ |
2294 int ii; | 2590 int ii; |
2295 int rc = SQLITE_OK; | 2591 int rc = SQLITE_OK; |
2296 int nCell = NCELL(pNode); | 2592 int nCell = NCELL(pNode); |
2297 | 2593 |
(...skipping 24 matching lines...) Expand all Loading... |
2322 static int newRowid(Rtree *pRtree, i64 *piRowid){ | 2618 static int newRowid(Rtree *pRtree, i64 *piRowid){ |
2323 int rc; | 2619 int rc; |
2324 sqlite3_bind_null(pRtree->pWriteRowid, 1); | 2620 sqlite3_bind_null(pRtree->pWriteRowid, 1); |
2325 sqlite3_bind_null(pRtree->pWriteRowid, 2); | 2621 sqlite3_bind_null(pRtree->pWriteRowid, 2); |
2326 sqlite3_step(pRtree->pWriteRowid); | 2622 sqlite3_step(pRtree->pWriteRowid); |
2327 rc = sqlite3_reset(pRtree->pWriteRowid); | 2623 rc = sqlite3_reset(pRtree->pWriteRowid); |
2328 *piRowid = sqlite3_last_insert_rowid(pRtree->db); | 2624 *piRowid = sqlite3_last_insert_rowid(pRtree->db); |
2329 return rc; | 2625 return rc; |
2330 } | 2626 } |
2331 | 2627 |
2332 #ifndef NDEBUG | |
2333 static int hashIsEmpty(Rtree *pRtree){ | |
2334 int ii; | |
2335 for(ii=0; ii<HASHSIZE; ii++){ | |
2336 assert( !pRtree->aHash[ii] ); | |
2337 } | |
2338 return 1; | |
2339 } | |
2340 #endif | |
2341 | |
2342 /* | 2628 /* |
2343 ** The xUpdate method for rtree module virtual tables. | 2629 ** The xUpdate method for rtree module virtual tables. |
2344 */ | 2630 */ |
2345 static int rtreeUpdate( | 2631 static int rtreeUpdate( |
2346 sqlite3_vtab *pVtab, | 2632 sqlite3_vtab *pVtab, |
2347 int nData, | 2633 int nData, |
2348 sqlite3_value **azData, | 2634 sqlite3_value **azData, |
2349 sqlite_int64 *pRowid | 2635 sqlite_int64 *pRowid |
2350 ){ | 2636 ){ |
2351 Rtree *pRtree = (Rtree *)pVtab; | 2637 Rtree *pRtree = (Rtree *)pVtab; |
2352 int rc = SQLITE_OK; | 2638 int rc = SQLITE_OK; |
2353 | 2639 |
2354 rtreeReference(pRtree); | 2640 rtreeReference(pRtree); |
2355 | 2641 |
2356 assert(nData>=1); | 2642 assert(nData>=1); |
2357 assert(hashIsEmpty(pRtree)); | |
2358 | 2643 |
2359 /* If azData[0] is not an SQL NULL value, it is the rowid of a | 2644 /* If azData[0] is not an SQL NULL value, it is the rowid of a |
2360 ** record to delete from the r-tree table. The following block does | 2645 ** record to delete from the r-tree table. The following block does |
2361 ** just that. | 2646 ** just that. |
2362 */ | 2647 */ |
2363 if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ | 2648 if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ |
2364 i64 iDelete; /* The rowid to delete */ | 2649 i64 iDelete; /* The rowid to delete */ |
2365 RtreeNode *pLeaf; /* Leaf node containing record iDelete */ | 2650 RtreeNode *pLeaf; /* Leaf node containing record iDelete */ |
2366 int iCell; /* Index of iDelete cell in pLeaf */ | 2651 int iCell; /* Index of iDelete cell in pLeaf */ |
2367 RtreeNode *pRoot; | 2652 RtreeNode *pRoot; |
2368 | 2653 |
2369 /* Obtain a reference to the root node to initialise Rtree.iDepth */ | 2654 /* Obtain a reference to the root node to initialise Rtree.iDepth */ |
2370 rc = nodeAcquire(pRtree, 1, 0, &pRoot); | 2655 rc = nodeAcquire(pRtree, 1, 0, &pRoot); |
2371 | 2656 |
2372 /* Obtain a reference to the leaf node that contains the entry | 2657 /* Obtain a reference to the leaf node that contains the entry |
2373 ** about to be deleted. | 2658 ** about to be deleted. |
2374 */ | 2659 */ |
2375 if( rc==SQLITE_OK ){ | 2660 if( rc==SQLITE_OK ){ |
2376 iDelete = sqlite3_value_int64(azData[0]); | 2661 iDelete = sqlite3_value_int64(azData[0]); |
2377 rc = findLeafNode(pRtree, iDelete, &pLeaf); | 2662 rc = findLeafNode(pRtree, iDelete, &pLeaf); |
2378 } | 2663 } |
2379 | 2664 |
2380 /* Delete the cell in question from the leaf node. */ | 2665 /* Delete the cell in question from the leaf node. */ |
2381 if( rc==SQLITE_OK ){ | 2666 if( rc==SQLITE_OK ){ |
2382 int rc2; | 2667 int rc2; |
2383 iCell = nodeRowidIndex(pRtree, pLeaf, iDelete); | 2668 rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell); |
2384 rc = deleteCell(pRtree, pLeaf, iCell, 0); | 2669 if( rc==SQLITE_OK ){ |
| 2670 rc = deleteCell(pRtree, pLeaf, iCell, 0); |
| 2671 } |
2385 rc2 = nodeRelease(pRtree, pLeaf); | 2672 rc2 = nodeRelease(pRtree, pLeaf); |
2386 if( rc==SQLITE_OK ){ | 2673 if( rc==SQLITE_OK ){ |
2387 rc = rc2; | 2674 rc = rc2; |
2388 } | 2675 } |
2389 } | 2676 } |
2390 | 2677 |
2391 /* Delete the corresponding entry in the <rtree>_rowid table. */ | 2678 /* Delete the corresponding entry in the <rtree>_rowid table. */ |
2392 if( rc==SQLITE_OK ){ | 2679 if( rc==SQLITE_OK ){ |
2393 sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete); | 2680 sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete); |
2394 sqlite3_step(pRtree->pDeleteRowid); | 2681 sqlite3_step(pRtree->pDeleteRowid); |
2395 rc = sqlite3_reset(pRtree->pDeleteRowid); | 2682 rc = sqlite3_reset(pRtree->pDeleteRowid); |
2396 } | 2683 } |
2397 | 2684 |
2398 /* Check if the root node now has exactly one child. If so, remove | 2685 /* Check if the root node now has exactly one child. If so, remove |
2399 ** it, schedule the contents of the child for reinsertion and | 2686 ** it, schedule the contents of the child for reinsertion and |
2400 ** reduce the tree height by one. | 2687 ** reduce the tree height by one. |
2401 ** | 2688 ** |
2402 ** This is equivalent to copying the contents of the child into | 2689 ** This is equivalent to copying the contents of the child into |
2403 ** the root node (the operation that Gutman's paper says to perform | 2690 ** the root node (the operation that Gutman's paper says to perform |
2404 ** in this scenario). | 2691 ** in this scenario). |
2405 */ | 2692 */ |
2406 if( rc==SQLITE_OK && pRtree->iDepth>0 ){ | 2693 if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ |
2407 if( rc==SQLITE_OK && NCELL(pRoot)==1 ){ | 2694 int rc2; |
2408 RtreeNode *pChild; | 2695 RtreeNode *pChild; |
2409 i64 iChild = nodeGetRowid(pRtree, pRoot, 0); | 2696 i64 iChild = nodeGetRowid(pRtree, pRoot, 0); |
2410 rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); | 2697 rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); |
2411 if( rc==SQLITE_OK ){ | 2698 if( rc==SQLITE_OK ){ |
2412 rc = removeNode(pRtree, pChild, pRtree->iDepth-1); | 2699 rc = removeNode(pRtree, pChild, pRtree->iDepth-1); |
2413 } | 2700 } |
2414 if( rc==SQLITE_OK ){ | 2701 rc2 = nodeRelease(pRtree, pChild); |
2415 pRtree->iDepth--; | 2702 if( rc==SQLITE_OK ) rc = rc2; |
2416 writeInt16(pRoot->zData, pRtree->iDepth); | 2703 if( rc==SQLITE_OK ){ |
2417 pRoot->isDirty = 1; | 2704 pRtree->iDepth--; |
2418 } | 2705 writeInt16(pRoot->zData, pRtree->iDepth); |
| 2706 pRoot->isDirty = 1; |
2419 } | 2707 } |
2420 } | 2708 } |
2421 | 2709 |
2422 /* Re-insert the contents of any underfull nodes removed from the tree. */ | 2710 /* Re-insert the contents of any underfull nodes removed from the tree. */ |
2423 for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){ | 2711 for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){ |
2424 if( rc==SQLITE_OK ){ | 2712 if( rc==SQLITE_OK ){ |
2425 rc = reinsertNodeContent(pRtree, pLeaf); | 2713 rc = reinsertNodeContent(pRtree, pLeaf); |
2426 } | 2714 } |
2427 pRtree->pDeleted = pLeaf->pNext; | 2715 pRtree->pDeleted = pLeaf->pNext; |
2428 sqlite3_free(pLeaf); | 2716 sqlite3_free(pLeaf); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2474 }else{ | 2762 }else{ |
2475 cell.iRowid = sqlite3_value_int64(azData[2]); | 2763 cell.iRowid = sqlite3_value_int64(azData[2]); |
2476 sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); | 2764 sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); |
2477 if( SQLITE_ROW==sqlite3_step(pRtree->pReadRowid) ){ | 2765 if( SQLITE_ROW==sqlite3_step(pRtree->pReadRowid) ){ |
2478 sqlite3_reset(pRtree->pReadRowid); | 2766 sqlite3_reset(pRtree->pReadRowid); |
2479 rc = SQLITE_CONSTRAINT; | 2767 rc = SQLITE_CONSTRAINT; |
2480 goto constraint; | 2768 goto constraint; |
2481 } | 2769 } |
2482 rc = sqlite3_reset(pRtree->pReadRowid); | 2770 rc = sqlite3_reset(pRtree->pReadRowid); |
2483 } | 2771 } |
| 2772 *pRowid = cell.iRowid; |
2484 | 2773 |
2485 if( rc==SQLITE_OK ){ | 2774 if( rc==SQLITE_OK ){ |
2486 rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); | 2775 rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); |
2487 } | 2776 } |
2488 if( rc==SQLITE_OK ){ | 2777 if( rc==SQLITE_OK ){ |
2489 int rc2; | 2778 int rc2; |
2490 pRtree->iReinsertHeight = -1; | 2779 pRtree->iReinsertHeight = -1; |
2491 rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); | 2780 rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); |
2492 rc2 = nodeRelease(pRtree, pLeaf); | 2781 rc2 = nodeRelease(pRtree, pLeaf); |
2493 if( rc==SQLITE_OK ){ | 2782 if( rc==SQLITE_OK ){ |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2611 }else{ | 2900 }else{ |
2612 rc = SQLITE_NOMEM; | 2901 rc = SQLITE_NOMEM; |
2613 } | 2902 } |
2614 sqlite3_free(zSql); | 2903 sqlite3_free(zSql); |
2615 } | 2904 } |
2616 | 2905 |
2617 return rc; | 2906 return rc; |
2618 } | 2907 } |
2619 | 2908 |
2620 /* | 2909 /* |
2621 ** This routine queries database handle db for the page-size used by | 2910 ** The second argument to this function contains the text of an SQL statement |
2622 ** database zDb. If successful, the page-size in bytes is written to | 2911 ** that returns a single integer value. The statement is compiled and executed |
2623 ** *piPageSize and SQLITE_OK returned. Otherwise, and an SQLite error | 2912 ** using database connection db. If successful, the integer value returned |
2624 ** code is returned. | 2913 ** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error |
| 2914 ** code is returned and the value of *piVal after returning is not defined. |
2625 */ | 2915 */ |
2626 static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){ | 2916 static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){ |
2627 int rc = SQLITE_NOMEM; | 2917 int rc = SQLITE_NOMEM; |
| 2918 if( zSql ){ |
| 2919 sqlite3_stmt *pStmt = 0; |
| 2920 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 2921 if( rc==SQLITE_OK ){ |
| 2922 if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 2923 *piVal = sqlite3_column_int(pStmt, 0); |
| 2924 } |
| 2925 rc = sqlite3_finalize(pStmt); |
| 2926 } |
| 2927 } |
| 2928 return rc; |
| 2929 } |
| 2930 |
| 2931 /* |
| 2932 ** This function is called from within the xConnect() or xCreate() method to |
| 2933 ** determine the node-size used by the rtree table being created or connected |
| 2934 ** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned. |
| 2935 ** Otherwise, an SQLite error code is returned. |
| 2936 ** |
| 2937 ** If this function is being called as part of an xConnect(), then the rtree |
| 2938 ** table already exists. In this case the node-size is determined by inspecting |
| 2939 ** the root node of the tree. |
| 2940 ** |
| 2941 ** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. |
| 2942 ** This ensures that each node is stored on a single database page. If the |
| 2943 ** database page-size is so large that more than RTREE_MAXCELLS entries |
| 2944 ** would fit in a single node, use a smaller node-size. |
| 2945 */ |
| 2946 static int getNodeSize( |
| 2947 sqlite3 *db, /* Database handle */ |
| 2948 Rtree *pRtree, /* Rtree handle */ |
| 2949 int isCreate /* True for xCreate, false for xConnect */ |
| 2950 ){ |
| 2951 int rc; |
2628 char *zSql; | 2952 char *zSql; |
2629 sqlite3_stmt *pStmt = 0; | 2953 if( isCreate ){ |
2630 | 2954 int iPageSize; |
2631 zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb); | 2955 zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); |
2632 if( !zSql ){ | 2956 rc = getIntFromStmt(db, zSql, &iPageSize); |
2633 return SQLITE_NOMEM; | 2957 if( rc==SQLITE_OK ){ |
| 2958 pRtree->iNodeSize = iPageSize-64; |
| 2959 if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ |
| 2960 pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; |
| 2961 } |
| 2962 } |
| 2963 }else{ |
| 2964 zSql = sqlite3_mprintf( |
| 2965 "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", |
| 2966 pRtree->zDb, pRtree->zName |
| 2967 ); |
| 2968 rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); |
2634 } | 2969 } |
2635 | 2970 |
2636 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); | |
2637 sqlite3_free(zSql); | 2971 sqlite3_free(zSql); |
2638 if( rc!=SQLITE_OK ){ | 2972 return rc; |
2639 return rc; | |
2640 } | |
2641 | |
2642 if( SQLITE_ROW==sqlite3_step(pStmt) ){ | |
2643 *piPageSize = sqlite3_column_int(pStmt, 0); | |
2644 } | |
2645 return sqlite3_finalize(pStmt); | |
2646 } | 2973 } |
2647 | 2974 |
2648 /* | 2975 /* |
2649 ** This function is the implementation of both the xConnect and xCreate | 2976 ** This function is the implementation of both the xConnect and xCreate |
2650 ** methods of the r-tree virtual table. | 2977 ** methods of the r-tree virtual table. |
2651 ** | 2978 ** |
2652 ** argv[0] -> module name | 2979 ** argv[0] -> module name |
2653 ** argv[1] -> database name | 2980 ** argv[1] -> database name |
2654 ** argv[2] -> table name | 2981 ** argv[2] -> table name |
2655 ** argv[...] -> column names... | 2982 ** argv[...] -> column names... |
2656 */ | 2983 */ |
2657 static int rtreeInit( | 2984 static int rtreeInit( |
2658 sqlite3 *db, /* Database connection */ | 2985 sqlite3 *db, /* Database connection */ |
2659 void *pAux, /* One of the RTREE_COORD_* constants */ | 2986 void *pAux, /* One of the RTREE_COORD_* constants */ |
2660 int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ | 2987 int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ |
2661 sqlite3_vtab **ppVtab, /* OUT: New virtual table */ | 2988 sqlite3_vtab **ppVtab, /* OUT: New virtual table */ |
2662 char **pzErr, /* OUT: Error message, if any */ | 2989 char **pzErr, /* OUT: Error message, if any */ |
2663 int isCreate /* True for xCreate, false for xConnect */ | 2990 int isCreate /* True for xCreate, false for xConnect */ |
2664 ){ | 2991 ){ |
2665 int rc = SQLITE_OK; | 2992 int rc = SQLITE_OK; |
2666 int iPageSize = 0; | |
2667 Rtree *pRtree; | 2993 Rtree *pRtree; |
2668 int nDb; /* Length of string argv[1] */ | 2994 int nDb; /* Length of string argv[1] */ |
2669 int nName; /* Length of string argv[2] */ | 2995 int nName; /* Length of string argv[2] */ |
2670 int eCoordType = (int)pAux; | 2996 int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); |
2671 | 2997 |
2672 const char *aErrMsg[] = { | 2998 const char *aErrMsg[] = { |
2673 0, /* 0 */ | 2999 0, /* 0 */ |
2674 "Wrong number of columns for an rtree table", /* 1 */ | 3000 "Wrong number of columns for an rtree table", /* 1 */ |
2675 "Too few columns for an rtree table", /* 2 */ | 3001 "Too few columns for an rtree table", /* 2 */ |
2676 "Too many columns for an rtree table" /* 3 */ | 3002 "Too many columns for an rtree table" /* 3 */ |
2677 }; | 3003 }; |
2678 | 3004 |
2679 int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; | 3005 int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; |
2680 if( aErrMsg[iErr] ){ | 3006 if( aErrMsg[iErr] ){ |
2681 *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); | 3007 *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); |
2682 return SQLITE_ERROR; | 3008 return SQLITE_ERROR; |
2683 } | 3009 } |
2684 | 3010 |
2685 rc = getPageSize(db, argv[1], &iPageSize); | |
2686 if( rc!=SQLITE_OK ){ | |
2687 return rc; | |
2688 } | |
2689 | |
2690 /* Allocate the sqlite3_vtab structure */ | 3011 /* Allocate the sqlite3_vtab structure */ |
2691 nDb = strlen(argv[1]); | 3012 nDb = strlen(argv[1]); |
2692 nName = strlen(argv[2]); | 3013 nName = strlen(argv[2]); |
2693 pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); | 3014 pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); |
2694 if( !pRtree ){ | 3015 if( !pRtree ){ |
2695 return SQLITE_NOMEM; | 3016 return SQLITE_NOMEM; |
2696 } | 3017 } |
2697 memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); | 3018 memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); |
2698 pRtree->nBusy = 1; | 3019 pRtree->nBusy = 1; |
2699 pRtree->base.pModule = &rtreeModule; | 3020 pRtree->base.pModule = &rtreeModule; |
2700 pRtree->zDb = (char *)&pRtree[1]; | 3021 pRtree->zDb = (char *)&pRtree[1]; |
2701 pRtree->zName = &pRtree->zDb[nDb+1]; | 3022 pRtree->zName = &pRtree->zDb[nDb+1]; |
2702 pRtree->nDim = (argc-4)/2; | 3023 pRtree->nDim = (argc-4)/2; |
2703 pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; | 3024 pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; |
2704 pRtree->eCoordType = eCoordType; | 3025 pRtree->eCoordType = eCoordType; |
2705 memcpy(pRtree->zDb, argv[1], nDb); | 3026 memcpy(pRtree->zDb, argv[1], nDb); |
2706 memcpy(pRtree->zName, argv[2], nName); | 3027 memcpy(pRtree->zName, argv[2], nName); |
2707 | 3028 |
2708 /* Figure out the node size to use. By default, use 64 bytes less than | 3029 /* Figure out the node size to use. */ |
2709 ** the database page-size. This ensures that each node is stored on | 3030 rc = getNodeSize(db, pRtree, isCreate); |
2710 ** a single database page. | |
2711 ** | |
2712 ** If the databasd page-size is so large that more than RTREE_MAXCELLS | |
2713 ** entries would fit in a single node, use a smaller node-size. | |
2714 */ | |
2715 pRtree->iNodeSize = iPageSize-64; | |
2716 if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ | |
2717 pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; | |
2718 } | |
2719 | 3031 |
2720 /* Create/Connect to the underlying relational database schema. If | 3032 /* Create/Connect to the underlying relational database schema. If |
2721 ** that is successful, call sqlite3_declare_vtab() to configure | 3033 ** that is successful, call sqlite3_declare_vtab() to configure |
2722 ** the r-tree table schema. | 3034 ** the r-tree table schema. |
2723 */ | 3035 */ |
2724 if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ | 3036 if( rc==SQLITE_OK ){ |
2725 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | 3037 if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ |
2726 }else{ | 3038 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
2727 char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); | 3039 }else{ |
2728 char *zTmp; | 3040 char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); |
2729 int ii; | 3041 char *zTmp; |
2730 for(ii=4; zSql && ii<argc; ii++){ | 3042 int ii; |
2731 zTmp = zSql; | 3043 for(ii=4; zSql && ii<argc; ii++){ |
2732 zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); | 3044 zTmp = zSql; |
2733 sqlite3_free(zTmp); | 3045 zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); |
| 3046 sqlite3_free(zTmp); |
| 3047 } |
| 3048 if( zSql ){ |
| 3049 zTmp = zSql; |
| 3050 zSql = sqlite3_mprintf("%s);", zTmp); |
| 3051 sqlite3_free(zTmp); |
| 3052 } |
| 3053 if( !zSql ){ |
| 3054 rc = SQLITE_NOMEM; |
| 3055 }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ |
| 3056 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 3057 } |
| 3058 sqlite3_free(zSql); |
2734 } | 3059 } |
2735 if( zSql ){ | |
2736 zTmp = zSql; | |
2737 zSql = sqlite3_mprintf("%s);", zTmp); | |
2738 sqlite3_free(zTmp); | |
2739 } | |
2740 if( !zSql ){ | |
2741 rc = SQLITE_NOMEM; | |
2742 }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ | |
2743 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | |
2744 } | |
2745 sqlite3_free(zSql); | |
2746 } | 3060 } |
2747 | 3061 |
2748 if( rc==SQLITE_OK ){ | 3062 if( rc==SQLITE_OK ){ |
2749 *ppVtab = (sqlite3_vtab *)pRtree; | 3063 *ppVtab = (sqlite3_vtab *)pRtree; |
2750 }else{ | 3064 }else{ |
2751 rtreeRelease(pRtree); | 3065 rtreeRelease(pRtree); |
2752 } | 3066 } |
2753 return rc; | 3067 return rc; |
2754 } | 3068 } |
2755 | 3069 |
(...skipping 13 matching lines...) Expand all Loading... |
2769 ** entry for each cell in the r-tree node. Each entry is itself a | 3083 ** entry for each cell in the r-tree node. Each entry is itself a |
2770 ** list, containing the 8-byte rowid/pageno followed by the | 3084 ** list, containing the 8-byte rowid/pageno followed by the |
2771 ** <num-dimension>*2 coordinates. | 3085 ** <num-dimension>*2 coordinates. |
2772 */ | 3086 */ |
2773 static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ | 3087 static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ |
2774 char *zText = 0; | 3088 char *zText = 0; |
2775 RtreeNode node; | 3089 RtreeNode node; |
2776 Rtree tree; | 3090 Rtree tree; |
2777 int ii; | 3091 int ii; |
2778 | 3092 |
| 3093 UNUSED_PARAMETER(nArg); |
2779 memset(&node, 0, sizeof(RtreeNode)); | 3094 memset(&node, 0, sizeof(RtreeNode)); |
2780 memset(&tree, 0, sizeof(Rtree)); | 3095 memset(&tree, 0, sizeof(Rtree)); |
2781 tree.nDim = sqlite3_value_int(apArg[0]); | 3096 tree.nDim = sqlite3_value_int(apArg[0]); |
2782 tree.nBytesPerCell = 8 + 8 * tree.nDim; | 3097 tree.nBytesPerCell = 8 + 8 * tree.nDim; |
2783 node.zData = (u8 *)sqlite3_value_blob(apArg[1]); | 3098 node.zData = (u8 *)sqlite3_value_blob(apArg[1]); |
2784 | 3099 |
2785 for(ii=0; ii<NCELL(&node); ii++){ | 3100 for(ii=0; ii<NCELL(&node); ii++){ |
2786 char zCell[512]; | 3101 char zCell[512]; |
2787 int nCell = 0; | 3102 int nCell = 0; |
2788 RtreeCell cell; | 3103 RtreeCell cell; |
2789 int jj; | 3104 int jj; |
2790 | 3105 |
2791 nodeGetCell(&tree, &node, ii, &cell); | 3106 nodeGetCell(&tree, &node, ii, &cell); |
2792 sqlite3_snprintf(512-nCell,&zCell[nCell],"%d", cell.iRowid); | 3107 sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); |
2793 nCell = strlen(zCell); | 3108 nCell = strlen(zCell); |
2794 for(jj=0; jj<tree.nDim*2; jj++){ | 3109 for(jj=0; jj<tree.nDim*2; jj++){ |
2795 sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f); | 3110 sqlite3_snprintf(512-nCell,&zCell[nCell]," %f",(double)cell.aCoord[jj].f); |
2796 nCell = strlen(zCell); | 3111 nCell = strlen(zCell); |
2797 } | 3112 } |
2798 | 3113 |
2799 if( zText ){ | 3114 if( zText ){ |
2800 char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell); | 3115 char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell); |
2801 sqlite3_free(zText); | 3116 sqlite3_free(zText); |
2802 zText = zTextNew; | 3117 zText = zTextNew; |
2803 }else{ | 3118 }else{ |
2804 zText = sqlite3_mprintf("{%s}", zCell); | 3119 zText = sqlite3_mprintf("{%s}", zCell); |
2805 } | 3120 } |
2806 } | 3121 } |
2807 | 3122 |
2808 sqlite3_result_text(ctx, zText, -1, sqlite3_free); | 3123 sqlite3_result_text(ctx, zText, -1, sqlite3_free); |
2809 } | 3124 } |
2810 | 3125 |
2811 static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ | 3126 static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ |
| 3127 UNUSED_PARAMETER(nArg); |
2812 if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB | 3128 if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB |
2813 || sqlite3_value_bytes(apArg[0])<2 | 3129 || sqlite3_value_bytes(apArg[0])<2 |
2814 ){ | 3130 ){ |
2815 sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); | 3131 sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); |
2816 }else{ | 3132 }else{ |
2817 u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]); | 3133 u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]); |
2818 sqlite3_result_int(ctx, readInt16(zBlob)); | 3134 sqlite3_result_int(ctx, readInt16(zBlob)); |
2819 } | 3135 } |
2820 } | 3136 } |
2821 | 3137 |
2822 /* | 3138 /* |
2823 ** Register the r-tree module with database handle db. This creates the | 3139 ** Register the r-tree module with database handle db. This creates the |
2824 ** virtual table module "rtree" and the debugging/analysis scalar | 3140 ** virtual table module "rtree" and the debugging/analysis scalar |
2825 ** function "rtreenode". | 3141 ** function "rtreenode". |
2826 */ | 3142 */ |
2827 int sqlite3RtreeInit(sqlite3 *db){ | 3143 int sqlite3RtreeInit(sqlite3 *db){ |
2828 int rc = SQLITE_OK; | 3144 const int utf8 = SQLITE_UTF8; |
| 3145 int rc; |
2829 | 3146 |
| 3147 rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); |
2830 if( rc==SQLITE_OK ){ | 3148 if( rc==SQLITE_OK ){ |
2831 int utf8 = SQLITE_UTF8; | |
2832 rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); | |
2833 } | |
2834 if( rc==SQLITE_OK ){ | |
2835 int utf8 = SQLITE_UTF8; | |
2836 rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); | 3149 rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); |
2837 } | 3150 } |
2838 if( rc==SQLITE_OK ){ | 3151 if( rc==SQLITE_OK ){ |
2839 void *c = (void *)RTREE_COORD_REAL32; | 3152 void *c = (void *)RTREE_COORD_REAL32; |
2840 rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); | 3153 rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); |
2841 } | 3154 } |
2842 if( rc==SQLITE_OK ){ | 3155 if( rc==SQLITE_OK ){ |
2843 void *c = (void *)RTREE_COORD_INT32; | 3156 void *c = (void *)RTREE_COORD_INT32; |
2844 rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); | 3157 rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); |
2845 } | 3158 } |
2846 | 3159 |
2847 return rc; | 3160 return rc; |
2848 } | 3161 } |
2849 | 3162 |
| 3163 /* |
| 3164 ** A version of sqlite3_free() that can be used as a callback. This is used |
| 3165 ** in two places - as the destructor for the blob value returned by the |
| 3166 ** invocation of a geometry function, and as the destructor for the geometry |
| 3167 ** functions themselves. |
| 3168 */ |
| 3169 static void doSqlite3Free(void *p){ |
| 3170 sqlite3_free(p); |
| 3171 } |
| 3172 |
| 3173 /* |
| 3174 ** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite |
| 3175 ** scalar user function. This C function is the callback used for all such |
| 3176 ** registered SQL functions. |
| 3177 ** |
| 3178 ** The scalar user functions return a blob that is interpreted by r-tree |
| 3179 ** table MATCH operators. |
| 3180 */ |
| 3181 static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ |
| 3182 RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); |
| 3183 RtreeMatchArg *pBlob; |
| 3184 int nBlob; |
| 3185 |
| 3186 nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(double); |
| 3187 pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); |
| 3188 if( !pBlob ){ |
| 3189 sqlite3_result_error_nomem(ctx); |
| 3190 }else{ |
| 3191 int i; |
| 3192 pBlob->magic = RTREE_GEOMETRY_MAGIC; |
| 3193 pBlob->xGeom = pGeomCtx->xGeom; |
| 3194 pBlob->pContext = pGeomCtx->pContext; |
| 3195 pBlob->nParam = nArg; |
| 3196 for(i=0; i<nArg; i++){ |
| 3197 pBlob->aParam[i] = sqlite3_value_double(aArg[i]); |
| 3198 } |
| 3199 sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); |
| 3200 } |
| 3201 } |
| 3202 |
| 3203 /* |
| 3204 ** Register a new geometry function for use with the r-tree MATCH operator. |
| 3205 */ |
| 3206 int sqlite3_rtree_geometry_callback( |
| 3207 sqlite3 *db, |
| 3208 const char *zGeom, |
| 3209 int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *), |
| 3210 void *pContext |
| 3211 ){ |
| 3212 RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ |
| 3213 |
| 3214 /* Allocate and populate the context object. */ |
| 3215 pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); |
| 3216 if( !pGeomCtx ) return SQLITE_NOMEM; |
| 3217 pGeomCtx->xGeom = xGeom; |
| 3218 pGeomCtx->pContext = pContext; |
| 3219 |
| 3220 /* Create the new user-function. Register a destructor function to delete |
| 3221 ** the context object when it is no longer required. */ |
| 3222 return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, |
| 3223 (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free |
| 3224 ); |
| 3225 } |
| 3226 |
2850 #if !SQLITE_CORE | 3227 #if !SQLITE_CORE |
2851 int sqlite3_extension_init( | 3228 int sqlite3_extension_init( |
2852 sqlite3 *db, | 3229 sqlite3 *db, |
2853 char **pzErrMsg, | 3230 char **pzErrMsg, |
2854 const sqlite3_api_routines *pApi | 3231 const sqlite3_api_routines *pApi |
2855 ){ | 3232 ){ |
2856 SQLITE_EXTENSION_INIT2(pApi) | 3233 SQLITE_EXTENSION_INIT2(pApi) |
2857 return sqlite3RtreeInit(db); | 3234 return sqlite3RtreeInit(db); |
2858 } | 3235 } |
2859 #endif | 3236 #endif |
2860 | 3237 |
2861 #endif | 3238 #endif |
OLD | NEW |