Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Added documentation for the sqlite3_rtree_query_callback() enhancement. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
89557fb903338f730eee5263d93e0448 |
User & Date: | drh 2014-04-29 15:08:38.073 |
Context
2014-05-01
| ||
14:44 | Updates to the R*Tree documentation. (check-in: bd0fe1c3e1 user: drh tags: trunk) | |
2014-04-29
| ||
15:08 | Added documentation for the sqlite3_rtree_query_callback() enhancement. (check-in: 89557fb903 user: drh tags: trunk) | |
2014-04-25
| ||
20:46 | Fix more typos in the foreignkey.html document. (check-in: 2de942054f user: drh tags: trunk) | |
Changes
Changes to pages/changes.in.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | chng {2014-06-?? (3.8.5)} { <li>Added support for sorting subsets of the result when the result comes out of the query engine already partially sorted. <li>Enhance the query planner so that it always prefers an index that uses a superset of WHERE clause terms relative to some other index. <li>Added the [SQLITE_TESTCTRL_BYTEORDER] test control. <p><b>Bug Fixes:</b> <li>OFFSET clause ignored on queries without a FROM clause. Ticket [http://www.sqlite.org/src/info/07d6a0453d | 07d6a0453d] <li>Assertion fault on queries involving expressions of the form "x IN (?)". Ticket [http://www.sqlite.org/src/info/e39d032577|e39d032577]. <li>Incorrect column datatype reported. Ticket [http://www.sqlite.org/src/info/a8a0d2996a | a8a0d2996a] | > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | chng {2014-06-?? (3.8.5)} { <li>Added support for sorting subsets of the result when the result comes out of the query engine already partially sorted. <li>Enhance the query planner so that it always prefers an index that uses a superset of WHERE clause terms relative to some other index. <li>Added the [SQLITE_TESTCTRL_BYTEORDER] test control. <li>Added the [sqlite3_rtree_query_callback()] interface to [R-Tree extension] <p><b>Bug Fixes:</b> <li>OFFSET clause ignored on queries without a FROM clause. Ticket [http://www.sqlite.org/src/info/07d6a0453d | 07d6a0453d] <li>Assertion fault on queries involving expressions of the form "x IN (?)". Ticket [http://www.sqlite.org/src/info/e39d032577|e39d032577]. <li>Incorrect column datatype reported. Ticket [http://www.sqlite.org/src/info/a8a0d2996a | a8a0d2996a] |
︙ | ︙ |
Changes to pages/rtree.in.
︙ | ︙ | |||
10 11 12 13 14 15 16 | used in geospatial systems where each entry is a rectangle with minimum and maximum X and Y coordinates. Given a query rectangle, an R-Tree is able to quickly find all entries that are contained within the query rectangle or which overlap the query rectangle. This idea is easily extended to three dimensions for use in CAD systems. R-Trees also find use in time-domain range look-ups. For example, suppose a database records the starting and ending times for a large number of events. A R-Tree is able to quickly | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | used in geospatial systems where each entry is a rectangle with minimum and maximum X and Y coordinates. Given a query rectangle, an R-Tree is able to quickly find all entries that are contained within the query rectangle or which overlap the query rectangle. This idea is easily extended to three dimensions for use in CAD systems. R-Trees also find use in time-domain range look-ups. For example, suppose a database records the starting and ending times for a large number of events. A R-Tree is able to quickly find all events that were active at any time during a given time interval, or all events that started during a particular time interval, or all events that both started and ended within a given time interval. And so forth. </p> <p> The R-Tree concept originated with |
︙ | ︙ | |||
50 51 52 53 54 55 56 | The SQLite R*Tree module is implemented as a [sqlite3_create_module | virtual table]. ^Each R*Tree index is a virtual table with an odd number of columns between 3 and 11. ^The first column is always a 64-bit signed integer primary key. ^The other columns are minimum- and maximum-value pairs (stored as 32-bit floating point numbers) for each dimension. ^A 1-dimensional R*Tree thus has 3 columns. | | > > | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | The SQLite R*Tree module is implemented as a [sqlite3_create_module | virtual table]. ^Each R*Tree index is a virtual table with an odd number of columns between 3 and 11. ^The first column is always a 64-bit signed integer primary key. ^The other columns are minimum- and maximum-value pairs (stored as 32-bit floating point numbers) for each dimension. ^A 1-dimensional R*Tree thus has 3 columns. ^A 2-dimensional R*Tree has 5 columns. ^A 3-dimensional R*Tree has 7 columns. ^A 4-dimensional R*Tree has 9 columns. ^And a 5-dimensional R*Tree has 11 columns. The SQLite R*Tree implementation does not support R*Trees wider than 5 dimensions. </p> <p> ^The first column of an SQLite R*Tree must always be an integer primary key. ^The min/max-value pair columns are always stored as |
︙ | ︙ | |||
98 99 100 101 102 103 104 | <p> ^The shadow tables are ordinary SQLite data tables. You can query them directly if you like, though this unlikely to reveal anything particularly useful. ^And you can [UPDATE], [DELETE], [INSERT] or even [DROP TABLE | DROP] the shadow tables, though doing so will corrupt your R*Tree index. So it is best to simply ignore the shadow tables. Recognize that they | | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | <p> ^The shadow tables are ordinary SQLite data tables. You can query them directly if you like, though this unlikely to reveal anything particularly useful. ^And you can [UPDATE], [DELETE], [INSERT] or even [DROP TABLE | DROP] the shadow tables, though doing so will corrupt your R*Tree index. So it is best to simply ignore the shadow tables. Recognize that they hold your R*Tree index information and let it go as that. </p> <p> ^(As an example, consider creating a two-dimensional R*Tree index for use in spatial queries: </p> |
︙ | ︙ | |||
191 192 193 194 195 196 197 | ^(This second query would find both entry 1 (the SQLite.org office) which is entirely contained within the query box and also the 12th Congressional District which extends well outside the query box but still overlaps the query box.)^ </p> <p> | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | ^(This second query would find both entry 1 (the SQLite.org office) which is entirely contained within the query box and also the 12th Congressional District which extends well outside the query box but still overlaps the query box.)^ </p> <p> ^Note that it is not necessary for all coordinates in an R*Tree index to be constrained in order for the index search to be efficient. ^(One might, for example, want to query all objects that overlap with the 35th parallel: </p> <blockquote><pre> SELECT id FROM demo_index |
︙ | ︙ | |||
340 341 342 343 344 345 346 | virtual tables store 32-bit integers and only integer values are used for internal computations. <tcl>hd_fragment {customquery} {custom r-tree queries}</tcl> <h2>6.0 Custom R-Tree Queries</h2> <p>By using standard SQL expressions in the WHERE clause of a SELECT query, | | | | | | > > > | | | > > > > > > > | | | | < < > | > | < | < < | < < < < < < < < < < < < | < < > | | | < < | | < | | | > > > | | | > > | > | > > > | > > | | | < | | | | | | > | > > > | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | virtual tables store 32-bit integers and only integer values are used for internal computations. <tcl>hd_fragment {customquery} {custom r-tree queries}</tcl> <h2>6.0 Custom R-Tree Queries</h2> <p>By using standard SQL expressions in the WHERE clause of a SELECT query, a programmer can query for all R*Tree entries that have a spatial relationship (they intersect with or are contained within) a particular bounding-box. Custom R*Tree queries, using the MATCH operator in the WHERE clause of a SELECT, allow the programmer to query for the set of R*Tree entries that intersect any arbitrary region or shape, not just a box. This capability is useful, for example, in computing the subset of objects in the R*Tree that are visible from a camera positioned in 3-D space. <p>Regions for custom R*Tree queries are defined by R*Tree geometry callbacks implemented by the application and registered with SQLite via a call to one of the following two APIs: <blockquote><pre> int sqlite3_rtree_query_callback( sqlite3 *db, const char *zQueryFunc, int (*xQueryFunc)(sqlite3_rtree_query_info*), void *pContext, void (*xDestructor)(void*) ); int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), void *pContext ); </pre></blockquote> <p>The sqlite3_rtree_query_callback() became available with SQLite [version 3.8.5] and is the preferred interface. The sqlite3_rtree_geometry_callback() is an older and less flexible interface that is supported for backwards compatiblity. <p>A call to one of the above APIs creates a new SQL function named by the second parameter (zQueryFunc or zGeom). When that SQL function appears on the right-hand side of the MATCH operator and the left-hand side of the MATCH operator is any column in the R*Tree virtual table, then the callback defined by the third argument (xQueryFunc or xGeom) is invoked to determine if a particular object or subtree overlaps the desired region. <p>For example, a query like the following might be used to find all R*Tree entries that overlap with a circle centered a 45.3,22.9 with a radius of 5.0: <blockquote><pre> SELECT id FROM demo_index WHERE id MATCH circle(45.3, 22.9, 5.0) </blockquote></pre> <p>The SQL syntax for custom queries is the same regardless of which interface, sqlite3_rtree_geometry_callback() or sqlite3_rtree_query_callback(), is used to register the SQL function. However, the newer query-style callbacks give the application greater control over how the query proceeds. <h3>6.1 The Legacy xGeom Callback</h3> <p>The legacy xGeom callback is invoked with four arguments. The first argument is a pointer to an sqlite3_rtree_geometry structure which provides information about how the SQL function was invoked. The second argument is the number of coordinates in each r-tree entry, and is always the same for any given R*Tree. The number coordinates is 2 for a 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a 3-dimensional R*Tree, and so forth. The third argument, aCoord[], is an array of nCoord coordinates that defines a bounding box to be tested. The last argument is a pointer into which the callback result should be written. The result is zero if the bounding-box defined by aCoord[] is completely outside the region defined by the xGeom callback and the result is non-zero if the bounding-box is inside or overlaps with the xGeom region. The xGeom callback should normally return SQLITE_OK. If xGeom returns anything other than SQLITE_OK, then the r-tree query will abort with an error. <p>The sqlite3_rtree_geometry structure that the first argument to the xGeom callback points to has a structure shown below. The exact same structure is used for every callback for same MATCH operator in the same query. The contents of the structure are initialized by SQLite but are not subsequently modifed. The callback is free to make changes to the pUser and xDelUser elements of the structure if desired. <blockquote><pre> typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; struct sqlite3_rtree_geometry { void *pContext; /* Copy of pContext passed to s_r_g_c() */ int nParam; /* Size of array aParam */ double *aParam; /* Parameters passed to SQL geom function */ void *pUser; /* Callback implementation user data */ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ }; </pre></blockquote> <p>The pContext member of the structure is always set to a copy of the pContext argument passed to sqlite3_rtree_geometry_callback() when the callback is registered. The aParam[] array (size nParam) contains the parameter values passed to the SQL function on the right-hand side of the MATCH operator. In the example "circle" query above, nParam would be set to 3 and the aParam[] array would contain the three values 45.3, 22.9 and 5.0. <p>The pUser and xDelUser members of the sqlite3_rtree_geometry structure are initially set to NULL. The pUser variable may be set by the callback implementation to any arbitrary value that may be useful to subsequent invocations of the callback within the same query (for example, a pointer to a complicated data structure used to test for region intersection). If the xDelUser variable is set to a non-NULL value, then after the query has finished running SQLite automatically invokes it with the value of the pUser variable as the only argument. In other words, xDelUser may be set to a destructor function for the pUser value. <p>The xGeom callback always does a depth-first search of the r-tree. <tcl>hd_fragment xquery {xQueryFunc R*Tree callback} {sqlite3_rtree_query_callback} </tcl> <h3>6.2 The New xQueryFunc Callback</h3> <p>The newer xQueryFunc callback receives more information from the r-tree query engine on each call, and it send more information back to the query engine before it returns. To help keep the interface manageable, the xQueryFunc callback sends and receives information from the query engine as fields in the sqlite3_rtree_query_info structure: <blockquote><pre> struct sqlite3_rtree_query_info { void *pContext; /* pContext from when function registered */ int nParam; /* Number of function parameters */ sqlite3_rtree_dbl *aParam; /* value of function parameters */ void *pUser; /* callback can use this, if desired */ void (*xDelUser)(void*); /* function to free pUser */ sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ unsigned int *anQueue; /* Number of pending entries in the queue */ int nCoord; /* Number of coordinates */ int iLevel; /* Level of current node or entry */ int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ int eWithin; /* OUT: Visiblity */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ }; </pre></blockquote> <p>The first five fields of the sqlite3_rtree_query_info structure are identical to the sqlite3_rtree_geometry structure, and have exactly the same meaning. The sqlite3_rtree_query_info structure also contains nCoord and aCoord fields which have the same meaning as the parameter of the same name in the xGeom callback. <p>The xQueryFunc must set the eWithin field of sqlite3_rtree_query_info to on of the values NOT_WITHIN, PARTLY_WITHIN, or FULLY_WITHIN depending on whether or not the bounding box defined by aCoord[] is completely outside the region, overlaps the region, or is completely inside the region, respectively. In addition, the xQueryFunc must set the rScore field to a non-negative value that indicates the order in which subtrees and entries of the query should be analyzed and returned. Smaller scores are processed first. <p>As its name implies, an R*Tree is organized as a tree. Each node of the tree is a bounding box. The root of the tree is a bounding box that encapsulates all elements of the tree. Beneath the root are a number of subtrees (typically 20 or more) each with their own smaller bounding boxes and each containing some subset of the R*Tree entries. The subtrees may have sub-subtrees, and so forth until finally one reaches the leaves of the tree which are the actual R*Tree entries. <p>An R*Tree query is initialized by making the root node the only entry in a priority queue sorted by rScore. The query proceeds by extracting the entry from the priority queue that has the lowest score. If that entry is a leaf (meaning that it is an actual R*Tree entry and not a subtree) then that entry is returned as one row of the query result. If the extracted priority queue entry is a node (a subtree), then sub-subtrees or leaves contained within that entry are passed to the xQueryFunc callback, one by one. Those subelements for which the xQueryFunc callback sets eWithin to PARTLY_WITHIN or FULLY_WITHIN are added to the priority queue using the score supplied by the callback. Subelements that return NOT_WITHIN are discarded. The query runs until the priority queue is empty. <p>Every leaf entry and node (subtree) within the R*Tree has an integer "level". The leaves have a level of 0. The first containing subtree of the leaves has a level of 1. The root of the R*Tree has the largest level value. The mxLevel entry in the sqlite3_rtree_query_info structure is the level value for the root of the R*Tree. The iLevel entry in sqlite3_rtree_query_info gives the level for the object being interrogated. <p>Most R*Tree queries use a depth-first search. This is accomplished by setting the rScore equal to iLevel. A depth-first search is usually preferred since it minimizes the number of elements in the priority queue, which reduces memory requirements and speeds processing. However, some application may prefer a breadth-first search, which can be accomplished by setting rScore to mxLevel-iLevel. By creating more complex formulas for rScore, applications can exercise detailed control over the order in which subtree are searched and leaf R*Tree entries are returned. For example, in an application with many millions of R*Tree entries, the rScore might be arranged so that the largest or most significant entries are returned first, allowing the application to display the most important information quickly, and filling in smaller and less important details as they become available. <p>Other information fields of the sqlite3_rtree_query_info structure are available for use by the xQueryFunc callback, if desired. The iRowid field is the rowid (the first of the 3 to 11 columns in the R*Tree) for the element being considered. iRowid is only valid for leaves. The eParentWithin and rParentScore values are copies of the eWithin and rScore values from the containing subtree of the current row. The anQueue field is an array of mxLevel+1 unsigned integers that tell the current number of elements in the priority queue at each level. |