Merge updates from trunk.
FossilOrigin-Name: 8dc0cdf652f099d464d3de416dffd83efb895009
This commit is contained in:
commit
fad4208f2f
@ -1893,7 +1893,7 @@ static int spellfix1Init(
|
||||
char **pzErr
|
||||
){
|
||||
spellfix1_vtab *pNew = 0;
|
||||
const char *zModule = argv[0];
|
||||
/* const char *zModule = argv[0]; // not used */
|
||||
const char *zDbName = argv[1];
|
||||
const char *zTableName = argv[2];
|
||||
int nDbName;
|
||||
@ -1947,7 +1947,7 @@ static int spellfix1Init(
|
||||
spellfix1DbExec(&rc, db,
|
||||
"CREATE INDEX IF NOT EXISTS \"%w\".\"%w_vocab_index_langid_k2\" "
|
||||
"ON \"%w_vocab\"(langid,k2);",
|
||||
zDbName, zModule, zTableName
|
||||
zDbName, zTableName, zTableName
|
||||
);
|
||||
}
|
||||
for(i=3; rc==SQLITE_OK && i<argc; i++){
|
||||
|
55
manifest
55
manifest
@ -1,5 +1,5 @@
|
||||
C Add\snew\sASCII\smode\sto\sthe\sshell\scapable\sof\simporting\sand\sexporting\susing\sthe\sofficial\sunit\sand\srecord\sseparators\s(i.e.\s0x1F\sand\s0x1E,\srespectively).
|
||||
D 2014-07-19T20:15:16.631
|
||||
C Merge\supdates\sfrom\strunk.
|
||||
D 2014-07-24T22:13:12.489
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -116,7 +116,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/spellfix.c 93f3961074cebe63c31fcefe62ca2a032ee8dfed
|
||||
F ext/misc/spellfix.c cb016c2dab951ffd7b819a7bc8a750ebd6c26c0f
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
@ -161,7 +161,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
|
||||
F src/analyze.c 61bc3467bd7803158d460dd92f5ba5205371bdce
|
||||
F src/analyze.c 1c9831015e8c575796a97692d1493ba720d16f27
|
||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
@ -170,13 +170,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 70c60a3807b2072982f184d9614e020d2953f89c
|
||||
F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
|
||||
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
|
||||
F src/build.c 927e39b6aaf872c7b28f154f6acfeb9a05a72442
|
||||
F src/build.c 48f400fa14fd6add244b954ce7e223ce7ccacf0b
|
||||
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
|
||||
F src/expr.c 40d06d1543b1355aa02efa9666178f7642a96ed6
|
||||
F src/expr.c b989d07fc7c8780fff77365a4fc59881223e340c
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c a549cff9fe8b736cdae21650ea0af6de29b77619
|
||||
F src/func.c 3bc223ea36cd29a91c481485343d0ee4257ab8dc
|
||||
@ -189,7 +189,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c 7c2c3cafdd6313c8f9319ebec1565782e624372e
|
||||
F src/main.c cfdb2aa5d248ff1af60227cc3f6d485ba86f92dc
|
||||
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
|
||||
@ -216,18 +216,18 @@ F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
||||
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
|
||||
F src/pragma.c 810ef31ccfaa233201dcf100637a9777cc24e897
|
||||
F src/pragma.c e17c5ea1cb9eb9d93c41bbb7c3a17e747d5e0335
|
||||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||
F src/printf.c af06f66927919730f03479fed6ae9854f73419f4
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02
|
||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||
F src/select.c 6762c62e11b504aa014edceab8886495165e3a77
|
||||
F src/shell.c f1524cdcf12af7eeff98c7846518ce5424d38d60
|
||||
F src/sqlite.h.in fd8e3a36b0aded082dc93a4b89c1e85324b4cf75
|
||||
F src/shell.c 3af679cad9c2e7caf7f8b997fb543afbc76d7c13
|
||||
F src/sqlite.h.in ac4451c9da2771d2f4d702ef89722407242906d9
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h e88614d7371b80ff69dbbb5e4b9813ee93dfd890
|
||||
F src/sqliteInt.h 152134c6223369e2e1acb7b9cc2c0db052dae28a
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -277,17 +277,17 @@ F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
|
||||
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
|
||||
F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec
|
||||
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
|
||||
F src/update.c 01564b3c430f6c7b0a35afaf7aba7987206fa3a5
|
||||
F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05
|
||||
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
|
||||
F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 9bfe6becfc094382ae213656fbe511055ad83a54
|
||||
F src/vdbe.c fa74c6563486022920db4d73897bd9b837c7441d
|
||||
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
|
||||
F src/vdbeInt.h 5df5e9afe9b7839cd17256220fc4f7af84b8b1cd
|
||||
F src/vdbeInt.h f41a7cf5a40e7abd994d5fe3a04589ae3e1154e7
|
||||
F src/vdbeapi.c 24e40422382beb774daab11fe9fe9d37e8a04949
|
||||
F src/vdbeaux.c 8d32b5a68670ccc6c64904924e6a0dddbc3a2fc5
|
||||
F src/vdbeaux.c 1ffe0bbc3a2c8aedd95622de9be6b6d07b3d3c6b
|
||||
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
|
||||
F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394
|
||||
F src/vdbesort.c 44441d73b08b3a638dcdb725afffb87c6574ad27
|
||||
@ -296,7 +296,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c 3a451b00516b59f414c59f817508edce51c732f1
|
||||
F src/where.c 9454af8e5e18d6e91e5169eadfb61878e2cb42b1
|
||||
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@ -313,12 +313,13 @@ F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
F test/analyze3.test bf41f0f680dd1e0d44eed5e769531e93a5320275
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test bd5aaf2a8fd2dd774b08251416897185531a8adf
|
||||
F test/analyze9.test 3ef1b471247308e710a794b6e50a6ab536c5604b
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
|
||||
@ -600,6 +601,7 @@ F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497
|
||||
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
|
||||
@ -818,11 +820,11 @@ F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
|
||||
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 4e4f8e6be18384f0bde93acc01947d7217e81774
|
||||
F test/shell1.test d13ff516e3fcd4061bd072f56fd1551f2bf7fe52
|
||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
||||
F test/shell5.test 3c9264ddf171d778d7d93bda5eea0bafe8a65069
|
||||
F test/shell5.test 7dbc03751ceda1e5ce75553dff735a7ef0dea15c
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
@ -1096,7 +1098,7 @@ F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
|
||||
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
|
||||
F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b
|
||||
F test/where2.test 455a2eb2666e66c1e84e2cb5815173a85e6237db
|
||||
F test/where2.test 23fdb5d8e756554aad4ca7ae03de9dd8367a2c6e
|
||||
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
|
||||
F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
@ -1182,10 +1184,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 61cee3c0678f5abd9131a29ab946a5e71f55643e
|
||||
R 2620c0e44150895c6e6dda7db94cda7b
|
||||
T *branch * asciiMode
|
||||
T *sym-asciiMode *
|
||||
T -sym-trunk *
|
||||
P 7fe601ead0d0ae26cb09d0dbc7d6367785376567 fb1048cb2b613a0dbfe625a5df05e9dcd736a433
|
||||
R 551b1710cff332eae579e1d24ac340a5
|
||||
U mistachkin
|
||||
Z 0122ab3028becc4213d4d02208439f07
|
||||
Z 5a827010d4d8351c000cbf9e79de9417
|
||||
|
@ -1 +1 @@
|
||||
7fe601ead0d0ae26cb09d0dbc7d6367785376567
|
||||
8dc0cdf652f099d464d3de416dffd83efb895009
|
@ -1109,7 +1109,7 @@ static void analyzeOneTable(
|
||||
** goto chng_addr_N
|
||||
*/
|
||||
addrNextRow = sqlite3VdbeCurrentAddr(v);
|
||||
for(i=0; i<nCol; i++){
|
||||
for(i=0; i<nCol-1; i++){
|
||||
char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
|
||||
@ -1118,7 +1118,7 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol-1, regChng);
|
||||
aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
|
||||
/*
|
||||
@ -1129,7 +1129,7 @@ static void analyzeOneTable(
|
||||
** ...
|
||||
*/
|
||||
sqlite3VdbeJumpHere(v, addrGotoChng0);
|
||||
for(i=0; i<nCol; i++){
|
||||
for(i=0; i<nCol-1; i++){
|
||||
sqlite3VdbeJumpHere(v, aGotoChng[i]);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
|
||||
}
|
||||
@ -1320,6 +1320,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
||||
Table *pTab;
|
||||
Index *pIdx;
|
||||
Token *pTableName;
|
||||
Vdbe *v;
|
||||
|
||||
/* Read the database schema. If an error occurs, leave an error message
|
||||
** and code in pParse and return NULL. */
|
||||
@ -1367,6 +1368,8 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
||||
}
|
||||
}
|
||||
}
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1425,14 +1428,19 @@ static void decodeIntArray(
|
||||
#else
|
||||
if( pIndex )
|
||||
#endif
|
||||
{
|
||||
if( strcmp(z, "unordered")==0 ){
|
||||
while( z[0] ){
|
||||
if( sqlite3_strglob("unordered*", z)==0 ){
|
||||
pIndex->bUnordered = 1;
|
||||
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
|
||||
int v32 = 0;
|
||||
sqlite3GetInt32(z+3, &v32);
|
||||
pIndex->szIdxRow = sqlite3LogEst(v32);
|
||||
pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
|
||||
pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
|
||||
}
|
||||
#endif
|
||||
while( z[0]!=0 && z[0]!=' ' ) z++;
|
||||
while( z[0]==' ' ) z++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1473,11 +1481,15 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
||||
z = argv[2];
|
||||
|
||||
if( pIndex ){
|
||||
pIndex->bUnordered = 0;
|
||||
decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
|
||||
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
|
||||
}else{
|
||||
Index fakeIdx;
|
||||
fakeIdx.szIdxRow = pTable->szTabRow;
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
fakeIdx.pTable = pTable;
|
||||
#endif
|
||||
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
|
||||
pTable->szTabRow = fakeIdx.szIdxRow;
|
||||
}
|
||||
|
34
src/build.c
34
src/build.c
@ -113,6 +113,19 @@ static void codeTableLocks(Parse *pParse){
|
||||
#define codeTableLocks(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return TRUE if the given yDbMask object is empty - if it contains no
|
||||
** 1 bits. This routine is used by the DbMaskAllZero() and DbMaskNotZero()
|
||||
** macros when SQLITE_MAX_ATTACHED is greater than 30.
|
||||
*/
|
||||
#if SQLITE_MAX_ATTACHED>30
|
||||
int sqlite3DbMaskAllZero(yDbMask m){
|
||||
int i;
|
||||
for(i=0; i<sizeof(yDbMask); i++) if( m[i] ) return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine is called after a single SQL statement has been
|
||||
** parsed and a VDBE program to execute that statement has been
|
||||
@ -149,18 +162,19 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
** transaction on each used database and to verify the schema cookie
|
||||
** on each used database.
|
||||
*/
|
||||
if( db->mallocFailed==0 && (pParse->cookieMask || pParse->pConstExpr) ){
|
||||
yDbMask mask;
|
||||
if( db->mallocFailed==0
|
||||
&& (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
|
||||
){
|
||||
int iDb, i;
|
||||
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
|
||||
sqlite3VdbeJumpHere(v, 0);
|
||||
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
|
||||
if( (mask & pParse->cookieMask)==0 ) continue;
|
||||
for(iDb=0; iDb<db->nDb; iDb++){
|
||||
if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp4Int(v,
|
||||
OP_Transaction, /* Opcode */
|
||||
iDb, /* P1 */
|
||||
(mask & pParse->writeMask)!=0, /* P2 */
|
||||
DbMaskTest(pParse->writeMask,iDb), /* P2 */
|
||||
pParse->cookieValue[iDb], /* P3 */
|
||||
db->aDb[iDb].pSchema->iGeneration /* P4 */
|
||||
);
|
||||
@ -216,7 +230,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
pParse->nMem = 0;
|
||||
pParse->nSet = 0;
|
||||
pParse->nVar = 0;
|
||||
pParse->cookieMask = 0;
|
||||
DbMaskZero(pParse->cookieMask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3843,15 +3857,13 @@ int sqlite3OpenTempDatabase(Parse *pParse){
|
||||
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
sqlite3 *db = pToplevel->db;
|
||||
yDbMask mask;
|
||||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
|
||||
assert( iDb<SQLITE_MAX_ATTACHED+2 );
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
mask = ((yDbMask)1)<<iDb;
|
||||
if( (pToplevel->cookieMask & mask)==0 ){
|
||||
pToplevel->cookieMask |= mask;
|
||||
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
|
||||
DbMaskSet(pToplevel->cookieMask, iDb);
|
||||
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
sqlite3OpenTempDatabase(pToplevel);
|
||||
@ -3890,7 +3902,7 @@ void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
|
||||
void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
pToplevel->writeMask |= ((yDbMask)1)<<iDb;
|
||||
DbMaskSet(pToplevel->writeMask, iDb);
|
||||
pToplevel->isMultiWrite |= setStatement;
|
||||
}
|
||||
|
||||
|
11
src/expr.c
11
src/expr.c
@ -2075,7 +2075,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
i64 value;
|
||||
const char *z = pExpr->u.zToken;
|
||||
assert( z!=0 );
|
||||
c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
c = sqlite3DecOrHexToI64(z, &value);
|
||||
if( c==0 || (c==2 && negFlag) ){
|
||||
char *zV;
|
||||
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
|
||||
@ -2085,7 +2085,14 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
|
||||
#else
|
||||
codeReal(v, z, negFlag, iMem);
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
if( sqlite3_strnicmp(z,"0x",2)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
codeReal(v, z, negFlag, iMem);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -2101,8 +2101,8 @@ static const int aHardLimit[] = {
|
||||
#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
|
||||
# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
|
||||
#endif
|
||||
#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62
|
||||
# error SQLITE_MAX_ATTACHED must be between 0 and 62
|
||||
#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
|
||||
# error SQLITE_MAX_ATTACHED must be between 0 and 125
|
||||
#endif
|
||||
#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
|
||||
# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
|
||||
@ -3409,7 +3409,7 @@ sqlite3_int64 sqlite3_uri_int64(
|
||||
){
|
||||
const char *z = sqlite3_uri_parameter(zFilename, zParam);
|
||||
sqlite3_int64 v;
|
||||
if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
|
||||
if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
|
||||
bDflt = v;
|
||||
}
|
||||
return bDflt;
|
||||
|
@ -1048,7 +1048,7 @@ void sqlite3Pragma(
|
||||
Pager *pPager = sqlite3BtreePager(pDb->pBt);
|
||||
i64 iLimit = -2;
|
||||
if( zRight ){
|
||||
sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8);
|
||||
sqlite3DecOrHexToI64(zRight, &iLimit);
|
||||
if( iLimit<-1 ) iLimit = -1;
|
||||
}
|
||||
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
|
||||
@ -1176,7 +1176,7 @@ void sqlite3Pragma(
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
if( zRight ){
|
||||
int ii;
|
||||
sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8);
|
||||
sqlite3DecOrHexToI64(zRight, &sz);
|
||||
if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
|
||||
if( pId2->n==0 ) db->szMmap = sz;
|
||||
for(ii=db->nDb-1; ii>=0; ii--){
|
||||
@ -2219,7 +2219,7 @@ void sqlite3Pragma(
|
||||
*/
|
||||
case PragTyp_SOFT_HEAP_LIMIT: {
|
||||
sqlite3_int64 N;
|
||||
if( zRight && sqlite3Atoi64(zRight, &N, 1000000, SQLITE_UTF8)==SQLITE_OK ){
|
||||
if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
|
||||
sqlite3_soft_heap_limit64(N);
|
||||
}
|
||||
returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
|
||||
|
155
src/shell.c
155
src/shell.c
@ -64,6 +64,7 @@
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
#define isatty(h) _isatty(h)
|
||||
#ifndef access
|
||||
# define access(f,m) _access((f),(m))
|
||||
@ -459,6 +460,7 @@ struct callback_data {
|
||||
char *zDestTable; /* Name of destination table when MODE_Insert */
|
||||
char colSeparator[20]; /* Column separator character for several modes */
|
||||
char rowSeparator[20]; /* Row separator character for MODE_Ascii */
|
||||
char newline[20]; /* Record separator in MODE_Csv */
|
||||
int colWidth[100]; /* Requested width of each column when in column mode*/
|
||||
int actualWidth[100]; /* Actual width of each column */
|
||||
char nullvalue[20]; /* The text to print when a NULL comes back from
|
||||
@ -505,11 +507,17 @@ static const char *modeDescr[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
** These are the column/row separators used by the ASCII mode.
|
||||
** These are the column/row/line separators used by the various
|
||||
** import/export modes.
|
||||
*/
|
||||
#define SEP_Line "\n"
|
||||
#define SEP_Column "\x1F"
|
||||
#define SEP_Row "\x1E"
|
||||
#define SEP_Column "|"
|
||||
#define SEP_Row "\n"
|
||||
#define SEP_Tab "\t"
|
||||
#define SEP_Space " "
|
||||
#define SEP_Comma ","
|
||||
#define SEP_CrLf "\r\n"
|
||||
#define SEP_Unit "\x1F"
|
||||
#define SEP_Record "\x1E"
|
||||
|
||||
/*
|
||||
** Number of elements in an array
|
||||
@ -669,7 +677,8 @@ static const char needCsvQuote[] = {
|
||||
/*
|
||||
** Output a single term of CSV. Actually, p->separator is used for
|
||||
** the separator, which may or may not be a comma. p->nullvalue is
|
||||
** the null value. Strings are quoted if necessary.
|
||||
** the null value. Strings are quoted if necessary. The separator
|
||||
** is only issued if bSep is true.
|
||||
*/
|
||||
static void output_csv(struct callback_data *p, const char *z, int bSep){
|
||||
FILE *out = p->out;
|
||||
@ -870,17 +879,26 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
|
||||
break;
|
||||
}
|
||||
case MODE_Csv: {
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
fflush(p->out);
|
||||
_setmode(_fileno(p->out), _O_BINARY);
|
||||
#endif
|
||||
if( p->cnt++==0 && p->showHeader ){
|
||||
for(i=0; i<nArg; i++){
|
||||
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
|
||||
}
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->newline);
|
||||
}
|
||||
if( azArg==0 ) break;
|
||||
for(i=0; i<nArg; i++){
|
||||
output_csv(p, azArg[i], i<nArg-1);
|
||||
if( azArg>0 ){
|
||||
for(i=0; i<nArg; i++){
|
||||
output_csv(p, azArg[i], i<nArg-1);
|
||||
}
|
||||
fprintf(p->out, "%s", p->newline);
|
||||
}
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
fflush(p->out);
|
||||
_setmode(_fileno(p->out), _O_TEXT);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case MODE_Insert: {
|
||||
@ -1653,7 +1671,8 @@ static char zHelp[] =
|
||||
".schema ?TABLE? Show the CREATE statements\n"
|
||||
" If TABLE specified, only show tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".separator STRING Change column separator for output mode and .import\n"
|
||||
".separator STRING ?NL? Change column separator for output mode and .import\n"
|
||||
" NL is the end-of-line mark for CSV\n"
|
||||
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
".show Show the current values for various settings\n"
|
||||
".stats on|off Turn stats on or off\n"
|
||||
@ -1671,6 +1690,69 @@ static char zHelp[] =
|
||||
|
||||
/* Forward reference */
|
||||
static int process_input(struct callback_data *p, FILE *in);
|
||||
/*
|
||||
** Implementation of the "readfile(X)" SQL function. The entire content
|
||||
** of the file named X is read and returned as a BLOB. NULL is returned
|
||||
** if the file does not exist or is unreadable.
|
||||
*/
|
||||
static void readfileFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zName;
|
||||
FILE *in;
|
||||
long nIn;
|
||||
void *pBuf;
|
||||
|
||||
zName = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zName==0 ) return;
|
||||
in = fopen(zName, "rb");
|
||||
if( in==0 ) return;
|
||||
fseek(in, 0, SEEK_END);
|
||||
nIn = ftell(in);
|
||||
rewind(in);
|
||||
pBuf = sqlite3_malloc( nIn );
|
||||
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
|
||||
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
|
||||
}else{
|
||||
sqlite3_free(pBuf);
|
||||
}
|
||||
fclose(in);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
|
||||
** is written into file X. The number of bytes written is returned. Or
|
||||
** NULL is returned if something goes wrong, such as being unable to open
|
||||
** file X for writing.
|
||||
*/
|
||||
static void writefileFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
FILE *out;
|
||||
const char *z;
|
||||
int n;
|
||||
sqlite3_int64 rc;
|
||||
const char *zFile;
|
||||
|
||||
zFile = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zFile==0 ) return;
|
||||
out = fopen(zFile, "wb");
|
||||
if( out==0 ) return;
|
||||
z = (const char*)sqlite3_value_blob(argv[1]);
|
||||
if( z==0 ){
|
||||
n = 0;
|
||||
rc = 0;
|
||||
}else{
|
||||
n = sqlite3_value_bytes(argv[1]);
|
||||
rc = fwrite(z, 1, n, out);
|
||||
}
|
||||
fclose(out);
|
||||
sqlite3_result_int64(context, rc);
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure the database is open. If it is not, then open it. If
|
||||
@ -1694,6 +1776,10 @@ static void open_db(struct callback_data *p, int keepAlive){
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
sqlite3_enable_load_extension(p->db, 1);
|
||||
#endif
|
||||
sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
|
||||
readfileFunc, 0, 0);
|
||||
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
writefileFunc, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2846,23 +2932,24 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
p->mode = MODE_Html;
|
||||
}else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
|
||||
p->mode = MODE_Tcl;
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, " ");
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Line);
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
||||
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
|
||||
p->mode = MODE_Csv;
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, ",");
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Line);
|
||||
sqlite3_snprintf(sizeof(p->newline), p->newline, SEP_CrLf);
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
||||
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
|
||||
p->mode = MODE_List;
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, "\t");
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Line);
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
||||
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
|
||||
p->mode = MODE_Insert;
|
||||
set_table_name(p, nArg>=3 ? azArg[2] : "table");
|
||||
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
|
||||
p->mode = MODE_Ascii;
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
|
||||
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
|
||||
}else {
|
||||
fprintf(stderr,"Error: mode should be one of: "
|
||||
"ascii column csv html insert line list tabs tcl\n");
|
||||
@ -3155,12 +3242,17 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
if( nArg<2 || nArg>3 ){
|
||||
fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
|
||||
rc = 1;
|
||||
}
|
||||
if( nArg>=2 ){
|
||||
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
|
||||
"%.*s", (int)sizeof(p->colSeparator)-1, azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .separator STRING\n");
|
||||
rc = 1;
|
||||
}
|
||||
if( nArg>=3 ){
|
||||
sqlite3_snprintf(sizeof(p->newline), p->newline,
|
||||
"%.*s", (int)sizeof(p->newline)-1, azArg[2]);
|
||||
}
|
||||
}else
|
||||
|
||||
@ -3206,6 +3298,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
fprintf(p->out,"%12.12s: ", "rowseparator");
|
||||
output_c_string(p->out, p->rowSeparator);
|
||||
fprintf(p->out, "\n");
|
||||
fprintf(p->out,"%12.12s: ", "newline");
|
||||
output_c_string(p->out, p->newline);
|
||||
fprintf(p->out, "\n");
|
||||
fprintf(p->out,"%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
|
||||
fprintf(p->out,"%12.12s: ","width");
|
||||
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
|
||||
@ -3823,6 +3918,7 @@ static const char zOptions[] =
|
||||
#ifdef SQLITE_ENABLE_MULTIPLEX
|
||||
" -multiplex enable the multiplexor VFS\n"
|
||||
#endif
|
||||
" -newline SEP set newline character(s) for CSV\n"
|
||||
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
||||
" -rowseparator SEP set output line separator. Default: '\\n'\n"
|
||||
" -separator SEP set output field separator. Default: '|'\n"
|
||||
@ -3852,8 +3948,9 @@ static void usage(int showDetail){
|
||||
static void main_init(struct callback_data *data) {
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->mode = MODE_List;
|
||||
memcpy(data->colSeparator,"|", 2);
|
||||
memcpy(data->rowSeparator,"\n", 2);
|
||||
memcpy(data->colSeparator,SEP_Column, 2);
|
||||
memcpy(data->rowSeparator,SEP_Row, 2);
|
||||
memcpy(data->newline,SEP_CrLf, 3);
|
||||
data->showHeader = 0;
|
||||
sqlite3_config(SQLITE_CONFIG_URI, 1);
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
|
||||
@ -3946,6 +4043,7 @@ int main(int argc, char **argv){
|
||||
if( z[1]=='-' ) z++;
|
||||
if( strcmp(z,"-separator")==0
|
||||
|| strcmp(z,"-nullvalue")==0
|
||||
|| strcmp(z,"-newline")==0
|
||||
|| strcmp(z,"-cmd")==0
|
||||
){
|
||||
(void)cmdline_option_value(argc, argv, ++i);
|
||||
@ -4055,15 +4153,18 @@ int main(int argc, char **argv){
|
||||
}else if( strcmp(z,"-ascii")==0 ){
|
||||
data.mode = MODE_Ascii;
|
||||
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
||||
SEP_Column);
|
||||
SEP_Unit);
|
||||
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
|
||||
SEP_Row);
|
||||
SEP_Record);
|
||||
}else if( strcmp(z,"-separator")==0 || strcmp(z,"-colseparator")==0 ){
|
||||
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
||||
"%s",cmdline_option_value(argc,argv,++i));
|
||||
}else if( strcmp(z,"-rowseparator")==0 ){
|
||||
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
|
||||
"%s",cmdline_option_value(argc,argv,++i));
|
||||
}else if( strcmp(z,"-newline")==0 ){
|
||||
sqlite3_snprintf(sizeof(data.newline), data.newline,
|
||||
"%s",cmdline_option_value(argc,argv,++i));
|
||||
}else if( strcmp(z,"-nullvalue")==0 ){
|
||||
sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
|
||||
"%s",cmdline_option_value(argc,argv,++i));
|
||||
|
@ -4711,6 +4711,13 @@ int sqlite3_sleep(int);
|
||||
** is a NULL pointer, then SQLite performs a search for an appropriate
|
||||
** temporary file directory.
|
||||
**
|
||||
** Applications are strongly discouraged from using this global variable.
|
||||
** It is required to set a temporary folder on Windows Runtime (WinRT).
|
||||
** But for all other platforms, it is highly recommended that applications
|
||||
** neither read nor write this variable. This global variable is a relic
|
||||
** that exists for backwards compatibility of legacy applications and should
|
||||
** be avoided in new projects.
|
||||
**
|
||||
** It is not safe to read or modify this variable in more than one
|
||||
** thread at a time. It is not safe to read or modify this variable
|
||||
** if a [database connection] is being used at the same time in a separate
|
||||
@ -4729,6 +4736,11 @@ int sqlite3_sleep(int);
|
||||
** Hence, if this variable is modified directly, either it should be
|
||||
** made NULL or made to point to memory obtained from [sqlite3_malloc]
|
||||
** or else the use of the [temp_store_directory pragma] should be avoided.
|
||||
** Except when requested by the [temp_store_directory pragma], SQLite
|
||||
** does not free the memory that sqlite3_temp_directory points to. If
|
||||
** the application wants that memory to be freed, it must do
|
||||
** so itself, taking care to only do so after all [database connection]
|
||||
** objects have been destroyed.
|
||||
**
|
||||
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
|
||||
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
|
||||
|
@ -1477,6 +1477,9 @@ struct Table {
|
||||
i16 nCol; /* Number of columns in this table */
|
||||
u16 nRef; /* Number of pointers to this Table */
|
||||
LogEst szTabRow; /* Estimated size of each table row in bytes */
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
LogEst costMult; /* Cost multiplier for using this table */
|
||||
#endif
|
||||
u8 tabFlags; /* Mask of TF_* values */
|
||||
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
@ -2136,6 +2139,7 @@ struct SrcList {
|
||||
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
|
||||
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
|
||||
|
||||
/* Allowed return values from sqlite3WhereIsDistinct()
|
||||
*/
|
||||
@ -2392,9 +2396,19 @@ struct TriggerPrg {
|
||||
** The yDbMask datatype for the bitmask of all attached databases.
|
||||
*/
|
||||
#if SQLITE_MAX_ATTACHED>30
|
||||
typedef sqlite3_uint64 yDbMask;
|
||||
typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
|
||||
# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0)
|
||||
# define DbMaskZero(M) memset((M),0,sizeof(M))
|
||||
# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7))
|
||||
# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M)
|
||||
# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0)
|
||||
#else
|
||||
typedef unsigned int yDbMask;
|
||||
# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
|
||||
# define DbMaskZero(M) (M)=0
|
||||
# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I))
|
||||
# define DbMaskAllZero(M) (M)==0
|
||||
# define DbMaskNonZero(M) (M)!=0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -3067,6 +3081,9 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
|
||||
# define sqlite3ViewGetColumnNames(A,B) 0
|
||||
#endif
|
||||
|
||||
#if SQLITE_MAX_ATTACHED>30
|
||||
int sqlite3DbMaskAllZero(yDbMask);
|
||||
#endif
|
||||
void sqlite3DropTable(Parse*, SrcList*, int, int);
|
||||
void sqlite3CodeDropTable(Parse*, Table*, int, int);
|
||||
void sqlite3DeleteTable(sqlite3*, Table*);
|
||||
@ -3317,6 +3334,7 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
||||
char sqlite3ExprAffinity(Expr *pExpr);
|
||||
int sqlite3Atoi64(const char*, i64*, int, u8);
|
||||
int sqlite3DecOrHexToI64(const char*, i64*);
|
||||
void sqlite3Error(sqlite3*, int, const char*,...);
|
||||
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
||||
u8 sqlite3HexToInt(int h);
|
||||
|
@ -270,6 +270,12 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
|
||||
testcase( z[0]=='9' );
|
||||
*tokenType = TK_INTEGER;
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
|
||||
for(i=3; sqlite3Isxdigit(z[i]); i++){}
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
for(i=0; sqlite3Isdigit(z[i]); i++){}
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
if( z[i]=='.' ){
|
||||
|
58
src/util.c
58
src/util.c
@ -475,9 +475,9 @@ static int compare2pow63(const char *zNum, int incr){
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert zNum to a 64-bit signed integer.
|
||||
** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
|
||||
** routine does *not* accept hexadecimal notation.
|
||||
**
|
||||
** If the zNum value is representable as a 64-bit twos-complement
|
||||
** integer, then write that value into *pNum and return 0.
|
||||
@ -565,10 +565,44 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
|
||||
** into a 64-bit signed integer. This routine accepts hexadecimal literals,
|
||||
** whereas sqlite3Atoi64() does not.
|
||||
**
|
||||
** Returns:
|
||||
**
|
||||
** 0 Successful transformation. Fits in a 64-bit signed integer.
|
||||
** 1 Integer too large for a 64-bit signed integer or is malformed
|
||||
** 2 Special case of 9223372036854775808
|
||||
*/
|
||||
int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
if( z[0]=='0'
|
||||
&& (z[1]=='x' || z[1]=='X')
|
||||
&& sqlite3Isxdigit(z[2])
|
||||
){
|
||||
u64 u = 0;
|
||||
int i, k;
|
||||
for(i=2; z[i]=='0'; i++){}
|
||||
for(k=i; sqlite3Isxdigit(z[k]); k++){
|
||||
u = u*16 + sqlite3HexToInt(z[k]);
|
||||
}
|
||||
memcpy(pOut, &u, 8);
|
||||
return (z[k]==0 && k-i<=16) ? 0 : 1;
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_HEX_INTEGER */
|
||||
{
|
||||
return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If zNum represents an integer that will fit in 32-bits, then set
|
||||
** *pValue to that integer and return true. Otherwise return false.
|
||||
**
|
||||
** This routine accepts both decimal and hexadecimal notation for integers.
|
||||
**
|
||||
** Any non-numeric characters that following zNum are ignored.
|
||||
** This is different from sqlite3Atoi64() which requires the
|
||||
** input number to be zero-terminated.
|
||||
@ -583,7 +617,25 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
}else if( zNum[0]=='+' ){
|
||||
zNum++;
|
||||
}
|
||||
while( zNum[0]=='0' ) zNum++;
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
else if( zNum[0]=='0'
|
||||
&& (zNum[1]=='x' || zNum[1]=='X')
|
||||
&& sqlite3Isxdigit(zNum[2])
|
||||
){
|
||||
u32 u = 0;
|
||||
zNum += 2;
|
||||
while( zNum[0]=='0' ) zNum++;
|
||||
for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){
|
||||
u = u*16 + sqlite3HexToInt(zNum[i]);
|
||||
}
|
||||
if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
|
||||
memcpy(pValue, &u, 4);
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
|
||||
v = v*10 + c;
|
||||
}
|
||||
|
64
src/vdbe.c
64
src/vdbe.c
@ -3034,7 +3034,7 @@ case OP_Transaction: {
|
||||
assert( p->bIsReader );
|
||||
assert( p->readOnly==0 || pOp->p2==0 );
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
||||
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
|
||||
rc = SQLITE_READONLY;
|
||||
goto abort_due_to_error;
|
||||
@ -3129,7 +3129,7 @@ case OP_ReadCookie: { /* out2-prerelease */
|
||||
assert( pOp->p3<SQLITE_N_BTREE_META );
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, iDb) );
|
||||
|
||||
sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
|
||||
pOut->u.i = iMeta;
|
||||
@ -3150,7 +3150,7 @@ case OP_SetCookie: { /* in3 */
|
||||
Db *pDb;
|
||||
assert( pOp->p2<SQLITE_N_BTREE_META );
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
||||
assert( p->readOnly==0 );
|
||||
pDb = &db->aDb[pOp->p1];
|
||||
assert( pDb->pBt!=0 );
|
||||
@ -3205,7 +3205,21 @@ case OP_SetCookie: { /* in3 */
|
||||
** sequence of the index being opened. Otherwise, if P4 is an integer
|
||||
** value, it is set to the number of columns in the table.
|
||||
**
|
||||
** See also OpenWrite.
|
||||
** See also: OpenWrite, ReopenIdx
|
||||
*/
|
||||
/* Opcode: ReopenIdx P1 P2 P3 P4 P5
|
||||
** Synopsis: root=P2 iDb=P3
|
||||
**
|
||||
** The ReopenIdx opcode works exactly like ReadOpen except that it first
|
||||
** checks to see if the cursor on P1 is already open with a root page
|
||||
** number of P2 and if it is this opcode becomes a no-op. In other words,
|
||||
** if the cursor is already open, do not reopen it.
|
||||
**
|
||||
** The ReopenIdx opcode may only be used with P5==0 and with P4 being
|
||||
** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
|
||||
** every other ReopenIdx or OpenRead for the same cursor number.
|
||||
**
|
||||
** See the OpenRead opcode documentation for additional information.
|
||||
*/
|
||||
/* Opcode: OpenWrite P1 P2 P3 P4 P5
|
||||
** Synopsis: root=P2 iDb=P3
|
||||
@ -3227,6 +3241,19 @@ case OP_SetCookie: { /* in3 */
|
||||
**
|
||||
** See also OpenRead.
|
||||
*/
|
||||
case OP_ReopenIdx: {
|
||||
VdbeCursor *pCur;
|
||||
|
||||
assert( pOp->p5==0 );
|
||||
assert( pOp->p4type==P4_KEYINFO );
|
||||
pCur = p->apCsr[pOp->p1];
|
||||
if( pCur && pCur->pgnoRoot==pOp->p2 ){
|
||||
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
|
||||
break;
|
||||
}
|
||||
/* If the cursor is not currently open or is open on a different
|
||||
** index, then fall through into OP_OpenRead to force a reopen */
|
||||
}
|
||||
case OP_OpenRead:
|
||||
case OP_OpenWrite: {
|
||||
int nField;
|
||||
@ -3241,7 +3268,8 @@ case OP_OpenWrite: {
|
||||
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
|
||||
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
|
||||
assert( p->bIsReader );
|
||||
assert( pOp->opcode==OP_OpenRead || p->readOnly==0 );
|
||||
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|
||||
|| p->readOnly==0 );
|
||||
|
||||
if( p->expired ){
|
||||
rc = SQLITE_ABORT;
|
||||
@ -3253,7 +3281,7 @@ case OP_OpenWrite: {
|
||||
p2 = pOp->p2;
|
||||
iDb = pOp->p3;
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, iDb) );
|
||||
pDb = &db->aDb[iDb];
|
||||
pX = pDb->pBt;
|
||||
assert( pX!=0 );
|
||||
@ -3298,6 +3326,7 @@ case OP_OpenWrite: {
|
||||
if( pCur==0 ) goto no_mem;
|
||||
pCur->nullRow = 1;
|
||||
pCur->isOrdered = 1;
|
||||
pCur->pgnoRoot = p2;
|
||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
||||
@ -4844,7 +4873,7 @@ case OP_Destroy: { /* out2-prerelease */
|
||||
}else{
|
||||
iDb = pOp->p3;
|
||||
assert( iCnt==1 );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, iDb) );
|
||||
iMoved = 0; /* Not needed. Only to silence a warning. */
|
||||
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
|
||||
pOut->flags = MEM_Int;
|
||||
@ -4884,7 +4913,7 @@ case OP_Clear: {
|
||||
|
||||
nChange = 0;
|
||||
assert( p->readOnly==0 );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p2) );
|
||||
rc = sqlite3BtreeClearTable(
|
||||
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
|
||||
);
|
||||
@ -4954,7 +4983,7 @@ case OP_CreateTable: { /* out2-prerelease */
|
||||
|
||||
pgno = 0;
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
||||
assert( p->readOnly==0 );
|
||||
pDb = &db->aDb[pOp->p1];
|
||||
assert( pDb->pBt!=0 );
|
||||
@ -5119,7 +5148,7 @@ case OP_IntegrityCk: {
|
||||
}
|
||||
aRoot[j] = 0;
|
||||
assert( pOp->p5<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p5) );
|
||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
|
||||
(int)pnErr->u.i, &nErr);
|
||||
sqlite3DbFree(db, aRoot);
|
||||
@ -5779,7 +5808,7 @@ case OP_IncrVacuum: { /* jump */
|
||||
Btree *pBt;
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
||||
assert( p->readOnly==0 );
|
||||
pBt = db->aDb[pOp->p1].pBt;
|
||||
rc = sqlite3BtreeIncrVacuum(pBt);
|
||||
@ -5794,12 +5823,13 @@ case OP_IncrVacuum: { /* jump */
|
||||
|
||||
/* Opcode: Expire P1 * * * *
|
||||
**
|
||||
** Cause precompiled statements to become expired. An expired statement
|
||||
** fails with an error code of SQLITE_SCHEMA if it is ever executed
|
||||
** (via sqlite3_step()).
|
||||
** Cause precompiled statements to expire. When an expired statement
|
||||
** is executed using sqlite3_step() it will either automatically
|
||||
** reprepare itself (if it was originally created using sqlite3_prepare_v2())
|
||||
** or it will fail with SQLITE_SCHEMA.
|
||||
**
|
||||
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
|
||||
** then only the currently executing statement is affected.
|
||||
** then only the currently executing statement is expired.
|
||||
*/
|
||||
case OP_Expire: {
|
||||
if( !pOp->p1 ){
|
||||
@ -5831,7 +5861,7 @@ case OP_TableLock: {
|
||||
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
|
||||
int p1 = pOp->p1;
|
||||
assert( p1>=0 && p1<db->nDb );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
|
||||
assert( DbMaskTest(p->btreeMask, p1) );
|
||||
assert( isWriteLock==0 || isWriteLock==1 );
|
||||
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
|
||||
if( (rc&0xFF)==SQLITE_LOCKED ){
|
||||
@ -6281,7 +6311,7 @@ case OP_Init: { /* jump */
|
||||
if( zTrace ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
|
||||
if( DbMaskTest(p->btreeMask, i)==0 ) continue;
|
||||
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ struct VdbeCursor {
|
||||
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
|
||||
Bool isTable:1; /* True if a table requiring integer keys */
|
||||
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
|
||||
Pgno pgnoRoot; /* Root page of the open btree cursor */
|
||||
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
|
||||
i64 seqCount; /* Sequence counter */
|
||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||
|
@ -499,7 +499,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
pParse->aLabel = 0;
|
||||
pParse->nLabel = 0;
|
||||
*pMaxFuncArgs = nMaxArgs;
|
||||
assert( p->bIsReader!=0 || p->btreeMask==0 );
|
||||
assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -526,7 +526,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
|
||||
assert( aOp && !p->db->mallocFailed );
|
||||
|
||||
/* Check that sqlite3VdbeUsesBtree() was not called on this VM */
|
||||
assert( p->btreeMask==0 );
|
||||
assert( DbMaskAllZero(p->btreeMask) );
|
||||
|
||||
resolveP2Values(p, pnMaxArg);
|
||||
*pnOp = p->nOp;
|
||||
@ -1111,9 +1111,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
||||
assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
|
||||
assert( i<(int)sizeof(p->btreeMask)*8 );
|
||||
p->btreeMask |= ((yDbMask)1)<<i;
|
||||
DbMaskSet(p->btreeMask, i);
|
||||
if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
|
||||
p->lockMask |= ((yDbMask)1)<<i;
|
||||
DbMaskSet(p->lockMask, i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1141,16 +1141,15 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
||||
*/
|
||||
void sqlite3VdbeEnter(Vdbe *p){
|
||||
int i;
|
||||
yDbMask mask;
|
||||
sqlite3 *db;
|
||||
Db *aDb;
|
||||
int nDb;
|
||||
if( p->lockMask==0 ) return; /* The common case */
|
||||
if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
|
||||
db = p->db;
|
||||
aDb = db->aDb;
|
||||
nDb = db->nDb;
|
||||
for(i=0, mask=1; i<nDb; i++, mask += mask){
|
||||
if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
|
||||
for(i=0; i<nDb; i++){
|
||||
if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
|
||||
sqlite3BtreeEnter(aDb[i].pBt);
|
||||
}
|
||||
}
|
||||
@ -1163,16 +1162,15 @@ void sqlite3VdbeEnter(Vdbe *p){
|
||||
*/
|
||||
void sqlite3VdbeLeave(Vdbe *p){
|
||||
int i;
|
||||
yDbMask mask;
|
||||
sqlite3 *db;
|
||||
Db *aDb;
|
||||
int nDb;
|
||||
if( p->lockMask==0 ) return; /* The common case */
|
||||
if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
|
||||
db = p->db;
|
||||
aDb = db->aDb;
|
||||
nDb = db->nDb;
|
||||
for(i=0, mask=1; i<nDb; i++, mask += mask){
|
||||
if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
|
||||
for(i=0; i<nDb; i++){
|
||||
if( i!=1 && DbMaskTest(p->lockMask,i) && ALWAYS(aDb[i].pBt!=0) ){
|
||||
sqlite3BtreeLeave(aDb[i].pBt);
|
||||
}
|
||||
}
|
||||
|
32
src/where.c
32
src/where.c
@ -3422,6 +3422,7 @@ static Bitmask codeOneLoopStart(
|
||||
int iRetInit; /* Address of regReturn init */
|
||||
int untestedTerms = 0; /* Some terms not completely tested */
|
||||
int ii; /* Loop counter */
|
||||
u16 wctrlFlags; /* Flags for sub-WHERE clause */
|
||||
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
|
||||
Table *pTab = pTabItem->pTab;
|
||||
|
||||
@ -3517,6 +3518,8 @@ static Bitmask codeOneLoopStart(
|
||||
** eliminating duplicates from other WHERE clauses, the action for each
|
||||
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
||||
*/
|
||||
wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
@ -3529,8 +3532,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
||||
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
|
||||
wctrlFlags, iCovCur);
|
||||
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
||||
if( pSubWInfo ){
|
||||
WhereLoop *pSubLoop;
|
||||
@ -3621,6 +3623,7 @@ static Bitmask codeOneLoopStart(
|
||||
){
|
||||
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
|
||||
pCov = pSubLoop->u.btree.pIndex;
|
||||
wctrlFlags |= WHERE_REOPEN_IDX;
|
||||
}else{
|
||||
pCov = 0;
|
||||
}
|
||||
@ -4227,6 +4230,16 @@ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Adjust the cost C by the costMult facter T. This only occurs if
|
||||
** compiled with -DSQLITE_ENABLE_COSTMULT
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
# define ApplyCostMultiplier(C,T) C += T
|
||||
#else
|
||||
# define ApplyCostMultiplier(C,T)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
|
||||
** index pIndex. Try to match one more.
|
||||
@ -4423,7 +4436,6 @@ static int whereLoopAddBtreeIndex(
|
||||
}else{
|
||||
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
|
||||
}
|
||||
assert( rc!=SQLITE_OK || nOut>0 );
|
||||
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
||||
if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
|
||||
if( nOut ){
|
||||
@ -4455,6 +4467,7 @@ static int whereLoopAddBtreeIndex(
|
||||
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
|
||||
}
|
||||
ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
|
||||
|
||||
nOutUnadjusted = pNew->nOut;
|
||||
pNew->rRun += nInMul + nIn;
|
||||
@ -4574,6 +4587,14 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
|
||||
** Normally, nSeek is 1. nSeek values greater than 1 come about if the
|
||||
** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when
|
||||
** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans.
|
||||
**
|
||||
** The estimated values (nRow, nVisit, nSeek) often contain a large amount
|
||||
** of uncertainty. For this reason, scoring is designed to pick plans that
|
||||
** "do the least harm" if the estimates are inaccurate. For example, a
|
||||
** log(nRow) factor is omitted from a non-covering index scan in order to
|
||||
** bias the scoring in favor of using an index, since the worst-case
|
||||
** performance of using an index is far better than the worst-case performance
|
||||
** of a full table scan.
|
||||
*/
|
||||
static int whereLoopAddBtree(
|
||||
WhereLoopBuilder *pBuilder, /* WHERE clause information */
|
||||
@ -4661,6 +4682,7 @@ static int whereLoopAddBtree(
|
||||
** approximately 7*N*log2(N) where N is the number of rows in
|
||||
** the table being indexed. */
|
||||
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
|
||||
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
|
||||
/* TUNING: Each index lookup yields 20 rows in the table. This
|
||||
** is more than the usual guess of 10 rows, since we have no way
|
||||
** of knowning how selective the index will ultimately be. It would
|
||||
@ -4702,6 +4724,7 @@ static int whereLoopAddBtree(
|
||||
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||
/* TUNING: Cost of full table scan is (N*3.0). */
|
||||
pNew->rRun = rSize + 16;
|
||||
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
|
||||
whereLoopOutputAdjust(pWC, pNew);
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
pNew->nOut = rSize;
|
||||
@ -4737,7 +4760,7 @@ static int whereLoopAddBtree(
|
||||
if( m!=0 ){
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
|
||||
}
|
||||
|
||||
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
|
||||
whereLoopOutputAdjust(pWC, pNew);
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
pNew->nOut = rSize;
|
||||
@ -6212,6 +6235,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pWInfo->aiCurOnePass[1] = iIndexCur;
|
||||
}else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
|
||||
iIndexCur = iIdxCur;
|
||||
if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
|
||||
}else{
|
||||
iIndexCur = pParse->nTab++;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ do_test analyze6-2.3 {
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
do_test analyze6-2.4 {
|
||||
execsql {
|
||||
INSERT INTO t201 VALUES(1,2,3);
|
||||
INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
|
||||
ANALYZE t201;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
|
@ -1089,5 +1089,3 @@ foreach {tn where eqp} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
167
test/analyzeC.test
Normal file
167
test/analyzeC.test
Normal file
@ -0,0 +1,167 @@
|
||||
# 2014-07-22
|
||||
#
|
||||
# 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 contains automated tests used to verify that the text terms
|
||||
# at the end of sqlite_stat1.stat are processed correctly.
|
||||
#
|
||||
# (1) "unordered" means that the index cannot be used for ORDER BY
|
||||
# or for range queries
|
||||
#
|
||||
# (2) "sz=NNN" sets the relative size of the index entries
|
||||
#
|
||||
# (3) All other fields are silently ignored
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix analyzeC
|
||||
|
||||
# Baseline case. Range queries work OK. Indexes can be used for
|
||||
# ORDER BY.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
INSERT INTO t1(a,b,c)
|
||||
VALUES(1,2,3),(7,8,9),(4,5,6),(10,11,12),(4,8,12),(1,11,111);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat)
|
||||
VALUES('t1','t1a','12345 2'),('t1','t1b','12345 4');
|
||||
ANALYZE sqlite_master;
|
||||
SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c;
|
||||
} {4 5 6 # 7 8 9 # 4 8 12 #}
|
||||
do_execsql_test 1.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c;
|
||||
} {/.* USING INDEX t1a .a>. AND a<...*/}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {3 111 6 12 9 12}
|
||||
do_execsql_test 1.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {/.*SCAN TABLE t1 USING INDEX t1a.*/}
|
||||
do_execsql_test 1.3x {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {~/.*B-TREE FOR ORDER BY.*/}
|
||||
|
||||
# Now mark the t1a index as "unordered". Range queries and ORDER BY no
|
||||
# longer use the index, but equality queries do.
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
UPDATE sqlite_stat1 SET stat='12345 2 unordered' WHERE idx='t1a';
|
||||
ANALYZE sqlite_master;
|
||||
SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c;
|
||||
} {4 5 6 # 7 8 9 # 4 8 12 #}
|
||||
do_execsql_test 2.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c;
|
||||
} {~/.*USING INDEX.*/}
|
||||
do_execsql_test 2.2 {
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {3 111 6 12 9 12}
|
||||
do_execsql_test 2.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {~/.*USING INDEX.*/}
|
||||
do_execsql_test 2.3x {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {/.*B-TREE FOR ORDER BY.*/}
|
||||
|
||||
# Ignore extraneous text parameters in the sqlite_stat1.stat field.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
UPDATE sqlite_stat1 SET stat='12345 2 whatever=5 unordered xyzzy=11'
|
||||
WHERE idx='t1a';
|
||||
ANALYZE sqlite_master;
|
||||
SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c;
|
||||
} {4 5 6 # 7 8 9 # 4 8 12 #}
|
||||
do_execsql_test 3.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT *, '#' FROM t1 WHERE a BETWEEN 3 AND 8 ORDER BY c;
|
||||
} {~/.*USING INDEX.*/}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {3 111 6 12 9 12}
|
||||
do_execsql_test 3.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {~/.*USING INDEX.*/}
|
||||
do_execsql_test 3.3x {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT c FROM t1 ORDER BY a;
|
||||
} {/.*B-TREE FOR ORDER BY.*/}
|
||||
|
||||
# The sz=NNN parameter determines which index to scan
|
||||
#
|
||||
do_execsql_test 4.0 {
|
||||
DROP INDEX t1a;
|
||||
CREATE INDEX t1ab ON t1(a,b);
|
||||
CREATE INDEX t1ca ON t1(c,a);
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat)
|
||||
VALUES('t1','t1ab','12345 3 2 sz=10'),('t1','t1ca','12345 3 2 sz=20');
|
||||
ANALYZE sqlite_master;
|
||||
SELECT count(a) FROM t1;
|
||||
} {6}
|
||||
do_execsql_test 4.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT count(a) FROM t1;
|
||||
} {/.*INDEX t1ab.*/}
|
||||
do_execsql_test 4.2 {
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat)
|
||||
VALUES('t1','t1ab','12345 3 2 sz=20'),('t1','t1ca','12345 3 2 sz=10');
|
||||
ANALYZE sqlite_master;
|
||||
SELECT count(a) FROM t1;
|
||||
} {6}
|
||||
do_execsql_test 4.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT count(a) FROM t1;
|
||||
} {/.*INDEX t1ca.*/}
|
||||
|
||||
|
||||
# The sz=NNN parameter works even if there is other extraneous text
|
||||
# in the sqlite_stat1.stat column.
|
||||
#
|
||||
do_execsql_test 5.0 {
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat)
|
||||
VALUES('t1','t1ab','12345 3 2 x=5 sz=10 y=10'),
|
||||
('t1','t1ca','12345 3 2 whatever sz=20 junk');
|
||||
ANALYZE sqlite_master;
|
||||
SELECT count(a) FROM t1;
|
||||
} {6}
|
||||
do_execsql_test 5.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT count(a) FROM t1;
|
||||
} {/.*INDEX t1ab.*/}
|
||||
do_execsql_test 5.2 {
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat)
|
||||
VALUES('t1','t1ca','12345 3 2 x=5 sz=10 y=10'),
|
||||
('t1','t1ab','12345 3 2 whatever sz=20 junk');
|
||||
ANALYZE sqlite_master;
|
||||
SELECT count(a) FROM t1;
|
||||
} {6}
|
||||
do_execsql_test 5.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT count(a) FROM t1;
|
||||
} {/.*INDEX t1ca.*/}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
114
test/hexlit.test
Normal file
114
test/hexlit.test
Normal file
@ -0,0 +1,114 @@
|
||||
# 2014-07-23
|
||||
#
|
||||
# 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 tests for hexadecimal literals
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
proc hexlit1 {tnum val ans} {
|
||||
do_execsql_test hexlit-$tnum "SELECT $val" $ans
|
||||
}
|
||||
|
||||
hexlit1 100 0x0 0
|
||||
hexlit1 101 0x0000000000000000000000000000000000000000000001 1
|
||||
hexlit1 102 0x2 2
|
||||
hexlit1 103 0x4 4
|
||||
hexlit1 104 0x8 8
|
||||
hexlit1 105 0x00000000000000000000000000000000000000000000010 16
|
||||
hexlit1 103 0x20 32
|
||||
hexlit1 106 0x40 64
|
||||
hexlit1 107 0x80 128
|
||||
hexlit1 108 0x100 256
|
||||
hexlit1 109 0x200 512
|
||||
hexlit1 110 0X400 1024
|
||||
hexlit1 111 0x800 2048
|
||||
hexlit1 112 0x1000 4096
|
||||
hexlit1 113 0x2000 8192
|
||||
hexlit1 114 0x4000 16384
|
||||
hexlit1 115 0x8000 32768
|
||||
hexlit1 116 0x10000 65536
|
||||
hexlit1 117 0x20000 131072
|
||||
hexlit1 118 0x40000 262144
|
||||
hexlit1 119 0x80000 524288
|
||||
hexlit1 120 0x100000 1048576
|
||||
hexlit1 121 0x200000 2097152
|
||||
hexlit1 122 0x400000 4194304
|
||||
hexlit1 123 0x800000 8388608
|
||||
hexlit1 124 0x1000000 16777216
|
||||
hexlit1 125 0x2000000 33554432
|
||||
hexlit1 126 0x4000000 67108864
|
||||
hexlit1 127 0x8000000 134217728
|
||||
hexlit1 128 0x10000000 268435456
|
||||
hexlit1 129 0x20000000 536870912
|
||||
hexlit1 130 0x40000000 1073741824
|
||||
hexlit1 131 0x80000000 2147483648
|
||||
hexlit1 132 0x100000000 4294967296
|
||||
hexlit1 133 0x200000000 8589934592
|
||||
hexlit1 134 0x400000000 17179869184
|
||||
hexlit1 135 0x800000000 34359738368
|
||||
hexlit1 136 0x1000000000 68719476736
|
||||
hexlit1 137 0x2000000000 137438953472
|
||||
hexlit1 138 0x4000000000 274877906944
|
||||
hexlit1 139 0x8000000000 549755813888
|
||||
hexlit1 140 0x10000000000 1099511627776
|
||||
hexlit1 141 0x20000000000 2199023255552
|
||||
hexlit1 142 0x40000000000 4398046511104
|
||||
hexlit1 143 0x80000000000 8796093022208
|
||||
hexlit1 144 0x100000000000 17592186044416
|
||||
hexlit1 145 0x200000000000 35184372088832
|
||||
hexlit1 146 0x400000000000 70368744177664
|
||||
hexlit1 147 0x800000000000 140737488355328
|
||||
hexlit1 148 0x1000000000000 281474976710656
|
||||
hexlit1 149 0x2000000000000 562949953421312
|
||||
hexlit1 150 0x4000000000000 1125899906842624
|
||||
hexlit1 151 0x8000000000000 2251799813685248
|
||||
hexlit1 152 0x10000000000000 4503599627370496
|
||||
hexlit1 153 0x20000000000000 9007199254740992
|
||||
hexlit1 154 0x40000000000000 18014398509481984
|
||||
hexlit1 155 0x80000000000000 36028797018963968
|
||||
hexlit1 156 0x100000000000000 72057594037927936
|
||||
hexlit1 157 0x200000000000000 144115188075855872
|
||||
hexlit1 158 0x400000000000000 288230376151711744
|
||||
hexlit1 159 0x800000000000000 576460752303423488
|
||||
hexlit1 160 0X1000000000000000 1152921504606846976
|
||||
hexlit1 161 0x2000000000000000 2305843009213693952
|
||||
hexlit1 162 0X4000000000000000 4611686018427387904
|
||||
hexlit1 163 0x8000000000000000 -9223372036854775808
|
||||
hexlit1 164 0XFFFFFFFFFFFFFFFF -1
|
||||
|
||||
for {set n 1} {$n < 0x10} {incr n} {
|
||||
hexlit1 200.$n.1 0X[format %03X $n] $n
|
||||
hexlit1 200.$n.2 0x[format %03X $n] $n
|
||||
hexlit1 200.$n.3 0X[format %03x $n] $n
|
||||
hexlit1 200.$n.4 0x[format %03x $n] $n
|
||||
}
|
||||
|
||||
# String literals that look like hex do not get cast or coerced.
|
||||
#
|
||||
do_execsql_test hexlit-300 {
|
||||
CREATE TABLE t1(x INT, y REAL);
|
||||
INSERT INTO t1 VALUES('1234','4567'),('0x1234','0x4567');
|
||||
SELECT typeof(x), x, typeof(y), y, '#' FROM t1 ORDER BY rowid;
|
||||
} {integer 1234 real 4567.0 # text 0x1234 text 0x4567 #}
|
||||
do_execsql_test hexlit-301 {
|
||||
SELECT CAST('0x1234' AS INTEGER);
|
||||
} {0}
|
||||
|
||||
# Oversized hex literals are rejected
|
||||
#
|
||||
do_catchsql_test hexlist-400 {
|
||||
SELECT 0x10000000000000000;
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
|
||||
|
||||
finish_test
|
@ -589,14 +589,17 @@ db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
|
||||
# .separator STRING Change column separator used by output and .import
|
||||
do_test shell1-3.22.1 {
|
||||
catchcmd "test.db" ".separator"
|
||||
} {1 {Usage: .separator STRING}}
|
||||
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||
do_test shell1-3.22.2 {
|
||||
catchcmd "test.db" ".separator FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-3.22.3 {
|
||||
catchcmd "test.db" ".separator ABC XYZ"
|
||||
} {0 {}}
|
||||
do_test shell1-3.22.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".separator FOO BAD"
|
||||
} {1 {Usage: .separator STRING}}
|
||||
catchcmd "test.db" ".separator FOO BAD BAD2"
|
||||
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||
|
||||
# .show Show the current values for various settings
|
||||
do_test shell1-3.23.1 {
|
||||
|
@ -55,14 +55,17 @@ do_test shell5-1.1.3 {
|
||||
# .separator STRING Change separator used by output mode and .import
|
||||
do_test shell5-1.2.1 {
|
||||
catchcmd "test.db" ".separator"
|
||||
} {1 {Usage: .separator STRING}}
|
||||
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||
do_test shell5-1.2.2 {
|
||||
catchcmd "test.db" ".separator FOO"
|
||||
catchcmd "test.db" ".separator ONE"
|
||||
} {0 {}}
|
||||
do_test shell5-1.2.3 {
|
||||
catchcmd "test.db" ".separator ONE TWO"
|
||||
} {0 {}}
|
||||
do_test shell5-1.2.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".separator FOO BAD"
|
||||
} {1 {Usage: .separator STRING}}
|
||||
catchcmd "test.db" ".separator ONE TWO THREE"
|
||||
} {1 {Usage: .separator SEPARATOR ?NEWLINE?}}
|
||||
|
||||
# column separator should default to "|"
|
||||
do_test shell5-1.3.1.1 {
|
||||
|
@ -751,5 +751,13 @@ do_execsql_test where2-12.1 {
|
||||
} {/.*SEARCH TABLE t12 AS b .*SEARCH TABLE t12 AS b .*/}
|
||||
}
|
||||
|
||||
# Verify that all necessary OP_OpenRead opcodes occur in the OR optimization.
|
||||
#
|
||||
do_execsql_test where2-13.1 {
|
||||
CREATE TABLE t13(a,b);
|
||||
CREATE INDEX t13a ON t13(a);
|
||||
INSERT INTO t13 VALUES(4,5);
|
||||
SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4;
|
||||
} {4 5}
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user