mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Refactor the constraint checking logic in RTree. The new-style constraint
callbacks created by sqlite3_rtree_query_callback() are now hooked up from end to end, though still untested. FossilOrigin-Name: 32a13870175a1dd1d33af3572dde09ff607a04b6
This commit is contained in:
@ -274,13 +274,13 @@ struct RtreeConstraint {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Possible values for RtreeConstraint.op */
|
/* Possible values for RtreeConstraint.op */
|
||||||
#define RTREE_EQ 0x41
|
#define RTREE_EQ 0x41 /* A */
|
||||||
#define RTREE_LE 0x42
|
#define RTREE_LE 0x42 /* B */
|
||||||
#define RTREE_LT 0x43
|
#define RTREE_LT 0x43 /* C */
|
||||||
#define RTREE_GE 0x44
|
#define RTREE_GE 0x44 /* D */
|
||||||
#define RTREE_GT 0x45
|
#define RTREE_GT 0x45 /* E */
|
||||||
#define RTREE_MATCH 0x46 /* Old-style sqlite3_rtree_geometry_callback() */
|
#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */
|
||||||
#define RTREE_QUERY 0x47 /* New-style sqlite3_rtree_query_callback() */
|
#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -900,149 +900,131 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The r-tree constraint passed as the second argument to this function is
|
** Convert raw bits from the on-disk RTree record into a coordinate value
|
||||||
** guaranteed to be a MATCH constraint.
|
** The on-disk record stores integer coordinates if eInt is true and it
|
||||||
|
** stores 32-bit floating point records if eInt is false. a[] is the four
|
||||||
|
** bytes of the on-disk record to be decoded. Store the results in "r".
|
||||||
*/
|
*/
|
||||||
static int rtreeTestGeom(
|
#define RTREE_DECODE_COORD(eInt, a, r) { \
|
||||||
Rtree *pRtree, /* R-Tree object */
|
u32 x; /* Raw bits of the coordinate value */ \
|
||||||
RtreeConstraint *pConstraint, /* MATCH constraint to test */
|
RtreeCoord c; /* Coordinate decoded */ \
|
||||||
RtreeCell *pCell, /* Cell to test */
|
x = ((u32)a[0]<<24) + ((u32)a[1]<<16) \
|
||||||
int *pbRes /* OUT: Test result */
|
+((u32)a[2]<<8) + a[3]; \
|
||||||
|
c.i = *(int*)&x; \
|
||||||
|
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check the RTree node or entry given by pCellData and p against the MATCH
|
||||||
|
** constraint pConstraint.
|
||||||
|
*/
|
||||||
|
static int rtreeCallbackConstraint(
|
||||||
|
RtreeConstraint *pConstraint, /* The constraint to test */
|
||||||
|
int eInt, /* True if RTree holding integer coordinates */
|
||||||
|
u8 *pCellData, /* Raw cell content */
|
||||||
|
RtreeSearchPoint *pSearch, /* Container of this cell */
|
||||||
|
sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */
|
||||||
|
int *peWithin /* OUT: visibility of the cell */
|
||||||
){
|
){
|
||||||
int i;
|
int i; /* Loop counter */
|
||||||
RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2];
|
sqlite3_rtree_query_info *pGeom = pConstraint->pGeom; /* Callback info */
|
||||||
int nCoord = pRtree->nDim*2;
|
int nCoord = pGeom->nCoord; /* No. of coordinates */
|
||||||
|
int rc; /* Callback return code */
|
||||||
|
sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */
|
||||||
|
|
||||||
assert( pConstraint->op==RTREE_MATCH );
|
assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY );
|
||||||
assert( pConstraint->pGeom );
|
assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 );
|
||||||
|
|
||||||
for(i=0; i<nCoord; i++){
|
pCellData += 8;
|
||||||
aCoord[i] = DCOORD(pCell->aCoord[i]);
|
for(i=0; i<nCoord; i++, pCellData += 4){
|
||||||
|
RTREE_DECODE_COORD(eInt, pCellData, aCoord[i]);
|
||||||
}
|
}
|
||||||
return pConstraint->u.xGeom((sqlite3_rtree_geometry*)pConstraint->pGeom,
|
if( pConstraint->op==RTREE_MATCH ){
|
||||||
nCoord, aCoord, pbRes);
|
rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pGeom,
|
||||||
|
nCoord, aCoord, &i);
|
||||||
|
if( i==0 ) *peWithin = NOT_WITHIN;
|
||||||
|
}else{
|
||||||
|
pGeom->aCoord = aCoord;
|
||||||
|
pGeom->iLevel = pSearch->iLevel;
|
||||||
|
pGeom->rScore = pGeom->rParentScore = pSearch->rScore;
|
||||||
|
pGeom->eWithin = pGeom->eParentWithin = pSearch->eWithin;
|
||||||
|
rc = pConstraint->u.xQueryFunc(pGeom);
|
||||||
|
if( pGeom->eWithin<*peWithin ) *peWithin = pGeom->eWithin;
|
||||||
|
if( pGeom->rScore<*prScore ) *prScore = pGeom->rScore;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Cursor pCursor currently points to a cell in a non-leaf page.
|
** Check the internal RTree node given by pCellData against constraint p.
|
||||||
** Set *peWithin to NOT_WITHIN if the constraints in pCursor->aConstraint[]
|
** If this constraint cannot be satisfied by any child within the node,
|
||||||
** are guaranteed to never be satisfied by any subelement under the
|
** set *peWithin to NOT_WITHIN.
|
||||||
** current cell. If some subelement of the cell might satisfy all
|
|
||||||
** constraints, then set *peWithin to PARTLY_WITHIN. If all subelements
|
|
||||||
** of the cell are guaranteed to fully satisfy all constraints, then
|
|
||||||
** set *peWithin to FULLY_WITHIN.
|
|
||||||
**
|
|
||||||
** In other words, set *peWithin to NOT_WITHIN, PARTLY_WITHIN, or
|
|
||||||
** FULLY_WITHIN if the cell is completely outside of the field-of-view,
|
|
||||||
** overlaps the field of view, or is completely contained within the
|
|
||||||
** field of view, respectively.
|
|
||||||
**
|
|
||||||
** It is not an error to set *peWithin to PARTLY_WITHIN when FULLY_WITHIN
|
|
||||||
** would be correct. Doing so is suboptimal, but will still give the
|
|
||||||
** correct answer.
|
|
||||||
**
|
|
||||||
** Return SQLITE_OK if successful or an SQLite error code if an error
|
|
||||||
** occurs. Errors can only possible if there is a geometry callback.
|
|
||||||
*/
|
*/
|
||||||
static int rtreeTestCell(
|
static void rtreeNonleafConstraint(
|
||||||
RtreeCursor *pCursor, /* The cursor to check */
|
RtreeConstraint *p, /* The constraint to test */
|
||||||
RtreeCell *pCell, /* The cell to check */
|
int eInt, /* True if RTree holds integer coordinates */
|
||||||
int *peWithin /* Set true if element is out-of-bounds */
|
u8 *pCellData, /* Raw cell content as appears on disk */
|
||||||
|
int *peWithin /* Adjust downward, as appropriate */
|
||||||
){
|
){
|
||||||
int ii;
|
sqlite3_rtree_dbl val; /* Coordinate value convert to a double */
|
||||||
int bOutOfBounds = 0;
|
|
||||||
int rc = SQLITE_OK;
|
|
||||||
Rtree *pRtree = RTREE_OF_CURSOR(pCursor);
|
|
||||||
|
|
||||||
for(ii=0; bOutOfBounds==0 && ii<pCursor->nConstraint; ii++){
|
/* p->iCoord might point to either a lower or upper bound coordinate
|
||||||
RtreeConstraint *p = &pCursor->aConstraint[ii];
|
** in a coordinate pair. But make pCellData point to the lower bound.
|
||||||
RtreeDValue cell_min = DCOORD(pCell->aCoord[(p->iCoord>>1)*2]);
|
*/
|
||||||
RtreeDValue cell_max = DCOORD(pCell->aCoord[(p->iCoord>>1)*2+1]);
|
pCellData += 8 + 4*(p->iCoord&0xfe);
|
||||||
|
|
||||||
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|
||||||
|| p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
|
|| p->op==RTREE_GT || p->op==RTREE_EQ );
|
||||||
);
|
|
||||||
|
|
||||||
switch( p->op ){
|
switch( p->op ){
|
||||||
case RTREE_LE: case RTREE_LT:
|
case RTREE_LE:
|
||||||
bOutOfBounds = p->u.rValue<cell_min;
|
case RTREE_LT:
|
||||||
break;
|
|
||||||
|
|
||||||
case RTREE_GE: case RTREE_GT:
|
|
||||||
bOutOfBounds = p->u.rValue>cell_max;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RTREE_EQ:
|
case RTREE_EQ:
|
||||||
bOutOfBounds = (p->u.rValue>cell_max || p->u.rValue<cell_min);
|
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||||
break;
|
/* val now holds the lower bound of the coordinate pair */
|
||||||
|
if( p->u.rValue>=val ) return;
|
||||||
|
if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */
|
||||||
|
/* Fall through for the RTREE_EQ case */
|
||||||
|
|
||||||
default: {
|
default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */
|
||||||
assert( p->op==RTREE_MATCH );
|
pCellData += 4;
|
||||||
rc = rtreeTestGeom(pRtree, p, pCell, &bOutOfBounds);
|
RTREE_DECODE_COORD(eInt, pCellData, val);
|
||||||
bOutOfBounds = !bOutOfBounds;
|
/* val now holds the upper bound of the coordinate pair */
|
||||||
break;
|
if( p->u.rValue<=val ) return;
|
||||||
}
|
}
|
||||||
}
|
*peWithin = NOT_WITHIN;
|
||||||
}
|
|
||||||
|
|
||||||
*peWithin = bOutOfBounds ? NOT_WITHIN : PARTLY_WITHIN;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** pCursor points to a leaf r-tree entry which is a candidate for output.
|
** Check the leaf RTree cell given by pCellData against constraint p.
|
||||||
** This routine sets *peWithin to one of NOT_WITHIN, PARTLY_WITHIN, or
|
** If this constraint is not satisfied, set *peWithin to NOT_WITHIN.
|
||||||
** FULLY_WITHIN depending on whether or not the leaf entry is completely
|
** If the constraint is satisfied, leave *peWithin unchanged.
|
||||||
** outside the region defined by pCursor->aConstraints[], or overlaps the
|
|
||||||
** region, or is completely within the region, respectively.
|
|
||||||
**
|
**
|
||||||
** This routine is more selective than rtreeTestCell(). rtreeTestCell()
|
** The constraint is of the form: xN op $val
|
||||||
** will return PARTLY_WITHIN or FULLY_WITHIN if the constraints are such
|
|
||||||
** that a subelement of the cell to be included in the result set. This
|
|
||||||
** routine is is only called for leaf r-tree entries and does not need
|
|
||||||
** to concern itself with subelements. Hence it only sets *peWithin to
|
|
||||||
** PARTLY_WITHIN or FULLY_WITHIN if the cell itself meets the requirements.
|
|
||||||
**
|
**
|
||||||
** Return SQLITE_OK if successful or an SQLite error code if an error
|
** The op is given by p->op. The xN is p->iCoord-th coordinate in
|
||||||
** occurs within a geometry callback.
|
** pCellData. $val is given by p->u.rValue.
|
||||||
**
|
|
||||||
** This function assumes that the cell is part of a leaf node.
|
|
||||||
*/
|
*/
|
||||||
static int rtreeTestEntry(
|
static void rtreeLeafConstraint(
|
||||||
RtreeCursor *pCursor, /* Cursor pointing to the leaf element */
|
RtreeConstraint *p, /* The constraint to test */
|
||||||
RtreeCell *pCell, /* The cell to check */
|
int eInt, /* True if RTree holds integer coordinates */
|
||||||
int *peWithin /* OUT: NOT_WITHIN, PARTLY_WITHIN, or FULLY_WITHIN */
|
u8 *pCellData, /* Raw cell content as appears on disk */
|
||||||
|
int *peWithin /* Adjust downward, as appropriate */
|
||||||
){
|
){
|
||||||
Rtree *pRtree = RTREE_OF_CURSOR(pCursor);
|
RtreeDValue xN; /* Coordinate value converted to a double */
|
||||||
int ii;
|
|
||||||
int res = 1; /* Innocent until proven guilty */
|
|
||||||
|
|
||||||
for(ii=0; res && ii<pCursor->nConstraint; ii++){
|
|
||||||
RtreeConstraint *p = &pCursor->aConstraint[ii];
|
|
||||||
RtreeDValue coord = DCOORD(pCell->aCoord[p->iCoord]);
|
|
||||||
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|
||||||
|| p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
|
|| p->op==RTREE_GT || p->op==RTREE_EQ );
|
||||||
);
|
pCellData += 8 + p->iCoord*4;
|
||||||
|
RTREE_DECODE_COORD(eInt, pCellData, xN);
|
||||||
switch( p->op ){
|
switch( p->op ){
|
||||||
case RTREE_LE: res = (coord<=p->u.rValue); break;
|
case RTREE_LE: if( xN <= p->u.rValue ) return; break;
|
||||||
case RTREE_LT: res = (coord<p->u.rValue); break;
|
case RTREE_LT: if( xN < p->u.rValue ) return; break;
|
||||||
case RTREE_GE: res = (coord>=p->u.rValue); break;
|
case RTREE_GE: if( xN >= p->u.rValue ) return; break;
|
||||||
case RTREE_GT: res = (coord>p->u.rValue); break;
|
case RTREE_GT: if( xN > p->u.rValue ) return; break;
|
||||||
case RTREE_EQ: res = (coord==p->u.rValue); break;
|
default: if( xN == p->u.rValue ) return; break;
|
||||||
default: {
|
|
||||||
int rc;
|
|
||||||
assert( p->op==RTREE_MATCH );
|
|
||||||
rc = rtreeTestGeom(pRtree, p, pCell, &res);
|
|
||||||
if( rc!=SQLITE_OK ){
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
break;
|
*peWithin = NOT_WITHIN;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*peWithin = res ? FULLY_WITHIN : NOT_WITHIN;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1295,39 +1277,53 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
|
|||||||
int eWithin;
|
int eWithin;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
int nCell;
|
int nCell;
|
||||||
RtreeCell cell;
|
int nConstraint = pCur->nConstraint;
|
||||||
|
int ii;
|
||||||
|
int eInt;
|
||||||
RtreeSearchPoint x;
|
RtreeSearchPoint x;
|
||||||
|
|
||||||
|
eInt = pRtree->eCoordType==RTREE_COORD_INT32;
|
||||||
while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
|
while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
|
||||||
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
|
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
nCell = NCELL(pNode);
|
nCell = NCELL(pNode);
|
||||||
assert( nCell<200 );
|
assert( nCell<200 );
|
||||||
while( p->iCell<nCell ){
|
while( p->iCell<nCell ){
|
||||||
nodeGetCell(pRtree, pNode, p->iCell, &cell);
|
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)0;
|
||||||
if( p->iLevel==1 ){
|
u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
|
||||||
rc = rtreeTestEntry(pCur, &cell, &eWithin);
|
eWithin = FULLY_WITHIN;
|
||||||
}else{
|
for(ii=0; ii<nConstraint; ii++){
|
||||||
rc = rtreeTestCell(pCur, &cell, &eWithin);
|
RtreeConstraint *pConstraint = pCur->aConstraint + ii;
|
||||||
}
|
if( pConstraint->op>=RTREE_MATCH ){
|
||||||
|
rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p,
|
||||||
|
&rScore, &eWithin);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
x = *p;
|
}else if( p->iLevel==1 ){
|
||||||
|
rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin);
|
||||||
|
}else{
|
||||||
|
rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
|
||||||
|
}
|
||||||
|
if( eWithin==NOT_WITHIN ) break;
|
||||||
|
}
|
||||||
p->iCell++;
|
p->iCell++;
|
||||||
if( eWithin==NOT_WITHIN ) continue;
|
if( eWithin==NOT_WITHIN ) continue;
|
||||||
|
x.iLevel = p->iLevel - 1;
|
||||||
|
if( x.iLevel ){
|
||||||
|
x.id = readInt64(pCellData);
|
||||||
|
x.iCell = 0;
|
||||||
|
}else{
|
||||||
|
x.id = p->id;
|
||||||
|
x.iCell = p->iCell - 1;
|
||||||
|
}
|
||||||
if( p->iCell>=nCell ){
|
if( p->iCell>=nCell ){
|
||||||
RTREE_QUEUE_TRACE(pCur, "POP-S:");
|
RTREE_QUEUE_TRACE(pCur, "POP-S:");
|
||||||
rtreeSearchPointPop(pCur);
|
rtreeSearchPointPop(pCur);
|
||||||
}
|
}
|
||||||
p = rtreeSearchPointNew(pCur, /*rScore*/0.0, x.iLevel-1);
|
p = rtreeSearchPointNew(pCur, rScore, x.iLevel);
|
||||||
if( p==0 ) return SQLITE_NOMEM;
|
if( p==0 ) return SQLITE_NOMEM;
|
||||||
p->eWithin = eWithin;
|
p->eWithin = eWithin;
|
||||||
if( p->iLevel ){
|
|
||||||
p->id = cell.iRowid;
|
|
||||||
p->iCell = 0;
|
|
||||||
}else{
|
|
||||||
p->id = x.id;
|
p->id = x.id;
|
||||||
p->iCell = x.iCell;
|
p->iCell = x.iCell;
|
||||||
}
|
|
||||||
RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
|
RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1460,7 +1456,6 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
|
|||||||
sqlite3_free(pGeom);
|
sqlite3_free(pGeom);
|
||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pGeom->pContext = p->cb.pContext;
|
pGeom->pContext = p->cb.pContext;
|
||||||
pGeom->nParam = p->nParam;
|
pGeom->nParam = p->nParam;
|
||||||
pGeom->aParam = p->aParam;
|
pGeom->aParam = p->aParam;
|
||||||
@ -1525,7 +1520,7 @@ static int rtreeFilter(
|
|||||||
for(ii=0; ii<argc; ii++){
|
for(ii=0; ii<argc; ii++){
|
||||||
RtreeConstraint *p = &pCsr->aConstraint[ii];
|
RtreeConstraint *p = &pCsr->aConstraint[ii];
|
||||||
p->op = idxStr[ii*2];
|
p->op = idxStr[ii*2];
|
||||||
p->iCoord = idxStr[ii*2+1]-'a';
|
p->iCoord = idxStr[ii*2+1]-'0';
|
||||||
if( p->op==RTREE_MATCH ){
|
if( p->op==RTREE_MATCH ){
|
||||||
/* A MATCH operator. The right-hand-side must be a blob that
|
/* A MATCH operator. The right-hand-side must be a blob that
|
||||||
** can be cast into an RtreeMatchArg object. One created using
|
** can be cast into an RtreeMatchArg object. One created using
|
||||||
@ -1535,6 +1530,7 @@ static int rtreeFilter(
|
|||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
p->pGeom->nCoord = pRtree->nDim*2;
|
||||||
}else{
|
}else{
|
||||||
#ifdef SQLITE_RTREE_INT_ONLY
|
#ifdef SQLITE_RTREE_INT_ONLY
|
||||||
p->u.rValue = sqlite3_value_int64(argv[ii]);
|
p->u.rValue = sqlite3_value_int64(argv[ii]);
|
||||||
@ -1663,7 +1659,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
zIdxStr[iIdx++] = op;
|
zIdxStr[iIdx++] = op;
|
||||||
zIdxStr[iIdx++] = p->iColumn - 1 + 'a';
|
zIdxStr[iIdx++] = p->iColumn - 1 + '0';
|
||||||
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
|
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
|
||||||
pIdxInfo->aConstraintUsage[ii].omit = 1;
|
pIdxInfo->aConstraintUsage[ii].omit = 1;
|
||||||
}
|
}
|
||||||
|
@ -57,31 +57,31 @@ do_test rtree6-1.1 {
|
|||||||
|
|
||||||
do_test rtree6-1.2 {
|
do_test rtree6-1.2 {
|
||||||
rtree_strategy {SELECT * FROM t1 WHERE x1>10}
|
rtree_strategy {SELECT * FROM t1 WHERE x1>10}
|
||||||
} {Ea}
|
} {E0}
|
||||||
|
|
||||||
do_test rtree6-1.3 {
|
do_test rtree6-1.3 {
|
||||||
rtree_strategy {SELECT * FROM t1 WHERE x1<10}
|
rtree_strategy {SELECT * FROM t1 WHERE x1<10}
|
||||||
} {Ca}
|
} {C0}
|
||||||
|
|
||||||
do_test rtree6-1.4 {
|
do_test rtree6-1.4 {
|
||||||
rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10}
|
rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10}
|
||||||
} {Ca}
|
} {C0}
|
||||||
|
|
||||||
do_test rtree6-1.5 {
|
do_test rtree6-1.5 {
|
||||||
rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
|
rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
|
||||||
} {Ca}
|
} {C0}
|
||||||
|
|
||||||
do_eqp_test rtree6.2.1 {
|
do_eqp_test rtree6.2.1 {
|
||||||
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
|
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca}
|
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
|
||||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test rtree6.2.2 {
|
do_eqp_test rtree6.2.2 {
|
||||||
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
|
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca}
|
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
|
||||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ do_eqp_test rtree6.2.3 {
|
|||||||
do_eqp_test rtree6.2.4 {
|
do_eqp_test rtree6.2.4 {
|
||||||
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
|
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:CaEb}
|
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
|
||||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
|
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ do_test rtree6.3.2 {
|
|||||||
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
|
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
|
||||||
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
|
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
|
||||||
}
|
}
|
||||||
} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa}
|
} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
|
||||||
do_test rtree6.3.3 {
|
do_test rtree6.3.3 {
|
||||||
rtree_strategy {
|
rtree_strategy {
|
||||||
SELECT * FROM t3 WHERE
|
SELECT * FROM t3 WHERE
|
||||||
@ -137,7 +137,7 @@ do_test rtree6.3.3 {
|
|||||||
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
|
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
|
||||||
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
|
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
|
||||||
}
|
}
|
||||||
} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa}
|
} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
|
||||||
|
|
||||||
do_execsql_test rtree6-3.4 {
|
do_execsql_test rtree6-3.4 {
|
||||||
SELECT * FROM t3 WHERE x1>0.5 AND x1>0.8 AND x1>1.1
|
SELECT * FROM t3 WHERE x1>0.5 AND x1>0.8 AND x1>1.1
|
||||||
|
@ -29,7 +29,7 @@ do_eqp_test 1.1 {
|
|||||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||||
} {
|
} {
|
||||||
0 0 1 {SCAN TABLE t}
|
0 0 1 {SCAN TABLE t}
|
||||||
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
|
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 1.2 {
|
do_eqp_test 1.2 {
|
||||||
@ -37,7 +37,7 @@ do_eqp_test 1.2 {
|
|||||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t}
|
0 0 0 {SCAN TABLE t}
|
||||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
|
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 1.3 {
|
do_eqp_test 1.3 {
|
||||||
@ -45,7 +45,7 @@ do_eqp_test 1.3 {
|
|||||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t}
|
0 0 0 {SCAN TABLE t}
|
||||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
|
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 1.5 {
|
do_eqp_test 1.5 {
|
||||||
@ -82,7 +82,7 @@ do_eqp_test 2.1 {
|
|||||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||||
} {
|
} {
|
||||||
0 0 1 {SCAN TABLE t}
|
0 0 1 {SCAN TABLE t}
|
||||||
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
|
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 2.2 {
|
do_eqp_test 2.2 {
|
||||||
@ -90,7 +90,7 @@ do_eqp_test 2.2 {
|
|||||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t}
|
0 0 0 {SCAN TABLE t}
|
||||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
|
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 2.3 {
|
do_eqp_test 2.3 {
|
||||||
@ -98,7 +98,7 @@ do_eqp_test 2.3 {
|
|||||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
||||||
} {
|
} {
|
||||||
0 0 0 {SCAN TABLE t}
|
0 0 0 {SCAN TABLE t}
|
||||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
|
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 2.5 {
|
do_eqp_test 2.5 {
|
||||||
@ -271,4 +271,3 @@ ifcapable rtree {
|
|||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Performance\soptimization\son\snodeGetCell()\sin\sR-Tree.
|
C Refactor\sthe\sconstraint\schecking\slogic\sin\sRTree.\s\sThe\snew-style\sconstraint\ncallbacks\screated\sby\ssqlite3_rtree_query_callback()\sare\snow\shooked\sup\sfrom\nend\sto\send,\sthough\sstill\suntested.
|
||||||
D 2014-04-16T21:02:28.844
|
D 2014-04-17T13:15:33.281
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a
|
F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -120,20 +120,20 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
|||||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||||
F ext/rtree/rtree.c 1a59db351a8dfaa46c59b3105865a1aaa5192a61
|
F ext/rtree/rtree.c 117aaebed87a7c1e5d3e03afbad83c3700aa5ab8
|
||||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||||
F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290
|
F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290
|
||||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||||
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
|
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
|
||||||
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
|
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
|
||||||
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
|
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
|
||||||
F ext/rtree/rtree6.test fe0bd377a21c68ce2826129d14354c884cb1f354
|
F ext/rtree/rtree6.test 756585abc51727fec97c77852476445c10c0ee95
|
||||||
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
|
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
|
||||||
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
|
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
|
||||||
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
|
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
|
||||||
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
|
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
|
||||||
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
|
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
|
||||||
F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d
|
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
|
||||||
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
|
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
|
||||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||||
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
||||||
@ -1175,7 +1175,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P f26936f71a16ab25590540f7feb273514dfb69ff
|
P 5d20ff9ec837ad35bc44d6c25d13764b350e81dd
|
||||||
R b2b62cbe51f5e73202ce646c31659a05
|
R 9ddd572c495f4e9fca0e8e969ae19d88
|
||||||
U drh
|
U drh
|
||||||
Z 74eaec9038e9087250153055260f329f
|
Z 43698a2882be63e69b530e3c48875378
|
||||||
|
@ -1 +1 @@
|
|||||||
5d20ff9ec837ad35bc44d6c25d13764b350e81dd
|
32a13870175a1dd1d33af3572dde09ff607a04b6
|
Reference in New Issue
Block a user