Compare commits

...

6 Commits

Author SHA1 Message Date
drh 13977eda16 Merge updates from trunk.
FossilOrigin-Name: 2383aa2cb864734cccca6c98605df6026c732cbfb9a173660d2993dc63970f63
2020-03-21 14:05:56 +00:00
drh fda3dd5e67 Back out the sqlite3_stmt_mode() and EXPLAIN TABLES enhancements, but keep
the other miscellaneous improvements to EXPLAIN that were implemented while
adding the above:  Turn magic numbers into symbolic constants.
Add the sqlite3MemPrint() interface accessible to the debugger.  Improve
the performance and reduce the code size.

FossilOrigin-Name: 62aece66774587590bf7f88883cca1c1e76866e9df93bb1a17c4d9db894f06aa
2020-03-21 03:40:21 +00:00
drh 27de99df79 Add the EXPLAIN TABLES syntax that uses SQLITE_STMTMODE_TABLELIST. Seems
to work, but not well-tested.

FossilOrigin-Name: e7343ce7514f61eb1aeba22ab83da5b05779080db394332e2e90b4d54cabe123
2020-03-20 20:00:10 +00:00
drh 3041bf593b Further simplification of the EXPLAIN logic. Fix the test errors from
the previous check-in.

FossilOrigin-Name: 5eaba9af1c35ea7b7c08cad7d0d9b5a4b63b11b3177bb84a570ce1cea44b9f57
2020-03-20 17:49:37 +00:00
drh cc6408ffa3 Revamp the EXPLAIN infrastructure to facilitate sqlite3_stmt_mode(). The
currently code mostly works, but there are test failures.  This is an
incremental check-in.

FossilOrigin-Name: e9e17e2125dbbafd5da4adb3bd2893735fa4d0aaa5f3daee75f866cb32231a8d
2020-03-20 16:13:41 +00:00
drh 8e8c2f1498 Initial code for a proposed new sqlite3_stmt_mode() API.
This is an incomplete snapshot of a work-in-progress.

