Merge all the latest trunk enhancements into the autosetup branch.

FossilOrigin-Name: d0554ac46866b5ad467b88de6fae06695fd81e7fdf38157702a395f7282cbe9d
This commit is contained in:
drh 2024-10-24 11:20:25 +00:00
commit b79997a7c0
16 changed files with 287 additions and 86 deletions

View File

@ -23,7 +23,27 @@ set G(src) [string map [list %dir% $srcdir] {
}]
set G(hdr) {
/*
** This, the "fts5.c" source file, is a composite file that is itself
** assembled from the following files:
**
** fts5.h
** fts5Int.h
** fts5parse.h <--- Generated from fts5parse.y by Lemon
** fts5parse.c <--- Generated from fts5parse.y by Lemon
** fts5_aux.c
** fts5_buffer.c
** fts5_config.c
** fts5_expr.c
** fts5_hash.c
** fts5_index.c
** fts5_main.c
** fts5_storage.c
** fts5_tokenize.c
** fts5_unicode2.c
** fts5_varint.c
** fts5_vocab.c
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
@ -33,10 +53,16 @@ set G(hdr) {
# undef NDEBUG
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
}
set G(footer) {
/* Here ends the fts5.c composite file. */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
}

View File

@ -1,5 +1,5 @@
C Update\sthe\sversion\snumber\sfor\sthe\sTEA\sextension.
D 2024-10-24T11:11:31.638
C Merge\sall\sthe\slatest\strunk\senhancements\sinto\sthe\sautosetup\sbranch.
D 2024-10-24T11:20:25.409
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -273,7 +273,7 @@ F ext/fts5/test/fts5vocab2.test bbba149c254375d00055930c1a501c9a51e80b0d20bf7b98
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
F ext/fts5/tool/fts5txt2db.tcl c0d43c8590656f8240e622b00957b3a0facc49482411a9fdc2870b45c0c82f9f
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl 3eba8e9bee4221ed165f3304b51b2a74a705f4ec5df3d044573a2be539534af8
F ext/fts5/tool/mkfts5c.tcl 6649ed963a9135e36866f7cc9f8de5c8dcec85b5df089388274cee6381702cb7
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c 3add8197e0a86c1761771a39500ebae749438bcf1836160b407a56b4eaa8721c
@ -771,10 +771,10 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 14d0f80e4779f5f76bcc71e7af97e3efe318fa3d0b22335623c59fab7d39302b
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
F src/os_unix.c 0ad4e0885294b3a0e135a18533590ec9ad91ffe82f6a08e55b40babd51772928
F src/os_win.c 69fa1aaff68270423c85cff4327ba17ef99a1eb017e1a2bfb97416d9b8398b05
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
F src/pager.c 9656ad4e8331efb8a4f94f7a0c6440b98caea073950a367ea0c728a53b8e62c9
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
F src/parse.y a7a8d42eeff01d267444ddb476029b0b1726fb70ae3d77984140f17ad02e2d61
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
@ -789,15 +789,15 @@ F src/resolve.c c8a5372b97b2a2e972a280676f06ddb5b74e885d3b1f5ce383f839907b57ef68
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4b14337a2742f0c0beeba490e9a05507e9b4b12184b9cd12773501d08d48e3fe
F src/shell.c.in 0662f9bcf0725461778d0254a06150e5d61c08c5a87a7281ccdf45552050c79d
F src/sqlite.h.in add9e064d6b42af8f1a4a3322bddadec76696e520aedebd83e0d3211c15ac999
F src/sqlite.h.in 29fc900a58f394c7488d093fd7a8dcb14d3fa6399d5178cb20adcf88dbedfe39
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
F src/sqliteInt.h baae24292817e13e7fe748851c62efc381dcc4dac241b1182eac3d2f05eae52c
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c e2b752dd08034c834e3639afa3300940d6e847fcd94207e1f2f1b83ce08b87be
F src/tclsqlite.h c6af51f31a2b2172d674608763a4b98fdf5cd587e4025053e546fb8077757262
F src/tclsqlite.c 47d4bb6eb06aab48d643eeb8c4f65b5fa9529fa5526fdcbf223ea32277ed1b56
F src/tclsqlite.h 529047feec49e7f463374749147f64d3f17505b0ebd84b3477a364c6f46a9de1
F src/test1.c 8bf8b74145b768f42386787f93f6d6dad7bc400a4ee2d50e4ad5a06a20a97ef1
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
F src/test3.c e7573aa0f78ee4e070a4bc8c3493941c1aa64d5c66d4825c74c0f055451f432b
@ -872,9 +872,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 8b7e309a8012659ac9275ad8cdcc6acaf73fa04b1090e38a01335f230fd10681
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c ed0e1e9ef15f01f5da54168ae2fdb5eb789a881fd20d7b4820e38454dedf9947
F src/whereInt.h a5d079c346a658b7a6e9e47bb943d021e02fa1e6aed3b964ca112112a4892192
F src/wherecode.c 5172d647798134e7c92536ddffe7e530c393d79b5dedd648b88faf2646c65baf
F src/where.c 4de9e7ca5f49e4a21c1d733e2b2fbbc8b62b1a157a58a562c569da84cfcb005b
F src/whereInt.h 1e36ec50392f7cc3d93d1152d4338064cd522b87156a0739388b7e273735f0ca
F src/wherecode.c 81b9af89f4f85c8097d0da6a31499f015eabc4d3584963d30ba7b7b782e26514
F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f
F src/window.c 499d48f315a09242dc68f2fac635ed27dcf6bbb0d9ab9084857898c64489e975
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@ -1340,9 +1340,9 @@ F test/index8.test caa097735c91dbc23d8a402f5e63a2a03c83840ba3928733ed7f9a03f8a91
F test/index9.test 2ac891806a4136ef3e91280477e23114e67575207dc331e6797fa0ed9379f997
F test/indexA.test 11d84f6995e6e5b9d8315953fb1b6d29772ee7c7803ee9112715e7e4dd3e4974
F test/indexedby.test f21eca4f7a6ffe14c8500a7ad6cd53166666c99e5ccd311842a28bc94a195fe0
F test/indexexpr1.test 24fa85a12da384dd1d56f7b24e593c51a8a54b4c5e2e8bbb9e5fdf1099427faf
F test/indexexpr1.test 928671af9d7374bb56ed4dcfbc157f4eeddb1e86ab5615ceb3ac97a713c2dd8f
F test/indexexpr2.test 1c382e81ef996d8ae8b834a74f2a9013dddf59214c32201d7c8a656d739f999a
F test/indexexpr3.test 9d893bf440937ebcc1e59c7c9c1505c40c918346a3ddde76a69078f3c733c45d
F test/indexexpr3.test 47b91bc7999805c9a34d356f672259bc49295ecc797448511cae554a309b47cd
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
@ -1736,7 +1736,7 @@ F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d163
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 7b44f1a9b9a2de8112695b908afc21dd9a68cd2d44e84b73f1b27b53492c0d59
F test/testrunner.tcl 3dd75b45593d2afa2e3bca76121297a9f163bebb98474b13536f326829a71db1 x
F test/testrunner.tcl bc1a8d21a1aa3a5cf7c4883cbee4b6748790fe960fad06ca5db74ec914bd6525 x
F test/testrunner_data.tcl c7b3b911e44f7e8c01cc6bc7571e16115cdc2e4db46630bd2acd7a931a46380e
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
@ -2197,7 +2197,7 @@ F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c 2a0987d183027c795ced13d6749061c1d2f38e24eddb428f56fa64c3a8f51e4b
F tool/sqlite3_analyzer.c.in 348ba349bbdc93c9866439f9f935d7284866a2a4e6898bc906ae1204ade56918
F tool/sqlite3_rsync.c d832c69265d32d3694e469d5ccb2da03360d2088d7871743a76a32f71854ad91
F tool/sqlite3_rsync.c 6c9cac5a9197f591985b271aeff803ec4fb4db36c8eab97e1331ff64aa1b8d94
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/src-verify.c d00f93263aa2fa6ba0cba0106d95458e6effb94fdb5fc634f56834f90c05bbb4
@ -2236,8 +2236,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 58a0f7e79ce913b432dfd4db018e5a92efa8a6bd8a50bd78ab705ceac0322e9c
R c66389447c3b7b2175096c4d28a4e3c7
P 56353bcffa1bad425b1645b09e7192aa418d6b989df5958e0a770226bfc2ce63 da9124fee28c155c4d1cc0d3949eb7b588a7236c12883a010af7909ad8e534ef
R cc1b154ed902ce297ea76c4a560a28a4
U drh
Z 8cb6d5a8498acf453471a00efb00ba92
Z 11c0afa471c73db054eb415d8e2d3805
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
56353bcffa1bad425b1645b09e7192aa418d6b989df5958e0a770226bfc2ce63
d0554ac46866b5ad467b88de6fae06695fd81e7fdf38157702a395f7282cbe9d

