Compare commits

..

3 Commits

Author SHA1 Message Date
drh 6c92a7711e Add the built-in affinity() SQL function. This turns out to be not as useful
as originally envisioned, so abandon it on a branch.

FossilOrigin-Name: 80889306bf57b886a248b880bc90197b8975a666
2015-06-02 16:09:58 +00:00
drh 05883a3409 Rename SQLITE_AFF_NONE to SQLITE_AFF_BLOB.
FossilOrigin-Name: bce3f04186cd2d69414a5a98b5b77dc8f060554a
2015-06-02 15:32:08 +00:00
drh cd8fb7cfd5 Fix a faulty assert() in btree.c. Update the database fuzz test file with
new test cases.

FossilOrigin-Name: 4e621af1345a001360938de76e3b0a14deb5e991
2015-06-02 14:02:18 +00:00
15 changed files with 242 additions and 214 deletions
+21 -20
View File
@@ -1,5 +1,5 @@
C For\sFROM-clause\ssubqueries\sthat\scannot\sbe\sflattened,\stry\sto\spush\sWHERE\sclause\nterms\sof\sthe\souter\squery\sdown\sinto\sthe\ssubquery\sin\sorder\sto\shelp\sthe\ssubquery\nrun\sfaster\sand/or\suse\sless\smemory.
D 2015-06-01T20:28:03.248
C Add\sthe\sbuilt-in\saffinity()\sSQL\sfunction.\s\sThis\sturns\sout\sto\sbe\snot\sas\suseful\nas\soriginally\senvisioned,\sso\sabandon\sit\son\sa\sbranch.
D 2015-06-02T16:09:58.099
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 994bab32a3a69e0c35bd148b65cde49879772964
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -185,32 +185,32 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 8f6dc4a6ddc1ebc0ed5cc470c4e57ff0d1605e90
F src/alter.c 48e14b8aea28dc58baafe3cfcb8889c086b7744a
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 9e837a0e7e35c54bedddf55db906b7902d175078
F src/btree.c c73a170115df068764126a85288cdec092ec180c
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
F src/build.c 85a169a0a22f8b80caf513eaf2944d39b979f571
F src/build.c 73da2b9e9311abc4fcb4e36f76c7800c2d2504a4
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
F src/expr.c 5de0af7c63a3722d4eb5335f81841f386daa4c20
F src/expr.c 5abe19af1c41dd8b334318611c6614cc21155b88
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
F src/func.c c215efa308b831f7ea147c7a6a03080c870caf8a
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 35b7816918406ec49fbcc6c7fa7ab622597f662e
F src/insert.c d6e1623a97ce33e9af2f1a0c1f0085a2f63327ef
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
@@ -250,12 +250,12 @@ F src/printf.c 13ce37e5574f9b0682fa86dbcf9faf76b9d82a15
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 7acdb105dccfa226ea30f3c08a847d448e216240
F src/select.c 7bb5c6334128877a30d4644fb948098a3ec41bbc
F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
F src/sqlite.h.in d165beeceb6b40af60f352a4d4e37e02d9af7df0
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
F src/sqliteInt.h bc8496de6a514ac66a5a938ee0e4f0d17d150c77
F src/sqliteInt.h 98c49cbd565f08f2e516399734e497340ca9549c
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -312,13 +312,13 @@ F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c a6431c92803b975b7322724a7b433e538d243539
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 6aee8a041742413ab3113e6682bc7ad1628a2bbe
F src/vdbe.c 0a6a1df5c31415a0e974e74e7bd412616889453d
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
F src/vdbeInt.h f0ccddac48583d5f762dc554a9f79e85ea8807e0
F src/vdbeapi.c 6a0d7757987018ff6b1b81bc5293219cd26bb299
F src/vdbeaux.c 46f9bc4b32866082eb87a36b461e487a0bbdbe8e
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
F src/vdbemem.c 21f9169289a804308f6cdde55e9417fb8336997f
F src/vdbemem.c 67b302dc6df64b4d6785881c5d22bd4f9b17739d
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c c535e80259ebe616467181a83a4263555b97c694
@@ -326,9 +326,10 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c f6f41c2f8b9903854992170ea5178898f9cb6c9c
F src/where.c dcdfee81d35ae9261a4c5bda6289ed5fa6d7e1ae
F src/whereInt.h a6f5a762bc1b4b1c76e1cea79976b437ac35a435
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity1.test 3f68d94550f47bac467f916844d939c94882b557
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -655,7 +656,7 @@ F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c a60f926e3fa86c8d33908406d75eec868c22b9ca
F test/fuzzdata1.db b60254eeb6bc11474071b883059662a73c48da7f
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db 2701a08185d24d8570eb6e765201131fe75eff84
F test/fuzzdata3.db 3632e598ff8574228aadf09897bd040d3c5f5ffb
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -1281,10 +1282,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P f925389eaf5bf8962a28fcaa652b75caa606efba
R 033219587dbe88756604bf887ec3da43
T *branch * subquery-opt
T *sym-subquery-opt *
T -sym-trunk *
P bce3f04186cd2d69414a5a98b5b77dc8f060554a
R 98be638f0f819b9a8a15b45777fdc534
T *branch * affinity-func
T *sym-affinity-func *
T -sym-blob-affinity-rename *
U drh
Z 48ce2765ca9875a4f4c27e6792269bfa
Z 13640b2e248aab3cf67f2fff3528da6a
+1 -1
View File
@@ -1 +1 @@
297fae7551a2af9e600d833801ff79fca0602ad5
80889306bf57b886a248b880bc90197b8975a666
+1 -1
View File
@@ -692,7 +692,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
if( pDflt ){
sqlite3_value *pVal = 0;
int rc;
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc!=SQLITE_OK ){
db->mallocFailed = 1;
+3 -3
View File
@@ -6141,9 +6141,9 @@ static void insertCell(
ins = cellOffset + 2*i;
rc = allocateSpace(pPage, sz, &idx);
if( rc ){ *pRC = rc; return; }
/* The allocateSpace() routine guarantees the following two properties
** if it returns success */
assert( idx >= end+2 );
/* The allocateSpace() routine guarantees the following properties
** if it returns successfully */
assert( idx >= 0 && (idx >= end+2 || CORRUPT_DB) );
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nCell++;
pPage->nFree -= (u16)(2 + sz);
+10 -10
View File
@@ -1092,10 +1092,10 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
pCol->zName = z;
/* If there is no type specified, columns have the default affinity
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
** 'BLOB'. If there is a type specified, then sqlite3AddColumnType() will
** be called next to set pCol->affinity correctly.
*/
pCol->affinity = SQLITE_AFF_NONE;
pCol->affinity = SQLITE_AFF_BLOB;
pCol->szEst = 1;
p->nCol++;
}
@@ -1130,7 +1130,7 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
** 'CHAR' | SQLITE_AFF_TEXT
** 'CLOB' | SQLITE_AFF_TEXT
** 'TEXT' | SQLITE_AFF_TEXT
** 'BLOB' | SQLITE_AFF_NONE
** 'BLOB' | SQLITE_AFF_BLOB
** 'REAL' | SQLITE_AFF_REAL
** 'FLOA' | SQLITE_AFF_REAL
** 'DOUB' | SQLITE_AFF_REAL
@@ -1156,7 +1156,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
aff = SQLITE_AFF_TEXT;
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
aff = SQLITE_AFF_NONE;
aff = SQLITE_AFF_BLOB;
if( zIn[0]=='(' ) zChar = zIn;
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
@@ -1548,7 +1548,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
static const char * const azType[] = {
/* SQLITE_AFF_NONE */ "",
/* SQLITE_AFF_BLOB */ "",
/* SQLITE_AFF_TEXT */ " TEXT",
/* SQLITE_AFF_NUMERIC */ " NUM",
/* SQLITE_AFF_INTEGER */ " INT",
@@ -1561,17 +1561,17 @@ static char *createTableStmt(sqlite3 *db, Table *p){
k += sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, pCol->zName);
assert( pCol->affinity-SQLITE_AFF_NONE >= 0 );
assert( pCol->affinity-SQLITE_AFF_NONE < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_NONE );
assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_BLOB );
testcase( pCol->affinity==SQLITE_AFF_TEXT );
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
testcase( pCol->affinity==SQLITE_AFF_REAL );
zType = azType[pCol->affinity - SQLITE_AFF_NONE];
zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
len = sqlite3Strlen30(zType);
assert( pCol->affinity==SQLITE_AFF_NONE
assert( pCol->affinity==SQLITE_AFF_BLOB
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
memcpy(&zStmt[k], zType, len);
k += len;
+22 -6
View File
@@ -191,13 +191,13 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){
return SQLITE_AFF_NUMERIC;
}else{
return SQLITE_AFF_NONE;
return SQLITE_AFF_BLOB;
}
}else if( !aff1 && !aff2 ){
/* Neither side of the comparison is a column. Compare the
** results directly.
*/
return SQLITE_AFF_NONE;
return SQLITE_AFF_BLOB;
}else{
/* One side is a column, the other is not. Use the columns affinity. */
assert( aff1==0 || aff2==0 );
@@ -221,7 +221,7 @@ static char comparisonAffinity(Expr *pExpr){
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( !aff ){
aff = SQLITE_AFF_NONE;
aff = SQLITE_AFF_BLOB;
}
return aff;
}
@@ -235,7 +235,7 @@ static char comparisonAffinity(Expr *pExpr){
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
char aff = comparisonAffinity(pExpr);
switch( aff ){
case SQLITE_AFF_NONE:
case SQLITE_AFF_BLOB:
return 1;
case SQLITE_AFF_TEXT:
return idx_affinity==SQLITE_AFF_TEXT;
@@ -1482,7 +1482,7 @@ int sqlite3ExprCanBeNull(const Expr *p){
*/
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
u8 op;
if( aff==SQLITE_AFF_NONE ) return 1;
if( aff==SQLITE_AFF_BLOB ) return 1;
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
@@ -1933,7 +1933,7 @@ int sqlite3CodeSubselect(
int r1, r2, r3;
if( !affinity ){
affinity = SQLITE_AFF_NONE;
affinity = SQLITE_AFF_BLOB;
}
if( pKeyInfo ){
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
@@ -2874,6 +2874,22 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
/* The AFFINITY() function returns the type affinity of its argument.
** The type affinity is a compile-time value, so we might as well
** code it directly.
*/
if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
int aff;
static const char *const azAffName[] = {
"", "BLOB", "TEXT", "NUMERIC", "INTEGER", "REAL"
};
assert( nFarg==1 );
aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
if( aff ) aff -= SQLITE_AFF_BLOB - 1;
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, azAffName[aff], 0);
break;
}
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
testcase( i==31 );
+1
View File
@@ -1717,6 +1717,7 @@ void sqlite3RegisterGlobalFunctions(void){
AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
SQLITE_FUNC_MINMAX ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
+5 -5
View File
@@ -56,7 +56,7 @@ void sqlite3OpenTable(
**
** Character Column affinity
** ------------------------------
** 'A' NONE
** 'A' BLOB
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
@@ -99,9 +99,9 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
/*
** Compute the affinity string for table pTab, if it has not already been
** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities.
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
**
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and
** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
** for register iReg and following. Or if affinities exists and iReg==0,
** then just set the P4 operand of the previous opcode (which should be
@@ -111,7 +111,7 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
**
** Character Column affinity
** ------------------------------
** 'A' NONE
** 'A' BLOB
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
@@ -133,7 +133,7 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}
do{
zColAff[i--] = 0;
}while( i>=0 && zColAff[i]==SQLITE_AFF_NONE );
}while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
pTab->zColAff = zColAff;
}
i = sqlite3Strlen30(zColAff);
+51 -130
View File
@@ -1709,7 +1709,7 @@ static void selectAddColumnTypeAndCollation(
}
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl && pCol->zColl==0 ){
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
@@ -3718,73 +3718,6 @@ static int flattenSubquery(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery. Example:
**
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
**
** Transformed into:
**
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
** WHERE x=5 AND y=10;
**
** The hope is that the terms added to the inner query will make it more
** efficient.
**
** Do not attempt this optimization if:
**
** (1) The inner query is an aggregate. (In that case, we'd really want
** to copy the outer WHERE-clause terms onto the HAVING clause of the
** inner query. But they probably won't help there so do not bother.)
**
** (2) The inner query is the recursive part of a common table expression.
**
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
** close would change the meaning of the LIMIT).
**
** (4) The inner query is the right operand of a LEFT JOIN. (The caller
** enforces this restriction since this routine does not have enough
** information to know.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
sqlite3 *db, /* The database connection (for malloc()) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor /* Cursor number of the subquery */
){
Expr *pNew;
int nChng = 0;
if( pWhere==0 ) return 0;
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
return 0; /* restrictions (1) and (2) */
}
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
pNew = sqlite3ExprDup(db, pWhere, 0);
pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
pSubq = pSubq->pPrior;
}
}
return nChng;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** Based on the contents of the AggInfo structure indicated by the first
** argument, this function checks if the following are true:
@@ -4883,72 +4816,60 @@ int sqlite3Select(
p->selFlags |= SF_Aggregate;
}
i = -1;
}else if( pTabList->nSrc==1
&& (p->selFlags & SF_All)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
VdbeComment((v, "%s", pItem->pTab->zName));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
pItem->viaCoroutine = 1;
pItem->regResult = dest.iSdst;
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
}else{
if( (pItem->jointype & JT_OUTER)==0
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
sqlite3DebugPrintf("After WHERE-clause push-down:\n");
sqlite3TreeViewSelect(0, p, 0);
}
#endif
}
if( pTabList->nSrc==1
&& (p->selFlags & SF_All)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
VdbeComment((v, "%s", pItem->pTab->zName));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
pItem->viaCoroutine = 1;
pItem->regResult = dest.iSdst;
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
/* Generate a subroutine that will fill an ephemeral table with
** the content of this subquery. pItem->addrFillSub will point
** to the address of the generated subroutine. pItem->regReturn
** is a register allocated to hold the subroutine return address
*/
int topAddr;
int onceAddr = 0;
int retAddr;
assert( pItem->addrFillSub==0 );
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
if( pItem->isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
}else{
/* Generate a subroutine that will fill an ephemeral table with
** the content of this subquery. pItem->addrFillSub will point
** to the address of the generated subroutine. pItem->regReturn
** is a register allocated to hold the subroutine return address
*/
int topAddr;
int onceAddr = 0;
int retAddr;
assert( pItem->addrFillSub==0 );
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
if( pItem->isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
}else{
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
}
if( db->mallocFailed ){
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
}
pParse->nHeight -= sqlite3SelectExprHeight(p);
+15 -14
View File
@@ -1348,18 +1348,19 @@ struct FuncDestructor {
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
** are assert() statements in the code to verify this.
*/
#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */
#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq might be called */
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_AFFINITY 0x2000 /* Built-in affinity() function */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -1501,9 +1502,9 @@ struct CollSeq {
** used as the P4 operand, they will be more readable.
**
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison. And the NONE type is first.
** for a numeric type is a single comparison. And the BLOB type is first.
*/
#define SQLITE_AFF_NONE 'A'
#define SQLITE_AFF_BLOB 'A'
#define SQLITE_AFF_TEXT 'B'
#define SQLITE_AFF_NUMERIC 'C'
#define SQLITE_AFF_INTEGER 'D'
+4 -4
View File
@@ -270,7 +270,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
** SQLITE_AFF_TEXT:
** Convert pRec to a text representation.
**
** SQLITE_AFF_NONE:
** SQLITE_AFF_BLOB:
** No-op. pRec is unchanged.
*/
static void applyAffinity(
@@ -1780,9 +1780,9 @@ case OP_RealAffinity: { /* in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_Cast: { /* in1 */
assert( pOp->p2>=SQLITE_AFF_NONE && pOp->p2<=SQLITE_AFF_REAL );
assert( pOp->p2>=SQLITE_AFF_BLOB && pOp->p2<=SQLITE_AFF_REAL );
testcase( pOp->p2==SQLITE_AFF_TEXT );
testcase( pOp->p2==SQLITE_AFF_NONE );
testcase( pOp->p2==SQLITE_AFF_BLOB );
testcase( pOp->p2==SQLITE_AFF_NUMERIC );
testcase( pOp->p2==SQLITE_AFF_INTEGER );
testcase( pOp->p2==SQLITE_AFF_REAL );
@@ -2593,7 +2593,7 @@ case OP_Affinity: {
** The mapping from character to affinity is given by the SQLITE_AFF_
** macros defined in sqliteInt.h.
**
** If P4 is NULL then all index fields have the affinity NONE.
** If P4 is NULL then all index fields have the affinity BLOB.
*/
case OP_MakeRecord: {
u8 *zNewRecord; /* A buffer to hold the data for the new record */
+2 -2
View File
@@ -588,7 +588,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
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 */
case SQLITE_AFF_BLOB: { /* 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 );
@@ -1311,7 +1311,7 @@ static int valueFromExpr(
if( zVal==0 ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
}
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_BLOB ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
}else{
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
+18 -18
View File
@@ -680,7 +680,7 @@ static int isLikeOrGlob(
if( op==TK_VARIABLE ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_NONE);
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = (char *)sqlite3_value_text(pVal);
}
@@ -2824,9 +2824,9 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
** Code an OP_Affinity opcode to apply the column affinity string zAff
** to the n registers starting at base.
**
** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the
** beginning and end of zAff are ignored. If all entries in zAff are
** SQLITE_AFF_NONE, then no code gets generated.
** SQLITE_AFF_BLOB, then no code gets generated.
**
** This routine makes its own copy of zAff so that the caller is free
** to modify zAff after this routine returns.
@@ -2839,15 +2839,15 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
}
assert( v!=0 );
/* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
/* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning
** and end of the affinity string.
*/
while( n>0 && zAff[0]==SQLITE_AFF_NONE ){
while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){
n--;
base++;
zAff++;
}
while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){
while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){
n--;
}
@@ -2977,17 +2977,17 @@ static int codeEqualityTerm(
** Before returning, *pzAff is set to point to a buffer containing a
** copy of the column affinity string of the index allocated using
** sqlite3DbMalloc(). Except, entries in the copy of the string associated
** with equality constraints that use NONE affinity are set to
** SQLITE_AFF_NONE. This is to deal with SQL such as the following:
** with equality constraints that use BLOB or NONE affinity are set to
** SQLITE_AFF_BLOB. This is to deal with SQL such as the following:
**
** CREATE TABLE t1(a TEXT PRIMARY KEY, b);
** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
**
** In the example above, the index on t1(a) has TEXT affinity. But since
** the right hand side of the equality constraint (t2.b) has NONE affinity,
** the right hand side of the equality constraint (t2.b) has BLOB/NONE affinity,
** no conversion should be attempted before using a t2.b value as part of
** a key to search the index. Hence the first byte in the returned affinity
** string in this example would be set to SQLITE_AFF_NONE.
** string in this example would be set to SQLITE_AFF_BLOB.
*/
static int codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
@@ -3074,11 +3074,11 @@ static int codeAllEqualityTerms(
VdbeCoverage(v);
}
if( zAff ){
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
zAff[j] = SQLITE_AFF_NONE;
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
zAff[j] = SQLITE_AFF_BLOB;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
zAff[j] = SQLITE_AFF_NONE;
zAff[j] = SQLITE_AFF_BLOB;
}
}
}
@@ -3725,14 +3725,14 @@ static Bitmask codeOneLoopStart(
VdbeCoverage(v);
}
if( zStartAff ){
if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_BLOB){
/* Since the comparison is to be performed with no conversions
** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zStartAff[nEq] = SQLITE_AFF_NONE;
** SQLITE_AFF_BLOB. */
zStartAff[nEq] = SQLITE_AFF_BLOB;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){
zStartAff[nEq] = SQLITE_AFF_NONE;
zStartAff[nEq] = SQLITE_AFF_BLOB;
}
}
nConstraint++;
@@ -3770,7 +3770,7 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
VdbeCoverage(v);
}
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_BLOB
&& !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
){
codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff);
+88
View File
@@ -0,0 +1,88 @@
# 2015-06-02
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is type affinity and the affinity() built-in
# function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix affinity1
do_execsql_test 100 {
CREATE TABLE t1(
c01 INT,
c02 INTEGER,
c03 TINYINT,
c04 SMALLINT,
c05 MEDIUMINT,
c06 BIGINT,
c07 UNSIGNED BIG INT,
c08 INT2,
c09 INT4,
c10 CHARACTER(20),
c11 VARCHAR(255),
c12 VARYING CHARACTER(255),
c13 NCHAR(55),
c14 NATIVE CHARACTER(70),
c15 NVARCHAR(100),
c16 TEXT,
c17 CLOB,
c20 BLOB,
c21,
c30 REAL,
c31 DOUBLE,
c32 DOUBLE PRECISION,
c33 FLOAT,
c40 NUMERIC,
c41 DECIMAL(10,5),
c42 BOOLEAN,
c43 DATE,
c44 DATETIME,
c50 FLOATING POINT,
c60 STRING
);
INSERT INTO t1 DEFAULT VALUES;
} {}
do_execsql_test 201 {
SELECT affinity(c01), affinity(c01+1), affinity(+c01) FROM t1;
} {INTEGER {} {}}
do_execsql_test 202 {SELECT affinity(c02) FROM t1} {INTEGER}
do_execsql_test 203 {SELECT affinity(c03) FROM t1} {INTEGER}
do_execsql_test 204 {SELECT affinity(c04) FROM t1} {INTEGER}
do_execsql_test 205 {SELECT affinity(c05) FROM t1} {INTEGER}
do_execsql_test 206 {SELECT affinity(c06) FROM t1} {INTEGER}
do_execsql_test 207 {SELECT affinity(c07) FROM t1} {INTEGER}
do_execsql_test 208 {SELECT affinity(c08) FROM t1} {INTEGER}
do_execsql_test 209 {SELECT affinity(c09) FROM t1} {INTEGER}
do_execsql_test 210 {SELECT affinity(c10) FROM t1} {TEXT}
do_execsql_test 211 {SELECT affinity(c11) FROM t1} {TEXT}
do_execsql_test 212 {SELECT affinity(c12) FROM t1} {TEXT}
do_execsql_test 213 {SELECT affinity(c13) FROM t1} {TEXT}
do_execsql_test 214 {SELECT affinity(c14) FROM t1} {TEXT}
do_execsql_test 215 {SELECT affinity(c15) FROM t1} {TEXT}
do_execsql_test 216 {SELECT affinity(c16) FROM t1} {TEXT}
do_execsql_test 220 {SELECT affinity(c20) FROM t1} {BLOB}
do_execsql_test 221 {SELECT affinity(c21) FROM t1} {BLOB}
do_execsql_test 230 {SELECT affinity(c30) FROM t1} {REAL}
do_execsql_test 231 {SELECT affinity(c31) FROM t1} {REAL}
do_execsql_test 232 {SELECT affinity(c32) FROM t1} {REAL}
do_execsql_test 233 {SELECT affinity(c33) FROM t1} {REAL}
do_execsql_test 240 {SELECT affinity(c40) FROM t1} {NUMERIC}
do_execsql_test 241 {SELECT affinity(c41) FROM t1} {NUMERIC}
do_execsql_test 242 {SELECT affinity(c42) FROM t1} {NUMERIC}
do_execsql_test 243 {SELECT affinity(c43) FROM t1} {NUMERIC}
do_execsql_test 244 {SELECT affinity(c44) FROM t1} {NUMERIC}
do_execsql_test 250 {SELECT affinity(c50) FROM t1} {INTEGER}
do_execsql_test 260 {SELECT affinity(c60) FROM t1} {NUMERIC}
finish_test
BIN
View File
Binary file not shown.