FossilOrigin-Name: 3cf7537b5e14e218218b18b3c0c668c950a71fcddc68a5faf0f197519718a6c2
2020-03-19 21:17:11 +00:00
10 changed files with 180 additions and 123 deletions
+13 -13
View File
@@ -1,5 +1,5 @@
C Recompute\sthe\sset\sof\scolumns\sused\sfor\seach\stable\swhen\sthe\stable\sis\ninvolved\sin\squery\sflattening.
D 2020-03-21T00:05:53.338
C Merge\supdates\sfrom\strunk.
D 2020-03-21T14:05:56.197
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -529,14 +529,14 @@ F src/pragma.h 9473160d220416456b40f27323bb4b316d4e4e08ffbf8bf88c5f7045d49c38e5
F src/prepare.c 8d4d6c8aa6afefc48027c54b41cdf134b4d6bc2fc4badbe483ad7fd9e1728a28
F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 38e3a5636f5bdc92e3683e4cafbba6418c0aa15e0d89ca5b28bd0b621dbb80bf
F src/resolve.c ad43b2ed4bea58abca3092993382aa2ac91b89144d2066faae4ac924b39396f9
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c cb7588bfe9e1a900801e5ca345296b32b85ded0d57b2f277a9962294eb4c7aa2
F src/select.c ba6d286edbf0dcb0c9b90ad6b8020d7f2e0b21fb2f19d33d5972db831756b2c1
F src/shell.c.in f76590931c0cbbfef347f44f81ade6b335f80c46bc6e59b8b6114383a8df30e0
F src/sqlite.h.in 802957feeb249ede54f8dfe99b72aa19e70a0b7737969c46e625dc2f9f2d42b0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9c5269260409eb3275324ccace6a13a96f4ad330c708415f70ca6097901ff4ee
F src/sqliteInt.h 3ccd2aedc57f61009285c4fa7ca1d75b380a48b5168f9605c10c86a7be62156c
F src/sqliteInt.h 84e11419a13b8d20b9dd91eb5c5547cdb905f0c0b658f70669dae07843c35356
F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -603,11 +603,11 @@ F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c 95fb6e03a5ca679045c5adccd05380f0addccabef5911abddcb06af069500ab7
F src/util.c a285c1e026907b69fa2592bd05047a565a1d8a1aef2b73c924b6a8ffe772871a
F src/vacuum.c 813b510ba887fee6492bcb11f2bf77d7eb58b232b83649136372e0a2fc17f4b9
F src/vdbe.c c1c123c6248fa88940b932a00bcc75056921b6d046d45a82566cb97415d2299c
F src/vdbe.c b7b9ec1d604a12f4cafedf796027a297bc306f0d3afb340948898256cb4473b9
F src/vdbe.h 51282fbe819ee0e8eeeaab176240860d334c20a12b14f3b363e7f1a4e05d60b9
F src/vdbeInt.h a17146053a1aa438474012998fe07e314f3df274a61491ad838ad85d848ac051
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
F src/vdbeaux.c e8baf66528e36474f4071e3171b660a454606eb5b54459a729982c939ad7a5bb
F src/vdbeInt.h 37a1cb667c80b4cbceb80a7b3947e3b15892cc84bff0cde788ec1781cfab5bde
F src/vdbeapi.c d7540ad79510d3baa30a09db93f305e3d12f069dbd7bd49ebed51b14a3024681
F src/vdbeaux.c 99703bb60f4f7f7700f801510cb9732e50abfcf5ba65958121c017dcd595d78e
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c 39b942ecca179f4f30a32b54579a85d74ccaefa5af2a0ad2700abe5ef0768b22
F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df
@@ -619,7 +619,7 @@ F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed
F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9
F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c
F src/wherecode.c 7b939de85d65cc4b4bfa197513136b9e0ae03167e3b82842ca5a0ba1055ba65d
F src/wherecode.c 9e931b9d01c3c6ffa9b150f4535dacea0dd38360fa740b6f525cf27c17415ba0
F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
F src/window.c ba1ffb78d73c5831433681aab7ee634230ee32f14ad508efa585044662141d5a
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1860,7 +1860,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 86e98ddc19470410ccc6d2cf4ad56ef0bc5a23b7fbe6331b8cae374689f54529
R ee0c3203501becfb0c0fab4a61c04589
P 62aece66774587590bf7f88883cca1c1e76866e9df93bb1a17c4d9db894f06aa a9bb71ba708ba72255ba8d18c9856e38ddf53eae2d61c8435149354fb2b2459e
R d7e5eecaf46db6237774ccab2e4497bb
U drh
Z 54b4f622fc0ff39925380e9e68d902eb
Z d68a3bb48f89136a3b7a1e13c312fa0b
+1 -1
View File
@@ -1 +1 @@
a9bb71ba708ba72255ba8d18c9856e38ddf53eae2d61c8435149354fb2b2459e
2383aa2cb864734cccca6c98605df6026c732cbfb9a173660d2993dc63970f63
+1 -1
View File
@@ -934,7 +934,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
else if( no_such_func && pParse->db->init.busy==0
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
&& pParse->explain==0
&& pParse->explain==SQLITE_STMTMODE_RUN
#endif
){
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+1 -1
View File
@@ -5546,7 +5546,7 @@ static void explainSimpleCount(
Table *pTab, /* Table being queried */
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
if( pParse->explain==SQLITE_STMTMODE_EQP ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
pTab->zName,
+7
View File
@@ -3370,6 +3370,13 @@ struct Parse {
#define PARSE_MODE_RENAME 2
#define PARSE_MODE_UNMAP 3
/*
** Allowed values for Vdbe.explain and Parse.explain
*/
#define SQLITE_STMTMODE_RUN 0
#define SQLITE_STMTMODE_EXPLAIN 1
#define SQLITE_STMTMODE_EQP 2
/*
** Sizes and pointers of various parts of the Parse object.
*/
+17 -5
View File
@@ -539,9 +539,10 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){
#ifdef SQLITE_DEBUG
/*
** Print the value of a register for tracing purposes:
** Print the value of a Mem object on standard output.
** Used for tracing and for interactive debugging only.
*/
static void memTracePrint(Mem *p){
static void memPrint(Mem *p){
if( p->flags & MEM_Undefined ){
printf(" undefined");
}else if( p->flags & MEM_Null ){
@@ -567,9 +568,19 @@ static void memTracePrint(Mem *p){
}
if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype);
}
/* Print N Mem objects beginning with p. Used for interactive debugging */
void sqlite3MemPrint(Mem *p, int N){
int i;
for(i=0; i<N; i++){
if( N>1 ) printf("%3d:", i);
memPrint(p+i);
printf("\n");
}
fflush(stdout);
}
static void registerTrace(int iReg, Mem *p){
printf("R[%d] = ", iReg);
memTracePrint(p);
memPrint(p);
if( p->pScopyFrom ){
printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
}
@@ -704,8 +715,8 @@ int sqlite3VdbeExec(
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
assert( p->bIsReader || p->readOnly!=0 );
p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
assert( p->explain==SQLITE_STMTMODE_RUN );
p->nRes = 0;
db->busyHandler.nBusy = 0;
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
sqlite3VdbeIOTraceSql(p);
@@ -1493,6 +1504,7 @@ case OP_ResultRow: {
** a side effect.
*/
pMem = p->pResultSet = &aMem[pOp->p1];
p->nRes = pOp->p2;
for(i=0; i<pOp->p2; i++){
assert( memIsValid(&pMem[i]) );
Deephemeralize(&pMem[i]);
+24 -14
View File
@@ -26,6 +26,11 @@
# define SQLITE_MAX_SCHEMA_RETRY 50
#endif
/*
** Maximum number of columns in any "EXPLAIN" output
*/
#define VDBE_EXPLAIN_COLS 9
/*
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
** "explain" P4 display logic is enabled.
@@ -337,11 +342,6 @@ struct sqlite3_context {
sqlite3_value *argv[1]; /* Argument set */
};
/* A bitfield type for use inside of structures. Always follow with :N where
** N is the number of bits.
*/
typedef unsigned bft; /* Bit Field Type */
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
*/
@@ -414,21 +414,23 @@ struct Vdbe {
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u16 nResColumn; /* Columns in one row of a normal result set */
u16 nRes; /* Columns in the current actual result set */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
bft explain:2; /* True if EXPLAIN present on SQL command */
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
bft changeCntOn:1; /* True to update the change-counter */
bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
u8 explain:2; /* True if EXPLAIN present on SQL command */
u8 expired:2; /* 1: recompile VM immediately 2: when convenient */
u8 doingRerun:1; /* True if rerunning after an auto-reprepare */
u8 changeCntOn:1; /* True to update the change-counter */
u8 runOnlyOnce:1; /* Automatically expire on reset */
u8 usesStmtJournal:1; /* True if uses a statement journal */
u8 readOnly:1; /* True for statements that do not write */
u8 bIsReader:1; /* True for statements that read */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
u32 nColName; /* Number of slots allocated to aColName[] above */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
@@ -457,6 +459,13 @@ struct Vdbe {
#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
/*
** Values for Vdbe.explain
*/
#define SQLITE_STMTMODE_RUN 0
#define SQLITE_STMTMODE_EXPLAIN 1
#define SQLITE_STMTMODE_EQP 2
/*
** Structure used to store the context required by the
** sqlite3_preupdate_*() API functions.
@@ -497,6 +506,7 @@ int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
int sqlite3VdbeExec(Vdbe*);
#ifndef SQLITE_OMIT_EXPLAIN
Mem *sqlite3VdbeSetExplainColumnNames(Vdbe*);
int sqlite3VdbeList(Vdbe*);
#endif
int sqlite3VdbeHalt(Vdbe*);
+13 -4
View File
@@ -996,8 +996,16 @@ int sqlite3_aggregate_count(sqlite3_context *p){
** Return the number of columns in the result set for the statement pStmt.
*/
int sqlite3_column_count(sqlite3_stmt *pStmt){
static const u8 anColumn[] = {
0, /* SQLITE_STMTMODE_RUN (Use pVm->nResColumn instead) */
8, /* SQLITE_STMTMODE_EXPLAIN */
4 /* SQLITE_STMTMODE_EQP */
};
Vdbe *pVm = (Vdbe *)pStmt;
return pVm ? pVm->nResColumn : 0;
if( pVm==0 ) return 0;
assert( pVm->explain>=0 && pVm->explain<=2 );
if( pVm->explain==0 ) return pVm->nResColumn;
return (int)anColumn[pVm->explain];
}
/*
@@ -1006,8 +1014,8 @@ int sqlite3_column_count(sqlite3_stmt *pStmt){
*/
int sqlite3_data_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
if( pVm==0 || pVm->pResultSet==0 ) return 0;
return pVm->nResColumn;
if( pVm==0 || pVm->nRes==0 ) return 0;
return sqlite3_column_count(pStmt);
}
/*
@@ -1061,7 +1069,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
if( pVm==0 ) return (Mem*)columnNullValue();
assert( pVm->db );
sqlite3_mutex_enter(pVm->db->mutex);
if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
if( i<pVm->nRes && i>=0 ){
pOut = &pVm->pResultSet[i];
}else{
sqlite3Error(pVm->db, SQLITE_RANGE);
@@ -1211,6 +1219,7 @@ static const void *columnName(
N += useType*n;
sqlite3_mutex_enter(db->mutex);
assert( db->mallocFailed==0 );
assert( N>=0 && N<p->nColName );
#ifndef SQLITE_OMIT_UTF16
if( useUtf16 ){
ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
+102 -83
View File
@@ -1872,7 +1872,11 @@ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
}
/*
** Release an array of N Mem elements
** Release all content from an array of N Mem elements. All elements
** are left in a state of "MEM_Undefined".
**
** This routine does not free the array itself. It just frees the
** content held by the Mem elements in the array.
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
@@ -1961,24 +1965,62 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
sqlite3DbFree(p->v->db, p);
}
#ifndef SQLITE_OMIT_EXPLAIN
/*
** There should are VDBE_EXPLAIN_COLS*2+1 extra registers on the end of the
** Vdbe.aColName array for statements that are in one of the
** "explain" modes.
**
** * VDBE_EXPLAIN_COLS registers for the column names
** * 1 register to keep track of subprograms
** * VDBE_EXPLAIN_COLS registers to hold row output
**
** This routine makes sure those extra register exist and returns
** a pointer to the first of them. If the extra registers do
** not exist, then the are allocated.
**
** NULL is returned if there is a memory allocation error.
*/
Mem *sqlite3VdbeSetExplainColumnNames(Vdbe *p){
int n = p->nResColumn*COLNAME_N;
if( p->nColName<=n ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"id", "parent", "notused", "detail"
};
int iFirst, cnt, i;
Mem *pNew = sqlite3DbRealloc(p->db, p->aColName,
(n+VDBE_EXPLAIN_COLS*2+1)*sizeof(Mem));
if( pNew==0 ){
return 0;
}
p->aColName = pNew;
p->nColName = n+VDBE_EXPLAIN_COLS*2+1;
initMemArray(p->aColName+n, VDBE_EXPLAIN_COLS*2+1, p->db, MEM_Null);
if( p->explain==SQLITE_STMTMODE_EXPLAIN ){
iFirst = 0;
cnt = 8;
}else{
iFirst = 8;
cnt = 4;
}
assert( cnt<=VDBE_EXPLAIN_COLS );
for(i=0; i<cnt; i++){
sqlite3VdbeMemSetStr(pNew+n+i, azColName[i+iFirst], -1,
SQLITE_UTF8, SQLITE_STATIC);
}
}
return p->aColName + n;
}
#endif
#ifndef SQLITE_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
**
** The interface is the same as sqlite3VdbeExec(). But instead of
** running the code, it invokes the callback once for each instruction.
** This feature is used to implement "EXPLAIN".
**
** When p->explain==1, each instruction is listed. When
** p->explain==2, only OP_Explain instructions are listed and these
** are shown in a different format. p->explain==2 is used to implement
** EXPLAIN QUERY PLAN.
** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers
** are also shown, so that the boundaries between the main program and
** each trigger are clear.
**
** When p->explain==1, first the main program is listed, then each of
** the trigger subprograms are listed one by one.
** running the code, it returns rows based on the bytecode content,
** rather than on actually running the bytecode.
*/
int sqlite3VdbeList(
Vdbe *p /* The VDBE */
@@ -1990,11 +2032,12 @@ int sqlite3VdbeList(
sqlite3 *db = p->db; /* The database connection */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
Mem *pMem; /* First Mem of result set */
int bListSubprogs; /* Also show subprograms */
Op *pOp = 0;
assert( p->explain );
assert( p->explain==SQLITE_STMTMODE_EXPLAIN
|| p->explain==SQLITE_STMTMODE_EQP );
assert( p->magic==VDBE_MAGIC_RUN );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
@@ -2002,8 +2045,13 @@ int sqlite3VdbeList(
** the result, result columns may become dynamic if the user calls
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
*/
releaseMemArray(pMem, 8);
p->pResultSet = 0;
pMem = sqlite3VdbeSetExplainColumnNames(p);
if( pMem==0 ){
p->rc = SQLITE_NOMEM;
return SQLITE_ERROR;
}
pMem += VDBE_EXPLAIN_COLS;
p->nRes = 0;
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
@@ -2020,13 +2068,10 @@ int sqlite3VdbeList(
** encountered, but p->pc will eventually catch up to nRow.
*/
nRow = p->nOp;
bListSubprogs = p->explain!=SQLITE_STMTMODE_EQP
|| (db->flags & SQLITE_TriggerEQP)!=0;
if( bListSubprogs ){
/* The first 8 memory cells are used for the result set. So we will
** commandeer the 9th cell to use as storage for an array of pointers
** to trigger subprograms. The VDBE is guaranteed to have at least 9
** cells. */
assert( p->nMem>9 );
pSub = &p->aMem[9];
pSub = pMem++;
if( pSub->flags&MEM_Blob ){
/* On the first call to sqlite3_step(), pSub will hold a NULL. It is
** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
@@ -2037,6 +2082,7 @@ int sqlite3VdbeList(
nRow += apSub[i]->nOp;
}
}
p->pResultSet = pMem;
while(1){ /* Loop exits via break */
i = p->pc++;
@@ -2065,7 +2111,7 @@ int sqlite3VdbeList(
/* When an OP_Program opcode is encounter (the only opcode that has
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
** to hold the new program - assuming this subprogram
** has not already been seen.
*/
if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
@@ -2082,14 +2128,18 @@ int sqlite3VdbeList(
}
apSub = (SubProgram **)pSub->z;
apSub[nSub++] = pOp->p4.pProgram;
pSub->flags |= MEM_Blob;
MemSetTypeFlag(pSub, MEM_Blob);
pSub->n = nSub*sizeof(SubProgram*);
nRow += pOp->p4.pProgram->nOp;
}
}
if( p->explain<2 ) break;
if( pOp->opcode==OP_Explain ) break;
if( pOp->opcode==OP_Init && p->pc>1 ) break;
if( p->explain==SQLITE_STMTMODE_EXPLAIN ){
break; /* Show every bytecode line for SQLITE_STMTMODE_EXPLAIN */
}else{
/* Only OP_Init and OP_Explain opcodes are significant for EQP */
if( pOp->opcode==OP_Explain ) break;
if( pOp->opcode==OP_Init && p->pc>1 ) break;
}
}
if( rc==SQLITE_OK ){
@@ -2099,30 +2149,14 @@ int sqlite3VdbeList(
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
}else{
char *zP4;
if( p->explain==1 ){
pMem->flags = MEM_Int;
pMem->u.i = i; /* Program counter */
pMem++;
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem++;
if( p->explain==SQLITE_STMTMODE_EXPLAIN ){
sqlite3VdbeMemSetInt64(pMem++, i); /* Program counter */
sqlite3VdbeMemSetStr(pMem++, (char*)sqlite3OpcodeName(pOp->opcode),
-1, SQLITE_UTF8, SQLITE_STATIC);
}
pMem->flags = MEM_Int;
pMem->u.i = pOp->p1; /* P1 */
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p2; /* P2 */
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
pMem++;
sqlite3VdbeMemSetInt64(pMem++, pOp->p1); /* P1 */
sqlite3VdbeMemSetInt64(pMem++, pOp->p2); /* P2 */
sqlite3VdbeMemSetInt64(pMem++, pOp->p3); /* P3 */
if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
assert( p->db->mallocFailed );
@@ -2140,7 +2174,7 @@ int sqlite3VdbeList(
}
pMem++;
if( p->explain==1 ){
if( p->explain==SQLITE_STMTMODE_EXPLAIN ){
if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
assert( p->db->mallocFailed );
return SQLITE_ERROR;
@@ -2162,10 +2196,11 @@ int sqlite3VdbeList(
#else
pMem->flags = MEM_Null; /* Comment */
#endif
pMem++;
}
p->nResColumn = 8 - 4*(p->explain-1);
p->pResultSet = &p->aMem[1];
p->nRes = (int)(pMem - p->pResultSet);
assert( p->nRes<=VDBE_EXPLAIN_COLS );
p->rc = SQLITE_OK;
rc = SQLITE_ROW;
}
@@ -2369,25 +2404,7 @@ void sqlite3VdbeMakeReady(
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
if( pParse->explain ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"id", "parent", "notused", "detail"
};
int iFirst, mx, i;
if( nMem<10 ) nMem = 10;
if( pParse->explain==2 ){
sqlite3VdbeSetNumCols(p, 4);
iFirst = 8;
mx = 12;
}else{
sqlite3VdbeSetNumCols(p, 8);
iFirst = 0;
mx = 8;
}
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(p, i-iFirst, COLNAME_NAME,
azColName[i], SQLITE_STATIC);
}
p->explain = pParse->explain;
}
p->expired = 0;
@@ -2425,7 +2442,6 @@ void sqlite3VdbeMakeReady(
p->pVList = pParse->pVList;
pParse->pVList = 0;
p->explain = pParse->explain;
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
@@ -2563,17 +2579,20 @@ static void closeAllCursors(Vdbe *p){
** be called on an SQL statement before sqlite3_step().
*/
void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
int n;
sqlite3 *db = p->db;
u32 n;
if( p->nResColumn ){
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
if( p->nColName ){
releaseMemArray(p->aColName, p->nColName);
sqlite3DbFree(db, p->aColName);
}
n = nResColumn*COLNAME_N;
p->nResColumn = (u16)nResColumn;
n = p->nColName = (u32)nResColumn*COLNAME_N;
p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
if( p->aColName==0 ){
p->nColName = 0;
return;
}
initMemArray(p->aColName, n, db, MEM_Null);
}
@@ -3307,7 +3326,7 @@ int sqlite3VdbeReset(Vdbe *p){
#endif
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
p->pResultSet = 0;
p->nRes = 0;
#ifdef SQLITE_DEBUG
p->nWrite = 0;
#endif
@@ -3412,7 +3431,7 @@ void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, int mask){
void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
assert( p->db==0 || p->db==db );
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
releaseMemArray(p->aColName, p->nColName);
for(pSub=p->pProgram; pSub; pSub=pNext){
pNext = pSub->pNext;
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
+1 -1
View File
@@ -126,7 +126,7 @@ int sqlite3WhereExplainOneScan(
){
int ret = 0;
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
if( sqlite3ParseToplevel(pParse)->explain==2 )
if( sqlite3ParseToplevel(pParse)->explain==SQLITE_STMTMODE_EQP )
#endif
{
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];