View File

@ -4128,6 +4128,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ;
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}

View File

@ -3660,7 +3660,7 @@ static int winSectorSize(sqlite3_file *id){
*/
static int winDeviceCharacteristics(sqlite3_file *id){
winFile *p = (winFile*)id;
return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ |
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}

View File

@ -808,20 +808,28 @@ static const unsigned char aJournalMagic[] = {
** Return true if page pgno can be read directly from the database file
** by the b-tree layer. This is the case if:
**
** * the database file is open,
** * there are no dirty pages in the cache, and
** * the desired page is not currently in the wal file.
** (1) the database file is open
** (2) the VFS for the database is able to do unaligned sub-page reads
** (3) there are no dirty pages in the cache, and
** (4) the desired page is not currently in the wal file.
*/
int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
if( pPager->fd->pMethods==0 ) return 0;
if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
assert( pPager!=0 );
assert( pPager->fd!=0 );
if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */
if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
return iRead==0;
return iRead==0; /* Condition (4) */
}
#endif
assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
& SQLITE_IOCAP_SUBPAGE_READ)==0 ){
return 0; /* Case (2) */
}
return 1;
}
#endif

View File

@ -652,6 +652,13 @@ int sqlite3_exec(
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
**
** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
** from the database file in amounts that are not a multiple of the
** page size and that do not begin at a page boundary. Without this
** property, SQLite is careful to only do full-page reads and write
** on aligned pages, with the one exception that it will do a sub-page
** read of the first page to access the database header.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@ -668,6 +675,7 @@ int sqlite3_exec(
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
/*
** CAPI3REF: File Locking Levels
@ -814,6 +822,7 @@ struct sqlite3_file {
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** <li> [SQLITE_IOCAP_IMMUTABLE]
** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
** <li> [SQLITE_IOCAP_SUBPAGE_READ]
** </ul>
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of

View File

@ -47,7 +47,7 @@
/* Compatability between Tcl8.6 and Tcl9.0 */
#if TCL_MAJOR_VERSION==9
# define CONST const
#else
#elif !defined(Tcl_Size)
typedef int Tcl_Size;
#endif
/**** End copy of tclsqlite.h ****/

View File

@ -35,7 +35,7 @@
/* Compatability between Tcl8.6 and Tcl9.0 */
#if TCL_MAJOR_VERSION==9
# define CONST const
#else
#elif !defined(Tcl_Size)
typedef int Tcl_Size;
#endif

View File

@ -7441,14 +7441,28 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
}else{
/* Unable to translate the table reference into an index
** reference. Verify that this is harmless - that the
** table being referenced really is open.
*/
}else if( pLoop->wsFlags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
if( pLoop->wsFlags & WHERE_IDX_ONLY ){
/* An error. pLoop is supposed to be a covering index loop,
** and yet the VM code refers to a column of the table that
** is not part of the index. */
sqlite3ErrorMsg(pParse, "internal query planner error");
pParse->rc = SQLITE_INTERNAL;
}else{
/* The WHERE_EXPRIDX flag is set by the planner when it is likely
** that pLoop is a covering index loop, but it is not possible
** to be 100% sure. In this case, any OP_Explain opcode
** corresponding to this loop describes the index as a "COVERING
** INDEX". But, pOp proves that pLoop is not actually a covering
** index loop. So clear the WHERE_EXPRIDX flag and rewrite the
** text that accompanies the OP_Explain opcode, if any. */
pLoop->wsFlags &= ~WHERE_EXPRIDX;
sqlite3WhereAddExplainText(pParse,
pLevel->addrBody-1,
pTabList,
pLevel,
pWInfo->wctrlFlags
);
}
}
}else if( pOp->opcode==OP_Rowid ){

View File

@ -533,9 +533,17 @@ int sqlite3WhereExplainBloomFilter(
const WhereInfo *pWInfo, /* WHERE clause */
const WhereLevel *pLevel /* Bloom filter on this level */
);
void sqlite3WhereAddExplainText(
Parse *pParse, /* Parse context */
int addr,
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
# define sqlite3WhereAddExplainText(u,v,w,x,y)
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
void sqlite3WhereAddScanStatus(

View File

@ -110,38 +110,38 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
}
/*
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
** was defined at compile-time. If it is not a no-op, a single OP_Explain
** opcode is added to the output to describe the table scan strategy in pLevel.
**
** If an OP_Explain opcode is added to the VM, its address is returned.
** Otherwise, if no OP_Explain is coded, zero is returned.
** This function sets the P4 value of an existing OP_Explain opcode to
** text describing the loop in pLevel. If the OP_Explain opcode already has
** a P4 value, it is freed before it is overwritten.
*/
int sqlite3WhereExplainOneScan(
void sqlite3WhereAddExplainText(
Parse *pParse, /* Parse context */
int addr, /* Address of OP_Explain opcode */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
int ret = 0;
#if !defined(SQLITE_DEBUG)
if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr);
SrcItem *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
char *zMsg; /* Text to add to EQP output */
#endif
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
if( db->mallocFailed ) return;
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
@ -165,7 +165,7 @@ int sqlite3WhereExplainOneScan(
zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
}else if( flags & WHERE_IDX_ONLY ){
}else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
zFmt = "COVERING INDEX %s";
}else{
zFmt = "INDEX %s";
@ -217,11 +217,50 @@ int sqlite3WhereExplainOneScan(
sqlite3_str_append(&str, " (~1 row)", 9);
}
#endif
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
pParse->addrExplain, pLoop->rRun,
zMsg, P4_DYNAMIC);
#endif
assert( pOp->opcode==OP_Explain );
assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 );
sqlite3DbFree(db, pOp->p4.z);
pOp->p4type = P4_DYNAMIC;
pOp->p4.z = sqlite3StrAccumFinish(&str);
}
}
/*
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
** was defined at compile-time. If it is not a no-op, a single OP_Explain
** opcode is added to the output to describe the table scan strategy in pLevel.
**
** If an OP_Explain opcode is added to the VM, its address is returned.
** Otherwise, if no OP_Explain is coded, zero is returned.
*/
int sqlite3WhereExplainOneScan(
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
int ret = 0;
#if !defined(SQLITE_DEBUG)
if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0
&& (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
){
Vdbe *v = pParse->pVdbe;
int addr = sqlite3VdbeCurrentAddr(v);
ret = sqlite3VdbeAddOp3(
v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun
);
sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags);
}
}
return ret;
}
@ -320,9 +359,10 @@ void sqlite3WhereAddScanStatus(
}
}else{
int addr;
VdbeOp *pOp;
assert( pSrclist->a[pLvl->iFrom].fg.isSubquery );
addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub;
VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1);
pOp = sqlite3VdbeGetOp(v, addr-1);
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine );
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr );
sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1);

