Merge the latest fixes and enhancements from trunk into the
coroutines-exp2 branch. FossilOrigin-Name: 1c5f41986f5af181bf389675361c9f176e9195e847319f07ebd5c87992ded38b
This commit is contained in:
+2
-1
@@ -91,7 +91,8 @@ static const ubyte b64DigitValues[128] = {
|
||||
static const char b64Numerals[64+1]
|
||||
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
#define BX_DV_PROTO(c) ((((ubyte)(c))<0x80)? b64DigitValues[c] : 0x80)
|
||||
#define BX_DV_PROTO(c) \
|
||||
((((ubyte)(c))<0x80)? (ubyte)(b64DigitValues[(ubyte)(c)]) : 0x80)
|
||||
#define IS_BX_DIGIT(bdp) (((ubyte)(bdp))<0x80)
|
||||
#define IS_BX_WS(bdp) ((bdp)==WS)
|
||||
#define IS_BX_PAD(bdp) ((bdp)==PC)
|
||||
|
||||
@@ -69,7 +69,6 @@ int sqlite3_basexx_init(sqlite3 *db, char **pzErr,
|
||||
init_api_ptr(pApi);
|
||||
int rc1 = BASE64_INIT(db);
|
||||
int rc2 = BASE85_INIT(db);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( rc1==SQLITE_OK && rc2==SQLITE_OK ){
|
||||
BASE64_EXPOSE(db, pzErr);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Simplified\sexperimental\schanges\sto\spromote\sthe\suse\sof\sco-routines.\s\sLess\ncruft\sthan\sthe\scoroutines-exp1\sbranch,\sbut\sstill\sdoes\snot\swork.\s\sChecked\sin\nas\sa\swork-in-progress.
|
||||
D 2022-12-06T15:24:05.905
|
||||
C Merge\sthe\slatest\sfixes\sand\senhancements\sfrom\strunk\sinto\sthe\ncoroutines-exp2\sbranch.
|
||||
D 2022-12-07T21:19:37.022
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -289,9 +289,9 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23
|
||||
F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c fb140039d4e15710298e28cafe12d2bdff1b927fc57540cbcd07996f82bf9800 x
|
||||
F ext/misc/base64.c 1ad313d38dc081abe5a87fa51e44f07ec6cfb618aa9606a77e42bd2fe706a67f x
|
||||
F ext/misc/base85.c ace591246855806a70e63eb6705ce8736f4b782da2137bdbb5d39cc337346e0d
|
||||
F ext/misc/basexx.c b37ea21f00deea1029d2ddc670f5701d9370ae06f7d173c5bed79d0f26a67ec1
|
||||
F ext/misc/basexx.c 58f72b3c159e875bfd2d30a56254e7f2098961c31dc733773a9270de7066aa4c
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
|
||||
F ext/misc/carray.c b752f46411e4e47e34dce6f0c88bc8e51bb821ba9e49bfcd882506451c928f69
|
||||
@@ -615,7 +615,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c 5a3dbd8ac8a6501152a4fc1fcae9b0900c2d7eb0589c4ec7456fdde15725a26c
|
||||
F src/memdb.c fa280078fb48c4bb7ef47e361cd958938a1a3c46a9a45f6622da6efcb57cc055
|
||||
F src/memdb.c 3c1f3a3daa670294bad0056e66c17f5fe75cfa1da1850056a5a94347ec32e6bd
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
|
||||
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
|
||||
@@ -646,7 +646,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c cbb0ce95039273f436cdad9308251ab3affd69482fd9927495e1c37875afeeb1
|
||||
F src/shell.c.in f37273af2d5cd2299091b3c1e260254ebd7cd16d7602426983b36009290e8577
|
||||
F src/shell.c.in bcf8552c82f2c84650e39a6d638373569c2035942c0497b83eef197169e0305a
|
||||
F src/sqlite.h.in 1fe1836879ecbb2e28f00f44eb6092db09a2a06bf072af351c6c2466bd515496
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f
|
||||
@@ -672,7 +672,7 @@ F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 8264637b06a3c1f0727c88d1ea32dcf7986b9e7e358a970cae87cdac8a5b2708
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 7cc7623d1025d1e92c51da20fd25060759733b7a356a121545a3b7d2faa8a0f1
|
||||
F src/test_demovfs.c 38a459d1c78fd9afa770445b224c485e079018d6ac07332ff9bd07b54d2b8ce9
|
||||
F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
|
||||
F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480
|
||||
F src/test_func.c 24df3a346c012b1fc9e1001d346db6054deb426db0a7437e92490630e71c9b0a
|
||||
@@ -717,11 +717,11 @@ F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c 313f3154e2b85a447326f5dd15de8d31a4df6ab0c3579bd58f426ff634ec9050
|
||||
F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
|
||||
F src/vdbe.c e744259050ec9bbcd47acf9a03a66fe3305d7429c823995de11ed524ca06d16f
|
||||
F src/vdbe.h c93d4bc242fc9109558aa6b3ce8acef7effe100a42c148dc63239c488ad6c060
|
||||
F src/vdbeInt.h e83be1eea422758d42302941e96e59d93193c373da655a87befdc03a851e0f95
|
||||
F src/vdbeapi.c 959cef4c1e5cb6589e67b3295fe9d3e45cbd109ae6618d57b74c900dbd6be0cd
|
||||
F src/vdbeaux.c 0b81f317c86ed9f4ba822af66a52777fed6e8180edc79d4fc62ffe75c8e52d80
|
||||
F src/vdbe.c df9ff3fcaa3c60fa9b0bca340c3f3cfc63a51361901ca06fe18bdeadeb2a1a24
|
||||
F src/vdbe.h 934387e28f0a6b1a6a60904ddfe4ab61099e8767daf3cf59e6bbc3981d7ce426
|
||||
F src/vdbeInt.h 8651e4c4e04d1860d0bdcf330cb8294e3778a9d4222be30ce4c490d9220af783
|
||||
F src/vdbeapi.c df3f73a4d0a487f2068e3c84776cd6e3fba5ae80ff612659dcfda4307686420b
|
||||
F src/vdbeaux.c 25691b395bf57ae0a754570fc3ba2d6f8bd2f0a8944f1d2589b9e68114e01c2b
|
||||
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
|
||||
F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a
|
||||
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
|
||||
@@ -732,9 +732,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c 20f4f51d2d5fb19b984e6ea381b26cf627cc93e64dd9b2ce6a94531aec2f5916
|
||||
F src/where.c 3ee4050e453dfd03da4a8e4b5561d20b20b2302ec9d02437fb62c6f29bb78401
|
||||
F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c
|
||||
F src/wherecode.c d3146e215f3a716c0e153ded68bfcc747aad550e114a79729bda887cf4ea6f00
|
||||
F src/wherecode.c 76bca3379219880d2527493b71a3be49e696f75396d3481e4de5d4ceec7886b2
|
||||
F src/whereexpr.c 05295b44b54eea76d1ba766f0908928d0e20e990c249344c9521454d3d09c7ae
|
||||
F src/window.c 14836767adb26573b50f528eb37f8b1336f2c430ab38de7cead1e5c546bb4d8c
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
@@ -1458,7 +1458,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
|
||||
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
|
||||
F test/scanstatus.test 7dbcfd6adc6a8df6abc59f83d6da5a27e1bce0b2f6fa55147c8176d7c44e0450
|
||||
F test/scanstatus2.test cc0be2f645c32ede50affa7d4ecfaffd2b4572a4fd7f723082397c65a910a2b5
|
||||
F test/scanstatus2.test 07e2d1b86a07cd8f6cbef9546c9d6b27af0de5e613b6f38f98666f9c729bd4c7
|
||||
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
|
||||
@@ -1886,7 +1886,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a
|
||||
F test/walvfs.test e1a6ad0f3c78e98b55c3d5f0889cf366cc0d0a1cb2bccb44ac9ec67384adc4a1
|
||||
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
|
||||
F test/wapptest.tcl 1bea58a6a8e68a73f542ee4fca28b771b84ed803bd0c9e385087070b3d747b3c x
|
||||
F test/where.test 98208c95b574269980132c347b4bdb8992c6d5fc30c1954938593336d12e7447
|
||||
F test/where.test 3954cf22ba7b17f9606e177001d2963bcd1ecfbc6e1e7caadb14462f7eecd099
|
||||
F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
|
||||
F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
@@ -1996,7 +1996,7 @@ F tool/mkctimec.tcl c185cf1bdcd3d9bd3c06f77a2fd2df8a4a0d07266f992ecda75286965ba3
|
||||
F tool/mkkeywordhash.c 35bfc41adacc4aa6ef6fca7fd0c63e0ec0534b78daf4d0cfdebe398216bbffc3
|
||||
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
F tool/mkopcodeh.tcl bcb2bd5affb545fd219ef0304c7978e2a356407ab723f45ec8569235892c1c3f
|
||||
F tool/mkopcodeh.tcl 769d9e6a8b462323150dc13a8539d6064664b72974f7894befe2491cc73e05cd
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl bd07bd59d45d0f3448e123d6937e9811195f9908a51e09d774609883055bfd3d
|
||||
F tool/mkshellc.tcl 02d0de8349ef830c0fb20d29680320bde2466e2ec422e5bd94c4317a7a7e8cc9
|
||||
@@ -2067,11 +2067,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 0d80500d358fa1c9b5867c2c8250d278ba813bf2ad81bb0bc3f820a71489b374
|
||||
R da3604bd27058bf7971e3104c707bf9f
|
||||
T *branch * coroutines-exp2
|
||||
T *sym-coroutines-exp2 *
|
||||
T -sym-trunk *
|
||||
P e2318a30bf6ad2aeb4c4cb29661bc24ff78eb51bf07decc4b8da1ecac0015ef0 212927e97e7be7d237de08359dce0dfb9211ac406b32009a6e15afd79c006475
|
||||
R 595e9e236a565d9694fd65430bde0de2
|
||||
U drh
|
||||
Z 83efea07fbf822c79733971b25cfb62c
|
||||
Z 74db0241280ec72e600d83e58941c231
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
e2318a30bf6ad2aeb4c4cb29661bc24ff78eb51bf07decc4b8da1ecac0015ef0
|
||||
1c5f41986f5af181bf389675361c9f176e9195e847319f07ebd5c87992ded38b
|
||||
+20
-8
@@ -370,21 +370,33 @@ static int memdbLock(sqlite3_file *pFile, int eLock){
|
||||
int rc = SQLITE_OK;
|
||||
if( eLock==pThis->eLock ) return SQLITE_OK;
|
||||
memdbEnter(p);
|
||||
assert( p->nWrLock==0 || p->nWrLock==1 ); /* No more than 1 write lock */
|
||||
if( eLock>SQLITE_LOCK_SHARED ){
|
||||
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
|
||||
if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
|
||||
rc = SQLITE_READONLY;
|
||||
}else if( eLock==SQLITE_LOCK_EXCLUSIVE ){
|
||||
/* Taking an EXCLUSIVE lock. Fail if we only have SHARED and any
|
||||
** other client has any kind of write-lock. Also fail if any other
|
||||
** client is holding read-lock. */
|
||||
if( pThis->eLock<=SQLITE_LOCK_SHARED && p->nWrLock ){
|
||||
rc = SQLITE_BUSY;
|
||||
}else if( p->nRdLock>1 ){
|
||||
/* We never go for an EXCLUSIVE lock unless we already hold SHARED or
|
||||
** higher */
|
||||
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
|
||||
testcase( pThis->eLock==SQLITE_LOCK_SHARED );
|
||||
|
||||
/* Because we are holding SHARED or more, there must be at least
|
||||
** one read lock */
|
||||
assert( p->nRdLock>0 );
|
||||
|
||||
/* The only way that there can be an existing write lock is if we
|
||||
** currently hold it. Otherwise, we would have never been able to
|
||||
** promote from NONE to SHARED. */
|
||||
assert( p->nWrLock==0 || pThis->eLock>SQLITE_LOCK_SHARED );
|
||||
|
||||
if( p->nRdLock>1 ){
|
||||
/* Cannot take EXCLUSIVE if somebody else is holding SHARED */
|
||||
rc = SQLITE_BUSY;
|
||||
}else{
|
||||
p->nWrLock = 1;
|
||||
}
|
||||
p->nWrLock = 1;
|
||||
}else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
|
||||
}else if( ALWAYS(pThis->eLock<=SQLITE_LOCK_SHARED) ){
|
||||
/* Upgrading to RESERVED or PENDING from SHARED. Fail if any other
|
||||
** client has a write-lock of any kind. */
|
||||
if( p->nWrLock ){
|
||||
|
||||
+73
-19
@@ -482,24 +482,26 @@ static char continuePrompt[PROMPT_LEN_MAX];
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_DYNAPROMPT
|
||||
# define CONTINUATION_PROMPT continuePrompt
|
||||
# define CONTINUE_PROMPT_RESET(p)
|
||||
# define CONTINUE_PROMPT_RESET
|
||||
# define CONTINUE_PROMPT_AWAITS(p,s)
|
||||
# define CONTINUE_PROMPT_AWAITC(p,c)
|
||||
# define CONTINUE_PAREN_INCR(p,n)
|
||||
# define CONTINUE_PROMPT_STATE 0
|
||||
# define SCAN_TRACKER_REFTYPE void*
|
||||
# define CONTINUE_PROMPT_PSTATE 0
|
||||
typedef void *t_NoDynaPrompt;
|
||||
# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt
|
||||
#else
|
||||
# define CONTINUATION_PROMPT dynamicContinuePrompt()
|
||||
# define CONTINUE_PROMPT_RESET(p) \
|
||||
if(p) (setLexemeOpen(p,0,0), trackParenLevel(p,0))
|
||||
# define CONTINUE_PROMPT_RESET \
|
||||
do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0)
|
||||
# define CONTINUE_PROMPT_AWAITS(p,s) \
|
||||
if(p && stdin_is_interactive) setLexemeOpen(p, s, 0)
|
||||
# define CONTINUE_PROMPT_AWAITC(p,c) \
|
||||
if(p && stdin_is_interactive) setLexemeOpen(p, 0, c)
|
||||
# define CONTINUE_PAREN_INCR(p,n) \
|
||||
if(p && stdin_is_interactive) (trackParenLevel(p,n))
|
||||
# define SCAN_TRACKER_REFTYPE struct DynaPrompt *
|
||||
# define CONTINUE_PROMPT_STATE (pDynPrompt)
|
||||
# define CONTINUE_PROMPT_PSTATE (&dynPrompt)
|
||||
typedef struct DynaPrompt *t_DynaPromptRef;
|
||||
# define SCAN_TRACKER_REFTYPE t_DynaPromptRef
|
||||
|
||||
static struct DynaPrompt {
|
||||
char dynamicPrompt[PROMPT_LEN_MAX];
|
||||
@@ -507,7 +509,6 @@ static struct DynaPrompt {
|
||||
int inParenLevel;
|
||||
char *zScannerAwaits;
|
||||
} dynPrompt = { {0}, {0}, 0, 0 };
|
||||
static struct DynaPrompt *pDynPrompt = &dynPrompt;
|
||||
|
||||
/* Record parenthesis nesting level change, or force level to 0. */
|
||||
static void trackParenLevel(struct DynaPrompt *p, int ni){
|
||||
@@ -536,17 +537,17 @@ static char *dynamicContinuePrompt(void){
|
||||
if( dynPrompt.zScannerAwaits ){
|
||||
int ncp = strlen(continuePrompt), ndp = strlen(dynPrompt.zScannerAwaits);
|
||||
if( ndp > ncp-3 ) return continuePrompt;
|
||||
strncpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits, ndp);
|
||||
strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
|
||||
while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
|
||||
strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
|
||||
PROMPT_LEN_MAX-4);
|
||||
}else{
|
||||
if( dynPrompt.inParenLevel>9 ){
|
||||
strncpy(dynPrompt.dynamicPrompt, "(..", 3);
|
||||
strncpy(dynPrompt.dynamicPrompt, "(..", 4);
|
||||
}else if( dynPrompt.inParenLevel<0 ){
|
||||
strncpy(dynPrompt.dynamicPrompt, ")x!", 3);
|
||||
strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
|
||||
}else{
|
||||
strncpy(dynPrompt.dynamicPrompt, "(x.", 3);
|
||||
strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
|
||||
dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
|
||||
}
|
||||
strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4);
|
||||
@@ -10261,12 +10262,12 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}
|
||||
if( bSchema ){
|
||||
zSql = "SELECT lower(name) FROM sqlite_schema"
|
||||
zSql = "SELECT lower(name) as tname FROM sqlite_schema"
|
||||
" WHERE type='table' AND coalesce(rootpage,0)>1"
|
||||
" UNION ALL SELECT 'sqlite_schema'"
|
||||
" ORDER BY 1 collate nocase";
|
||||
}else{
|
||||
zSql = "SELECT lower(name) FROM sqlite_schema"
|
||||
zSql = "SELECT lower(name) as tname FROM sqlite_schema"
|
||||
" WHERE type='table' AND coalesce(rootpage,0)>1"
|
||||
" AND name NOT LIKE 'sqlite_%'"
|
||||
" ORDER BY 1 collate nocase";
|
||||
@@ -10327,6 +10328,58 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else{
|
||||
shell_exec(p, zSql, 0);
|
||||
}
|
||||
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
{
|
||||
int lrc;
|
||||
char *zRevText = /* Query for reversible to-blob-to-text check */
|
||||
"SELECT lower(name) as tname FROM sqlite_schema\n"
|
||||
"WHERE type='table' AND coalesce(rootpage,0)>1\n"
|
||||
"AND name NOT LIKE 'sqlite_%%'%s\n"
|
||||
"ORDER BY 1 collate nocase";
|
||||
zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : "");
|
||||
zRevText = sqlite3_mprintf(
|
||||
/* lower-case query is first run, producing upper-case query. */
|
||||
"with tabcols as materialized(\n"
|
||||
"select tname, cname\n"
|
||||
"from ("
|
||||
" select ss.tname as tname, ti.name as cname\n"
|
||||
" from (%z) ss\n inner join pragma_table_info(tname) ti))\n"
|
||||
"select 'SELECT total(bad_text_count) AS bad_text_count\n"
|
||||
"FROM ('||group_concat(query, ' UNION ALL ')||')' as btc_query\n"
|
||||
" from (select 'SELECT COUNT(*) AS bad_text_count\n"
|
||||
"FROM '||tname||' WHERE '\n"
|
||||
"||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n"
|
||||
"|| ' AND typeof('||cname||')=''text'' ',\n"
|
||||
"' OR ') as query, tname from tabcols group by tname)"
|
||||
, zRevText);
|
||||
shell_check_oom(zRevText);
|
||||
if( bDebug ) utf8_printf(p->out, "%s\n", zRevText);
|
||||
lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
|
||||
assert(lrc==SQLITE_OK);
|
||||
if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC);
|
||||
lrc = SQLITE_ROW==sqlite3_step(pStmt);
|
||||
if( lrc ){
|
||||
const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
|
||||
sqlite3_stmt *pCheckStmt;
|
||||
lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
|
||||
if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery);
|
||||
if( SQLITE_OK==lrc ){
|
||||
if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){
|
||||
double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
|
||||
if( countIrreversible>0 ){
|
||||
int n = (int)(countIrreversible + 0.5);
|
||||
utf8_printf(stderr,
|
||||
"Digest includes %d invalidly encoded text field%s.\n",
|
||||
n, (n>1)? "s": "");
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pCheckStmt);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
sqlite3_free(zRevText);
|
||||
}
|
||||
#endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */
|
||||
sqlite3_free(zSql);
|
||||
}else
|
||||
|
||||
@@ -11118,6 +11171,7 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
||||
goto PlainScan;
|
||||
case '`': case '\'': case '"':
|
||||
if(*zLine==cWait){
|
||||
/* Swallow doubled end-delimiter.*/
|
||||
++zLine;
|
||||
continue;
|
||||
}
|
||||
@@ -11288,7 +11342,7 @@ static int process_input(ShellState *p){
|
||||
}
|
||||
++p->inputNesting;
|
||||
p->lineno = 0;
|
||||
CONTINUE_PROMPT_RESET(CONTINUE_PROMPT_STATE);
|
||||
CONTINUE_PROMPT_RESET;
|
||||
while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
|
||||
fflush(p->out);
|
||||
zLine = one_input_line(p->in, zLine, nSql>0);
|
||||
@@ -11307,7 +11361,7 @@ static int process_input(ShellState *p){
|
||||
&& line_is_complete(zSql, nSql) ){
|
||||
memcpy(zLine,";",2);
|
||||
}
|
||||
qss = quickscan(zLine, qss, CONTINUE_PROMPT_STATE);
|
||||
qss = quickscan(zLine, qss, CONTINUE_PROMPT_PSTATE);
|
||||
if( QSS_PLAINWHITE(qss) && nSql==0 ){
|
||||
/* Just swallow single-line whitespace */
|
||||
echo_group_input(p, zLine);
|
||||
@@ -11315,7 +11369,7 @@ static int process_input(ShellState *p){
|
||||
continue;
|
||||
}
|
||||
if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
|
||||
CONTINUE_PROMPT_RESET(CONTINUE_PROMPT_STATE);
|
||||
CONTINUE_PROMPT_RESET;
|
||||
echo_group_input(p, zLine);
|
||||
if( zLine[0]=='.' ){
|
||||
rc = do_meta_command(zLine, p);
|
||||
@@ -11351,7 +11405,7 @@ static int process_input(ShellState *p){
|
||||
if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
|
||||
echo_group_input(p, zSql);
|
||||
errCnt += runOneSqlLine(p, zSql, p->in, startline);
|
||||
CONTINUE_PROMPT_RESET(CONTINUE_PROMPT_STATE);
|
||||
CONTINUE_PROMPT_RESET;
|
||||
nSql = 0;
|
||||
if( p->outCount ){
|
||||
output_reset(p);
|
||||
@@ -11371,7 +11425,7 @@ static int process_input(ShellState *p){
|
||||
/* This may be incomplete. Let the SQL parser deal with that. */
|
||||
echo_group_input(p, zSql);
|
||||
errCnt += runOneSqlLine(p, zSql, p->in, startline);
|
||||
CONTINUE_PROMPT_RESET(CONTINUE_PROMPT_STATE);
|
||||
CONTINUE_PROMPT_RESET;
|
||||
}
|
||||
free(zSql);
|
||||
free(zLine);
|
||||
|
||||
@@ -461,7 +461,6 @@ static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
|
||||
if( rc==0 && dirSync ){
|
||||
int dfd; /* File descriptor open on directory */
|
||||
int i; /* Iterator variable */
|
||||
char *zSlash;
|
||||
char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */
|
||||
|
||||
|
||||
+50
-68
@@ -790,15 +790,12 @@ int sqlite3VdbeExec(
|
||||
assert( pOp>=aOp && pOp<&aOp[p->nOp]);
|
||||
nVmStep++;
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
if( p->anExec ){
|
||||
assert( p->anExec && p->anCycle );
|
||||
p->anExec[(int)(pOp-aOp)]++;
|
||||
pnCycle = &p->anCycle[pOp-aOp];
|
||||
pOp->nExec++;
|
||||
pnCycle = &pOp->nCycle;
|
||||
# ifdef VDBE_PROFILE
|
||||
if( sqlite3NProfileCnt==0 )
|
||||
if( sqlite3NProfileCnt==0 )
|
||||
# endif
|
||||
*pnCycle -= sqlite3Hwtime();
|
||||
}
|
||||
*pnCycle -= sqlite3Hwtime();
|
||||
#endif
|
||||
|
||||
/* Only allow tracing if SQLITE_DEBUG is defined.
|
||||
@@ -2780,7 +2777,7 @@ case OP_Offset: { /* out3 */
|
||||
** typeof() function or the IS NULL or IS NOT NULL operators or the
|
||||
** equivalent. In this case, all content loading can be omitted.
|
||||
*/
|
||||
case OP_Column: {
|
||||
case OP_Column: { /* ncycle */
|
||||
u32 p2; /* column number to retrieve */
|
||||
VdbeCursor *pC; /* The VDBE cursor */
|
||||
BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */
|
||||
@@ -4132,7 +4129,7 @@ case OP_SetCookie: {
|
||||
**
|
||||
** See also: OP_OpenRead, OP_ReopenIdx
|
||||
*/
|
||||
case OP_ReopenIdx: {
|
||||
case OP_ReopenIdx: { /* ncycle */
|
||||
int nField;
|
||||
KeyInfo *pKeyInfo;
|
||||
u32 p2;
|
||||
@@ -4153,7 +4150,7 @@ case OP_ReopenIdx: {
|
||||
}
|
||||
/* If the cursor is not currently open or is open on a different
|
||||
** index, then fall through into OP_OpenRead to force a reopen */
|
||||
case OP_OpenRead:
|
||||
case OP_OpenRead: /* ncycle */
|
||||
case OP_OpenWrite:
|
||||
|
||||
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
|
||||
@@ -4247,7 +4244,7 @@ open_cursor_set_hints:
|
||||
**
|
||||
** Duplicate ephemeral cursors are used for self-joins of materialized views.
|
||||
*/
|
||||
case OP_OpenDup: {
|
||||
case OP_OpenDup: { /* ncycle */
|
||||
VdbeCursor *pOrig; /* The original cursor to be duplicated */
|
||||
VdbeCursor *pCx; /* The new cursor */
|
||||
|
||||
@@ -4309,8 +4306,8 @@ case OP_OpenDup: {
|
||||
** by this opcode will be used for automatically created transient
|
||||
** indices in joins.
|
||||
*/
|
||||
case OP_OpenAutoindex:
|
||||
case OP_OpenEphemeral: {
|
||||
case OP_OpenAutoindex: /* ncycle */
|
||||
case OP_OpenEphemeral: { /* ncycle */
|
||||
VdbeCursor *pCx;
|
||||
KeyInfo *pKeyInfo;
|
||||
|
||||
@@ -4468,7 +4465,7 @@ case OP_OpenPseudo: {
|
||||
** Close a cursor previously opened as P1. If P1 is not
|
||||
** currently open, this instruction is a no-op.
|
||||
*/
|
||||
case OP_Close: {
|
||||
case OP_Close: { /* ncycle */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
|
||||
p->apCsr[pOp->p1] = 0;
|
||||
@@ -4585,10 +4582,10 @@ case OP_ColumnsUsed: {
|
||||
**
|
||||
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
|
||||
*/
|
||||
case OP_SeekLT: /* jump, in3, group */
|
||||
case OP_SeekLE: /* jump, in3, group */
|
||||
case OP_SeekGE: /* jump, in3, group */
|
||||
case OP_SeekGT: { /* jump, in3, group */
|
||||
case OP_SeekLT: /* jump, in3, group, ncycle */
|
||||
case OP_SeekLE: /* jump, in3, group, ncycle */
|
||||
case OP_SeekGE: /* jump, in3, group, ncycle */
|
||||
case OP_SeekGT: { /* jump, in3, group, ncycle */
|
||||
int res; /* Comparison result */
|
||||
int oc; /* Opcode */
|
||||
VdbeCursor *pC; /* The cursor to seek */
|
||||
@@ -4854,7 +4851,7 @@ seek_not_found:
|
||||
** jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0.
|
||||
** </ol>
|
||||
*/
|
||||
case OP_SeekScan: {
|
||||
case OP_SeekScan: { /* ncycle */
|
||||
VdbeCursor *pC;
|
||||
int res;
|
||||
int nStep;
|
||||
@@ -4976,7 +4973,7 @@ case OP_SeekScan: {
|
||||
**
|
||||
** P1 must be a valid b-tree cursor.
|
||||
*/
|
||||
case OP_SeekHit: {
|
||||
case OP_SeekHit: { /* ncycle */
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
@@ -5108,7 +5105,7 @@ case OP_IfNotOpen: { /* jump */
|
||||
**
|
||||
** See also: NotFound, Found, NotExists
|
||||
*/
|
||||
case OP_IfNoHope: { /* jump, in3 */
|
||||
case OP_IfNoHope: { /* jump, in3, ncycle */
|
||||
VdbeCursor *pC;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
@@ -5122,9 +5119,9 @@ case OP_IfNoHope: { /* jump, in3 */
|
||||
/* Fall through into OP_NotFound */
|
||||
/* no break */ deliberate_fall_through
|
||||
}
|
||||
case OP_NoConflict: /* jump, in3 */
|
||||
case OP_NotFound: /* jump, in3 */
|
||||
case OP_Found: { /* jump, in3 */
|
||||
case OP_NoConflict: /* jump, in3, ncycle */
|
||||
case OP_NotFound: /* jump, in3, ncycle */
|
||||
case OP_Found: { /* jump, in3, ncycle */
|
||||
int alreadyExists;
|
||||
int ii;
|
||||
VdbeCursor *pC;
|
||||
@@ -5254,7 +5251,7 @@ case OP_Found: { /* jump, in3 */
|
||||
**
|
||||
** See also: Found, NotFound, NoConflict, SeekRowid
|
||||
*/
|
||||
case OP_SeekRowid: { /* jump, in3 */
|
||||
case OP_SeekRowid: { /* jump, in3, ncycle */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
@@ -5279,7 +5276,7 @@ case OP_SeekRowid: { /* jump, in3 */
|
||||
}
|
||||
/* Fall through into OP_NotExists */
|
||||
/* no break */ deliberate_fall_through
|
||||
case OP_NotExists: /* jump, in3 */
|
||||
case OP_NotExists: /* jump, in3, ncycle */
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
@@ -5903,7 +5900,7 @@ case OP_RowData: {
|
||||
** be a separate OP_VRowid opcode for use with virtual tables, but this
|
||||
** one opcode now works for both table types.
|
||||
*/
|
||||
case OP_Rowid: { /* out2 */
|
||||
case OP_Rowid: { /* out2, ncycle */
|
||||
VdbeCursor *pC;
|
||||
i64 v;
|
||||
sqlite3_vtab *pVtab;
|
||||
@@ -6002,8 +5999,8 @@ case OP_NullRow: {
|
||||
** from the end toward the beginning. In other words, the cursor is
|
||||
** configured to use Prev, not Next.
|
||||
*/
|
||||
case OP_SeekEnd:
|
||||
case OP_Last: { /* jump */
|
||||
case OP_SeekEnd: /* ncycle */
|
||||
case OP_Last: { /* jump, ncycle */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
@@ -6108,7 +6105,7 @@ case OP_Sort: { /* jump */
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
** configured to use Next, not Prev.
|
||||
*/
|
||||
case OP_Rewind: { /* jump */
|
||||
case OP_Rewind: { /* jump, ncycle */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
@@ -6202,7 +6199,7 @@ case OP_SorterNext: { /* jump */
|
||||
rc = sqlite3VdbeSorterNext(db, pC);
|
||||
goto next_tail;
|
||||
|
||||
case OP_Prev: /* jump */
|
||||
case OP_Prev: /* jump, ncycle */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p5==0
|
||||
|| pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
|
||||
@@ -6217,7 +6214,7 @@ case OP_Prev: /* jump */
|
||||
rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3);
|
||||
goto next_tail;
|
||||
|
||||
case OP_Next: /* jump */
|
||||
case OP_Next: /* jump, ncycle */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p5==0
|
||||
|| pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
|
||||
@@ -6409,8 +6406,8 @@ case OP_IdxDelete: {
|
||||
**
|
||||
** See also: Rowid, MakeRecord.
|
||||
*/
|
||||
case OP_DeferredSeek:
|
||||
case OP_IdxRowid: { /* out2 */
|
||||
case OP_DeferredSeek: /* ncycle */
|
||||
case OP_IdxRowid: { /* out2, ncycle */
|
||||
VdbeCursor *pC; /* The P1 index cursor */
|
||||
VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
|
||||
i64 rowid; /* Rowid that P1 current points to */
|
||||
@@ -6472,8 +6469,8 @@ case OP_IdxRowid: { /* out2 */
|
||||
** seek operation now, without further delay. If the cursor seek has
|
||||
** already occurred, this instruction is a no-op.
|
||||
*/
|
||||
case OP_FinishSeek: {
|
||||
VdbeCursor *pC; /* The P1 index cursor */
|
||||
case OP_FinishSeek: { /* ncycle */
|
||||
VdbeCursor *pC; /* The P1 index cursor */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
@@ -6528,10 +6525,10 @@ case OP_FinishSeek: {
|
||||
** If the P1 index entry is less than or equal to the key value then jump
|
||||
** to P2. Otherwise fall through to the next instruction.
|
||||
*/
|
||||
case OP_IdxLE: /* jump */
|
||||
case OP_IdxGT: /* jump */
|
||||
case OP_IdxLT: /* jump */
|
||||
case OP_IdxGE: { /* jump */
|
||||
case OP_IdxLE: /* jump, ncycle */
|
||||
case OP_IdxGT: /* jump, ncycle */
|
||||
case OP_IdxLT: /* jump, ncycle */
|
||||
case OP_IdxGE: { /* jump, ncycle */
|
||||
VdbeCursor *pC;
|
||||
int res;
|
||||
UnpackedRecord r;
|
||||
@@ -7152,10 +7149,6 @@ case OP_Program: { /* jump */
|
||||
pFrame->aOp = p->aOp;
|
||||
pFrame->nOp = p->nOp;
|
||||
pFrame->token = pProgram->token;
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
pFrame->anExec = p->anExec;
|
||||
pFrame->anCycle = p->anCycle;
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
|
||||
#endif
|
||||
@@ -7192,10 +7185,6 @@ case OP_Program: { /* jump */
|
||||
memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
|
||||
p->aOp = aOp = pProgram->aOp;
|
||||
p->nOp = pProgram->nOp;
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
p->anExec = 0;
|
||||
p->anCycle = 0;
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Verify that second and subsequent executions of the same trigger do not
|
||||
** try to reuse register values from the first use. */
|
||||
@@ -7952,7 +7941,7 @@ case OP_VDestroy: {
|
||||
** P1 is a cursor number. This opcode opens a cursor to the virtual
|
||||
** table and stores that cursor in P1.
|
||||
*/
|
||||
case OP_VOpen: {
|
||||
case OP_VOpen: { /* ncycle */
|
||||
VdbeCursor *pCur;
|
||||
sqlite3_vtab_cursor *pVCur;
|
||||
sqlite3_vtab *pVtab;
|
||||
@@ -7999,7 +7988,7 @@ case OP_VOpen: {
|
||||
** cursor. Register P3 is used to hold the values returned by
|
||||
** sqlite3_vtab_in_first() and sqlite3_vtab_in_next().
|
||||
*/
|
||||
case OP_VInitIn: { /* out2 */
|
||||
case OP_VInitIn: { /* out2, ncycle */
|
||||
VdbeCursor *pC; /* The cursor containing the RHS values */
|
||||
ValueList *pRhs; /* New ValueList object to put in reg[P2] */
|
||||
|
||||
@@ -8036,7 +8025,7 @@ case OP_VInitIn: { /* out2 */
|
||||
**
|
||||
** A jump is made to P2 if the result set after filtering would be empty.
|
||||
*/
|
||||
case OP_VFilter: { /* jump */
|
||||
case OP_VFilter: { /* jump, ncycle */
|
||||
int nArg;
|
||||
int iQuery;
|
||||
const sqlite3_module *pModule;
|
||||
@@ -8096,7 +8085,7 @@ case OP_VFilter: { /* jump */
|
||||
** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
|
||||
** unused by OP_VColumn.
|
||||
*/
|
||||
case OP_VColumn: {
|
||||
case OP_VColumn: { /* ncycle */
|
||||
sqlite3_vtab *pVtab;
|
||||
const sqlite3_module *pModule;
|
||||
Mem *pDest;
|
||||
@@ -8148,7 +8137,7 @@ case OP_VColumn: {
|
||||
** jump to instruction P2. Or, if the virtual table has reached
|
||||
** the end of its result set, then fall through to the next instruction.
|
||||
*/
|
||||
case OP_VNext: { /* jump */
|
||||
case OP_VNext: { /* jump, ncycle */
|
||||
sqlite3_vtab *pVtab;
|
||||
const sqlite3_module *pModule;
|
||||
int res;
|
||||
@@ -8732,17 +8721,11 @@ default: { /* This is really OP_Noop, OP_Explain */
|
||||
}
|
||||
|
||||
#if defined(VDBE_PROFILE)
|
||||
assert( pnCycle );
|
||||
if( pnCycle ){
|
||||
*pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
|
||||
assert( *pnCycle < (((u64)1) << 48) );
|
||||
pnCycle = 0;
|
||||
}
|
||||
*pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
|
||||
pnCycle = 0;
|
||||
#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
||||
if( pnCycle ){
|
||||
*pnCycle += sqlite3Hwtime();
|
||||
pnCycle = 0;
|
||||
}
|
||||
*pnCycle += sqlite3Hwtime();
|
||||
pnCycle = 0;
|
||||
#endif
|
||||
|
||||
/* The following code adds nothing to the actual functionality
|
||||
@@ -8819,11 +8802,10 @@ abort_due_to_error:
|
||||
** top. */
|
||||
vdbe_return:
|
||||
#if defined(VDBE_PROFILE)
|
||||
if( pnCycle ){
|
||||
*pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
|
||||
assert( *pnCycle < (((u64)1) << 48) );
|
||||
pnCycle = 0;
|
||||
}
|
||||
if( pnCycle ){
|
||||
*pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
|
||||
pnCycle = 0;
|
||||
}
|
||||
#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
||||
if( pnCycle ){
|
||||
*pnCycle += sqlite3Hwtime();
|
||||
|
||||
@@ -71,6 +71,10 @@ struct VdbeOp {
|
||||
u32 iSrcLine; /* Source-code line that generated this opcode
|
||||
** with flags in the upper 8 bits */
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
u64 nExec;
|
||||
u64 nCycle;
|
||||
#endif
|
||||
};
|
||||
typedef struct VdbeOp VdbeOp;
|
||||
|
||||
|
||||
@@ -171,8 +171,6 @@ struct VdbeFrame {
|
||||
Vdbe *v; /* VM this frame belongs to */
|
||||
VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
|
||||
Op *aOp; /* Program instructions for parent frame */
|
||||
i64 *anExec; /* Event counters from parent frame */
|
||||
u64 *anCycle; /* Cycle counters from parent frame */
|
||||
Mem *aMem; /* Array of memory cells for parent frame */
|
||||
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
|
||||
u8 *aOnce; /* Bitmask used by OP_Once */
|
||||
@@ -492,10 +490,6 @@ struct Vdbe {
|
||||
u32 expmask; /* Binding to these vars invalidates VM */
|
||||
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
|
||||
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
i64 *anExec; /* Number of times each op has been executed */
|
||||
u64 *anCycle; /* Sum of sqlite3HwTime() spent in each opcode */
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
int nScan; /* Entries in aScan[] */
|
||||
ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
|
||||
|
||||
+15
-13
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
#include "opcodes.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
/*
|
||||
@@ -2122,14 +2123,12 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
ScanStatus *pScan;
|
||||
int idx;
|
||||
|
||||
/* If the v2 flag is clear, then this function must ignore any ScanStatus
|
||||
** structures with ScanStatus.addrLoop set to 0. */
|
||||
if( iScan<0 ){
|
||||
int ii;
|
||||
if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){
|
||||
i64 res = 0;
|
||||
for(ii=0; ii<p->nOp; ii++){
|
||||
res += p->anCycle[ii];
|
||||
res += p->aOp[ii].nCycle;
|
||||
}
|
||||
*(i64*)pOut = res;
|
||||
return 0;
|
||||
@@ -2140,6 +2139,8 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
idx = iScan;
|
||||
pScan = &p->aScan[idx];
|
||||
}else{
|
||||
/* If the COMPLEX flag is clear, then this function must ignore any
|
||||
** ScanStatus structures with ScanStatus.addrLoop set to 0. */
|
||||
for(idx=0; idx<p->nScan; idx++){
|
||||
pScan = &p->aScan[idx];
|
||||
if( pScan->zName ){
|
||||
@@ -2153,7 +2154,7 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
switch( iScanStatusOp ){
|
||||
case SQLITE_SCANSTAT_NLOOP: {
|
||||
if( pScan->addrLoop>0 ){
|
||||
*(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
|
||||
*(sqlite3_int64*)pOut = p->aOp[pScan->addrLoop].nExec;
|
||||
}else{
|
||||
*(sqlite3_int64*)pOut = -1;
|
||||
}
|
||||
@@ -2161,7 +2162,7 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
}
|
||||
case SQLITE_SCANSTAT_NVISIT: {
|
||||
if( pScan->addrVisit>0 ){
|
||||
*(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
|
||||
*(sqlite3_int64*)pOut = p->aOp[pScan->addrVisit].nExec;
|
||||
}else{
|
||||
*(sqlite3_int64*)pOut = -1;
|
||||
}
|
||||
@@ -2217,7 +2218,7 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
if( iIns==0 ) break;
|
||||
if( iIns>0 ){
|
||||
while( iIns<=iEnd ){
|
||||
res += p->anCycle[iIns];
|
||||
res += p->aOp[iIns].nCycle;
|
||||
iIns++;
|
||||
}
|
||||
}else{
|
||||
@@ -2225,13 +2226,10 @@ int sqlite3_stmt_scanstatus_v2(
|
||||
for(iOp=0; iOp<p->nOp; iOp++){
|
||||
Op *pOp = &p->aOp[iOp];
|
||||
if( pOp->p1!=iEnd ) continue;
|
||||
if( pOp->opcode!=OP_VFilter && pOp->opcode!=OP_VColumn
|
||||
&& pOp->opcode!=OP_Rowid && pOp->opcode!=OP_VOpen
|
||||
&& pOp->opcode!=OP_VNext
|
||||
){
|
||||
if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){
|
||||
continue;
|
||||
}
|
||||
res += p->anCycle[iOp];
|
||||
res += p->aOp[iOp].nCycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2263,7 +2261,11 @@ int sqlite3_stmt_scanstatus(
|
||||
*/
|
||||
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
memset(p->anExec, 0, p->nOp * sizeof(i64));
|
||||
memset(p->anCycle, 0, p->nOp * sizeof(u64));
|
||||
int ii;
|
||||
for(ii=0; ii<p->nOp; ii++){
|
||||
Op *pOp = &p->aOp[ii];
|
||||
pOp->nExec = 0;
|
||||
pOp->nCycle = 0;
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */
|
||||
|
||||
+10
-20
@@ -262,6 +262,10 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
pOp->zComment = 0;
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
pOp->nExec = 0;
|
||||
pOp->nCycle = 0;
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
|
||||
@@ -2508,8 +2512,10 @@ void sqlite3VdbeRewind(Vdbe *p){
|
||||
p->iStatement = 0;
|
||||
p->nFkConstraint = 0;
|
||||
#ifdef VDBE_PROFILE
|
||||
memset(p->anExec, 0, sizeof(i64)*p->nOp);
|
||||
memset(p->anCycle, 0, sizeof(u64)*p->nOp);
|
||||
for(i=0; i<p->nOp; i++){
|
||||
p->aOp[i].nExec = 0;
|
||||
p->aOp[i].nCycle = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2617,10 +2623,6 @@ void sqlite3VdbeMakeReady(
|
||||
p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem));
|
||||
p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*));
|
||||
p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*));
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
p->anExec = allocSpace(&x, 0, p->nOp*sizeof(i64));
|
||||
p->anCycle = allocSpace(&x, 0, p->nOp*sizeof(u64));
|
||||
#endif
|
||||
if( x.nNeeded ){
|
||||
x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
|
||||
x.nFree = x.nNeeded;
|
||||
@@ -2629,10 +2631,6 @@ void sqlite3VdbeMakeReady(
|
||||
p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
|
||||
p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
|
||||
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
|
||||
p->anCycle = allocSpace(&x, p->anCycle, p->nOp*sizeof(u64));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2647,10 +2645,6 @@ void sqlite3VdbeMakeReady(
|
||||
p->nMem = nMem;
|
||||
initMemArray(p->aMem, nMem, db, MEM_Undefined);
|
||||
memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
memset(p->anExec, 0, p->nOp*sizeof(i64));
|
||||
memset(p->anCycle, 0, p->nOp*sizeof(u64));
|
||||
#endif
|
||||
}
|
||||
sqlite3VdbeRewind(p);
|
||||
}
|
||||
@@ -2708,10 +2702,6 @@ static void closeCursorsInFrame(Vdbe *p){
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
||||
Vdbe *v = pFrame->v;
|
||||
closeCursorsInFrame(v);
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
||||
v->anExec = pFrame->anExec;
|
||||
v->anCycle = pFrame->anCycle;
|
||||
#endif
|
||||
v->aOp = pFrame->aOp;
|
||||
v->nOp = pFrame->nOp;
|
||||
v->aMem = pFrame->aMem;
|
||||
@@ -3543,8 +3533,8 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
}
|
||||
for(i=0; i<p->nOp; i++){
|
||||
char zHdr[100];
|
||||
i64 cnt = p->anExec[i];
|
||||
i64 cycles = p->anCycle[i];
|
||||
i64 cnt = p->aOp[i].nExec;
|
||||
i64 cycles = p->aOp[i].nCycle;
|
||||
sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
|
||||
cnt,
|
||||
cycles,
|
||||
|
||||
+52
-1
@@ -67,7 +67,7 @@ int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
|
||||
** block sorting is required.
|
||||
*/
|
||||
int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
|
||||
return pWInfo->nOBSat;
|
||||
return pWInfo->nOBSat<0 ? 0 : pWInfo->nOBSat;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -812,6 +812,51 @@ static int termCanDriveIndex(
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
/*
|
||||
** Argument pIdx represents an automatic index that the current statement
|
||||
** will create and populate. Add an OP_Explain with text of the form:
|
||||
**
|
||||
** CREATE AUTOMATIC INDEX ON <table>(<cols>) [WHERE <expr>]
|
||||
**
|
||||
** This is only required if sqlite3_stmt_scanstatus() is enabled, to
|
||||
** associate an SQLITE_SCANSTAT_NCYCLE and SQLITE_SCANSTAT_NLOOP
|
||||
** values with. In order to avoid breaking legacy code and test cases,
|
||||
** the OP_Explain is not added if this is an EXPLAIN QUERY PLAN command.
|
||||
*/
|
||||
static void explainAutomaticIndex(
|
||||
Parse *pParse,
|
||||
Index *pIdx, /* Automatic index to explain */
|
||||
int bPartial, /* True if pIdx is a partial index */
|
||||
int *pAddrExplain /* OUT: Address of OP_Explain */
|
||||
){
|
||||
if( pParse->explain!=2 ){
|
||||
Table *pTab = pIdx->pTable;
|
||||
const char *zSep = "";
|
||||
char *zText = 0;
|
||||
int ii = 0;
|
||||
zText = sqlite3_mprintf("CREATE AUTOMATIC INDEX ON %s(", pTab->zName);
|
||||
assert( pIdx->nColumn>1 );
|
||||
assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID );
|
||||
for(ii=0; ii<(pIdx->nColumn-1); ii++){
|
||||
const char *zName = 0;
|
||||
int iCol = pIdx->aiColumn[ii];
|
||||
|
||||
zName = pTab->aCol[iCol].zCnName;
|
||||
zText = sqlite3_mprintf("%z%s%s", zText, zSep, zName);
|
||||
zSep = ", ";
|
||||
}
|
||||
*pAddrExplain = sqlite3VdbeExplain(
|
||||
pParse, 0, "%s)%s", zText, (bPartial ? " WHERE <expr>" : "")
|
||||
);
|
||||
sqlite3_free(zText);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define explainAutomaticIndex(a,b,c,d)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Generate code to construct the Index object for an automatic index
|
||||
** and to set up the WhereLevel object pLevel so that the code generator
|
||||
@@ -847,6 +892,9 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
SrcItem *pTabItem; /* FROM clause term being indexed */
|
||||
int addrCounter = 0; /* Address where integer counter is initialized */
|
||||
int regBase; /* Array of registers where record is assembled */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
int addrExp = 0; /* Address of OP_Explain */
|
||||
#endif
|
||||
|
||||
/* Generate code to skip over the creation and initialization of the
|
||||
** transient index on 2nd and subsequent iterations of the loop. */
|
||||
@@ -970,6 +1018,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
pIdx->azColl[n] = sqlite3StrBINARY;
|
||||
|
||||
/* Create the automatic index */
|
||||
explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp);
|
||||
assert( pLevel->iIdxCur>=0 );
|
||||
pLevel->iIdxCur = pParse->nTab++;
|
||||
sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
|
||||
@@ -1005,6 +1054,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0,
|
||||
regBase, pLoop->u.btree.nEq);
|
||||
}
|
||||
sqlite3VdbeScanStatusCounters(v, addrExp, addrExp, sqlite3VdbeCurrentAddr(v));
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
|
||||
@@ -1025,6 +1075,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
|
||||
|
||||
/* Jump here when skipping the initialization */
|
||||
sqlite3VdbeJumpHere(v, addrInit);
|
||||
sqlite3VdbeScanStatusRange(v, addrExp, addrExp, -1);
|
||||
|
||||
end_auto_index_create:
|
||||
sqlite3ExprDelete(pParse->db, pPartial);
|
||||
|
||||
+13
-3
@@ -294,16 +294,26 @@ void sqlite3WhereAddScanStatus(
|
||||
){
|
||||
const char *zObj = 0;
|
||||
WhereLoop *pLoop = pLvl->pWLoop;
|
||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){
|
||||
int wsFlags = pLoop->wsFlags;
|
||||
int viaCoroutine = 0;
|
||||
|
||||
if( (wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){
|
||||
zObj = pLoop->u.btree.pIndex->zName;
|
||||
}else{
|
||||
zObj = pSrclist->a[pLvl->iFrom].zName;
|
||||
viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine;
|
||||
}
|
||||
sqlite3VdbeScanStatus(
|
||||
v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
|
||||
);
|
||||
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
|
||||
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur);
|
||||
|
||||
if( viaCoroutine==0 ){
|
||||
if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){
|
||||
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur);
|
||||
}
|
||||
if( wsFlags & WHERE_INDEXED ){
|
||||
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+82
-6
@@ -88,8 +88,8 @@ proc get_graph {stmt} {
|
||||
proc do_graph_test {tn sql res} {
|
||||
db eval $sql
|
||||
set stmt [db version -last-stmt-ptr]
|
||||
|
||||
set graph [string trim [get_graph $stmt]]
|
||||
|
||||
set graph [regsub -all {nCycle=[0-9]+} $graph nCycle=nnn]
|
||||
uplevel [list do_test $tn [list set {} $graph] [string trim $res]]
|
||||
}
|
||||
@@ -119,9 +119,9 @@ do_graph_test 1.3 {
|
||||
SELECT (SELECT a FROM t1 WHERE b=x) FROM t2 WHERE y=2
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--SCAN t2
|
||||
--SCAN t2 (nCycle=nnn)
|
||||
--CORRELATED SCALAR SUBQUERY 1 (nCycle=nnn)
|
||||
----SCAN t1
|
||||
----SCAN t1 (nCycle=nnn)
|
||||
}
|
||||
|
||||
do_graph_test 1.4 {
|
||||
@@ -132,9 +132,9 @@ do_graph_test 1.4 {
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--MATERIALIZE v2 (nCycle=nnn)
|
||||
----SCAN t2
|
||||
--SCAN v2
|
||||
--SCAN t1
|
||||
----SCAN t2 (nCycle=nnn)
|
||||
--SCAN v2 (nCycle=nnn)
|
||||
--SCAN t1 (nCycle=nnn)
|
||||
--USE TEMP B-TREE FOR ORDER BY (nCycle=nnn)
|
||||
}
|
||||
|
||||
@@ -154,6 +154,82 @@ QUERY (nCycle=nnn)
|
||||
--SCAN ft VIRTUAL TABLE INDEX 0:M1 (nCycle=nnn)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE x1(a, b);
|
||||
CREATE TABLE x2(c, d);
|
||||
|
||||
WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000)
|
||||
INSERT INTO x1 SELECT i, i FROM s;
|
||||
INSERT INTO x2 SELECT a, b FROM x1;
|
||||
}
|
||||
|
||||
do_graph_test 2.1 {
|
||||
SELECT * FROM x1, x2 WHERE c=+a;
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--SCAN x1 (nCycle=nnn)
|
||||
--CREATE AUTOMATIC INDEX ON x2(c, d) (nCycle=nnn)
|
||||
--SEARCH x2 USING AUTOMATIC COVERING INDEX (c=?) (nCycle=nnn)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE rt1 (id INTEGER PRIMARY KEY, x1, x2);
|
||||
CREATE TABLE rt2 (id, x1, x2);
|
||||
}
|
||||
|
||||
do_graph_test 4.1 {
|
||||
SELECT * FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=rt1.x1;
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--SCAN rt1 (nCycle=nnn)
|
||||
--CREATE AUTOMATIC INDEX ON rt2(x1, id, x2) (nCycle=nnn)
|
||||
--SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
|
||||
}
|
||||
|
||||
do_graph_test 4.2 {
|
||||
SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=rt1.x1;
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--SCAN rt1 (nCycle=nnn)
|
||||
--CREATE AUTOMATIC INDEX ON rt2(x1, id) (nCycle=nnn)
|
||||
--SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
|
||||
}
|
||||
|
||||
do_graph_test 4.3 {
|
||||
SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND (rt2.x1+1)=(rt1.x1+1);
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--SCAN rt1 (nCycle=nnn)
|
||||
--SCAN rt2 (nCycle=nnn)
|
||||
}
|
||||
|
||||
do_graph_test 4.4 {
|
||||
SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=(rt1.x1+1) AND rt2.id>5;
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--SCAN rt1 (nCycle=nnn)
|
||||
--CREATE AUTOMATIC INDEX ON rt2(x1, id) WHERE <expr> (nCycle=nnn)
|
||||
--SEARCH rt2 USING AUTOMATIC PARTIAL COVERING INDEX (x1=?) (nCycle=nnn)
|
||||
}
|
||||
|
||||
do_graph_test 4.5 {
|
||||
SELECT v1.cnt FROM rt1, (
|
||||
SELECT count(*) AS cnt, rt2.x1 AS x1 FROM rt2 GROUP BY x1
|
||||
) AS v1 WHERE rt1.x1=v1.x1
|
||||
} {
|
||||
QUERY (nCycle=nnn)
|
||||
--MATERIALIZE v1 (nCycle=nnn)
|
||||
----SCAN rt2 (nCycle=nnn)
|
||||
----USE TEMP B-TREE FOR GROUP BY
|
||||
--SCAN rt1 (nCycle=nnn)
|
||||
--CREATE AUTOMATIC INDEX ON v1(x1, cnt) (nCycle=nnn)
|
||||
--SEARCH v1 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -1618,4 +1618,19 @@ do_execsql_test where-28.1 {
|
||||
19 5
|
||||
}
|
||||
|
||||
# 2022-12-07 Yong Heng [https://sqlite.org/forum/forumpost/dfe8084751]
|
||||
#
|
||||
do_execsql_test where-29.1 {
|
||||
SELECT DISTINCT 'xyz' FROM pragma_cache_size
|
||||
WHERE rowid OR abs(0)
|
||||
ORDER BY
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1;
|
||||
} {xyz}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -86,6 +86,7 @@ while {![eof $in]} {
|
||||
set in3($name) 0
|
||||
set out2($name) 0
|
||||
set out3($name) 0
|
||||
set ncycle($name) 0
|
||||
for {set i 3} {$i<[llength $line]-1} {incr i} {
|
||||
switch [string trim [lindex $line $i] ,] {
|
||||
same {
|
||||
@@ -107,6 +108,7 @@ while {![eof $in]} {
|
||||
in3 {set in3($name) 1}
|
||||
out2 {set out2($name) 1}
|
||||
out3 {set out3($name) 1}
|
||||
ncycle {set ncycle($name) 1}
|
||||
}
|
||||
}
|
||||
if {$group($name)} {
|
||||
@@ -140,6 +142,7 @@ foreach name {OP_Noop OP_Explain OP_Abortable} {
|
||||
set in3($name) 0
|
||||
set out2($name) 0
|
||||
set out3($name) 0
|
||||
set ncycle($name) 0
|
||||
set op($name) -1
|
||||
set order($nOp) $name
|
||||
incr nOp
|
||||
@@ -285,6 +288,7 @@ for {set i 0} {$i<=$max} {incr i} {
|
||||
if {$in3($name)} {incr x 8}
|
||||
if {$out2($name)} {incr x 16}
|
||||
if {$out3($name)} {incr x 32}
|
||||
if {$ncycle($name)} {incr x 64}
|
||||
}
|
||||
set bv($i) $x
|
||||
}
|
||||
@@ -299,6 +303,7 @@ puts "#define OPFLG_IN2 0x04 /* in2: P2 is an input */"
|
||||
puts "#define OPFLG_IN3 0x08 /* in3: P3 is an input */"
|
||||
puts "#define OPFLG_OUT2 0x10 /* out2: P2 is an output */"
|
||||
puts "#define OPFLG_OUT3 0x20 /* out3: P3 is an output */"
|
||||
puts "#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */"
|
||||
puts "#define OPFLG_INITIALIZER \173\\"
|
||||
for {set i 0} {$i<=$max} {incr i} {
|
||||
if {$i%8==0} {
|
||||
|
||||
Reference in New Issue
Block a user