Merge trunk changes into the sessions branch.
FossilOrigin-Name: 9f18e78f039ffa89a8806810ad385bdc51bc88ed
This commit is contained in:
commit
cbabb20390
@ -1376,7 +1376,7 @@ static int fts3InitVtab(
|
||||
int n = (int)strlen(p->azColumn[iCol]);
|
||||
for(i=0; i<nNotindexed; i++){
|
||||
char *zNot = azNotindexed[i];
|
||||
if( zNot && strlen(zNot)==n
|
||||
if( zNot && n==(int)strlen(zNot)
|
||||
&& 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
|
||||
){
|
||||
p->abNotindexed[iCol] = 1;
|
||||
|
@ -502,7 +502,7 @@ static int getNextNode(
|
||||
return rc;
|
||||
}else if( *zInput==')' ){
|
||||
pParse->nNest--;
|
||||
*pnConsumed = (zInput - z) + 1;
|
||||
*pnConsumed = (int)((zInput - z) + 1);
|
||||
*ppExpr = 0;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
|
@ -3065,7 +3065,7 @@ static int fts3PromoteSegments(
|
||||
sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
|
||||
sqlite3_bind_int64(pRange, 2, iLast);
|
||||
while( SQLITE_ROW==sqlite3_step(pRange) ){
|
||||
i64 nSize, dummy;
|
||||
i64 nSize = 0, dummy;
|
||||
fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
|
||||
if( nSize<=0 || nSize>nLimit ){
|
||||
/* If nSize==0, then the %_segdir.end_block field does not not
|
||||
@ -4870,7 +4870,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
|
||||
assert( bUseHint==1 || bUseHint==0 );
|
||||
if( iIdx==0 || (bUseHint && iIdx==1) ){
|
||||
int bIgnore;
|
||||
int bIgnore = 0;
|
||||
rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
|
||||
if( bIgnore ){
|
||||
pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
|
||||
|
53
manifest
53
manifest
@ -1,5 +1,5 @@
|
||||
C Merge\srecent\strunk\schanges\sinto\sthe\ssessions\sbranch.
|
||||
D 2014-05-26T20:00:00.506
|
||||
C Merge\strunk\schanges\sinto\sthe\ssessions\sbranch.
|
||||
D 2014-05-29T20:29:13.254
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in faf03dca4bd103f3e98b317aeba930dea49cfaa1
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -78,11 +78,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 0a9813c01ce7cc33d63680725ea30755d77c7b39
|
||||
F ext/fts3/fts3.c 20bc65862cfcea0a39bb64a819f8fe92a8e144c1
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 16cddf2d7b0e5f3681615ae1d8ca0e45fca44918
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
F ext/fts3/fts3_expr.c 2ac35bda474f00c14c19608e49a02c8c7ceb9970
|
||||
F ext/fts3/fts3_expr.c 351395fad6fcb16ecfc61db0861008a70101330c
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
|
||||
@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9
|
||||
F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d
|
||||
F ext/fts3/fts3_write.c 9e4e8579ad26cff3ee7743aaf5c3fe937fc441b4
|
||||
F ext/fts3/fts3_write.c 5ee9d894da74a5d15a3c317414fb8c84f1694fa4
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
|
||||
@ -173,16 +173,16 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
|
||||
F src/analyze.c 3596f863bb80126fe56ba217df5932749271efc8
|
||||
F src/analyze.c e8c8a9d20beb2ad156321330e8f4fea002d8deee
|
||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c e29fc07a968f8d1bbe38b5736d71db59959f545c
|
||||
F src/btree.c 70c60a3807b2072982f184d9614e020d2953f89c
|
||||
F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
|
||||
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
|
||||
F src/build.c 92539f47043ac9c48921450a9b2162da672bda4a
|
||||
F src/build.c 927e39b6aaf872c7b28f154f6acfeb9a05a72442
|
||||
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
|
||||
@ -190,13 +190,13 @@ F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c 50b74c1dde25d1ebcb4fa5c870762e6470ee46f1
|
||||
F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
|
||||
F src/fkey.c a549cff9fe8b736cdae21650ea0af6de29b77619
|
||||
F src/func.c 2e16316ec3a6365a0dc3e553c586f91b20f7f6c8
|
||||
F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4
|
||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c baf598f56d5ed36444f8d7a8752c0b66e48917ab
|
||||
F src/insert.c 3f5e6cb2cfea0c20a11d51da943395ac480122cb
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
@ -220,7 +220,7 @@ F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
|
||||
F src/os_win.c 485d06a93965f306c7281fca0937829292367234
|
||||
F src/os_win.c 648f842876e25391b7c454c8e49f7db1fd981d65
|
||||
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
|
||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
@ -234,12 +234,12 @@ F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
|
||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||
F src/select.c a6e8fe35d2929911448fe29fc9194eec73c6c0a5
|
||||
F src/shell.c bfac06fb15f3cd0d447e2e72ab3a283fac301813
|
||||
F src/select.c 7df17ec5506c2427576d412bee0e6ea740e12563
|
||||
F src/shell.c 33f6c0bc0e32eae099f7c2b79cfa7515b4b4702c
|
||||
F src/sqlite.h.in 78ac857a20a16d03b343320973b7da1736ff8fe9
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 01c7555ded7724ef808b27ccbf9af19da526e0a9
|
||||
F src/sqliteInt.h b9260ccf4c1ca2e26bc0789597c0a132aad4961b
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -291,24 +291,24 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
|
||||
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
|
||||
F src/update.c 7bb549d61efc6853f5cc708c1de6931179f8a12d
|
||||
F src/update.c 0f16e1d55d642a7ae3199bd0c2c1f51a7ef1b9d4
|
||||
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
|
||||
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 79b08ff97ab75ab5742cfc96f57ed196484d309a
|
||||
F src/vdbe.c 62f985592bfa011c2b35f8d7bfb4d4090340ae40
|
||||
F src/vdbe.h d03fcf47890ae1c79a335ca994cb878b302697ca
|
||||
F src/vdbeInt.h c05d4572211384c560b7579e7a299248cf31d6bd
|
||||
F src/vdbeapi.c d3c662762b62e330a03f29de8e2ac7098ef78030
|
||||
F src/vdbeaux.c e0c2e24ee12c94b6d7cb1c521a0b26cd2e3231d9
|
||||
F src/vdbeblob.c d7c232d1c6afc7ee1176c38b7d81b2e17af15ceb
|
||||
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
|
||||
F src/vdbesort.c 4abb7c0f8f19b7d7d82f4558d5da1a30fdf9ea38
|
||||
F src/vdbesort.c 44441d73b08b3a638dcdb725afffb87c6574ad27
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c 9d351a5ecefdcc104d0bb7d9b5631dce4d60757c
|
||||
F src/where.c b3be5eb4193b6327c4a02fe91411df503fe770e8
|
||||
F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@ -592,7 +592,7 @@ F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 9695c7c6c32480ea9fc20a2b38ed1de0640bcaec
|
||||
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
@ -828,11 +828,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 f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583
|
||||
F test/shell1.test fb080d67c81e8a80a79ea04b36f127209b5bd112
|
||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
|
||||
F test/shell5.test fa5583230c0aea5c9ff33f0ac1e26b1e3f03d153
|
||||
F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5
|
||||
F test/shell5.test 6b1a53c49a4ff5c3bd0bad17a85ecba505608278
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
@ -1121,6 +1121,7 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 0ac23e5e8311b69d87245f4a85112de321031658
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
@ -1185,9 +1186,9 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
||||
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 2d33afe0c43cb99caa521c48b721c3b0971e967c 856d44a206d82e96265103556dedda39ca3602b1
|
||||
R 1b56b8009ead47f6ec1e1c4ec0687826
|
||||
P a769c7e03e6d4163986d49652687de34d15906a0 8f916ed1e185ac728e00624d90e1d7bd2dda4469
|
||||
R 3370b40cbcc7803475544bb7516ae78d
|
||||
U drh
|
||||
Z 82cfe2ea739284c5d6fb20e24280c01d
|
||||
Z cb38c4d301930323a7c7581f1a945fe2
|
||||
|
@ -1 +1 @@
|
||||
a769c7e03e6d4163986d49652687de34d15906a0
|
||||
9f18e78f039ffa89a8806810ad385bdc51bc88ed
|
@ -1002,7 +1002,7 @@ static void analyzeOneTable(
|
||||
if( aGotoChng==0 ) continue;
|
||||
|
||||
/* Populate the register containing the index name. */
|
||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
zIdxName = pTab->zName;
|
||||
}else{
|
||||
zIdxName = pIdx->zName;
|
||||
|
@ -4218,12 +4218,6 @@ static const void *fetchPayload(
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
assert( pCur->info.nSize>0 );
|
||||
#if 0
|
||||
if( pCur->info.nSize==0 ){
|
||||
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
|
||||
&pCur->info);
|
||||
}
|
||||
#endif
|
||||
*pAmt = pCur->info.nLocal;
|
||||
return (void*)(pCur->info.pCell + pCur->info.nHeader);
|
||||
}
|
||||
|
19
src/build.c
19
src/build.c
@ -757,7 +757,7 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){
|
||||
*/
|
||||
Index *sqlite3PrimaryKeyIndex(Table *pTab){
|
||||
Index *p;
|
||||
for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){}
|
||||
for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -1286,7 +1286,7 @@ void sqlite3AddPrimaryKey(
|
||||
p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
|
||||
0, sortOrder, 0);
|
||||
if( p ){
|
||||
p->autoIndex = 2;
|
||||
p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
|
||||
if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
|
||||
}
|
||||
pList = 0;
|
||||
@ -1661,7 +1661,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
assert( pParse->pNewTable==pTab );
|
||||
pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
|
||||
if( pPk==0 ) return;
|
||||
pPk->autoIndex = 2;
|
||||
pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
|
||||
pTab->iPKey = -1;
|
||||
}else{
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
@ -1684,7 +1684,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
*/
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
int n;
|
||||
if( pIdx->autoIndex==2 ) continue;
|
||||
if( IsPrimaryKeyIndex(pIdx) ) continue;
|
||||
for(i=n=0; i<nPk; i++){
|
||||
if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
|
||||
}
|
||||
@ -2764,7 +2764,7 @@ Index *sqlite3AllocateIndexObject(
|
||||
**
|
||||
** If the index is created successfully, return a pointer to the new Index
|
||||
** structure. This is used by sqlite3AddPrimaryKey() to mark the index
|
||||
** as the tables primary key (Index.autoIndex==2).
|
||||
** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY)
|
||||
*/
|
||||
Index *sqlite3CreateIndex(
|
||||
Parse *pParse, /* All information about this parse */
|
||||
@ -2979,7 +2979,7 @@ Index *sqlite3CreateIndex(
|
||||
pIndex->pTable = pTab;
|
||||
pIndex->onError = (u8)onError;
|
||||
pIndex->uniqNotNull = onError!=OE_None;
|
||||
pIndex->autoIndex = (u8)(pName==0);
|
||||
pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE;
|
||||
pIndex->pSchema = db->aDb[iDb].pSchema;
|
||||
pIndex->nKeyCol = pList->nExpr;
|
||||
if( pPIWhere ){
|
||||
@ -3091,7 +3091,7 @@ Index *sqlite3CreateIndex(
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
int k;
|
||||
assert( pIdx->onError!=OE_None );
|
||||
assert( pIdx->autoIndex );
|
||||
assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
|
||||
assert( pIndex->onError!=OE_None );
|
||||
|
||||
if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
|
||||
@ -3314,7 +3314,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
pParse->checkSchema = 1;
|
||||
goto exit_drop_index;
|
||||
}
|
||||
if( pIndex->autoIndex ){
|
||||
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
|
||||
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
|
||||
"or PRIMARY KEY constraint cannot be dropped", 0);
|
||||
goto exit_drop_index;
|
||||
@ -3973,7 +3973,8 @@ void sqlite3UniqueConstraint(
|
||||
}
|
||||
zErr = sqlite3StrAccumFinish(&errMsg);
|
||||
sqlite3HaltConstraint(pParse,
|
||||
(pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE,
|
||||
IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
|
||||
: SQLITE_CONSTRAINT_UNIQUE,
|
||||
onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
|
||||
}
|
||||
|
||||
|
@ -233,8 +233,8 @@ int sqlite3FkLocateIndex(
|
||||
if( zKey==0 ){
|
||||
/* If zKey is NULL, then this foreign key is implicitly mapped to
|
||||
** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
|
||||
** identified by the test (Index.autoIndex==2). */
|
||||
if( pIdx->autoIndex==2 ){
|
||||
** identified by the test. */
|
||||
if( IsPrimaryKeyIndex(pIdx) ){
|
||||
if( aiCol ){
|
||||
int i;
|
||||
for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
|
||||
|
@ -1475,7 +1475,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** KEY values of this row before the update. */
|
||||
int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
|
||||
int op = OP_Ne;
|
||||
int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
|
||||
int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
|
||||
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
|
||||
@ -1576,7 +1576,7 @@ void sqlite3CompleteInsertion(
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
|
||||
pik_flags = 0;
|
||||
if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
|
||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
||||
assert( pParse->nested==0 );
|
||||
pik_flags |= OPFLAG_NCHANGE;
|
||||
}
|
||||
@ -1662,7 +1662,7 @@ int sqlite3OpenTableAndIndices(
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||
int iIdxCur = iBase++;
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
|
||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
|
||||
*piDataCur = iIdxCur;
|
||||
}
|
||||
if( aToOpen==0 || aToOpen[i+1] ){
|
||||
|
24
src/os_win.c
24
src/os_win.c
@ -2825,7 +2825,7 @@ static int winGetReadLock(winFile *pFile){
|
||||
pFile->lastErrno = osGetLastError();
|
||||
/* No need to log a failure to lock */
|
||||
}
|
||||
OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
|
||||
OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -2849,7 +2849,7 @@ static int winUnlockReadLock(winFile *pFile){
|
||||
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
|
||||
"winUnlockReadLock", pFile->zPath);
|
||||
}
|
||||
OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
|
||||
OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -2924,8 +2924,8 @@ static int winLock(sqlite3_file *id, int locktype){
|
||||
** If you are using this code as a model for alternative VFSes, do not
|
||||
** copy this retry logic. It is a hack intended for Windows only.
|
||||
*/
|
||||
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
|
||||
pFile->h, cnt, sqlite3ErrName(res)));
|
||||
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
|
||||
pFile->h, cnt, res));
|
||||
if( cnt ) sqlite3_win32_sleep(1);
|
||||
}
|
||||
gotPendingLock = res;
|
||||
@ -3010,7 +3010,7 @@ static int winLock(sqlite3_file *id, int locktype){
|
||||
** non-zero, otherwise zero.
|
||||
*/
|
||||
static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
int rc;
|
||||
int res;
|
||||
winFile *pFile = (winFile*)id;
|
||||
|
||||
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
||||
@ -3018,17 +3018,17 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
|
||||
assert( id!=0 );
|
||||
if( pFile->locktype>=RESERVED_LOCK ){
|
||||
rc = 1;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
|
||||
res = 1;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
|
||||
}else{
|
||||
rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
|
||||
if( rc ){
|
||||
res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
|
||||
if( res ){
|
||||
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
|
||||
}
|
||||
rc = !rc;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
|
||||
res = !res;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
|
||||
}
|
||||
*pResOut = rc;
|
||||
*pResOut = res;
|
||||
OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
|
||||
pFile->h, pResOut, *pResOut));
|
||||
return SQLITE_OK;
|
||||
|
@ -4498,7 +4498,7 @@ static void explainSimpleCount(
|
||||
Index *pIdx /* Index used to optimize scan, or NULL */
|
||||
){
|
||||
if( pParse->explain==2 ){
|
||||
int bCover = (pIdx!=0 && (HasRowid(pTab) || pIdx->autoIndex!=2));
|
||||
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
|
||||
char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
|
||||
pTab->zName,
|
||||
bCover ? " USING COVERING INDEX " : "",
|
||||
|
355
src/shell.c
355
src/shell.c
@ -446,8 +446,9 @@ struct previous_mode_data {
|
||||
struct callback_data {
|
||||
sqlite3 *db; /* The database */
|
||||
int echoOn; /* True to echo input commands */
|
||||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */
|
||||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
|
||||
int statsOn; /* True to display memory stats before each finalize */
|
||||
int outCount; /* Revert to stdout when reaching zero */
|
||||
int cnt; /* Number of records displayed so far */
|
||||
FILE *out; /* Write results here */
|
||||
FILE *traceOut; /* Output for sqlite3_trace() */
|
||||
@ -878,7 +879,8 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
|
||||
}else if( aiType && aiType[i]==SQLITE_TEXT ){
|
||||
if( zSep[0] ) fprintf(p->out,"%s",zSep);
|
||||
output_quoted_string(p->out, azArg[i]);
|
||||
}else if( aiType && (aiType[i]==SQLITE_INTEGER || aiType[i]==SQLITE_FLOAT) ){
|
||||
}else if( aiType && (aiType[i]==SQLITE_INTEGER
|
||||
|| aiType[i]==SQLITE_FLOAT) ){
|
||||
fprintf(p->out,"%s%s",zSep, azArg[i]);
|
||||
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
|
||||
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
|
||||
@ -1198,7 +1200,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
|
||||
|
||||
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
|
||||
"NextIfOpen", "PrevIfOpen", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", "Rewind", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", "Rewind", 0 };
|
||||
const char *azGoto[] = { "Goto", 0 };
|
||||
|
||||
/* Try to figure out if this is really an EXPLAIN statement. If this
|
||||
@ -1570,17 +1572,17 @@ static int run_schema_dump_query(
|
||||
*/
|
||||
static char zHelp[] =
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
".bail ON|OFF Stop after hitting an error. Default OFF\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".clone NEWDB Clone data into NEWDB from the existing database\n"
|
||||
".databases List names and files of attached databases\n"
|
||||
".dump ?TABLE? ... Dump the database in an SQL text format\n"
|
||||
" If TABLE specified, only dump tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".echo ON|OFF Turn command echo on or off\n"
|
||||
".echo on|off Turn command echo on or off\n"
|
||||
".exit Exit this program\n"
|
||||
".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n"
|
||||
".explain ?on|off? Turn output mode suitable for EXPLAIN on or off.\n"
|
||||
" With no args, it turns EXPLAIN on.\n"
|
||||
".header(s) ON|OFF Turn display of headers on or off\n"
|
||||
".headers on|off Turn display of headers on or off\n"
|
||||
".help Show this message\n"
|
||||
".import FILE TABLE Import data from FILE into TABLE\n"
|
||||
".indices ?TABLE? Show names of all indices\n"
|
||||
@ -1603,9 +1605,9 @@ static char zHelp[] =
|
||||
" tabs Tab-separated values\n"
|
||||
" tcl TCL list elements\n"
|
||||
".nullvalue STRING Use STRING in place of NULL values\n"
|
||||
".once FILENAME Output for the next SQL command only to FILENAME\n"
|
||||
".open ?FILENAME? Close existing database and reopen FILENAME\n"
|
||||
".output FILENAME Send output to FILENAME\n"
|
||||
".output stdout Send output to the screen\n"
|
||||
".output ?FILENAME? Send output to FILENAME or stdout\n"
|
||||
".print STRING... Print literal STRING\n"
|
||||
".prompt MAIN CONTINUE Replace the standard prompts\n"
|
||||
".quit Exit this program\n"
|
||||
@ -1616,19 +1618,19 @@ static char zHelp[] =
|
||||
" If TABLE specified, only show tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".separator STRING Change separator used by output mode and .import\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"
|
||||
".stats on|off Turn stats on or off\n"
|
||||
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
".tables ?TABLE? List names of tables\n"
|
||||
" If TABLE specified, only list tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".timeout MS Try opening locked tables for MS milliseconds\n"
|
||||
".timer on|off Turn SQL timer on or off\n"
|
||||
".trace FILE|off Output each SQL statement as it is run\n"
|
||||
".vfsname ?AUX? Print the name of the VFS stack\n"
|
||||
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
|
||||
;
|
||||
|
||||
static char zTimerHelp[] =
|
||||
".timer ON|OFF Turn the CPU timer measurement on or off\n"
|
||||
" Negative values right-justify\n"
|
||||
;
|
||||
|
||||
/* Forward reference */
|
||||
@ -1672,6 +1674,7 @@ static void open_db(struct callback_data *p, int keepAlive){
|
||||
static void resolve_backslashes(char *z){
|
||||
int i, j;
|
||||
char c;
|
||||
while( *z && *z!='\\' ) z++;
|
||||
for(i=j=0; (c = z[i])!=0; i++, j++){
|
||||
if( c=='\\' ){
|
||||
c = z[++i];
|
||||
@ -1697,7 +1700,7 @@ static void resolve_backslashes(char *z){
|
||||
}
|
||||
z[j] = c;
|
||||
}
|
||||
z[j] = 0;
|
||||
if( j<i ) z[j] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2141,6 +2144,19 @@ static void tryToClone(struct callback_data *p, const char *zNewDb){
|
||||
sqlite3_close(newDb);
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the output file back to stdout
|
||||
*/
|
||||
static void output_reset(struct callback_data *p){
|
||||
if( p->outfile[0]=='|' ){
|
||||
pclose(p->out);
|
||||
}else{
|
||||
output_file_close(p->out);
|
||||
}
|
||||
p->outfile[0] = 0;
|
||||
p->out = stdout;
|
||||
}
|
||||
|
||||
/*
|
||||
** If an input line begins with "." then invoke this routine to
|
||||
** process that line.
|
||||
@ -2239,8 +2255,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
sqlite3_close(pDest);
|
||||
}else
|
||||
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){
|
||||
bail_on_error = booleanValue(azArg[1]);
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
bail_on_error = booleanValue(azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .bail on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
/* The undocumented ".breakpoint" command causes a call to the no-op
|
||||
@ -2250,11 +2271,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
test_breakpoint();
|
||||
}else
|
||||
|
||||
if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){
|
||||
tryToClone(p, azArg[1]);
|
||||
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
tryToClone(p, azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .clone FILENAME\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
|
||||
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
|
||||
struct callback_data data;
|
||||
char *zErrMsg = 0;
|
||||
open_db(p, 0);
|
||||
@ -2273,11 +2299,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){
|
||||
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
|
||||
open_db(p, 0);
|
||||
/* When playing back a "dump", the content might appear in an order
|
||||
** which causes immediate foreign key constraints to be violated.
|
||||
** So disable foreign-key constraint enforcement to prevent problems. */
|
||||
if( nArg!=1 && nArg!=2 ){
|
||||
fprintf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
|
||||
fprintf(p->out, "BEGIN TRANSACTION;\n");
|
||||
p->writableSchema = 0;
|
||||
@ -2322,12 +2353,22 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
|
||||
p->echoOn = booleanValue(azArg[1]);
|
||||
if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->echoOn = booleanValue(azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .echo on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .eqp on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
|
||||
@ -2335,7 +2376,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
rc = 2;
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){
|
||||
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
|
||||
int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
|
||||
if(val == 1) {
|
||||
if(!p->explainPrev.valid) {
|
||||
@ -2370,19 +2411,20 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
|
||||
strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){
|
||||
p->showHeader = booleanValue(azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
|
||||
fprintf(stderr,"%s",zHelp);
|
||||
if( HAS_TIMER ){
|
||||
fprintf(stderr,"%s",zTimerHelp);
|
||||
if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->showHeader = booleanValue(azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .headers on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
|
||||
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
|
||||
fprintf(p->out, "%s", zHelp);
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
|
||||
char *zTable = azArg[2]; /* Insert data into this table */
|
||||
char *zFile = azArg[1]; /* Name of file to extra content from */
|
||||
sqlite3_stmt *pStmt = NULL; /* A statement */
|
||||
@ -2395,6 +2437,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
CSVReader sCsv; /* Reader context */
|
||||
int (*xCloser)(FILE*); /* Procedure to close th3 connection */
|
||||
|
||||
if( nArg!=3 ){
|
||||
fprintf(stderr, "Usage: .import FILE TABLE\n");
|
||||
goto meta_command_exit;
|
||||
}
|
||||
seenInterrupt = 0;
|
||||
memset(&sCsv, 0, sizeof(sCsv));
|
||||
open_db(p, 0);
|
||||
@ -2533,7 +2579,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
|
||||
if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
|
||||
struct callback_data data;
|
||||
char *zErrMsg = 0;
|
||||
open_db(p, 0);
|
||||
@ -2550,7 +2596,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
"ORDER BY 1",
|
||||
callback, &data, &zErrMsg
|
||||
);
|
||||
}else{
|
||||
}else if( nArg==2 ){
|
||||
zShellStatic = azArg[1];
|
||||
rc = sqlite3_exec(p->db,
|
||||
"SELECT name FROM sqlite_master "
|
||||
@ -2562,6 +2608,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
callback, &data, &zErrMsg
|
||||
);
|
||||
zShellStatic = 0;
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( zErrMsg ){
|
||||
fprintf(stderr,"Error: %s\n", zErrMsg);
|
||||
@ -2597,9 +2647,14 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
|
||||
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
|
||||
const char *zFile, *zProc;
|
||||
char *zErrMsg = 0;
|
||||
if( nArg<2 ){
|
||||
fprintf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
zFile = azArg[1];
|
||||
zProc = nArg>=3 ? azArg[2] : 0;
|
||||
open_db(p, 0);
|
||||
@ -2612,38 +2667,41 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}else
|
||||
#endif
|
||||
|
||||
if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){
|
||||
const char *zFile = azArg[1];
|
||||
output_file_close(p->pLog);
|
||||
p->pLog = output_file_open(zFile);
|
||||
if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
|
||||
if( nArg!=2 ){
|
||||
fprintf(stderr, "Usage: .log FILENAME\n");
|
||||
rc = 1;
|
||||
}else{
|
||||
const char *zFile = azArg[1];
|
||||
output_file_close(p->pLog);
|
||||
p->pLog = output_file_open(zFile);
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
|
||||
int n2 = strlen30(azArg[1]);
|
||||
if( (n2==4 && strncmp(azArg[1],"line",n2)==0)
|
||||
||
|
||||
(n2==5 && strncmp(azArg[1],"lines",n2)==0) ){
|
||||
if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
|
||||
const char *zMode = nArg>=2 ? azArg[1] : "";
|
||||
int n2 = (int)strlen(zMode);
|
||||
int c2 = zMode[0];
|
||||
if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
|
||||
p->mode = MODE_Line;
|
||||
}else if( (n2==6 && strncmp(azArg[1],"column",n2)==0)
|
||||
||
|
||||
(n2==7 && strncmp(azArg[1],"columns",n2)==0) ){
|
||||
}else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
|
||||
p->mode = MODE_Column;
|
||||
}else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){
|
||||
}else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
|
||||
p->mode = MODE_List;
|
||||
}else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){
|
||||
}else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
|
||||
p->mode = MODE_Html;
|
||||
}else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){
|
||||
}else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
|
||||
p->mode = MODE_Tcl;
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
|
||||
}else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
|
||||
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
|
||||
p->mode = MODE_Csv;
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
|
||||
}else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){
|
||||
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
|
||||
p->mode = MODE_List;
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
|
||||
}else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
|
||||
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
|
||||
p->mode = MODE_Insert;
|
||||
set_table_name(p, "table");
|
||||
set_table_name(p, nArg>=3 ? azArg[2] : "table");
|
||||
}else {
|
||||
fprintf(stderr,"Error: mode should be one of: "
|
||||
"column csv html insert line list tabs tcl\n");
|
||||
@ -2651,23 +2709,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){
|
||||
int n2 = strlen30(azArg[1]);
|
||||
if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
|
||||
p->mode = MODE_Insert;
|
||||
set_table_name(p, azArg[2]);
|
||||
}else {
|
||||
fprintf(stderr, "Error: invalid arguments: "
|
||||
" \"%s\". Enter \".help\" for help\n", azArg[2]);
|
||||
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
|
||||
"%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .nullvalue STRING\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
|
||||
sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
|
||||
"%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
|
||||
sqlite3 *savedDb = p->db;
|
||||
const char *zSavedFilename = p->zDbFilename;
|
||||
@ -2688,32 +2739,45 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
|
||||
if( p->outfile[0]=='|' ){
|
||||
pclose(p->out);
|
||||
}else{
|
||||
output_file_close(p->out);
|
||||
if( c=='o'
|
||||
&& (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)
|
||||
){
|
||||
const char *zFile = nArg>=2 ? azArg[1] : "stdout";
|
||||
if( nArg>2 ){
|
||||
fprintf(stderr, "Usage: .%s FILE\n", azArg[0]);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
p->outfile[0] = 0;
|
||||
if( azArg[1][0]=='|' ){
|
||||
p->out = popen(&azArg[1][1], "w");
|
||||
if( n>1 && strncmp(azArg[0], "once", n)==0 ){
|
||||
if( nArg<2 ){
|
||||
fprintf(stderr, "Usage: .once FILE\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
p->outCount = 2;
|
||||
}else{
|
||||
p->outCount = 0;
|
||||
}
|
||||
output_reset(p);
|
||||
if( zFile[0]=='|' ){
|
||||
p->out = popen(zFile + 1, "w");
|
||||
if( p->out==0 ){
|
||||
fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]);
|
||||
fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
|
||||
p->out = stdout;
|
||||
rc = 1;
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
||||
}
|
||||
}else{
|
||||
p->out = output_file_open(azArg[1]);
|
||||
p->out = output_file_open(zFile);
|
||||
if( p->out==0 ){
|
||||
if( strcmp(azArg[1],"off")!=0 ){
|
||||
fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]);
|
||||
if( strcmp(zFile,"off")!=0 ){
|
||||
fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
|
||||
}
|
||||
p->out = stdout;
|
||||
rc = 1;
|
||||
} else {
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
|
||||
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
||||
}
|
||||
}
|
||||
}else
|
||||
@ -2727,7 +2791,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
fprintf(p->out, "\n");
|
||||
}else
|
||||
|
||||
if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
|
||||
if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
|
||||
if( nArg >= 2) {
|
||||
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
|
||||
}
|
||||
@ -2736,12 +2800,18 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){
|
||||
if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
|
||||
rc = 2;
|
||||
}else
|
||||
|
||||
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
|
||||
FILE *alt = fopen(azArg[1], "rb");
|
||||
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
|
||||
FILE *alt;
|
||||
if( nArg!=2 ){
|
||||
fprintf(stderr, "Usage: .read FILE\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
alt = fopen(azArg[1], "rb");
|
||||
if( alt==0 ){
|
||||
fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
|
||||
rc = 1;
|
||||
@ -2751,7 +2821,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){
|
||||
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
|
||||
const char *zSrcFile;
|
||||
const char *zDb;
|
||||
sqlite3 *pSrc;
|
||||
@ -2761,9 +2831,13 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
if( nArg==2 ){
|
||||
zSrcFile = azArg[1];
|
||||
zDb = "main";
|
||||
}else{
|
||||
}else if( nArg==3 ){
|
||||
zSrcFile = azArg[2];
|
||||
zDb = azArg[1];
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .restore ?DB? FILE\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
rc = sqlite3_open(zSrcFile, &pSrc);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -2798,14 +2872,14 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
sqlite3_close(pSrc);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){
|
||||
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
|
||||
struct callback_data data;
|
||||
char *zErrMsg = 0;
|
||||
open_db(p, 0);
|
||||
memcpy(&data, p, sizeof(data));
|
||||
data.showHeader = 0;
|
||||
data.mode = MODE_Semi;
|
||||
if( nArg>1 ){
|
||||
if( nArg==2 ){
|
||||
int i;
|
||||
for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
|
||||
if( strcmp(azArg[1],"sqlite_master")==0 ){
|
||||
@ -2849,7 +2923,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
callback, &data, &zErrMsg);
|
||||
zShellStatic = 0;
|
||||
}
|
||||
}else{
|
||||
}else if( nArg==1 ){
|
||||
rc = sqlite3_exec(p->db,
|
||||
"SELECT sql FROM "
|
||||
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
|
||||
@ -2859,6 +2933,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
"ORDER BY rowid",
|
||||
callback, &data, &zErrMsg
|
||||
);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .schema ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( zErrMsg ){
|
||||
fprintf(stderr,"Error: %s\n", zErrMsg);
|
||||
@ -2888,20 +2966,49 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
for(i=1; i<nArg; i++){
|
||||
char zBuf[200];
|
||||
v = integerValue(azArg[i]);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%s: %lld 0x%llx\n", azArg[i], v, v);
|
||||
sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
|
||||
fprintf(p->out, "%s", zBuf);
|
||||
}
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator,
|
||||
"%.*s", (int)sizeof(p->separator)-1, azArg[1]);
|
||||
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator,
|
||||
"%.*s", (int)sizeof(p->separator)-1, azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .separator STRING\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
|
||||
if( c=='s'
|
||||
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
|
||||
){
|
||||
char *zCmd;
|
||||
int i;
|
||||
if( nArg<2 ){
|
||||
fprintf(stderr, "Usage: .system COMMAND\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
|
||||
for(i=2; i<nArg; i++){
|
||||
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
|
||||
zCmd, azArg[i]);
|
||||
}
|
||||
system(zCmd);
|
||||
sqlite3_free(zCmd);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
|
||||
int i;
|
||||
if( nArg!=1 ){
|
||||
fprintf(stderr, "Usage: .show\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
|
||||
fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
|
||||
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
|
||||
@ -2923,11 +3030,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
fprintf(p->out,"\n");
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
|
||||
p->statsOn = booleanValue(azArg[1]);
|
||||
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->statsOn = booleanValue(azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .stats on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
|
||||
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
|
||||
sqlite3_stmt *pStmt;
|
||||
char **azResult;
|
||||
int nRow, nAlloc;
|
||||
@ -3133,20 +3245,32 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){
|
||||
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
|
||||
open_db(p, 0);
|
||||
sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1]));
|
||||
sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
|
||||
}else
|
||||
|
||||
if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
|
||||
&& nArg==2
|
||||
){
|
||||
enableTimer = booleanValue(azArg[1]);
|
||||
if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
enableTimer = booleanValue(azArg[1]);
|
||||
if( enableTimer && !HAS_TIMER ){
|
||||
fprintf(stderr, "Error: timer not available on this system.\n");
|
||||
enableTimer = 0;
|
||||
}
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .timer on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){
|
||||
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
|
||||
open_db(p, 0);
|
||||
output_file_close(p->traceOut);
|
||||
if( nArg!=2 ){
|
||||
fprintf(stderr, "Usage: .trace FILE|off\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
p->traceOut = output_file_open(azArg[1]);
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
if( p->traceOut==0 ){
|
||||
@ -3177,11 +3301,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
|
||||
extern int sqlite3WhereTrace;
|
||||
sqlite3WhereTrace = booleanValue(azArg[1]);
|
||||
sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
|
||||
}else
|
||||
#endif
|
||||
|
||||
if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
|
||||
if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
|
||||
int j;
|
||||
assert( nArg<=ArraySize(azArg) );
|
||||
for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
|
||||
@ -3195,6 +3319,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
meta_command_exit:
|
||||
if( p->outCount ){
|
||||
p->outCount--;
|
||||
if( p->outCount==0 ) output_reset(p);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3362,6 +3491,10 @@ static int process_input(struct callback_data *p, FILE *in){
|
||||
errCnt++;
|
||||
}
|
||||
nSql = 0;
|
||||
if( p->outCount ){
|
||||
output_reset(p);
|
||||
p->outCount = 0;
|
||||
}
|
||||
}else if( nSql && _all_whitespace(zSql) ){
|
||||
if( p->echoOn ) printf("%s\n", zSql);
|
||||
nSql = 0;
|
||||
|
@ -1702,7 +1702,7 @@ struct Index {
|
||||
u16 nKeyCol; /* Number of columns forming the key */
|
||||
u16 nColumn; /* Number of columns stored in the index */
|
||||
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
|
||||
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
|
||||
unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
|
||||
unsigned bUnordered:1; /* Use this index for == or IN queries only */
|
||||
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
|
||||
unsigned isResized:1; /* True if resizeIndexObject() has been called */
|
||||
@ -1715,6 +1715,16 @@ struct Index {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for Index.idxType
|
||||
*/
|
||||
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
|
||||
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
|
||||
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
|
||||
|
||||
/* Return true if index X is a PRIMARY KEY index */
|
||||
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
|
||||
|
||||
/*
|
||||
** Each sample stored in the sqlite_stat3 table is represented in memory
|
||||
** using a structure of this type. See documentation at the top of the
|
||||
|
@ -187,7 +187,7 @@ void sqlite3Update(
|
||||
iIdxCur = iDataCur+1;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
|
||||
if( pIdx->autoIndex==2 && pPk!=0 ){
|
||||
if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){
|
||||
iDataCur = pParse->nTab;
|
||||
pTabList->a[0].iCursor = iDataCur;
|
||||
}
|
||||
|
@ -6342,7 +6342,7 @@ case OP_Init: { /* jump */
|
||||
if( zTrace ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( MASKBIT(i) & p->btreeMask)==0 ) continue;
|
||||
if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
|
||||
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +350,6 @@ static int vdbeSorterIterInit(
|
||||
rc = sqlite3OsRead(
|
||||
pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
|
||||
);
|
||||
assert( rc!=SQLITE_IOERR_SHORT_READ );
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
109
src/where.c
109
src/where.c
@ -2722,7 +2722,7 @@ static void explainOneScan(
|
||||
Index *pIdx = pLoop->u.btree.pIndex;
|
||||
char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
|
||||
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
|
||||
if( !HasRowid(pItem->pTab) && pIdx->autoIndex==2 ){
|
||||
if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
|
||||
zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s";
|
||||
}else if( flags & WHERE_AUTO_INDEX ){
|
||||
zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s";
|
||||
@ -3223,7 +3223,7 @@ static Bitmask codeOneLoopStart(
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
|
||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
|
||||
}else{
|
||||
}else if( iCur!=iIdxCur ){
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
|
||||
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
||||
for(j=0; j<pPk->nKeyCol; j++){
|
||||
@ -3293,6 +3293,10 @@ static Bitmask codeOneLoopStart(
|
||||
**
|
||||
** B: <after the loop>
|
||||
**
|
||||
** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
|
||||
** use an ephermeral index instead of a RowSet to record the primary
|
||||
** keys of the rows we have already seen.
|
||||
**
|
||||
*/
|
||||
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
||||
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
|
||||
@ -3307,6 +3311,7 @@ static Bitmask codeOneLoopStart(
|
||||
int untestedTerms = 0; /* Some terms not completely tested */
|
||||
int ii; /* Loop counter */
|
||||
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
|
||||
Table *pTab = pTabItem->pTab;
|
||||
|
||||
pTerm = pLoop->aLTerm[0];
|
||||
assert( pTerm!=0 );
|
||||
@ -3339,7 +3344,8 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
|
||||
/* Initialize the rowset register to contain NULL. An SQL NULL is
|
||||
** equivalent to an empty rowset.
|
||||
** equivalent to an empty rowset. Or, create an ephermeral index
|
||||
** capable of holding primary keys in the case of a WITHOUT ROWID.
|
||||
**
|
||||
** Also initialize regReturn to contain the address of the instruction
|
||||
** immediately following the OP_Return at the bottom of the loop. This
|
||||
@ -3350,9 +3356,16 @@ static Bitmask codeOneLoopStart(
|
||||
** called on an uninitialized cursor.
|
||||
*/
|
||||
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
regRowset = ++pParse->nMem;
|
||||
if( HasRowid(pTab) ){
|
||||
regRowset = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
regRowset = pParse->nTab++;
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
||||
}
|
||||
regRowid = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
|
||||
}
|
||||
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
|
||||
|
||||
@ -3388,11 +3401,16 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
}
|
||||
|
||||
/* Run a separate WHERE clause for each term of the OR clause. After
|
||||
** eliminating duplicates from other WHERE clauses, the action for each
|
||||
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
||||
*/
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
Expr *pOrExpr = pOrTerm->pExpr;
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
|
||||
int j1 = 0; /* Address of jump operation */
|
||||
if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
|
||||
pAndExpr->pLeft = pOrExpr;
|
||||
pOrExpr = pAndExpr;
|
||||
@ -3407,17 +3425,63 @@ static Bitmask codeOneLoopStart(
|
||||
explainOneScan(
|
||||
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
|
||||
);
|
||||
/* This is the sub-WHERE clause body. First skip over
|
||||
** duplicate rows from prior sub-WHERE clauses, and record the
|
||||
** rowid (or PRIMARY KEY) for the current row so that the same
|
||||
** row will be skipped in subsequent sub-WHERE clauses.
|
||||
*/
|
||||
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
int r;
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
|
||||
regRowid, 0);
|
||||
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
|
||||
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
|
||||
VdbeCoverage(v);
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
if( HasRowid(pTab) ){
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
int nPk = pPk->nKeyCol;
|
||||
int iPk;
|
||||
|
||||
/* Read the PK into an array of temp registers. */
|
||||
r = sqlite3GetTempRange(pParse, nPk);
|
||||
for(iPk=0; iPk<nPk; iPk++){
|
||||
int iCol = pPk->aiColumn[iPk];
|
||||
sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0);
|
||||
}
|
||||
|
||||
/* Check if the temp table already contains this key. If so,
|
||||
** the row has already been included in the result set and
|
||||
** can be ignored (by jumping past the Gosub below). Otherwise,
|
||||
** insert the key into the temp table and proceed with processing
|
||||
** the row.
|
||||
**
|
||||
** Use some of the same optimizations as OP_RowSetTest: If iSet
|
||||
** is zero, assume that the key cannot already be present in
|
||||
** the temp table. And if iSet is -1, assume that there is no
|
||||
** need to insert the key into the temp table, as it will never
|
||||
** be tested for. */
|
||||
if( iSet ){
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( iSet>=0 ){
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0);
|
||||
if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
}
|
||||
|
||||
/* Release the array of temp registers */
|
||||
sqlite3ReleaseTempRange(pParse, r, nPk);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the main loop body as a subroutine */
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
|
||||
|
||||
/* Jump here (skipping the main loop body subroutine) if the
|
||||
** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
|
||||
if( j1 ) sqlite3VdbeJumpHere(v, j1);
|
||||
|
||||
/* The pSubWInfo->untestedTerms flag means that this OR term
|
||||
** contained one or more AND term from a notReady table. The
|
||||
** terms from the notReady table could not be tested and will
|
||||
@ -3441,6 +3505,7 @@ static Bitmask codeOneLoopStart(
|
||||
assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
|
||||
if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
|
||||
&& (ii==0 || pSubLoop->u.btree.pIndex==pCov)
|
||||
&& (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
|
||||
){
|
||||
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
|
||||
pCov = pSubLoop->u.btree.pIndex;
|
||||
@ -4766,7 +4831,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
pNew = pBuilder->pNew;
|
||||
memset(&sSum, 0, sizeof(sSum));
|
||||
pItem = pWInfo->pTabList->a + pNew->iTab;
|
||||
if( !HasRowid(pItem->pTab) ) return SQLITE_OK;
|
||||
iCur = pItem->iCursor;
|
||||
|
||||
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
|
||||
@ -6015,7 +6079,14 @@ WhereInfo *sqlite3WhereBegin(
|
||||
int op = OP_OpenRead;
|
||||
/* iIdxCur is always set if to a positive value if ONEPASS is possible */
|
||||
assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
|
||||
if( pWInfo->okOnePass ){
|
||||
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
|
||||
&& (wctrlFlags & WHERE_ONETABLE_ONLY)!=0
|
||||
){
|
||||
/* This is one term of an OR-optimization using the PRIMARY KEY of a
|
||||
** WITHOUT ROWID table. No need for a separate index */
|
||||
iIndexCur = pLevel->iTabCur;
|
||||
op = 0;
|
||||
}else if( pWInfo->okOnePass ){
|
||||
Index *pJ = pTabItem->pTab->pIndex;
|
||||
iIndexCur = iIdxCur;
|
||||
assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
|
||||
@ -6033,9 +6104,11 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pLevel->iIdxCur = iIndexCur;
|
||||
assert( pIx->pSchema==pTab->pSchema );
|
||||
assert( iIndexCur>=0 );
|
||||
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
if( op ){
|
||||
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
}
|
||||
}
|
||||
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
|
||||
notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
|
||||
|
@ -210,6 +210,23 @@ do_execsql_test 6.2.5 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH '60*';
|
||||
} { Restaurant 6021 }
|
||||
|
||||
do_execsql_test 6.3.1 {
|
||||
DROP TABLE t1;
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(abc, ab, a, notindexed=abc);
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(a, ab, abc, notindexed=abc);
|
||||
|
||||
INSERT INTO t1 VALUES('no', 'yes', 'yep');
|
||||
INSERT INTO t2 VALUES('yep', 'yes', 'no');
|
||||
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'no';
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'yes';
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'yep';
|
||||
|
||||
SELECT count(*) FROM t2 WHERE t2 MATCH 'no';
|
||||
SELECT count(*) FROM t2 WHERE t2 MATCH 'yes';
|
||||
SELECT count(*) FROM t2 WHERE t2 MATCH 'yep';
|
||||
} {0 1 1 0 1 1}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
@ -268,7 +268,7 @@ do_test shell1-3.1.4 {
|
||||
# .bail ON|OFF Stop after hitting an error. Default OFF
|
||||
do_test shell1-3.2.1 {
|
||||
catchcmd "test.db" ".bail"
|
||||
} {1 {Error: unknown command or invalid arguments: "bail". Enter ".help" for help}}
|
||||
} {1 {Usage: .bail on|off}}
|
||||
do_test shell1-3.2.2 {
|
||||
catchcmd "test.db" ".bail ON"
|
||||
} {0 {}}
|
||||
@ -278,16 +278,16 @@ do_test shell1-3.2.3 {
|
||||
do_test shell1-3.2.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".bail OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "bail". Enter ".help" for help}}
|
||||
} {1 {Usage: .bail on|off}}
|
||||
|
||||
# .databases List names and files of attached databases
|
||||
do_test shell1-3.3.1 {
|
||||
catchcmd "-csv test.db" ".databases"
|
||||
} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/"
|
||||
do_test shell1-3.3.2 {
|
||||
# too many arguments
|
||||
# extra arguments ignored
|
||||
catchcmd "test.db" ".databases BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "databases". Enter ".help" for help}}
|
||||
} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/"
|
||||
|
||||
# .dump ?TABLE? ... Dump the database in an SQL text format
|
||||
# If TABLE specified, only dump tables matching
|
||||
@ -305,12 +305,12 @@ do_test shell1-3.4.2 {
|
||||
do_test shell1-3.4.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".dump FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "dump". Enter ".help" for help}}
|
||||
} {1 {Usage: .dump ?LIKE-PATTERN?}}
|
||||
|
||||
# .echo ON|OFF Turn command echo on or off
|
||||
do_test shell1-3.5.1 {
|
||||
catchcmd "test.db" ".echo"
|
||||
} {1 {Error: unknown command or invalid arguments: "echo". Enter ".help" for help}}
|
||||
} {1 {Usage: .echo on|off}}
|
||||
do_test shell1-3.5.2 {
|
||||
catchcmd "test.db" ".echo ON"
|
||||
} {0 {}}
|
||||
@ -320,7 +320,7 @@ do_test shell1-3.5.3 {
|
||||
do_test shell1-3.5.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".echo OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "echo". Enter ".help" for help}}
|
||||
} {1 {Usage: .echo on|off}}
|
||||
|
||||
# .exit Exit this program
|
||||
do_test shell1-3.6.1 {
|
||||
@ -339,15 +339,15 @@ do_test shell1-3.7.3 {
|
||||
catchcmd "test.db" ".explain OFF"
|
||||
} {0 {}}
|
||||
do_test shell1-3.7.4 {
|
||||
# too many arguments
|
||||
# extra arguments ignored
|
||||
catchcmd "test.db" ".explain OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "explain". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
|
||||
|
||||
# .header(s) ON|OFF Turn display of headers on or off
|
||||
do_test shell1-3.9.1 {
|
||||
catchcmd "test.db" ".header"
|
||||
} {1 {Error: unknown command or invalid arguments: "header". Enter ".help" for help}}
|
||||
} {1 {Usage: .headers on|off}}
|
||||
do_test shell1-3.9.2 {
|
||||
catchcmd "test.db" ".header ON"
|
||||
} {0 {}}
|
||||
@ -357,11 +357,11 @@ do_test shell1-3.9.3 {
|
||||
do_test shell1-3.9.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".header OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "header". Enter ".help" for help}}
|
||||
} {1 {Usage: .headers on|off}}
|
||||
|
||||
do_test shell1-3.9.5 {
|
||||
catchcmd "test.db" ".headers"
|
||||
} {1 {Error: unknown command or invalid arguments: "headers". Enter ".help" for help}}
|
||||
} {1 {Usage: .headers on|off}}
|
||||
do_test shell1-3.9.6 {
|
||||
catchcmd "test.db" ".headers ON"
|
||||
} {0 {}}
|
||||
@ -371,7 +371,7 @@ do_test shell1-3.9.7 {
|
||||
do_test shell1-3.9.8 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".headers OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "headers". Enter ".help" for help}}
|
||||
} {1 {Usage: .headers on|off}}
|
||||
|
||||
# .help Show this message
|
||||
do_test shell1-3.10.1 {
|
||||
@ -393,17 +393,17 @@ do_test shell1-3.10.2 {
|
||||
# .import FILE TABLE Import data from FILE into TABLE
|
||||
do_test shell1-3.11.1 {
|
||||
catchcmd "test.db" ".import"
|
||||
} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
do_test shell1-3.11.2 {
|
||||
catchcmd "test.db" ".import FOO"
|
||||
} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
#do_test shell1-3.11.2 {
|
||||
# catchcmd "test.db" ".import FOO BAR"
|
||||
#} {1 {Error: no such table: BAR}}
|
||||
do_test shell1-3.11.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".import FOO BAR BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
|
||||
# .indices ?TABLE? Show names of all indices
|
||||
# If TABLE specified, only show indices for tables
|
||||
@ -417,7 +417,7 @@ do_test shell1-3.12.2 {
|
||||
do_test shell1-3.12.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".indices FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "indices". Enter ".help" for help}}
|
||||
} {1 {Usage: .indices ?LIKE-PATTERN?}}
|
||||
|
||||
# .mode MODE ?TABLE? Set output mode where MODE is one of:
|
||||
# csv Comma-separated values
|
||||
@ -430,7 +430,7 @@ do_test shell1-3.12.3 {
|
||||
# tcl TCL list elements
|
||||
do_test shell1-3.13.1 {
|
||||
catchcmd "test.db" ".mode"
|
||||
} {1 {Error: unknown command or invalid arguments: "mode". Enter ".help" for help}}
|
||||
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
|
||||
do_test shell1-3.13.2 {
|
||||
catchcmd "test.db" ".mode FOO"
|
||||
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
|
||||
@ -459,9 +459,9 @@ do_test shell1-3.13.10 {
|
||||
catchcmd "test.db" ".mode tcl"
|
||||
} {0 {}}
|
||||
do_test shell1-3.13.11 {
|
||||
# too many arguments
|
||||
# extra arguments ignored
|
||||
catchcmd "test.db" ".mode tcl BAD"
|
||||
} {1 {Error: invalid arguments: "BAD". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
|
||||
# don't allow partial mode type matches
|
||||
do_test shell1-3.13.12 {
|
||||
@ -472,31 +472,31 @@ do_test shell1-3.13.13 {
|
||||
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
|
||||
do_test shell1-3.13.14 {
|
||||
catchcmd "test.db" ".mode lin"
|
||||
} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
|
||||
} {0 {}}
|
||||
|
||||
# .nullvalue STRING Print STRING in place of NULL values
|
||||
do_test shell1-3.14.1 {
|
||||
catchcmd "test.db" ".nullvalue"
|
||||
} {1 {Error: unknown command or invalid arguments: "nullvalue". Enter ".help" for help}}
|
||||
} {1 {Usage: .nullvalue STRING}}
|
||||
do_test shell1-3.14.2 {
|
||||
catchcmd "test.db" ".nullvalue FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-3.14.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".nullvalue FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "nullvalue". Enter ".help" for help}}
|
||||
} {1 {Usage: .nullvalue STRING}}
|
||||
|
||||
# .output FILENAME Send output to FILENAME
|
||||
do_test shell1-3.15.1 {
|
||||
catchcmd "test.db" ".output"
|
||||
} {1 {Error: unknown command or invalid arguments: "output". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
do_test shell1-3.15.2 {
|
||||
catchcmd "test.db" ".output FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-3.15.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".output FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "output". Enter ".help" for help}}
|
||||
} {1 {Usage: .output FILE}}
|
||||
|
||||
# .output stdout Send output to the screen
|
||||
do_test shell1-3.16.1 {
|
||||
@ -505,12 +505,12 @@ do_test shell1-3.16.1 {
|
||||
do_test shell1-3.16.2 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".output stdout BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "output". Enter ".help" for help}}
|
||||
} {1 {Usage: .output FILE}}
|
||||
|
||||
# .prompt MAIN CONTINUE Replace the standard prompts
|
||||
do_test shell1-3.17.1 {
|
||||
catchcmd "test.db" ".prompt"
|
||||
} {1 {Error: unknown command or invalid arguments: "prompt". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
do_test shell1-3.17.2 {
|
||||
catchcmd "test.db" ".prompt FOO"
|
||||
} {0 {}}
|
||||
@ -520,7 +520,7 @@ do_test shell1-3.17.3 {
|
||||
do_test shell1-3.17.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".prompt FOO BAR BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "prompt". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
|
||||
# .quit Exit this program
|
||||
do_test shell1-3.18.1 {
|
||||
@ -529,12 +529,12 @@ do_test shell1-3.18.1 {
|
||||
do_test shell1-3.18.2 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".quit BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "quit". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
|
||||
# .read FILENAME Execute SQL in FILENAME
|
||||
do_test shell1-3.19.1 {
|
||||
catchcmd "test.db" ".read"
|
||||
} {1 {Error: unknown command or invalid arguments: "read". Enter ".help" for help}}
|
||||
} {1 {Usage: .read FILE}}
|
||||
do_test shell1-3.19.2 {
|
||||
forcedelete FOO
|
||||
catchcmd "test.db" ".read FOO"
|
||||
@ -542,12 +542,12 @@ do_test shell1-3.19.2 {
|
||||
do_test shell1-3.19.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".read FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "read". Enter ".help" for help}}
|
||||
} {1 {Usage: .read FILE}}
|
||||
|
||||
# .restore ?DB? FILE Restore content of DB (default "main") from FILE
|
||||
do_test shell1-3.20.1 {
|
||||
catchcmd "test.db" ".restore"
|
||||
} {1 {Error: unknown command or invalid arguments: "restore". Enter ".help" for help}}
|
||||
} {1 {Usage: .restore ?DB? FILE}}
|
||||
do_test shell1-3.20.2 {
|
||||
catchcmd "test.db" ".restore FOO"
|
||||
} {0 {}}
|
||||
@ -557,7 +557,7 @@ do_test shell1-3.20.3 {
|
||||
do_test shell1-3.20.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".restore FOO BAR BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "restore". Enter ".help" for help}}
|
||||
} {1 {Usage: .restore ?DB? FILE}}
|
||||
|
||||
# .schema ?TABLE? Show the CREATE statements
|
||||
# If TABLE specified, only show tables matching
|
||||
@ -571,7 +571,7 @@ do_test shell1-3.21.2 {
|
||||
do_test shell1-3.21.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".schema FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "schema". Enter ".help" for help}}
|
||||
} {1 {Usage: .schema ?LIKE-PATTERN?}}
|
||||
|
||||
do_test shell1-3.21.4 {
|
||||
catchcmd "test.db" {
|
||||
@ -588,14 +588,14 @@ db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
|
||||
# .separator STRING Change separator used by output mode and .import
|
||||
do_test shell1-3.22.1 {
|
||||
catchcmd "test.db" ".separator"
|
||||
} {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}}
|
||||
} {1 {Usage: .separator STRING}}
|
||||
do_test shell1-3.22.2 {
|
||||
catchcmd "test.db" ".separator FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-3.22.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".separator FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}}
|
||||
} {1 {Usage: .separator STRING}}
|
||||
|
||||
# .show Show the current values for various settings
|
||||
do_test shell1-3.23.1 {
|
||||
@ -613,12 +613,12 @@ do_test shell1-3.23.1 {
|
||||
do_test shell1-3.23.2 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".show BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "show". Enter ".help" for help}}
|
||||
} {1 {Usage: .show}}
|
||||
|
||||
# .stats ON|OFF Turn stats on or off
|
||||
do_test shell1-3.23b.1 {
|
||||
catchcmd "test.db" ".stats"
|
||||
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
|
||||
} {1 {Usage: .stats on|off}}
|
||||
do_test shell1-3.23b.2 {
|
||||
catchcmd "test.db" ".stats ON"
|
||||
} {0 {}}
|
||||
@ -628,7 +628,7 @@ do_test shell1-3.23b.3 {
|
||||
do_test shell1-3.23b.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".stats OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
|
||||
} {1 {Usage: .stats on|off}}
|
||||
|
||||
# .tables ?TABLE? List names of tables
|
||||
# If TABLE specified, only list tables matching
|
||||
@ -642,12 +642,12 @@ do_test shell1-3.24.2 {
|
||||
do_test shell1-3.24.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".tables FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "tables". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
|
||||
# .timeout MS Try opening locked tables for MS milliseconds
|
||||
do_test shell1-3.25.1 {
|
||||
catchcmd "test.db" ".timeout"
|
||||
} {1 {Error: unknown command or invalid arguments: "timeout". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
do_test shell1-3.25.2 {
|
||||
catchcmd "test.db" ".timeout zzz"
|
||||
# this should be treated the same as a '0' timeout
|
||||
@ -658,12 +658,12 @@ do_test shell1-3.25.3 {
|
||||
do_test shell1-3.25.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".timeout 1 BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "timeout". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
|
||||
# .width NUM NUM ... Set column widths for "column" mode
|
||||
do_test shell1-3.26.1 {
|
||||
catchcmd "test.db" ".width"
|
||||
} {1 {Error: unknown command or invalid arguments: "width". Enter ".help" for help}}
|
||||
} {0 {}}
|
||||
do_test shell1-3.26.2 {
|
||||
catchcmd "test.db" ".width xxx"
|
||||
# this should be treated the same as a '0' width for col 1
|
||||
@ -689,7 +689,7 @@ do_test shell1-3.26.6 {
|
||||
# .timer ON|OFF Turn the CPU timer measurement on or off
|
||||
do_test shell1-3.27.1 {
|
||||
catchcmd "test.db" ".timer"
|
||||
} {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}}
|
||||
} {1 {Usage: .timer on|off}}
|
||||
do_test shell1-3.27.2 {
|
||||
catchcmd "test.db" ".timer ON"
|
||||
} {0 {}}
|
||||
@ -699,7 +699,7 @@ do_test shell1-3.27.3 {
|
||||
do_test shell1-3.27.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".timer OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "timer". Enter ".help" for help}}
|
||||
} {1 {Usage: .timer on|off}}
|
||||
|
||||
do_test shell1-3-28.1 {
|
||||
catchcmd test.db \
|
||||
|
@ -63,7 +63,7 @@ do_test shell4-1.2.2 {
|
||||
# .stats ON|OFF Turn stats on or off
|
||||
do_test shell4-1.3.1 {
|
||||
catchcmd "test.db" ".stats"
|
||||
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
|
||||
} {1 {Usage: .stats on|off}}
|
||||
do_test shell4-1.3.2 {
|
||||
catchcmd "test.db" ".stats ON"
|
||||
} {0 {}}
|
||||
@ -73,7 +73,7 @@ do_test shell4-1.3.3 {
|
||||
do_test shell4-1.3.4 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".stats OFF BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
|
||||
} {1 {Usage: .stats on|off}}
|
||||
|
||||
# NB. whitespace is important
|
||||
do_test shell4-1.4.1 {
|
||||
|
@ -40,29 +40,29 @@ forcedelete test.db test.db-journal test.db-wal
|
||||
# .import FILE TABLE Import data from FILE into TABLE
|
||||
do_test shell5-1.1.1 {
|
||||
catchcmd "test.db" ".import"
|
||||
} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
do_test shell5-1.1.2 {
|
||||
catchcmd "test.db" ".import FOO"
|
||||
} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
#do_test shell5-1.1.2 {
|
||||
# catchcmd "test.db" ".import FOO BAR"
|
||||
#} {1 {Error: no such table: BAR}}
|
||||
do_test shell5-1.1.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".import FOO BAR BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}}
|
||||
} {1 {Usage: .import FILE TABLE}}
|
||||
|
||||
# .separator STRING Change separator used by output mode and .import
|
||||
do_test shell1-1.2.1 {
|
||||
do_test shell5-1.2.1 {
|
||||
catchcmd "test.db" ".separator"
|
||||
} {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}}
|
||||
do_test shell1-1.2.2 {
|
||||
} {1 {Usage: .separator STRING}}
|
||||
do_test shell5-1.2.2 {
|
||||
catchcmd "test.db" ".separator FOO"
|
||||
} {0 {}}
|
||||
do_test shell1-1.2.3 {
|
||||
do_test shell5-1.2.3 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".separator FOO BAD"
|
||||
} {1 {Error: unknown command or invalid arguments: "separator". Enter ".help" for help}}
|
||||
} {1 {Usage: .separator STRING}}
|
||||
|
||||
# separator should default to "|"
|
||||
do_test shell5-1.3.1 {
|
||||
|
92
test/whereI.test
Normal file
92
test/whereI.test
Normal file
@ -0,0 +1,92 @@
|
||||
# 2014-03-31
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# The focus of this file is testing the OR optimization on WITHOUT ROWID
|
||||
# tables.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix whereI
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||
INSERT INTO t1 VALUES(1, 'a', 'z');
|
||||
INSERT INTO t1 VALUES(2, 'b', 'y');
|
||||
INSERT INTO t1 VALUES(3, 'c', 'x');
|
||||
INSERT INTO t1 VALUES(4, 'd', 'w');
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
CREATE INDEX i2 ON t1(c);
|
||||
}
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT a FROM t1 WHERE b='b' OR c='x'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b=?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT a FROM t1 WHERE b='b' OR c='x'
|
||||
} {2 3}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT a FROM t1 WHERE b='a' OR c='z'
|
||||
} {1}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Try that again, this time with non integer PRIMARY KEY values.
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t2(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
|
||||
INSERT INTO t2 VALUES('i', 'a', 'z');
|
||||
INSERT INTO t2 VALUES('ii', 'b', 'y');
|
||||
INSERT INTO t2 VALUES('iii', 'c', 'x');
|
||||
INSERT INTO t2 VALUES('iv', 'd', 'w');
|
||||
CREATE INDEX i3 ON t2(b);
|
||||
CREATE INDEX i4 ON t2(c);
|
||||
}
|
||||
|
||||
do_eqp_test 2.1 {
|
||||
SELECT a FROM t2 WHERE b='b' OR c='x'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i3 (b=?)}
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT a FROM t2 WHERE b='b' OR c='x'
|
||||
} {ii iii}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT a FROM t2 WHERE b='a' OR c='z'
|
||||
} {i}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# On a table with a multi-column PK.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t3(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID;
|
||||
|
||||
INSERT INTO t3 VALUES('f', 1, 1, 'o');
|
||||
INSERT INTO t3 VALUES('o', 2, 1, 't');
|
||||
INSERT INTO t3 VALUES('t', 1, 2, 't');
|
||||
INSERT INTO t3 VALUES('t', 2, 2, 'f');
|
||||
|
||||
CREATE INDEX t3i1 ON t3(d);
|
||||
CREATE INDEX t3i2 ON t3(a);
|
||||
|
||||
SELECT c||'.'||b FROM t3 WHERE a='t' OR d='t'
|
||||
} {
|
||||
2.1 2.2 1.2
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
@ -4,7 +4,7 @@
|
||||
# compiler warnings in SQLite.
|
||||
#
|
||||
rm -f sqlite3.c
|
||||
make sqlite3.c-debug
|
||||
make sqlite3.c
|
||||
echo '********** No optimizations. Includes FTS4 and RTREE *********'
|
||||
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
|
||||
|
Loading…
Reference in New Issue
Block a user