Update this branch with latest trunk changes.
FossilOrigin-Name: 0f66a093935100efd731e14aa63b57360ddd517c1ac97edd1ea9a9de95e1f3cc
This commit is contained in:
commit
0e0f5edbb5
@ -785,7 +785,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
||||
j = i+1;
|
||||
for(;;){
|
||||
c = z[j];
|
||||
if( c==0 ) return -1;
|
||||
if( c<=0x1f ) return -1; /* Control characters not allowed in strings */
|
||||
if( c=='\\' ){
|
||||
c = z[++j];
|
||||
if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
|
||||
|
41
manifest
41
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\sformatting\sissue\sin\sthe\soutput\sof\sthe\ssqlite3_expert\sprogram.
|
||||
D 2017-04-11T18:29:14.206
|
||||
C Update\sthis\s\sbranch\swith\slatest\strunk\schanges.
|
||||
D 2017-04-11T19:00:30.300
|
||||
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
|
||||
@ -224,7 +224,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c 312b4ddf4c7399dcbd2189f492e8ca92a872c2df7347473bfb38854f9d60c06a
|
||||
F ext/misc/json1.c 70d49f69ce61e54a83a29e425e704ca3e7e42e6bd9a7cf3c112d0ad995f6560b
|
||||
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
|
||||
@ -351,7 +351,7 @@ F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
||||
F src/btree.c 24ae5472bd0b53b4130ecdda389deb621af721d1fcb50890b878102b00bd10fa
|
||||
F src/btree.h bf64dfeeddeebdb775a5eba0098bbc00d073290d
|
||||
F src/btree.h 80f518c0788be6cec8d9f8e13bd8e380df299d2b5e4ac340dc887b0642647cfc
|
||||
F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610
|
||||
F src/build.c 4026a9c554b233e50c5e9ad46963e676cf54dd2306d952aa1eaa07a1bc9ce14f
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
@ -360,7 +360,7 @@ F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c
|
||||
F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae
|
||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
|
||||
F src/expr.c 6bce2cbdd822963cf28e782938a96274cc37f18ac28dec7a4e35ccac09f66ce8
|
||||
F src/expr.c f6572c7690fa619e85b1192b683ccc30cd123363415963c061ada3770b18f6a7
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
|
||||
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
|
||||
@ -407,12 +407,12 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c afcf31d8ed7c890328a31d3f350467ccd273af345b24562382b398d6d9cd0664
|
||||
F src/select.c e6f9afd8a5ef35bd186e51a6bea6d3d46bc93a530f26a21fe8a0a43dbeca9415
|
||||
F src/shell.c 70f4957b988572315e97c56941fdc81fd35907fee36b7b2e7be5ec4c7e9d065d
|
||||
F src/sqlite.h.in 8ed51474c7a9edacbf328e2a6ce63de5cde8f50793c6063cb508f9de128e5a4c
|
||||
F src/sqlite.h.in cf20591fa0eb09e435db647ab28b61159262cbebac69ddad3c8c01accfb6c856
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
|
||||
F src/sqliteInt.h 36eec0868d25b50e64a05bc7355557a0aa9bd14330c16b7d7568520b2bf2bb4e
|
||||
F src/sqliteInt.h 5bcafb7c36f7f8765ed1e7031b7eb5f5e84cfdfe5ea4b3af01178528bde259c8
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
@ -475,12 +475,12 @@ F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
|
||||
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
|
||||
F src/vdbe.c 808fda3d50f544120d27c731449b524b4ec8f8b0f734b228831078f0ba53ecb9
|
||||
F src/vdbe.h caa5346d52bae2a3c8c1dcfa60a7a4dc878a9e3865cb8239da55808b316c8158
|
||||
F src/vdbeInt.h 5db089ce18c4feff8820ec6e4cac2d2c82e03d4b1d96f10a6e43832147b8dffe
|
||||
F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848
|
||||
F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade
|
||||
F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860
|
||||
F src/vdbeaux.c 0ecacf8c7ca93e430b30819b8fc9b2c1ffe88202d1437e88c08a1f0b6159c58c
|
||||
F src/vdbeaux.c 6b3f6ce909e206d4c918988b13b7fa687e92b4471d137e0f2a37edac80ec60be
|
||||
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
|
||||
F src/vdbemem.c 8bb4dd22837da969bfda25ef3f92d41aaad192328f89a0951290d5e26ad7dbc4
|
||||
F src/vdbemem.c 3122f5a21064198c10ee1b4686937aab27d5395712d9af905b7fa1affc47a453
|
||||
F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c
|
||||
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
||||
F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790
|
||||
@ -488,10 +488,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
||||
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
||||
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
|
||||
F src/where.c 613b1cac781b2725bb0a841d5c264ae9475380ee3063c3ce9c81814b03a83c20
|
||||
F src/whereInt.h 2d50c2b74a33be44cb68fdecee30b4d93552f1f4
|
||||
F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
|
||||
F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
|
||||
F src/where.c f5acfb6fbac65e7da7b0e718fa6c6e784dee37eb29dad6efd42880ca117e7277
|
||||
F src/whereInt.h 7a21ef633e26acbf46df04add2eba6e0a2100c78dc5879049e93f981fc3344df
|
||||
F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681
|
||||
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@ -884,6 +884,7 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
|
||||
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
|
||||
F test/indexexpr1.test 038b3befa74e5a75126b6e9dd2ae5df61c1c7cf7
|
||||
F test/indexexpr2.test bcf694ae72efaaeb97691b990b61e39bf233884e27b9cc6b845a1f0c6bc9f0bb
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@ -917,7 +918,7 @@ F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
|
||||
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
|
||||
F test/json102.test de1728e8ffde4a57cbc77b6815a60ccb82a6c759967be44e71952757e7d7947b
|
||||
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
@ -1577,7 +1578,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 0c45c5eb9f0f171b8d7c5f0d2973f9f59915467506cdff1450f3e4b2134a01ca
|
||||
R 33f15deae23049b95df8ad5185895aff
|
||||
P cc8c3581060ffef02290b680183e6f6bc9837ba3550e74c8aaabdc7c45edc223 76cd611d41465fcec61c21520d55172cb236530f38386b7d4a5544ba87de2353
|
||||
R 598dc6bf3b8d38f8068b443f6c7f3624
|
||||
U dan
|
||||
Z 2806083003fa51636f951574e2a01b7d
|
||||
Z 7c38a019370c850a76053a951a01d320
|
||||
|
@ -1 +1 @@
|
||||
cc8c3581060ffef02290b680183e6f6bc9837ba3550e74c8aaabdc7c45edc223
|
||||
0f66a093935100efd731e14aa63b57360ddd517c1ac97edd1ea9a9de95e1f3cc
|
@ -276,7 +276,7 @@ struct BtreePayload {
|
||||
const void *pKey; /* Key content for indexes. NULL for tables */
|
||||
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
|
||||
const void *pData; /* Data for tables. NULL for indexes */
|
||||
struct Mem *aMem; /* First of nMem value in the unpacked pKey */
|
||||
sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
|
||||
u16 nMem; /* Number of aMem[] value. Might be zero */
|
||||
int nData; /* Size of pData. 0 if none. */
|
||||
int nZero; /* Extra zero data appended after pData,nData */
|
||||
|
@ -58,7 +58,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
||||
return sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
}
|
||||
#endif
|
||||
if( op==TK_AGG_COLUMN || op==TK_COLUMN ){
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
|
||||
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
|
||||
}
|
||||
if( op==TK_SELECT_COLUMN ){
|
||||
@ -3192,6 +3192,10 @@ void sqlite3ExprCodeGetColumnOfTable(
|
||||
int iCol, /* Index of the column to extract */
|
||||
int regOut /* Extract the value into this register */
|
||||
){
|
||||
if( pTab==0 ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
|
||||
return;
|
||||
}
|
||||
if( iCol<0 || iCol==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
|
||||
}else{
|
||||
|
44
src/select.c
44
src/select.c
@ -112,14 +112,13 @@ Select *sqlite3SelectNew(
|
||||
){
|
||||
Select *pNew;
|
||||
Select standin;
|
||||
sqlite3 *db = pParse->db;
|
||||
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
|
||||
pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
|
||||
if( pNew==0 ){
|
||||
assert( db->mallocFailed );
|
||||
assert( pParse->db->mallocFailed );
|
||||
pNew = &standin;
|
||||
}
|
||||
if( pEList==0 ){
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
|
||||
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0));
|
||||
}
|
||||
pNew->pEList = pEList;
|
||||
pNew->op = TK_SELECT;
|
||||
@ -132,7 +131,7 @@ Select *sqlite3SelectNew(
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
pNew->nSelectRow = 0;
|
||||
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
|
||||
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
|
||||
pNew->pSrc = pSrc;
|
||||
pNew->pWhere = pWhere;
|
||||
pNew->pGroupBy = pGroupBy;
|
||||
@ -143,9 +142,9 @@ Select *sqlite3SelectNew(
|
||||
pNew->pLimit = pLimit;
|
||||
pNew->pOffset = pOffset;
|
||||
pNew->pWith = 0;
|
||||
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
|
||||
if( db->mallocFailed ) {
|
||||
clearSelect(db, pNew, pNew!=&standin);
|
||||
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 );
|
||||
if( pParse->db->mallocFailed ) {
|
||||
clearSelect(pParse->db, pNew, pNew!=&standin);
|
||||
pNew = 0;
|
||||
}else{
|
||||
assert( pNew->pSrc!=0 || pParse->nErr>0 );
|
||||
@ -1530,6 +1529,7 @@ static void generateColumnTypes(
|
||||
NameContext sNC;
|
||||
sNC.pSrcList = pTabList;
|
||||
sNC.pParse = pParse;
|
||||
sNC.pNext = 0;
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
Expr *p = pEList->a[i].pExpr;
|
||||
const char *zType;
|
||||
@ -1554,6 +1554,19 @@ static void generateColumnTypes(
|
||||
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the Table objecct in the SrcList that has cursor iCursor.
|
||||
** Or return NULL if no such Table object exists in the SrcList.
|
||||
*/
|
||||
static Table *tableWithCursor(SrcList *pList, int iCursor){
|
||||
int j;
|
||||
for(j=0; j<pList->nSrc; j++){
|
||||
if( pList->a[j].iCursor==iCursor ) return pList->a[j].pTab;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Generate code that will tell the VDBE the names of columns
|
||||
** in the result set. This information is used to provide the
|
||||
@ -1565,7 +1578,8 @@ static void generateColumnNames(
|
||||
ExprList *pEList /* Expressions defining the result set */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i, j;
|
||||
int i;
|
||||
Table *pTab;
|
||||
sqlite3 *db = pParse->db;
|
||||
int fullNames, shortNames;
|
||||
|
||||
@ -1590,15 +1604,11 @@ static void generateColumnNames(
|
||||
if( pEList->a[i].zName ){
|
||||
char *zName = pEList->a[i].zName;
|
||||
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
|
||||
}else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){
|
||||
Table *pTab;
|
||||
}else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
|
||||
&& (pTab = tableWithCursor(pTabList, p->iTable))!=0
|
||||
){
|
||||
char *zCol;
|
||||
int iCol = p->iColumn;
|
||||
for(j=0; ALWAYS(j<pTabList->nSrc); j++){
|
||||
if( pTabList->a[j].iCursor==p->iTable ) break;
|
||||
}
|
||||
assert( j<pTabList->nSrc );
|
||||
pTab = pTabList->a[j].pTab;
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
|
||||
if( iCol<0 ){
|
||||
@ -3147,7 +3157,7 @@ static void substSelect(Parse*, Select *, int, ExprList*, int);
|
||||
** This routine is part of the flattening procedure. A subquery
|
||||
** whose result set is defined by pEList appears as entry in the
|
||||
** FROM clause of a SELECT such that the VDBE cursor assigned to that
|
||||
** FORM clause entry is iTable. This routine make the necessary
|
||||
** FORM clause entry is iTable. This routine makes the necessary
|
||||
** changes to pExpr so that it refers directly to the source table
|
||||
** of the subquery rather the result set of the subquery.
|
||||
*/
|
||||
|
@ -3701,7 +3701,7 @@ int sqlite3_stmt_busy(sqlite3_stmt*);
|
||||
** The [sqlite3_value_blob | sqlite3_value_type()] family of
|
||||
** interfaces require protected sqlite3_value objects.
|
||||
*/
|
||||
typedef struct Mem sqlite3_value;
|
||||
typedef struct sqlite3_value sqlite3_value;
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Function Context Object
|
||||
|
@ -3328,6 +3328,7 @@ struct Walker {
|
||||
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
|
||||
int *aiCol; /* array of column indexes */
|
||||
struct IdxCover *pIdxCover; /* Check for index coverage */
|
||||
struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,7 @@ typedef struct Vdbe Vdbe;
|
||||
** The names of the following types declared in vdbeInt.h are required
|
||||
** for the VdbeOp definition.
|
||||
*/
|
||||
typedef struct Mem Mem;
|
||||
typedef struct sqlite3_value Mem;
|
||||
typedef struct SubProgram SubProgram;
|
||||
|
||||
/*
|
||||
|
@ -185,7 +185,7 @@ struct VdbeFrame {
|
||||
** structures. Each Mem struct may cache multiple representations (string,
|
||||
** integer etc.) of the same value.
|
||||
*/
|
||||
struct Mem {
|
||||
struct sqlite3_value {
|
||||
union MemValue {
|
||||
double r; /* Real value used when MEM_Real is set in flags */
|
||||
i64 i; /* Integer value used when MEM_Int is set in flags */
|
||||
|
@ -879,7 +879,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
||||
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
|
||||
if( aOp ){
|
||||
Op *pOp;
|
||||
for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
|
||||
for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){
|
||||
if( pOp->p4type ) freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
sqlite3DbFree(db, pOp->zComment);
|
||||
|
@ -125,26 +125,24 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
|
||||
assert( pMem->szMalloc==0
|
||||
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
|
||||
if( pMem->szMalloc<n ){
|
||||
if( n<32 ) n = 32;
|
||||
if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){
|
||||
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
|
||||
bPreserve = 0;
|
||||
}else{
|
||||
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
|
||||
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
|
||||
}
|
||||
if( pMem->zMalloc==0 ){
|
||||
sqlite3VdbeMemSetNull(pMem);
|
||||
pMem->z = 0;
|
||||
pMem->szMalloc = 0;
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
|
||||
}
|
||||
if( n<32 ) n = 32;
|
||||
if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){
|
||||
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
|
||||
bPreserve = 0;
|
||||
}else{
|
||||
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
|
||||
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
|
||||
}
|
||||
if( pMem->zMalloc==0 ){
|
||||
sqlite3VdbeMemSetNull(pMem);
|
||||
pMem->z = 0;
|
||||
pMem->szMalloc = 0;
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
|
||||
}
|
||||
|
||||
if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){
|
||||
if( bPreserve && pMem->z && ALWAYS(pMem->z!=pMem->zMalloc) ){
|
||||
memcpy(pMem->zMalloc, pMem->z, pMem->n);
|
||||
}
|
||||
if( (pMem->flags&MEM_Dyn)!=0 ){
|
||||
|
@ -4642,6 +4642,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->pOrderBy = pOrderBy;
|
||||
pWInfo->pWhere = pWhere;
|
||||
pWInfo->pResultSet = pResultSet;
|
||||
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
|
||||
pWInfo->nLevel = nTabList;
|
||||
|
@ -417,6 +417,7 @@ struct WhereInfo {
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pResultSet; /* Result set of the query */
|
||||
Expr *pWhere; /* The complete WHERE clause */
|
||||
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
|
||||
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
|
@ -1039,6 +1039,69 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
|
||||
}
|
||||
}
|
||||
|
||||
/* An instance of the IdxExprTrans object carries information about a
|
||||
** mapping from an expression on table columns into a column in an index
|
||||
** down through the Walker.
|
||||
*/
|
||||
typedef struct IdxExprTrans {
|
||||
Expr *pIdxExpr; /* The index expression */
|
||||
int iTabCur; /* The cursor of the corresponding table */
|
||||
int iIdxCur; /* The cursor for the index */
|
||||
int iIdxCol; /* The column for the index */
|
||||
} IdxExprTrans;
|
||||
|
||||
/* The walker node callback used to transform matching expressions into
|
||||
** a reference to an index column for an index on an expression.
|
||||
**
|
||||
** If pExpr matches, then transform it into a reference to the index column
|
||||
** that contains the value of pExpr.
|
||||
*/
|
||||
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
|
||||
IdxExprTrans *pX = p->u.pIdxTrans;
|
||||
if( sqlite3ExprCompare(pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
|
||||
pExpr->op = TK_COLUMN;
|
||||
pExpr->iTable = pX->iIdxCur;
|
||||
pExpr->iColumn = pX->iIdxCol;
|
||||
pExpr->pTab = 0;
|
||||
return WRC_Prune;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** For an indexes on expression X, locate every instance of expression X in pExpr
|
||||
** and change that subexpression into a reference to the appropriate column of
|
||||
** the index.
|
||||
*/
|
||||
static void whereIndexExprTrans(
|
||||
Index *pIdx, /* The Index */
|
||||
int iTabCur, /* Cursor of the table that is being indexed */
|
||||
int iIdxCur, /* Cursor of the index itself */
|
||||
WhereInfo *pWInfo /* Transform expressions in this WHERE clause */
|
||||
){
|
||||
int iIdxCol; /* Column number of the index */
|
||||
ExprList *aColExpr; /* Expressions that are indexed */
|
||||
Walker w;
|
||||
IdxExprTrans x;
|
||||
aColExpr = pIdx->aColExpr;
|
||||
if( aColExpr==0 ) return; /* Not an index on expressions */
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = whereIndexExprTransNode;
|
||||
w.u.pIdxTrans = &x;
|
||||
x.iTabCur = iTabCur;
|
||||
x.iIdxCur = iIdxCur;
|
||||
for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
|
||||
if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
|
||||
assert( aColExpr->a[iIdxCol].pExpr!=0 );
|
||||
x.iIdxCol = iIdxCol;
|
||||
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
|
||||
sqlite3WalkExpr(&w, pWInfo->pWhere);
|
||||
sqlite3WalkExprList(&w, pWInfo->pOrderBy);
|
||||
sqlite3WalkExprList(&w, pWInfo->pResultSet);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||
** implementation described by pWInfo.
|
||||
@ -1620,6 +1683,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
|
||||
}
|
||||
|
||||
/* If pIdx is an index on one or more expressions, then look through
|
||||
** all the expressions in pWInfo and try to transform matching expressions
|
||||
** into reference to index columns.
|
||||
*/
|
||||
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
|
||||
|
||||
|
||||
/* Record the instruction used to terminate the loop. */
|
||||
if( pLoop->wsFlags & WHERE_ONEROW ){
|
||||
pLevel->op = OP_Noop;
|
||||
|
@ -830,8 +830,8 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
|
||||
** Expression pExpr is one operand of a comparison operator that might
|
||||
** be useful for indexing. This routine checks to see if pExpr appears
|
||||
** in any index. Return TRUE (1) if pExpr is an indexed term and return
|
||||
** FALSE (0) if not. If TRUE is returned, also set *piCur to the cursor
|
||||
** number of the table that is indexed and *piColumn to the column number
|
||||
** FALSE (0) if not. If TRUE is returned, also set aiCurCol[0] to the cursor
|
||||
** number of the table that is indexed and aiCurCol[1] to the column number
|
||||
** of the column that is indexed, or XN_EXPR (-2) if an expression is being
|
||||
** indexed.
|
||||
**
|
||||
@ -839,18 +839,37 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
|
||||
** true even if that particular column is not indexed, because the column
|
||||
** might be added to an automatic index later.
|
||||
*/
|
||||
static int exprMightBeIndexed(
|
||||
static SQLITE_NOINLINE int exprMightBeIndexed2(
|
||||
SrcList *pFrom, /* The FROM clause */
|
||||
int op, /* The specific comparison operator */
|
||||
Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */
|
||||
Expr *pExpr, /* An operand of a comparison operator */
|
||||
int *piCur, /* Write the referenced table cursor number here */
|
||||
int *piColumn /* Write the referenced table column number here */
|
||||
int *aiCurCol, /* Write the referenced table cursor and column here */
|
||||
Expr *pExpr /* An operand of a comparison operator */
|
||||
){
|
||||
Index *pIdx;
|
||||
int i;
|
||||
int iCur;
|
||||
|
||||
for(i=0; mPrereq>1; i++, mPrereq>>=1){}
|
||||
iCur = pFrom->a[i].iCursor;
|
||||
for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( pIdx->aColExpr==0 ) continue;
|
||||
for(i=0; i<pIdx->nKeyCol; i++){
|
||||
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
|
||||
if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
|
||||
aiCurCol[0] = iCur;
|
||||
aiCurCol[1] = XN_EXPR;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int exprMightBeIndexed(
|
||||
SrcList *pFrom, /* The FROM clause */
|
||||
Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */
|
||||
int *aiCurCol, /* Write the referenced table cursor & column here */
|
||||
Expr *pExpr, /* An operand of a comparison operator */
|
||||
int op /* The specific comparison operator */
|
||||
){
|
||||
/* If this expression is a vector to the left or right of a
|
||||
** inequality constraint (>, <, >= or <=), perform the processing
|
||||
** on the first element of the vector. */
|
||||
@ -862,26 +881,13 @@ static int exprMightBeIndexed(
|
||||
}
|
||||
|
||||
if( pExpr->op==TK_COLUMN ){
|
||||
*piCur = pExpr->iTable;
|
||||
*piColumn = pExpr->iColumn;
|
||||
aiCurCol[0] = pExpr->iTable;
|
||||
aiCurCol[1] = pExpr->iColumn;
|
||||
return 1;
|
||||
}
|
||||
if( mPrereq==0 ) return 0; /* No table references */
|
||||
if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */
|
||||
for(i=0; mPrereq>1; i++, mPrereq>>=1){}
|
||||
iCur = pFrom->a[i].iCursor;
|
||||
for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( pIdx->aColExpr==0 ) continue;
|
||||
for(i=0; i<pIdx->nKeyCol; i++){
|
||||
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
|
||||
if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
|
||||
*piCur = iCur;
|
||||
*piColumn = XN_EXPR;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -961,7 +967,7 @@ static void exprAnalyze(
|
||||
pTerm->iParent = -1;
|
||||
pTerm->eOperator = 0;
|
||||
if( allowedOp(op) ){
|
||||
int iCur, iColumn;
|
||||
int aiCurCol[2];
|
||||
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
|
||||
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
|
||||
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
|
||||
@ -972,14 +978,14 @@ static void exprAnalyze(
|
||||
pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
|
||||
}
|
||||
|
||||
if( exprMightBeIndexed(pSrc, op, prereqLeft, pLeft, &iCur, &iColumn) ){
|
||||
pTerm->leftCursor = iCur;
|
||||
pTerm->u.leftColumn = iColumn;
|
||||
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
|
||||
pTerm->leftCursor = aiCurCol[0];
|
||||
pTerm->u.leftColumn = aiCurCol[1];
|
||||
pTerm->eOperator = operatorMask(op) & opMask;
|
||||
}
|
||||
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
|
||||
if( pRight
|
||||
&& exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight, &iCur,&iColumn)
|
||||
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
|
||||
){
|
||||
WhereTerm *pNew;
|
||||
Expr *pDup;
|
||||
@ -1009,8 +1015,8 @@ static void exprAnalyze(
|
||||
pNew = pTerm;
|
||||
}
|
||||
exprCommute(pParse, pDup);
|
||||
pNew->leftCursor = iCur;
|
||||
pNew->u.leftColumn = iColumn;
|
||||
pNew->leftCursor = aiCurCol[0];
|
||||
pNew->u.leftColumn = aiCurCol[1];
|
||||
testcase( (prereqLeft | extraRight) != prereqLeft );
|
||||
pNew->prereqRight = prereqLeft | extraRight;
|
||||
pNew->prereqAll = prereqAll;
|
||||
|
36
test/indexexpr2.test
Normal file
36
test/indexexpr2.test
Normal file
@ -0,0 +1,36 @@
|
||||
# 2017 April 11
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix indexexpr2
|
||||
|
||||
do_execsql_test 1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
INSERT INTO t1 VALUES(3, 'three');
|
||||
|
||||
CREATE INDEX i1 ON t1(b || 'x');
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT 'TWOX' == (b || 'x') FROM t1 WHERE (b || 'x')>'onex'
|
||||
} {0 0}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT 'TWOX' == (b || 'x') COLLATE nocase FROM t1 WHERE (b || 'x')>'onex'
|
||||
} {0 1}
|
||||
|
||||
finish_test
|
||||
|
@ -319,4 +319,22 @@ do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0
|
||||
do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0
|
||||
do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# 2017-04-10 ticket 6c9b5514077fed34551f98e64c09a10dc2fc8e16
|
||||
# JSON extension accepts strings containing control characters.
|
||||
#
|
||||
# The JSON spec requires that all control characters be escaped.
|
||||
#
|
||||
do_execsql_test json102-1500 {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<0x20)
|
||||
SELECT x FROM c WHERE json_valid(printf('{"a":"x%sz"}', char(x))) ORDER BY x;
|
||||
} {32}
|
||||
|
||||
# All control characters are escaped
|
||||
#
|
||||
do_execsql_test json102-1501 {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<0x1f)
|
||||
SELECT sum(json_valid(json_quote('a'||char(x)||'z'))) FROM c ORDER BY x;
|
||||
} {31}
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user