mirror of https://github.com/sqlite/sqlite
Merge the CAST operator enhancements from trunk.
FossilOrigin-Name: 6c8f86e4e08d5d57e21496277613e0f9dcc06514
This commit is contained in:
commit
6c4ec84256
26
manifest
26
manifest
|
@ -1,5 +1,5 @@
|
|||
C Query\sor\schange\sthe\smaximum\snumber\sof\sworker\sthreads\sallowed\son\seach\ndatabase\sconnection\sseparately\susing\sthe\s"PRAGMA\sthreads"\scommand.
|
||||
D 2014-08-25T15:13:22.455
|
||||
C Merge\sthe\sCAST\soperator\senhancements\sfrom\strunk.
|
||||
D 2014-08-25T22:43:17.516
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -177,7 +177,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
|||
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c 5adcd322c6b08fc25d215d780ca62cebce66304d
|
||||
F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c
|
||||
F src/expr.c 358634f4ddeeb4e69643cb6db5819104a7834c60
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 8d81a780ad78d16ec9082585758a8f1d6bf02ca3
|
||||
F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7
|
||||
|
@ -285,20 +285,20 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059
|
|||
F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359
|
||||
F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 93cf510b8e59df5fffcc4a9de9bef9c046979ab1
|
||||
F src/vdbe.c 5d6a6ad63227dfd444d13b3391272b20d1a76100
|
||||
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
|
||||
F src/vdbeInt.h 94f5cb24803285c8b29026f55b5e05ac69232ce5
|
||||
F src/vdbeInt.h a1fcc0a04445c5d797694dc860a906010b9be7e6
|
||||
F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce
|
||||
F src/vdbeaux.c cef5d34a64ae3a65b56d96d3fd663246ec8e1c36
|
||||
F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4
|
||||
F src/vdbemem.c 4c9d686da474957d2e78834f13cc5f141fe6b87f
|
||||
F src/vdbemem.c 4e08ea087aea367dae7c45129b75487e0056e819
|
||||
F src/vdbesort.c 3a76f51efdf0790fd3d26afabdd81e0a21f52ae7
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f
|
||||
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c 4c499d185827a492643cf017ae5e3aa0523f9f18
|
||||
F src/where.c 4e2770a1914b8ce30f3e44ad954b720eca3b5efd
|
||||
F src/whereInt.h 923820bee9726033a501a08d2fc69b9c1ee4feb3
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
|
@ -308,7 +308,7 @@ F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
|
|||
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
|
||||
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
|
||||
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
|
||||
F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93
|
||||
F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
|
@ -318,8 +318,8 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
|||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test 3ef1b471247308e710a794b6e50a6ab536c5604b
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a
|
||||
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
|
@ -1193,7 +1193,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P dfdc900f5d1a31ee5c5f35a630c4a8253e69093b
|
||||
R 4c161b4070e5a7022237a28172d6e331
|
||||
P 29c5e8a7c9d7ce349a1e1d72082d23450e877b45 af364cce9da0961593ef876b646197f82df08ad5
|
||||
R c7c8cecd9a8ffa9d596fa5137e696964
|
||||
U drh
|
||||
Z 1c68bfb86ec54e7d60991aea6df8a67a
|
||||
Z 1d9d719c4b1a959a79787aab5421ad60
|
||||
|
|
|
@ -1 +1 @@
|
|||
29c5e8a7c9d7ce349a1e1d72082d23450e877b45
|
||||
6c8f86e4e08d5d57e21496277613e0f9dcc06514
|
17
src/expr.c
17
src/expr.c
|
@ -2595,26 +2595,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||
#ifndef SQLITE_OMIT_CAST
|
||||
case TK_CAST: {
|
||||
/* Expressions of the form: CAST(pLeft AS token) */
|
||||
int aff, to_op;
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
aff = sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
|
||||
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
|
||||
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
|
||||
assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
|
||||
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
|
||||
assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
|
||||
testcase( to_op==OP_ToText );
|
||||
testcase( to_op==OP_ToBlob );
|
||||
testcase( to_op==OP_ToNumeric );
|
||||
testcase( to_op==OP_ToInt );
|
||||
testcase( to_op==OP_ToReal );
|
||||
if( inReg!=target ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
|
||||
inReg = target;
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, to_op, inReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Cast, target,
|
||||
sqlite3AffinityType(pExpr->u.zToken, 0));
|
||||
testcase( usedAsColumnCache(pParse, inReg, inReg) );
|
||||
sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
|
||||
break;
|
||||
|
|
106
src/vdbe.c
106
src/vdbe.c
|
@ -1768,106 +1768,36 @@ case OP_RealAffinity: { /* in1 */
|
|||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
/* Opcode: ToText P1 * * * *
|
||||
/* Opcode: Cast P1 P2 * * *
|
||||
**
|
||||
** Force the value in register P1 to be text.
|
||||
** If the value is numeric, convert it to a string using the
|
||||
** equivalent of sprintf(). Blob values are unchanged and
|
||||
** are afterwards simply interpreted as text.
|
||||
** Force the value in register P1 to be the type defined by P2.
|
||||
**
|
||||
** <ul>
|
||||
** <li value="97"> TEXT
|
||||
** <li value="98"> BLOB
|
||||
** <li value="99"> NUMERIC
|
||||
** <li value="100"> INTEGER
|
||||
** <li value="101"> REAL
|
||||
** </ul>
|
||||
**
|
||||
** A NULL value is not changed by this routine. It remains NULL.
|
||||
*/
|
||||
case OP_ToText: { /* same as TK_TO_TEXT, in1 */
|
||||
case OP_Cast: { /* in1 */
|
||||
assert( pOp->p2>=SQLITE_AFF_TEXT && pOp->p2<=SQLITE_AFF_REAL );
|
||||
testcase( pOp->p2==SQLITE_AFF_TEXT );
|
||||
testcase( pOp->p2==SQLITE_AFF_NONE );
|
||||
testcase( pOp->p2==SQLITE_AFF_NUMERIC );
|
||||
testcase( pOp->p2==SQLITE_AFF_INTEGER );
|
||||
testcase( pOp->p2==SQLITE_AFF_REAL );
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
if( pIn1->flags & MEM_Null ) break;
|
||||
assert( MEM_Str==(MEM_Blob>>3) );
|
||||
pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
|
||||
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
|
||||
rc = ExpandBlob(pIn1);
|
||||
assert( pIn1->flags & MEM_Str || db->mallocFailed );
|
||||
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
|
||||
sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
|
||||
UPDATE_MAX_BLOBSIZE(pIn1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ToBlob P1 * * * *
|
||||
**
|
||||
** Force the value in register P1 to be a BLOB.
|
||||
** If the value is numeric, convert it to a string first.
|
||||
** Strings are simply reinterpreted as blobs with no change
|
||||
** to the underlying data.
|
||||
**
|
||||
** A NULL value is not changed by this routine. It remains NULL.
|
||||
*/
|
||||
case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
if( pIn1->flags & MEM_Null ) break;
|
||||
if( (pIn1->flags & MEM_Blob)==0 ){
|
||||
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
|
||||
assert( pIn1->flags & MEM_Str || db->mallocFailed );
|
||||
MemSetTypeFlag(pIn1, MEM_Blob);
|
||||
}else{
|
||||
pIn1->flags &= ~(MEM_TypeMask&~MEM_Blob);
|
||||
}
|
||||
UPDATE_MAX_BLOBSIZE(pIn1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: ToNumeric P1 * * * *
|
||||
**
|
||||
** Force the value in register P1 to be numeric (either an
|
||||
** integer or a floating-point number.)
|
||||
** If the value is text or blob, try to convert it to an using the
|
||||
** equivalent of atoi() or atof() and store 0 if no such conversion
|
||||
** is possible.
|
||||
**
|
||||
** A NULL value is not changed by this routine. It remains NULL.
|
||||
*/
|
||||
case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
sqlite3VdbeMemNumerify(pIn1);
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_CAST */
|
||||
|
||||
/* Opcode: ToInt P1 * * * *
|
||||
**
|
||||
** Force the value in register P1 to be an integer. If
|
||||
** The value is currently a real number, drop its fractional part.
|
||||
** If the value is text or blob, try to convert it to an integer using the
|
||||
** equivalent of atoi() and store 0 if no such conversion is possible.
|
||||
**
|
||||
** A NULL value is not changed by this routine. It remains NULL.
|
||||
*/
|
||||
case OP_ToInt: { /* same as TK_TO_INT, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
if( (pIn1->flags & MEM_Null)==0 ){
|
||||
sqlite3VdbeMemIntegerify(pIn1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
/* Opcode: ToReal P1 * * * *
|
||||
**
|
||||
** Force the value in register P1 to be a floating point number.
|
||||
** If The value is currently an integer, convert it.
|
||||
** If the value is text or blob, try to convert it to an integer using the
|
||||
** equivalent of atoi() and store 0.0 if no such conversion is possible.
|
||||
**
|
||||
** A NULL value is not changed by this routine. It remains NULL.
|
||||
*/
|
||||
case OP_ToReal: { /* same as TK_TO_REAL, in1 */
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
memAboutToChange(p, pIn1);
|
||||
if( (pIn1->flags & MEM_Null)==0 ){
|
||||
sqlite3VdbeMemRealify(pIn1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
|
||||
|
||||
/* Opcode: Lt P1 P2 P3 P4 P5
|
||||
** Synopsis: if r[P1]<r[P3] goto P2
|
||||
**
|
||||
|
|
|
@ -425,6 +425,7 @@ double sqlite3VdbeRealValue(Mem*);
|
|||
void sqlite3VdbeIntegerAffinity(Mem*);
|
||||
int sqlite3VdbeMemRealify(Mem*);
|
||||
int sqlite3VdbeMemNumerify(Mem*);
|
||||
void sqlite3VdbeMemCast(Mem*,u8,u8);
|
||||
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
|
||||
void sqlite3VdbeMemRelease(Mem *p);
|
||||
void sqlite3VdbeMemReleaseExternal(Mem *p);
|
||||
|
|
|
@ -409,7 +409,6 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
|
|||
}else if( flags & (MEM_Str|MEM_Blob) ){
|
||||
i64 value = 0;
|
||||
assert( pMem->z || pMem->n==0 );
|
||||
testcase( pMem->z==0 );
|
||||
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
|
||||
return value;
|
||||
}else{
|
||||
|
@ -522,6 +521,51 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
|
|||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Cast the datatype of the value in pMem according to the affinity
|
||||
** "aff". Casting is different from applying affinity in that a cast
|
||||
** is forced. In other words, the value is converted into the desired
|
||||
** affinity even if that results in loss of data. This routine is
|
||||
** used (for example) to implement the SQL "cast()" operator.
|
||||
*/
|
||||
void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
||||
if( pMem->flags & MEM_Null ) return;
|
||||
switch( aff ){
|
||||
case SQLITE_AFF_NONE: { /* Really a cast to BLOB */
|
||||
if( (pMem->flags & MEM_Blob)==0 ){
|
||||
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
||||
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
||||
MemSetTypeFlag(pMem, MEM_Blob);
|
||||
}else{
|
||||
pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_AFF_NUMERIC: {
|
||||
sqlite3VdbeMemNumerify(pMem);
|
||||
break;
|
||||
}
|
||||
case SQLITE_AFF_INTEGER: {
|
||||
sqlite3VdbeMemIntegerify(pMem);
|
||||
break;
|
||||
}
|
||||
case SQLITE_AFF_REAL: {
|
||||
sqlite3VdbeMemRealify(pMem);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert( aff==SQLITE_AFF_TEXT );
|
||||
assert( MEM_Str==(MEM_Blob>>3) );
|
||||
pMem->flags |= (pMem->flags&MEM_Blob)>>3;
|
||||
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
||||
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
||||
pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to NULL.
|
||||
*/
|
||||
|
@ -1015,9 +1059,20 @@ static int valueFromExpr(
|
|||
*ppVal = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
op = pExpr->op;
|
||||
while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft;
|
||||
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
||||
|
||||
if( op==TK_CAST ){
|
||||
u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
|
||||
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
if( *ppVal ){
|
||||
sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8);
|
||||
sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Handle negative integers in a single step. This is needed in the
|
||||
** case when the value is -9223372036854775808.
|
||||
*/
|
||||
|
|
|
@ -2220,6 +2220,7 @@ static int whereRangeScanEst(
|
|||
iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
|
||||
if( iNew>iLower ) iLower = iNew;
|
||||
nOut--;
|
||||
pLower = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2235,6 +2236,7 @@ static int whereRangeScanEst(
|
|||
iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
|
||||
if( iNew<iUpper ) iUpper = iNew;
|
||||
nOut--;
|
||||
pUpper = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2248,10 +2250,8 @@ static int whereRangeScanEst(
|
|||
if( nNew<nOut ){
|
||||
nOut = nNew;
|
||||
}
|
||||
pLoop->nOut = (LogEst)nOut;
|
||||
WHERETRACE(0x10, ("range scan regions: %u..%u est=%d\n",
|
||||
(u32)iLower, (u32)iUpper, nOut));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}else{
|
||||
int bDone = 0;
|
||||
|
@ -2262,8 +2262,8 @@ static int whereRangeScanEst(
|
|||
#else
|
||||
UNUSED_PARAMETER(pParse);
|
||||
UNUSED_PARAMETER(pBuilder);
|
||||
#endif
|
||||
assert( pLower || pUpper );
|
||||
#endif
|
||||
assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 );
|
||||
nNew = whereRangeAdjust(pLower, nOut);
|
||||
nNew = whereRangeAdjust(pUpper, nNew);
|
||||
|
|
|
@ -145,7 +145,7 @@ do_test alter4-2.6 {
|
|||
} {1 {Cannot add a column with non-constant default}}
|
||||
do_test alter4-2.7 {
|
||||
catchsql {
|
||||
alter table t1 add column d default (-+1);
|
||||
alter table t1 add column d default (-5+1);
|
||||
}
|
||||
} {1 {Cannot add a column with non-constant default}}
|
||||
do_test alter4-2.99 {
|
||||
|
|
|
@ -1088,4 +1088,50 @@ foreach {tn where eqp} {
|
|||
do_eqp_test 24.$tn "SeLeCt * FROM t5 WHERE $where" $eqp
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that if stat4 data is available but cannot be used because the
|
||||
# rhs of a range constraint is a complex expression, the default estimates
|
||||
# are used instead.
|
||||
ifcapable stat4&&cte {
|
||||
do_execsql_test 25.1 {
|
||||
CREATE TABLE t6(a, b);
|
||||
WITH ints(i,j) AS (
|
||||
SELECT 1,1 UNION ALL SELECT i+1,j+1 FROM ints WHERE i<100
|
||||
) INSERT INTO t6 SELECT * FROM ints;
|
||||
CREATE INDEX aa ON t6(a);
|
||||
CREATE INDEX bb ON t6(b);
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
# Term (b<?) is estimated at 25%. Better than (a<30) but not as
|
||||
# good as (a<20).
|
||||
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b<?)}
|
||||
}
|
||||
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
}
|
||||
|
||||
# Term (b BETWEEN ? AND ?) is estimated at 1/64.
|
||||
do_eqp_test 25.3.1 {
|
||||
SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
|
||||
# Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
|
||||
# 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
|
||||
# (a<20) but not as good as (a<10).
|
||||
do_eqp_test 25.4.1 {
|
||||
SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
}
|
||||
do_eqp_test 25.4.2 {
|
||||
SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -117,7 +117,7 @@ foreach {tn analyze_cmd} {
|
|||
} {
|
||||
reset_db
|
||||
do_test 1.$tn.1 {
|
||||
execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) }
|
||||
execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT) }
|
||||
for {set i 0} {$i < 100} {incr i} {
|
||||
set c [expr int(pow(1.1,$i)/100)]
|
||||
set b [expr 125 - int(pow(1.1,99-$i))/100]
|
||||
|
@ -161,7 +161,26 @@ foreach {tn analyze_cmd} {
|
|||
do_eqp_test 1.$tn.3.6 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
|
||||
do_eqp_test 1.$tn.3.7 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN +0 AND +50 AND c BETWEEN +0 AND +50
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
|
||||
do_eqp_test 1.$tn.3.8 {
|
||||
SELECT * FROM t1
|
||||
WHERE b BETWEEN cast('0' AS int) AND cast('50.0' AS real)
|
||||
AND c BETWEEN cast('0' AS numeric) AND cast('50.0' AS real)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
|
||||
do_eqp_test 1.$tn.3.9 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN +75 AND +125 AND c BETWEEN +75 AND +125
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
|
||||
do_eqp_test 1.$tn.3.10 {
|
||||
SELECT * FROM t1
|
||||
WHERE b BETWEEN cast('75' AS int) AND cast('125.0' AS real)
|
||||
AND c BETWEEN cast('75' AS numeric) AND cast('125.0' AS real)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
|
Loading…
Reference in New Issue