View File

@ -49,7 +49,7 @@ do_execsql_test indexexpr1-130 {
do_execsql_test indexexpr1-130eqp {
EXPLAIN QUERY PLAN
SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
} {/USING INDEX t1ba/}
} {/USING COVERING INDEX t1ba/}
do_execsql_test indexexpr1-140 {
SELECT rowid, substr(a,b,3), '|' FROM t1 ORDER BY 2;
@ -61,7 +61,7 @@ do_execsql_test indexexpr1-141 {
do_execsql_test indexexpr1-141eqp {
EXPLAIN QUERY PLAN
SELECT rowid FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +rowid;
} {/USING INDEX t1abx/}
} {/USING COVERING INDEX t1abx/}
do_execsql_test indexexpr1-142 {
SELECT rowid FROM t1 WHERE +substr(a,b,3)<='and' ORDER BY +rowid;
} {1 2 3}
@ -73,7 +73,7 @@ do_execsql_test indexexpr1-150eqp {
EXPLAIN QUERY PLAN
SELECT rowid FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
ORDER BY +rowid;
} {/USING INDEX t1abx/}
} {/USING COVERING INDEX t1abx/}
ifcapable altertable {
do_execsql_test indexexpr1-160 {
@ -99,14 +99,14 @@ do_execsql_test indexexpr1-170 {
do_execsql_test indexexpr1-170eqp {
EXPLAIN QUERY PLAN
SELECT length(a) FROM t1 ORDER BY length(a);
} {/SCAN t1 USING INDEX t1alen/}
} {/SCAN t1 USING COVERING INDEX t1alen/}
do_execsql_test indexexpr1-171 {
SELECT length(a) FROM t1 ORDER BY length(a) DESC;
} {52 38 29 27 25 20}
do_execsql_test indexexpr1-171eqp {
EXPLAIN QUERY PLAN
SELECT length(a) FROM t1 ORDER BY length(a) DESC;
} {/SCAN t1 USING INDEX t1alen/}
} {/SCAN t1 USING COVERING INDEX t1alen/}
do_execsql_test indexexpr1-200 {
DROP TABLE t1;
@ -142,7 +142,7 @@ do_execsql_test indexexpr1-230 {
do_execsql_test indexexpr1-230eqp {
EXPLAIN QUERY PLAN
SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
} {/USING INDEX t1ba/}
} {/USING COVERING INDEX t1ba/}
do_execsql_test indexexpr1-240 {
SELECT id, substr(a,b,3), '|' FROM t1 ORDER BY 2;
@ -154,7 +154,7 @@ do_execsql_test indexexpr1-241 {
do_execsql_test indexexpr1-241eqp {
EXPLAIN QUERY PLAN
SELECT id FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +id;
} {/USING INDEX t1abx/}
} {/USING COVERING INDEX t1abx/}
do_execsql_test indexexpr1-242 {
SELECT id FROM t1 WHERE +substr(a,b,3)<='and' ORDER BY +id;
} {1 2 3}
@ -166,7 +166,7 @@ do_execsql_test indexexpr1-250eqp {
EXPLAIN QUERY PLAN
SELECT id FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
ORDER BY +id;
} {/USING INDEX t1abx/}
} {/USING COVERING INDEX t1abx/}
ifcapable altertable {
do_execsql_test indexexpr1-260 {
@ -238,7 +238,7 @@ do_execsql_test indexexpr1-510 {
do_execsql_test indexexpr1-510eqp {
EXPLAIN QUERY PLAN
SELECT substr(a,4,3) AS k FROM cnt, t5 WHERE k=printf('%03d',x);
} {/USING INDEX t5ax/}
} {/USING COVERING INDEX t5ax/}
# Skip-scan on an indexed expression
#
@ -547,7 +547,7 @@ do_execsql_test indexexpr1-2030 {
(3, '{"x":1}', 6, 7);
CREATE INDEX t1x ON t1(d, a, b->>'x', c);
}
do_execsql_test indexexpr1-2030 {
do_execsql_test indexexpr1-2040 {
SELECT a,
SUM(1) AS t1,
SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
@ -555,7 +555,7 @@ do_execsql_test indexexpr1-2030 {
SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
FROM t1;
} {1 6 4 54 46}
do_execsql_test indexexpr1-2030 {
do_execsql_test indexexpr1-2050 {
explain query plan
SELECT a,
SUM(1) AS t1,
@ -563,7 +563,7 @@ do_execsql_test indexexpr1-2030 {
SUM(c) AS t3,
SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
FROM t1;
} {/.*SCAN t1 USING INDEX t1x.*/}
} {/.*SCAN t1 USING COVERING INDEX t1x.*/}
reset_db
do_execsql_test indexexpr1-2100 {

View File

@ -78,6 +78,44 @@ do_hasfunction_test 1.6 {
2 {{"y":"two"}}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(a, b, j);
CREATE INDEX i1 ON t1( a, json_extract(j, '$.x') );
}
do_eqp_test 2.1 {
SELECT json_extract(j, '$.x') FROM t1 WHERE a=?
} {
t1 USING COVERING INDEX i1
}
do_eqp_test 2.2 {
SELECT b, json_extract(j, '$.x') FROM t1 WHERE a=?
} {
t1 USING INDEX i1
}
do_eqp_test 2.3 {
SELECT json_insert( '{}', json_extract(j, '$.x') ) FROM t1 WHERE a=?
} {
t1 USING INDEX i1
}
do_eqp_test 2.4 {
SELECT sum( json_extract(j, '$.x') ) FROM t1 WHERE a=?
} {
t1 USING COVERING INDEX i1
}
do_eqp_test 2.5 {
SELECT json_extract(j, '$.x'), sum( json_extract(j, '$.x') ) FROM t1 WHERE a=?
} {
t1 USING INDEX i1
}
finish_test

View File

@ -91,6 +91,7 @@ Usage:
$a0 njob ?NJOB?
$a0 script ?-msvc? CONFIG
$a0 status ?-d SECS? ?--cls?
$a0 halt
where SWITCHES are:
--buildonly Build test exes but do not run tests
@ -245,6 +246,15 @@ switch -nocase -glob -- $tcl_platform(os) {
set TRG(run) run.sh
set TRG(runcmd) "bash run.sh"
}
*openbsd* {
set TRG(platform) linux
set TRG(make) make.sh
set TRG(makecmd) "sh make.sh"
set TRG(testfixture) testfixture
set TRG(shell) sqlite3
set TRG(run) run.sh
set TRG(runcmd) "sh run.sh"
}
*win* {
set TRG(platform) win
set TRG(make) make.bat
@ -315,7 +325,9 @@ set TRG(schema) {
/* Fields updated as jobs run */
starttime INTEGER, -- Start time (milliseconds since 1970)
endtime INTEGER, -- End time
state TEXT CHECK( state IN ('','ready','running','done','failed','omit') ),
span INTEGER, -- Total run-time in milliseconds
estwork INTEGER, -- Estimated amount of work
state TEXT CHECK( state IN ('','ready','running','done','failed','omit','halt') ),
ntest INT, -- Number of test cases run
nerr INT, -- Number of errors reported
svers TEXT, -- Reported SQLite version
@ -333,6 +345,13 @@ set TRG(schema) {
}
#-------------------------------------------------------------------------
# Estimated amount of work required by displaytype, relative to 'tcl'
#
set estwork(tcl) 1
set estwork(fuzz) 11
set estwork(bld) 56
set estwork(make) 97
#--------------------------------------------------------------------------
# Check if this script is being invoked to run a single file. If so,
# run it.
@ -406,6 +425,19 @@ if {([llength $argv]==2 || [llength $argv]==1)
}
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# Check if this is the "halt" command:
#
if {[llength $argv]==1
&& [string compare -nocase halt [lindex $argv 0]]==0
} {
sqlite3 mydb $TRG(dbname)
mydb eval {UPDATE jobs SET state='halt' WHERE state IN ('ready','')}
mydb close
exit
}
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# Check if this is the "help" command:
#
@ -486,19 +518,21 @@ proc show_status {db cls} {
}]
set total 0
foreach s {"" ready running done failed} { set S($s) 0 }
foreach s {"" ready running done failed omit} { set S($s) 0; set W($s) 0; }
set workpending 0
$db eval {
SELECT state, count(*) AS cnt FROM jobs GROUP BY 1
SELECT state, count(*) AS cnt, sum(estwork) AS ew FROM jobs GROUP BY 1
} {
incr S($state) $cnt
incr total $cnt
incr W($state) $ew
incr totalw $ew
}
set nt 0
set ne 0
$db eval {
SELECT sum(ntest) AS nt, sum(nerr) AS ne FROM jobs HAVING nt>0
} break
set fin [expr $S(done)+$S(failed)]
set fin [expr $W(done)+$W(failed)+$W(omit)]
if {$cmdline!=""} {set cmdline " $cmdline"}
if {$cls} {
@ -513,15 +547,12 @@ proc show_status {db cls} {
set srcdir [file dirname [file dirname $TRG(info_script)]]
set line "Running: $S(running) (max: $nJob)"
if {$S(running)>0 && $fin>100 && $fin>0.05*$total} {
# Only estimate the time remaining after completing at least 100
# jobs amounting to 10% of the total. Never estimate less than
# 2% of the total time used so far.
set tmleft [expr {($tm/$fin)*($total-$fin)}]
if {$S(running)>0 && $fin>10} {
set tmleft [expr {($tm/$fin)*($totalw-$fin)}]
if {$tmleft<0.02*$tm} {
set tmleft [expr {$tm*0.02}]
}
append line " est time left [elapsetime $tmleft]"
append line " ETC [elapsetime $tmleft]"
}
puts [format %-79.79s $line]
if {$S(running)>0} {
@ -905,6 +936,7 @@ proc r_get_next_job {iJob} {
# Returns the jobid value for the new job.
#
proc add_job {args} {
global estwork
set options {
-displaytype -displayname -build -dirname
@ -929,25 +961,29 @@ proc add_job {args} {
set state ""
if {$A(-depid)==""} { set state ready }
set type $A(-displaytype)
set ew $estwork($type)
trdb eval {
INSERT INTO jobs(
displaytype, displayname, build, dirname, cmd, depid, priority,
displaytype, displayname, build, dirname, cmd, depid, priority, estwork,
state
) VALUES (
$A(-displaytype),
$type,
$A(-displayname),
$A(-build),
$A(-dirname),
$A(-cmd),
$A(-depid),
$A(-priority),
$ew,
$state
)
}
trdb last_insert_rowid
}
# Argument $build is either an empty string, or else a list of length 3
# describing the job to build testfixture. In the usual form:
@ -1274,8 +1310,8 @@ proc make_new_testset {} {
trdb eval { REPLACE INTO config VALUES('start', $tm ); }
add_jobs_from_cmdline $TRG(patternlist)
}
}
}
proc mark_job_as_finished {jobid output state endtm} {
@ -1300,10 +1336,12 @@ proc mark_job_as_finished {jobid output state endtm} {
if {[info exists pltfm]} {set pltfm [string trim $pltfm]}
trdb eval {
UPDATE jobs
SET output=$output, state=$state, endtime=$endtm,
SET output=$output, state=$state, endtime=$endtm, span=$endtm-starttime,
ntest=$ntest, nerr=$nerr, svers=$svers, pltfm=$pltfm
WHERE jobid=$jobid;
UPDATE jobs SET state=$childstate WHERE depid=$jobid;
UPDATE jobs SET state=$childstate WHERE depid=$jobid AND state!='halt';
UPDATE config SET value=value+$nerr WHERE name='nfail';
UPDATE config SET value=value+$ntest WHERE name='ntest';
}
}
}
@ -1451,17 +1489,23 @@ proc progress_report {} {
show_status trdb 1
}
} else {
set tm [expr [clock_milliseconds] - $TRG(starttime)]
set tm [format "%d" [expr int($tm/1000.0 + 0.5)]]
set tmms [expr [clock_milliseconds] - $TRG(starttime)]
set tm [format "%d" [expr int($tmms/1000.0 + 0.5)]]
set wtotal 0
set wdone 0
r_write_db {
trdb eval {
SELECT displaytype, state, count(*) AS cnt
SELECT displaytype, state, count(*) AS cnt, sum(estwork) AS ew
FROM jobs
GROUP BY 1, 2
} {
set v($state,$displaytype) $cnt
incr t($displaytype) $cnt
incr wtotal $ew
if {$state=="done" || $state=="failed" || $state=="omit"} {
incr wdone $ew
}
}
}
@ -1477,11 +1521,15 @@ proc progress_report {} {
lappend text "r$v(running,$j)"
}
}
if {$wdone>0} {
set tmleft [expr {($tmms/$wdone)*($wtotal-$wdone)}]
append text " ETC [elapsetime $tmleft]"
}
if {[info exists TRG(reportlength)]} {
puts -nonewline "[string repeat " " $TRG(reportlength)]\r"
}
set report "${tm} [join $text { }]"
set report "[elapsetime $tmms] [join $text { }]"
set TRG(reportlength) [string length $report]
if {[string length $report]<100} {
puts -nonewline "$report\r"

View File

@ -93,6 +93,7 @@ struct SQLiteRsync {
****************************************************************************/
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#include <fcntl.h>
/*
** Print a fatal error and quit.
@ -240,9 +241,9 @@ static int popen2(
hStdinRd, hStdoutWr, hStderr,&childPid);
*pChildPid = childPid;
fd = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0);
*ppIn = fdopen(fd, "r");
*ppIn = fdopen(fd, "rb");
fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0);
*ppOut = _fdopen(fd, "w");
*ppOut = _fdopen(fd, "wb");
CloseHandle(hStdinRd);
CloseHandle(hStdoutWr);
return 0;
@ -1756,6 +1757,10 @@ int main(int argc, char const * const *argv){
ctx.pIn = stdin;
ctx.pOut = stdout;
ctx.isRemote = 1;
#ifdef _WIN32
_setmode(_fileno(ctx.pIn), _O_BINARY);
_setmode(_fileno(ctx.pOut), _O_BINARY);
#endif
originSide(&ctx);
return 0;
}
@ -1763,6 +1768,10 @@ int main(int argc, char const * const *argv){
ctx.pIn = stdin;
ctx.pOut = stdout;
ctx.isRemote = 1;
#ifdef _WIN32
_setmode(_fileno(ctx.pIn), _O_BINARY);
_setmode(_fileno(ctx.pOut), _O_BINARY);
#endif
replicaSide(&ctx);
return 0;
}