| 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 ** |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 /* | 344 /* |
| 345 ** An instance of this structure (in the form of a BLOB) is returned by | 345 ** An instance of this structure (in the form of a BLOB) is returned by |
| 346 ** the SQL functions that sqlite3_rtree_geometry_callback() and | 346 ** the SQL functions that sqlite3_rtree_geometry_callback() and |
| 347 ** sqlite3_rtree_query_callback() create, and is read as the right-hand | 347 ** sqlite3_rtree_query_callback() create, and is read as the right-hand |
| 348 ** operand to the MATCH operator of an R-Tree. | 348 ** operand to the MATCH operator of an R-Tree. |
| 349 */ | 349 */ |
| 350 struct RtreeMatchArg { | 350 struct RtreeMatchArg { |
| 351 u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ | 351 u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ |
| 352 RtreeGeomCallback cb; /* Info about the callback functions */ | 352 RtreeGeomCallback cb; /* Info about the callback functions */ |
| 353 int nParam; /* Number of parameters to the SQL function */ | 353 int nParam; /* Number of parameters to the SQL function */ |
| 354 sqlite3_value **apSqlParam; /* Original SQL parameter values */ |
| 354 RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ | 355 RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ |
| 355 }; | 356 }; |
| 356 | 357 |
| 357 #ifndef MAX | 358 #ifndef MAX |
| 358 # define MAX(x,y) ((x) < (y) ? (y) : (x)) | 359 # define MAX(x,y) ((x) < (y) ? (y) : (x)) |
| 359 #endif | 360 #endif |
| 360 #ifndef MIN | 361 #ifndef MIN |
| 361 # define MIN(x,y) ((x) > (y) ? (y) : (x)) | 362 # define MIN(x,y) ((x) > (y) ? (y) : (x)) |
| 362 #endif | 363 #endif |
| 363 | 364 |
| 364 /* | 365 /* |
| 365 ** Functions to deserialize a 16 bit integer, 32 bit real number and | 366 ** Functions to deserialize a 16 bit integer, 32 bit real number and |
| 366 ** 64 bit integer. The deserialized value is returned. | 367 ** 64 bit integer. The deserialized value is returned. |
| 367 */ | 368 */ |
| 368 static int readInt16(u8 *p){ | 369 static int readInt16(u8 *p){ |
| 369 return (p[0]<<8) + p[1]; | 370 return (p[0]<<8) + p[1]; |
| 370 } | 371 } |
| 371 static void readCoord(u8 *p, RtreeCoord *pCoord){ | 372 static void readCoord(u8 *p, RtreeCoord *pCoord){ |
| 372 u32 i = ( | 373 pCoord->u = ( |
| 373 (((u32)p[0]) << 24) + | 374 (((u32)p[0]) << 24) + |
| 374 (((u32)p[1]) << 16) + | 375 (((u32)p[1]) << 16) + |
| 375 (((u32)p[2]) << 8) + | 376 (((u32)p[2]) << 8) + |
| 376 (((u32)p[3]) << 0) | 377 (((u32)p[3]) << 0) |
| 377 ); | 378 ); |
| 378 *(u32 *)pCoord = i; | |
| 379 } | 379 } |
| 380 static i64 readInt64(u8 *p){ | 380 static i64 readInt64(u8 *p){ |
| 381 return ( | 381 return ( |
| 382 (((i64)p[0]) << 56) + | 382 (((i64)p[0]) << 56) + |
| 383 (((i64)p[1]) << 48) + | 383 (((i64)p[1]) << 48) + |
| 384 (((i64)p[2]) << 40) + | 384 (((i64)p[2]) << 40) + |
| 385 (((i64)p[3]) << 32) + | 385 (((i64)p[3]) << 32) + |
| 386 (((i64)p[4]) << 24) + | 386 (((i64)p[4]) << 24) + |
| 387 (((i64)p[5]) << 16) + | 387 (((i64)p[5]) << 16) + |
| 388 (((i64)p[6]) << 8) + | 388 (((i64)p[6]) << 8) + |
| 389 (((i64)p[7]) << 0) | 389 (((i64)p[7]) << 0) |
| 390 ); | 390 ); |
| 391 } | 391 } |
| 392 | 392 |
| 393 /* | 393 /* |
| 394 ** Functions to serialize a 16 bit integer, 32 bit real number and | 394 ** Functions to serialize a 16 bit integer, 32 bit real number and |
| 395 ** 64 bit integer. The value returned is the number of bytes written | 395 ** 64 bit integer. The value returned is the number of bytes written |
| 396 ** to the argument buffer (always 2, 4 and 8 respectively). | 396 ** to the argument buffer (always 2, 4 and 8 respectively). |
| 397 */ | 397 */ |
| 398 static int writeInt16(u8 *p, int i){ | 398 static int writeInt16(u8 *p, int i){ |
| 399 p[0] = (i>> 8)&0xFF; | 399 p[0] = (i>> 8)&0xFF; |
| 400 p[1] = (i>> 0)&0xFF; | 400 p[1] = (i>> 0)&0xFF; |
| 401 return 2; | 401 return 2; |
| 402 } | 402 } |
| 403 static int writeCoord(u8 *p, RtreeCoord *pCoord){ | 403 static int writeCoord(u8 *p, RtreeCoord *pCoord){ |
| 404 u32 i; | 404 u32 i; |
| 405 assert( sizeof(RtreeCoord)==4 ); | 405 assert( sizeof(RtreeCoord)==4 ); |
| 406 assert( sizeof(u32)==4 ); | 406 assert( sizeof(u32)==4 ); |
| 407 i = *(u32 *)pCoord; | 407 i = pCoord->u; |
| 408 p[0] = (i>>24)&0xFF; | 408 p[0] = (i>>24)&0xFF; |
| 409 p[1] = (i>>16)&0xFF; | 409 p[1] = (i>>16)&0xFF; |
| 410 p[2] = (i>> 8)&0xFF; | 410 p[2] = (i>> 8)&0xFF; |
| 411 p[3] = (i>> 0)&0xFF; | 411 p[3] = (i>> 0)&0xFF; |
| 412 return 4; | 412 return 4; |
| 413 } | 413 } |
| 414 static int writeInt64(u8 *p, i64 i){ | 414 static int writeInt64(u8 *p, i64 i){ |
| 415 p[0] = (i>>56)&0xFF; | 415 p[0] = (i>>56)&0xFF; |
| 416 p[1] = (i>>48)&0xFF; | 416 p[1] = (i>>48)&0xFF; |
| 417 p[2] = (i>>40)&0xFF; | 417 p[2] = (i>>40)&0xFF; |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 ** Deserialize cell iCell of node pNode. Populate the structure pointed | 728 ** Deserialize cell iCell of node pNode. Populate the structure pointed |
| 729 ** to by pCell with the results. | 729 ** to by pCell with the results. |
| 730 */ | 730 */ |
| 731 static void nodeGetCell( | 731 static void nodeGetCell( |
| 732 Rtree *pRtree, /* The overall R-Tree */ | 732 Rtree *pRtree, /* The overall R-Tree */ |
| 733 RtreeNode *pNode, /* The node containing the cell to be read */ | 733 RtreeNode *pNode, /* The node containing the cell to be read */ |
| 734 int iCell, /* Index of the cell within the node */ | 734 int iCell, /* Index of the cell within the node */ |
| 735 RtreeCell *pCell /* OUT: Write the cell contents here */ | 735 RtreeCell *pCell /* OUT: Write the cell contents here */ |
| 736 ){ | 736 ){ |
| 737 u8 *pData; | 737 u8 *pData; |
| 738 u8 *pEnd; | |
| 739 RtreeCoord *pCoord; | 738 RtreeCoord *pCoord; |
| 739 int ii; |
| 740 pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); | 740 pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); |
| 741 pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); | 741 pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); |
| 742 pEnd = pData + pRtree->nDim*8; | |
| 743 pCoord = pCell->aCoord; | 742 pCoord = pCell->aCoord; |
| 744 for(; pData<pEnd; pData+=4, pCoord++){ | 743 for(ii=0; ii<pRtree->nDim*2; ii++){ |
| 745 readCoord(pData, pCoord); | 744 readCoord(&pData[ii*4], &pCoord[ii]); |
| 746 } | 745 } |
| 747 } | 746 } |
| 748 | 747 |
| 749 | 748 |
| 750 /* Forward declaration for the function that does the work of | 749 /* Forward declaration for the function that does the work of |
| 751 ** the virtual table module xCreate() and xConnect() methods. | 750 ** the virtual table module xCreate() and xConnect() methods. |
| 752 */ | 751 */ |
| 753 static int rtreeInit( | 752 static int rtreeInit( |
| 754 sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int | 753 sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int |
| 755 ); | 754 ); |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 int nNew = pCur->nPointAlloc*2 + 8; | 1174 int nNew = pCur->nPointAlloc*2 + 8; |
| 1176 pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); | 1175 pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); |
| 1177 if( pNew==0 ) return 0; | 1176 if( pNew==0 ) return 0; |
| 1178 pCur->aPoint = pNew; | 1177 pCur->aPoint = pNew; |
| 1179 pCur->nPointAlloc = nNew; | 1178 pCur->nPointAlloc = nNew; |
| 1180 } | 1179 } |
| 1181 i = pCur->nPoint++; | 1180 i = pCur->nPoint++; |
| 1182 pNew = pCur->aPoint + i; | 1181 pNew = pCur->aPoint + i; |
| 1183 pNew->rScore = rScore; | 1182 pNew->rScore = rScore; |
| 1184 pNew->iLevel = iLevel; | 1183 pNew->iLevel = iLevel; |
| 1185 assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); | 1184 assert( iLevel<=RTREE_MAX_DEPTH ); |
| 1186 while( i>0 ){ | 1185 while( i>0 ){ |
| 1187 RtreeSearchPoint *pParent; | 1186 RtreeSearchPoint *pParent; |
| 1188 j = (i-1)/2; | 1187 j = (i-1)/2; |
| 1189 pParent = pCur->aPoint + j; | 1188 pParent = pCur->aPoint + j; |
| 1190 if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; | 1189 if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 1191 rtreeSearchPointSwap(pCur, j, i); | 1190 rtreeSearchPointSwap(pCur, j, i); |
| 1192 i = j; | 1191 i = j; |
| 1193 pNew = pParent; | 1192 pNew = pParent; |
| 1194 } | 1193 } |
| 1195 return pNew; | 1194 return pNew; |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1477 RtreeMatchArg *pBlob; /* BLOB returned by geometry function */ | 1476 RtreeMatchArg *pBlob; /* BLOB returned by geometry function */ |
| 1478 sqlite3_rtree_query_info *pInfo; /* Callback information */ | 1477 sqlite3_rtree_query_info *pInfo; /* Callback information */ |
| 1479 int nBlob; /* Size of the geometry function blob */ | 1478 int nBlob; /* Size of the geometry function blob */ |
| 1480 int nExpected; /* Expected size of the BLOB */ | 1479 int nExpected; /* Expected size of the BLOB */ |
| 1481 | 1480 |
| 1482 /* Check that value is actually a blob. */ | 1481 /* Check that value is actually a blob. */ |
| 1483 if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; | 1482 if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; |
| 1484 | 1483 |
| 1485 /* Check that the blob is roughly the right size. */ | 1484 /* Check that the blob is roughly the right size. */ |
| 1486 nBlob = sqlite3_value_bytes(pValue); | 1485 nBlob = sqlite3_value_bytes(pValue); |
| 1487 if( nBlob<(int)sizeof(RtreeMatchArg) | 1486 if( nBlob<(int)sizeof(RtreeMatchArg) ){ |
| 1488 || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 | |
| 1489 ){ | |
| 1490 return SQLITE_ERROR; | 1487 return SQLITE_ERROR; |
| 1491 } | 1488 } |
| 1492 | 1489 |
| 1493 pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); | 1490 pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); |
| 1494 if( !pInfo ) return SQLITE_NOMEM; | 1491 if( !pInfo ) return SQLITE_NOMEM; |
| 1495 memset(pInfo, 0, sizeof(*pInfo)); | 1492 memset(pInfo, 0, sizeof(*pInfo)); |
| 1496 pBlob = (RtreeMatchArg*)&pInfo[1]; | 1493 pBlob = (RtreeMatchArg*)&pInfo[1]; |
| 1497 | 1494 |
| 1498 memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); | 1495 memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); |
| 1499 nExpected = (int)(sizeof(RtreeMatchArg) + | 1496 nExpected = (int)(sizeof(RtreeMatchArg) + |
| 1497 pBlob->nParam*sizeof(sqlite3_value*) + |
| 1500 (pBlob->nParam-1)*sizeof(RtreeDValue)); | 1498 (pBlob->nParam-1)*sizeof(RtreeDValue)); |
| 1501 if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ | 1499 if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ |
| 1502 sqlite3_free(pInfo); | 1500 sqlite3_free(pInfo); |
| 1503 return SQLITE_ERROR; | 1501 return SQLITE_ERROR; |
| 1504 } | 1502 } |
| 1505 pInfo->pContext = pBlob->cb.pContext; | 1503 pInfo->pContext = pBlob->cb.pContext; |
| 1506 pInfo->nParam = pBlob->nParam; | 1504 pInfo->nParam = pBlob->nParam; |
| 1507 pInfo->aParam = pBlob->aParam; | 1505 pInfo->aParam = pBlob->aParam; |
| 1506 pInfo->apSqlParam = pBlob->apSqlParam; |
| 1508 | 1507 |
| 1509 if( pBlob->cb.xGeom ){ | 1508 if( pBlob->cb.xGeom ){ |
| 1510 pCons->u.xGeom = pBlob->cb.xGeom; | 1509 pCons->u.xGeom = pBlob->cb.xGeom; |
| 1511 }else{ | 1510 }else{ |
| 1512 pCons->op = RTREE_QUERY; | 1511 pCons->op = RTREE_QUERY; |
| 1513 pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; | 1512 pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; |
| 1514 } | 1513 } |
| 1515 pCons->pInfo = pInfo; | 1514 pCons->pInfo = pInfo; |
| 1516 return SQLITE_OK; | 1515 return SQLITE_OK; |
| 1517 } | 1516 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1664 ** ---------------------- | 1663 ** ---------------------- |
| 1665 ** | 1664 ** |
| 1666 ** The second of each pair of bytes identifies the coordinate column | 1665 ** The second of each pair of bytes identifies the coordinate column |
| 1667 ** to which the constraint applies. The leftmost coordinate column | 1666 ** to which the constraint applies. The leftmost coordinate column |
| 1668 ** is 'a', the second from the left 'b' etc. | 1667 ** is 'a', the second from the left 'b' etc. |
| 1669 */ | 1668 */ |
| 1670 static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ | 1669 static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
| 1671 Rtree *pRtree = (Rtree*)tab; | 1670 Rtree *pRtree = (Rtree*)tab; |
| 1672 int rc = SQLITE_OK; | 1671 int rc = SQLITE_OK; |
| 1673 int ii; | 1672 int ii; |
| 1673 int bMatch = 0; /* True if there exists a MATCH constraint */ |
| 1674 i64 nRow; /* Estimated rows returned by this scan */ | 1674 i64 nRow; /* Estimated rows returned by this scan */ |
| 1675 | 1675 |
| 1676 int iIdx = 0; | 1676 int iIdx = 0; |
| 1677 char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; | 1677 char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; |
| 1678 memset(zIdxStr, 0, sizeof(zIdxStr)); | 1678 memset(zIdxStr, 0, sizeof(zIdxStr)); |
| 1679 | 1679 |
| 1680 /* Check if there exists a MATCH constraint - even an unusable one. If there |
| 1681 ** is, do not consider the lookup-by-rowid plan as using such a plan would |
| 1682 ** require the VDBE to evaluate the MATCH constraint, which is not currently |
| 1683 ** possible. */ |
| 1684 for(ii=0; ii<pIdxInfo->nConstraint; ii++){ |
| 1685 if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ |
| 1686 bMatch = 1; |
| 1687 } |
| 1688 } |
| 1689 |
| 1680 assert( pIdxInfo->idxStr==0 ); | 1690 assert( pIdxInfo->idxStr==0 ); |
| 1681 for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ | 1691 for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ |
| 1682 struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; | 1692 struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; |
| 1683 | 1693 |
| 1684 if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ | 1694 if( bMatch==0 && p->usable |
| 1695 && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ |
| 1696 ){ |
| 1685 /* We have an equality constraint on the rowid. Use strategy 1. */ | 1697 /* We have an equality constraint on the rowid. Use strategy 1. */ |
| 1686 int jj; | 1698 int jj; |
| 1687 for(jj=0; jj<ii; jj++){ | 1699 for(jj=0; jj<ii; jj++){ |
| 1688 pIdxInfo->aConstraintUsage[jj].argvIndex = 0; | 1700 pIdxInfo->aConstraintUsage[jj].argvIndex = 0; |
| 1689 pIdxInfo->aConstraintUsage[jj].omit = 0; | 1701 pIdxInfo->aConstraintUsage[jj].omit = 0; |
| 1690 } | 1702 } |
| 1691 pIdxInfo->idxNum = 1; | 1703 pIdxInfo->idxNum = 1; |
| 1692 pIdxInfo->aConstraintUsage[ii].argvIndex = 1; | 1704 pIdxInfo->aConstraintUsage[ii].argvIndex = 1; |
| 1693 pIdxInfo->aConstraintUsage[jj].omit = 1; | 1705 pIdxInfo->aConstraintUsage[jj].omit = 1; |
| 1694 | 1706 |
| (...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2799 sqlite_int64 *pRowid | 2811 sqlite_int64 *pRowid |
| 2800 ){ | 2812 ){ |
| 2801 Rtree *pRtree = (Rtree *)pVtab; | 2813 Rtree *pRtree = (Rtree *)pVtab; |
| 2802 int rc = SQLITE_OK; | 2814 int rc = SQLITE_OK; |
| 2803 RtreeCell cell; /* New cell to insert if nData>1 */ | 2815 RtreeCell cell; /* New cell to insert if nData>1 */ |
| 2804 int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ | 2816 int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ |
| 2805 | 2817 |
| 2806 rtreeReference(pRtree); | 2818 rtreeReference(pRtree); |
| 2807 assert(nData>=1); | 2819 assert(nData>=1); |
| 2808 | 2820 |
| 2821 cell.iRowid = 0; /* Used only to suppress a compiler warning */ |
| 2822 |
| 2809 /* Constraint handling. A write operation on an r-tree table may return | 2823 /* Constraint handling. A write operation on an r-tree table may return |
| 2810 ** SQLITE_CONSTRAINT for two reasons: | 2824 ** SQLITE_CONSTRAINT for two reasons: |
| 2811 ** | 2825 ** |
| 2812 ** 1. A duplicate rowid value, or | 2826 ** 1. A duplicate rowid value, or |
| 2813 ** 2. The supplied data violates the "x2>=x1" constraint. | 2827 ** 2. The supplied data violates the "x2>=x1" constraint. |
| 2814 ** | 2828 ** |
| 2815 ** In the first case, if the conflict-handling mode is REPLACE, then | 2829 ** In the first case, if the conflict-handling mode is REPLACE, then |
| 2816 ** the conflicting row can be removed before proceeding. In the second | 2830 ** the conflicting row can be removed before proceeding. In the second |
| 2817 ** case, SQLITE_CONSTRAINT must be returned regardless of the | 2831 ** case, SQLITE_CONSTRAINT must be returned regardless of the |
| 2818 ** conflict-handling mode specified by the user. | 2832 ** conflict-handling mode specified by the user. |
| 2819 */ | 2833 */ |
| 2820 if( nData>1 ){ | 2834 if( nData>1 ){ |
| 2821 int ii; | 2835 int ii; |
| 2822 | 2836 |
| 2823 /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ | 2837 /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. |
| 2824 assert( nData==(pRtree->nDim*2 + 3) ); | 2838 ** |
| 2839 ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared |
| 2840 ** with "column" that are interpreted as table constraints. |
| 2841 ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5)); |
| 2842 ** This problem was discovered after years of use, so we silently ignore |
| 2843 ** these kinds of misdeclared tables to avoid breaking any legacy. |
| 2844 */ |
| 2845 assert( nData<=(pRtree->nDim*2 + 3) ); |
| 2846 |
| 2825 #ifndef SQLITE_RTREE_INT_ONLY | 2847 #ifndef SQLITE_RTREE_INT_ONLY |
| 2826 if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ | 2848 if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ |
| 2827 for(ii=0; ii<(pRtree->nDim*2); ii+=2){ | 2849 for(ii=0; ii<nData-4; ii+=2){ |
| 2828 cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); | 2850 cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); |
| 2829 cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); | 2851 cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); |
| 2830 if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ | 2852 if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ |
| 2831 rc = SQLITE_CONSTRAINT; | 2853 rc = SQLITE_CONSTRAINT; |
| 2832 goto constraint; | 2854 goto constraint; |
| 2833 } | 2855 } |
| 2834 } | 2856 } |
| 2835 }else | 2857 }else |
| 2836 #endif | 2858 #endif |
| 2837 { | 2859 { |
| 2838 for(ii=0; ii<(pRtree->nDim*2); ii+=2){ | 2860 for(ii=0; ii<nData-4; ii+=2){ |
| 2839 cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); | 2861 cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); |
| 2840 cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); | 2862 cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); |
| 2841 if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ | 2863 if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ |
| 2842 rc = SQLITE_CONSTRAINT; | 2864 rc = SQLITE_CONSTRAINT; |
| 2843 goto constraint; | 2865 goto constraint; |
| 2844 } | 2866 } |
| 2845 } | 2867 } |
| 2846 } | 2868 } |
| 2847 | 2869 |
| 2848 /* If a rowid value was supplied, check if it is already present in | 2870 /* If a rowid value was supplied, check if it is already present in |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3358 ** destructor for an RtreeGeomCallback objecct. This routine is called when | 3380 ** destructor for an RtreeGeomCallback objecct. This routine is called when |
| 3359 ** the corresponding SQL function is deleted. | 3381 ** the corresponding SQL function is deleted. |
| 3360 */ | 3382 */ |
| 3361 static void rtreeFreeCallback(void *p){ | 3383 static void rtreeFreeCallback(void *p){ |
| 3362 RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p; | 3384 RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p; |
| 3363 if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext); | 3385 if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext); |
| 3364 sqlite3_free(p); | 3386 sqlite3_free(p); |
| 3365 } | 3387 } |
| 3366 | 3388 |
| 3367 /* | 3389 /* |
| 3390 ** This routine frees the BLOB that is returned by geomCallback(). |
| 3391 */ |
| 3392 static void rtreeMatchArgFree(void *pArg){ |
| 3393 int i; |
| 3394 RtreeMatchArg *p = (RtreeMatchArg*)pArg; |
| 3395 for(i=0; i<p->nParam; i++){ |
| 3396 sqlite3_value_free(p->apSqlParam[i]); |
| 3397 } |
| 3398 sqlite3_free(p); |
| 3399 } |
| 3400 |
| 3401 /* |
| 3368 ** Each call to sqlite3_rtree_geometry_callback() or | 3402 ** Each call to sqlite3_rtree_geometry_callback() or |
| 3369 ** sqlite3_rtree_query_callback() creates an ordinary SQLite | 3403 ** sqlite3_rtree_query_callback() creates an ordinary SQLite |
| 3370 ** scalar function that is implemented by this routine. | 3404 ** scalar function that is implemented by this routine. |
| 3371 ** | 3405 ** |
| 3372 ** All this function does is construct an RtreeMatchArg object that | 3406 ** All this function does is construct an RtreeMatchArg object that |
| 3373 ** contains the geometry-checking callback routines and a list of | 3407 ** contains the geometry-checking callback routines and a list of |
| 3374 ** parameters to this function, then return that RtreeMatchArg object | 3408 ** parameters to this function, then return that RtreeMatchArg object |
| 3375 ** as a BLOB. | 3409 ** as a BLOB. |
| 3376 ** | 3410 ** |
| 3377 ** The R-Tree MATCH operator will read the returned BLOB, deserialize | 3411 ** The R-Tree MATCH operator will read the returned BLOB, deserialize |
| 3378 ** the RtreeMatchArg object, and use the RtreeMatchArg object to figure | 3412 ** the RtreeMatchArg object, and use the RtreeMatchArg object to figure |
| 3379 ** out which elements of the R-Tree should be returned by the query. | 3413 ** out which elements of the R-Tree should be returned by the query. |
| 3380 */ | 3414 */ |
| 3381 static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ | 3415 static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ |
| 3382 RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); | 3416 RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); |
| 3383 RtreeMatchArg *pBlob; | 3417 RtreeMatchArg *pBlob; |
| 3384 int nBlob; | 3418 int nBlob; |
| 3419 int memErr = 0; |
| 3385 | 3420 |
| 3386 nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue); | 3421 nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue) |
| 3422 + nArg*sizeof(sqlite3_value*); |
| 3387 pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); | 3423 pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); |
| 3388 if( !pBlob ){ | 3424 if( !pBlob ){ |
| 3389 sqlite3_result_error_nomem(ctx); | 3425 sqlite3_result_error_nomem(ctx); |
| 3390 }else{ | 3426 }else{ |
| 3391 int i; | 3427 int i; |
| 3392 pBlob->magic = RTREE_GEOMETRY_MAGIC; | 3428 pBlob->magic = RTREE_GEOMETRY_MAGIC; |
| 3393 pBlob->cb = pGeomCtx[0]; | 3429 pBlob->cb = pGeomCtx[0]; |
| 3430 pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg]; |
| 3394 pBlob->nParam = nArg; | 3431 pBlob->nParam = nArg; |
| 3395 for(i=0; i<nArg; i++){ | 3432 for(i=0; i<nArg; i++){ |
| 3433 pBlob->apSqlParam[i] = sqlite3_value_dup(aArg[i]); |
| 3434 if( pBlob->apSqlParam[i]==0 ) memErr = 1; |
| 3396 #ifdef SQLITE_RTREE_INT_ONLY | 3435 #ifdef SQLITE_RTREE_INT_ONLY |
| 3397 pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); | 3436 pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); |
| 3398 #else | 3437 #else |
| 3399 pBlob->aParam[i] = sqlite3_value_double(aArg[i]); | 3438 pBlob->aParam[i] = sqlite3_value_double(aArg[i]); |
| 3400 #endif | 3439 #endif |
| 3401 } | 3440 } |
| 3402 sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free); | 3441 if( memErr ){ |
| 3442 sqlite3_result_error_nomem(ctx); |
| 3443 rtreeMatchArgFree(pBlob); |
| 3444 }else{ |
| 3445 sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree); |
| 3446 } |
| 3403 } | 3447 } |
| 3404 } | 3448 } |
| 3405 | 3449 |
| 3406 /* | 3450 /* |
| 3407 ** Register a new geometry function for use with the r-tree MATCH operator. | 3451 ** Register a new geometry function for use with the r-tree MATCH operator. |
| 3408 */ | 3452 */ |
| 3409 int sqlite3_rtree_geometry_callback( | 3453 int sqlite3_rtree_geometry_callback( |
| 3410 sqlite3 *db, /* Register SQL function on this connection */ | 3454 sqlite3 *db, /* Register SQL function on this connection */ |
| 3411 const char *zGeom, /* Name of the new SQL function */ | 3455 const char *zGeom, /* Name of the new SQL function */ |
| 3412 int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ | 3456 int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3459 sqlite3 *db, | 3503 sqlite3 *db, |
| 3460 char **pzErrMsg, | 3504 char **pzErrMsg, |
| 3461 const sqlite3_api_routines *pApi | 3505 const sqlite3_api_routines *pApi |
| 3462 ){ | 3506 ){ |
| 3463 SQLITE_EXTENSION_INIT2(pApi) | 3507 SQLITE_EXTENSION_INIT2(pApi) |
| 3464 return sqlite3RtreeInit(db); | 3508 return sqlite3RtreeInit(db); |
| 3465 } | 3509 } |
| 3466 #endif | 3510 #endif |
| 3467 | 3511 |
| 3468 #endif | 3512 #endif |
| OLD | NEW |