Merge trunk changes into the sessions branch.

FossilOrigin-Name: 9f18e78f039ffa89a8806810ad385bdc51bc88ed
This commit is contained in:
drh 2014-05-29 20:29:13 +00:00
commit cbabb20390
24 changed files with 574 additions and 254 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -1 +1 @@
a769c7e03e6d4163986d49652687de34d15906a0
9f18e78f039ffa89a8806810ad385bdc51bc88ed

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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] ){

View File

@ -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;

View File

@ -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 " : "",

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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 ){

View File

@ -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);

View File

@ -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

View File

@ -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 \

View File

@ -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 {

View File

@ -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
View 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

View File

@ -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 \