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 |