| Index: third_party/sqlite/sqlite-src-3100200/ext/rtree/rtree.c
|
| diff --git a/third_party/sqlite/sqlite-src-3080704/ext/rtree/rtree.c b/third_party/sqlite/sqlite-src-3100200/ext/rtree/rtree.c
|
| similarity index 97%
|
| copy from third_party/sqlite/sqlite-src-3080704/ext/rtree/rtree.c
|
| copy to third_party/sqlite/sqlite-src-3100200/ext/rtree/rtree.c
|
| index 8150538d452d1b31ebc91b54b5fcb3e6dad8f3aa..4e473a22c28a45fd0a2ad9df0099b40c99397197 100644
|
| --- a/third_party/sqlite/sqlite-src-3080704/ext/rtree/rtree.c
|
| +++ b/third_party/sqlite/sqlite-src-3100200/ext/rtree/rtree.c
|
| @@ -351,6 +351,7 @@ struct RtreeMatchArg {
|
| u32 magic; /* Always RTREE_GEOMETRY_MAGIC */
|
| RtreeGeomCallback cb; /* Info about the callback functions */
|
| int nParam; /* Number of parameters to the SQL function */
|
| + sqlite3_value **apSqlParam; /* Original SQL parameter values */
|
| RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
|
| };
|
|
|
| @@ -369,13 +370,12 @@ static int readInt16(u8 *p){
|
| return (p[0]<<8) + p[1];
|
| }
|
| static void readCoord(u8 *p, RtreeCoord *pCoord){
|
| - u32 i = (
|
| + pCoord->u = (
|
| (((u32)p[0]) << 24) +
|
| (((u32)p[1]) << 16) +
|
| (((u32)p[2]) << 8) +
|
| (((u32)p[3]) << 0)
|
| );
|
| - *(u32 *)pCoord = i;
|
| }
|
| static i64 readInt64(u8 *p){
|
| return (
|
| @@ -404,7 +404,7 @@ static int writeCoord(u8 *p, RtreeCoord *pCoord){
|
| u32 i;
|
| assert( sizeof(RtreeCoord)==4 );
|
| assert( sizeof(u32)==4 );
|
| - i = *(u32 *)pCoord;
|
| + i = pCoord->u;
|
| p[0] = (i>>24)&0xFF;
|
| p[1] = (i>>16)&0xFF;
|
| p[2] = (i>> 8)&0xFF;
|
| @@ -735,14 +735,13 @@ static void nodeGetCell(
|
| RtreeCell *pCell /* OUT: Write the cell contents here */
|
| ){
|
| u8 *pData;
|
| - u8 *pEnd;
|
| RtreeCoord *pCoord;
|
| + int ii;
|
| pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);
|
| pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell);
|
| - pEnd = pData + pRtree->nDim*8;
|
| pCoord = pCell->aCoord;
|
| - for(; pData<pEnd; pData+=4, pCoord++){
|
| - readCoord(pData, pCoord);
|
| + for(ii=0; ii<pRtree->nDim*2; ii++){
|
| + readCoord(&pData[ii*4], &pCoord[ii]);
|
| }
|
| }
|
|
|
| @@ -1182,7 +1181,7 @@ static RtreeSearchPoint *rtreeEnqueue(
|
| pNew = pCur->aPoint + i;
|
| pNew->rScore = rScore;
|
| pNew->iLevel = iLevel;
|
| - assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH );
|
| + assert( iLevel<=RTREE_MAX_DEPTH );
|
| while( i>0 ){
|
| RtreeSearchPoint *pParent;
|
| j = (i-1)/2;
|
| @@ -1484,9 +1483,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
|
|
|
| /* Check that the blob is roughly the right size. */
|
| nBlob = sqlite3_value_bytes(pValue);
|
| - if( nBlob<(int)sizeof(RtreeMatchArg)
|
| - || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0
|
| - ){
|
| + if( nBlob<(int)sizeof(RtreeMatchArg) ){
|
| return SQLITE_ERROR;
|
| }
|
|
|
| @@ -1497,6 +1494,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
|
|
|
| memcpy(pBlob, sqlite3_value_blob(pValue), nBlob);
|
| nExpected = (int)(sizeof(RtreeMatchArg) +
|
| + pBlob->nParam*sizeof(sqlite3_value*) +
|
| (pBlob->nParam-1)*sizeof(RtreeDValue));
|
| if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){
|
| sqlite3_free(pInfo);
|
| @@ -1505,6 +1503,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
|
| pInfo->pContext = pBlob->cb.pContext;
|
| pInfo->nParam = pBlob->nParam;
|
| pInfo->aParam = pBlob->aParam;
|
| + pInfo->apSqlParam = pBlob->apSqlParam;
|
|
|
| if( pBlob->cb.xGeom ){
|
| pCons->u.xGeom = pBlob->cb.xGeom;
|
| @@ -1671,17 +1670,30 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
| Rtree *pRtree = (Rtree*)tab;
|
| int rc = SQLITE_OK;
|
| int ii;
|
| + int bMatch = 0; /* True if there exists a MATCH constraint */
|
| i64 nRow; /* Estimated rows returned by this scan */
|
|
|
| int iIdx = 0;
|
| char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
|
| memset(zIdxStr, 0, sizeof(zIdxStr));
|
|
|
| + /* Check if there exists a MATCH constraint - even an unusable one. If there
|
| + ** is, do not consider the lookup-by-rowid plan as using such a plan would
|
| + ** require the VDBE to evaluate the MATCH constraint, which is not currently
|
| + ** possible. */
|
| + for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
| + if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){
|
| + bMatch = 1;
|
| + }
|
| + }
|
| +
|
| assert( pIdxInfo->idxStr==0 );
|
| for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
|
| struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
|
|
|
| - if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
| + if( bMatch==0 && p->usable
|
| + && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
| + ){
|
| /* We have an equality constraint on the rowid. Use strategy 1. */
|
| int jj;
|
| for(jj=0; jj<ii; jj++){
|
| @@ -2806,6 +2818,8 @@ static int rtreeUpdate(
|
| rtreeReference(pRtree);
|
| assert(nData>=1);
|
|
|
| + cell.iRowid = 0; /* Used only to suppress a compiler warning */
|
| +
|
| /* Constraint handling. A write operation on an r-tree table may return
|
| ** SQLITE_CONSTRAINT for two reasons:
|
| **
|
| @@ -2820,11 +2834,19 @@ static int rtreeUpdate(
|
| if( nData>1 ){
|
| int ii;
|
|
|
| - /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
|
| - assert( nData==(pRtree->nDim*2 + 3) );
|
| + /* Populate the cell.aCoord[] array. The first coordinate is azData[3].
|
| + **
|
| + ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
|
| + ** with "column" that are interpreted as table constraints.
|
| + ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
|
| + ** This problem was discovered after years of use, so we silently ignore
|
| + ** these kinds of misdeclared tables to avoid breaking any legacy.
|
| + */
|
| + assert( nData<=(pRtree->nDim*2 + 3) );
|
| +
|
| #ifndef SQLITE_RTREE_INT_ONLY
|
| if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
|
| - for(ii=0; ii<(pRtree->nDim*2); ii+=2){
|
| + for(ii=0; ii<nData-4; ii+=2){
|
| cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
|
| cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
|
| if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
|
| @@ -2835,7 +2857,7 @@ static int rtreeUpdate(
|
| }else
|
| #endif
|
| {
|
| - for(ii=0; ii<(pRtree->nDim*2); ii+=2){
|
| + for(ii=0; ii<nData-4; ii+=2){
|
| cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
|
| cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
|
| if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
|
| @@ -3365,6 +3387,18 @@ static void rtreeFreeCallback(void *p){
|
| }
|
|
|
| /*
|
| +** This routine frees the BLOB that is returned by geomCallback().
|
| +*/
|
| +static void rtreeMatchArgFree(void *pArg){
|
| + int i;
|
| + RtreeMatchArg *p = (RtreeMatchArg*)pArg;
|
| + for(i=0; i<p->nParam; i++){
|
| + sqlite3_value_free(p->apSqlParam[i]);
|
| + }
|
| + sqlite3_free(p);
|
| +}
|
| +
|
| +/*
|
| ** Each call to sqlite3_rtree_geometry_callback() or
|
| ** sqlite3_rtree_query_callback() creates an ordinary SQLite
|
| ** scalar function that is implemented by this routine.
|
| @@ -3382,8 +3416,10 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
|
| RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
|
| RtreeMatchArg *pBlob;
|
| int nBlob;
|
| + int memErr = 0;
|
|
|
| - nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue);
|
| + nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
|
| + + nArg*sizeof(sqlite3_value*);
|
| pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
|
| if( !pBlob ){
|
| sqlite3_result_error_nomem(ctx);
|
| @@ -3391,15 +3427,23 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
|
| int i;
|
| pBlob->magic = RTREE_GEOMETRY_MAGIC;
|
| pBlob->cb = pGeomCtx[0];
|
| + pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
|
| pBlob->nParam = nArg;
|
| for(i=0; i<nArg; i++){
|
| + pBlob->apSqlParam[i] = sqlite3_value_dup(aArg[i]);
|
| + if( pBlob->apSqlParam[i]==0 ) memErr = 1;
|
| #ifdef SQLITE_RTREE_INT_ONLY
|
| pBlob->aParam[i] = sqlite3_value_int64(aArg[i]);
|
| #else
|
| pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
|
| #endif
|
| }
|
| - sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free);
|
| + if( memErr ){
|
| + sqlite3_result_error_nomem(ctx);
|
| + rtreeMatchArgFree(pBlob);
|
| + }else{
|
| + sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree);
|
| + }
|
| }
|
| }
|
|
|
|
|