Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 27de99df79 | |||
| 3041bf593b | |||
| cc6408ffa3 | |||
| 8e8c2f1498 |
@@ -1,5 +1,5 @@
|
||||
C Chagnes\sthe\sESCAPE\sclause\son\sthe\sLIKE\soperator\sto\soverwrite\swildcard\ncharacters,\sin\sorder\sot\smatch\sthe\sbehavior\sof\sPosgreSQL.
|
||||
D 2020-03-19T18:13:29.000
|
||||
C Add\sthe\sEXPLAIN\sTABLES\ssyntax\sthat\suses\sSQLITE_STMTMODE_TABLELIST.\s\sSeems\nto\swork,\sbut\snot\swell-tested.
|
||||
D 2020-03-20T20:00:10.751
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -520,7 +520,7 @@ F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c a71ffd145f55e28cbdc1bdabb5e6bef063da428a6c0de3c3a36e9a0c41d4c8c0
|
||||
F src/pager.h 3b33619a90180e0874c7eca31d6f6ceb464d9322c6fb4e9a7bbb318c8a17bdb3
|
||||
F src/parse.y 8575183809cf30f8c9d1fbea65ca34d1de78b659792bc7c42681e01fc596b520
|
||||
F src/parse.y dc4521689a9d91b9da0c74ec02ccc6529d4610eece436cdf21c53ca167fd2a93
|
||||
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
|
||||
@@ -529,11 +529,11 @@ 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 49d46acea0e69311aa891e18253973d63e81da2a9c135924bc827856d33872ad
|
||||
F src/select.c 128d9d6996eca5e0db686495559b6588f197ef1b6643fa8ec4914861226ff021
|
||||
F src/shell.c.in f76590931c0cbbfef347f44f81ade6b335f80c46bc6e59b8b6114383a8df30e0
|
||||
F src/sqlite.h.in 802957feeb249ede54f8dfe99b72aa19e70a0b7737969c46e625dc2f9f2d42b0
|
||||
F src/sqlite.h.in 416ef92b6b08bfb9a31de8001eb5d44243ecda036224421623cc8e5fdfdf1528
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 9c5269260409eb3275324ccace6a13a96f4ad330c708415f70ca6097901ff4ee
|
||||
F src/sqliteInt.h 5f74c1c52b152259ee07f241821620f11736e4f590936cfaf1cbbff9a2f563d3
|
||||
@@ -541,7 +541,7 @@ F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454
|
||||
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c d0aa320416efe88c4dbb0156ed6c494f2f9958871a940e46984ee57b3e7fcc50
|
||||
F src/test1.c 5e8b8cc54e8c88906ea8a084387aa79bad245e539f4cee73149e5c0527e1db16
|
||||
F src/test1.c 93cc6cb90fd708c1822ab74543fd586e4d3510236db24ddcc5ef046f74a4b19c
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 405834f6a93ec395cc4c9bb8ecebf7c3d8079e7ca16ae65e82d01afd229694bb
|
||||
@@ -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 1a8807b7dfac4142f5b9047767295327be41f02c17f7bb6bd8ffef6219dac588
|
||||
F src/vdbeapi.c d840fb3b80bbbd25fd44e1bb2d4a209e297832f527d21ea718fa53502a2a2d97
|
||||
F src/vdbeaux.c 66dcae8b09af6c2213da7cfb4ca9ad6e8c4be5d4c1b8dd3eb8c5a1ada9e36ec0
|
||||
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 a137468bf36c92e64d2275caa80c83902e3a0fc59273591b96c6416d3253d05d
|
||||
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
|
||||
@@ -1788,7 +1788,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
|
||||
F tool/mkkeywordhash.c 11a3f3af8e787d0c5ca459ed66fe80fd09e661876506e7b978ec08c19477bdc2
|
||||
F tool/mkkeywordhash.c cb015b0376aea574f00b3b7f7b8e8a43cb52c8adffb2d292454d27aa2567a7b4
|
||||
F tool/mkmsvcmin.tcl 6ecab9fe22c2c8de4d82d4c46797bda3d2deac8e763885f5a38d0c44a895ab33
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
|
||||
@@ -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 1d64f4a8af81fe1235fffa54884d8f842a48ff6a33d6172f0cd65bf42fe8b2a1
|
||||
R 199dfbc9c8ca72850da0099d6c1cde58
|
||||
P 5eaba9af1c35ea7b7c08cad7d0d9b5a4b63b11b3177bb84a570ce1cea44b9f57
|
||||
R b8dc18a0109dd1b6247089b6701d54e2
|
||||
U drh
|
||||
Z 2c8ae1f04515bf2ea893e9cb3af9713c
|
||||
Z 13571b2afccf3e4212df912e00f6dcfa
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
11e0844f71e8f2d27ce9363fb505e02fd7795c61dae0b3886cf0d8df4484dd97
|
||||
e7343ce7514f61eb1aeba22ab83da5b05779080db394332e2e90b4d54cabe123
|
||||
+4
-3
@@ -120,9 +120,10 @@ cmdlist ::= ecmd.
|
||||
ecmd ::= SEMI.
|
||||
ecmd ::= cmdx SEMI.
|
||||
%ifndef SQLITE_OMIT_EXPLAIN
|
||||
ecmd ::= explain cmdx SEMI. {NEVER-REDUCE}
|
||||
explain ::= EXPLAIN. { pParse->explain = 1; }
|
||||
explain ::= EXPLAIN QUERY PLAN. { pParse->explain = 2; }
|
||||
ecmd ::= explain cmdx SEMI. {NEVER-REDUCE}
|
||||
explain ::= EXPLAIN. { pParse->explain = SQLITE_STMTMODE_EXPLAIN; }
|
||||
explain ::= EXPLAIN QUERY PLAN. { pParse->explain = SQLITE_STMTMODE_EQP; }
|
||||
explain ::= EXPLAIN TABLES. { pParse->explain = SQLITE_STMTMODE_TABLELIST; }
|
||||
%endif SQLITE_OMIT_EXPLAIN
|
||||
cmdx ::= cmd. { sqlite3FinishCoding(pParse); }
|
||||
|
||||
|
||||
+1
-1
@@ -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
@@ -5505,7 +5505,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,
|
||||
|
||||
+79
-5
@@ -4132,14 +4132,88 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
|
||||
** prepared statement S is an EXPLAIN statement, or 2 if the
|
||||
** statement S is an EXPLAIN QUERY PLAN.
|
||||
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
|
||||
** an ordinary statement or a NULL pointer.
|
||||
** ^The sqlite3_stmt_isexplain(S) interface returns [SQLITE_STMTMODE_EXPLAIN]
|
||||
** if the prepared statement S is an EXPLAIN statement, or
|
||||
** [SQLITE_STMTMODE_EQP] if the* statement S is an [EXPLAIN QUERY PLAN].
|
||||
** ^The sqlite3_stmt_isexplain(S) interface returns [SQLITE_STMTMODE_RUN]
|
||||
** if S is an ordinary statement or a NULL pointer.
|
||||
**
|
||||
** The sqlite3_stmt_isexplain(S) call is the same thing as
|
||||
** [sqlite3_stmt_mode](S, [SQLITE_STMTMODE_QUERY]).
|
||||
*/
|
||||
int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Set Or Query The Operating Mode For A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** The sqlite3_stmt_mode(S,M) attempts to change the "mode" of
|
||||
** statement S to value M, where M is one of the
|
||||
** [SQLITE_STMTMODE_RUN|statement mode constants]. The value
|
||||
** of the statement mode (after the change) is returned. The mode
|
||||
** change might be disallowed, for example if the statement is currently
|
||||
** in use or for other reasons listed below. If the mode change is
|
||||
** disallowed, then the original mode is returned. The only way to
|
||||
** determine if mode change was effective is to compare the return value
|
||||
** against the second parameter to see if they are the same.
|
||||
**
|
||||
** The mode cannot be changed to SQLITE_STMTMODE_RUN unless the prepared
|
||||
** statement was originally compiled without either the "EXPLAIN" or
|
||||
** "EXPLAIN QUERY PLAN" prefix.
|
||||
**
|
||||
** The mode cannot be changed to SQLITE_STMTMODE_EQP unless the
|
||||
** statement was originally compiled using the "EXPLAIN QUERY PLAN"
|
||||
** prefix.
|
||||
**
|
||||
** If M is SQLITE_STMTMODE_QUERY, then the mode is not changed but the
|
||||
** current mode is still returned. This can be used to query the mode
|
||||
** of a statement without changing it.
|
||||
*/
|
||||
int sqlite3_stmt_mode(sqlite3_stmt*,int);
|
||||
|
||||
/* CAPI3REF: Prepared Statement Modes
|
||||
**
|
||||
** These integer constants are used as the second parameter and the
|
||||
** return value from the [sqlite3_stmt_mode()] interface and as the
|
||||
** return value from [sqlite3_stmt_isexplain()].
|
||||
**
|
||||
** <ul>
|
||||
** <li>[[SQLITE_STMTMODE_RUN]]
|
||||
** The [SQLITE_STMTMODE_RUN] value indicates that the statement will
|
||||
** run the SQL statement as normal. This is the default and usual
|
||||
** mode for a prepared statement.
|
||||
**
|
||||
** <li>[[SQLITE_STMTMODE_EXPLAIN]]
|
||||
** The [SQLITE_STMTMODE_EXPLAIN] value indicates that the statement will
|
||||
** output the [bytecode] used to implement the SQL statement. This is
|
||||
** the mode that a prepared statement is initialized to if the input
|
||||
** SQL begins with the "EXPLAIN" keyword.
|
||||
**
|
||||
** <li>[[SQLITE_STMTMODE_EQP]]
|
||||
** The [SQLITE_STMTMODE_EQP] value indicates that the statement is an
|
||||
** [EXPLAIN QUERY PLAN] statement. In order for this mode to operate
|
||||
** correctly, it is necessary to prepare the statement using the
|
||||
** "EXPLAIN QUERY PLAN" keywords. If a statement is converted into
|
||||
** this mode after having been prepared without the "EXPLAIN QUERY PLAN"
|
||||
** prefix, then it will probably not output the query plan.
|
||||
**
|
||||
** <li>[[SQLITE_STMTMODE_TABLELIST]]
|
||||
** The [SQLITE_STMTMODE_TABLELIST] value indicates that the statement
|
||||
** will output information about all (non-transient) tables and indexes that
|
||||
** are used by the prepared statement.
|
||||
**
|
||||
** <li>[[SQLITE_STMTMODE_QUERY]]
|
||||
** The [SQLITE_STMTMODE_QUERY] value is not an actual statement mode, but
|
||||
** this value can be used as the second parameter to [sqlite3_stmt_mode()]
|
||||
** in order to determine the statement mode without changing it.
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_STMTMODE_RUN 0
|
||||
#define SQLITE_STMTMODE_EXPLAIN 1
|
||||
#define SQLITE_STMTMODE_EQP 2
|
||||
#define SQLITE_STMTMODE_TABLELIST 3
|
||||
#define SQLITE_STMTMODE_QUERY (-1)
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
||||
** METHOD: sqlite3_stmt
|
||||
|
||||
+12
-5
@@ -2697,9 +2697,10 @@ static int SQLITE_TCLAPI test_stmt_readonly(
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_stmt_isexplain STMT
|
||||
** Usage: sqlite3_stmt_mode STMT NEWMODE
|
||||
**
|
||||
** Return 1, 2, or 0 respectively if STMT is an EXPLAIN statement, an
|
||||
** EXPLAIN QUERY PLAN statement or an ordinary statement or NULL pointer.
|
||||
** Return integers 0, 1, 2, or 3 depending on the mode of STMT. If the
|
||||
** 2nd argument is provided, change the mode to the integer in that argument.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_stmt_isexplain(
|
||||
void * clientData,
|
||||
@@ -2710,14 +2711,19 @@ static int SQLITE_TCLAPI test_stmt_isexplain(
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
|
||||
if( objc!=2 ){
|
||||
if( objc!=2 && objc!=3 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
rc = sqlite3_stmt_isexplain(pStmt);
|
||||
if( objc==3 ){
|
||||
int iNewMode = SQLITE_STMTMODE_QUERY;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &iNewMode) ) return TCL_ERROR;
|
||||
rc = sqlite3_stmt_mode(pStmt, iNewMode);
|
||||
}else{
|
||||
rc = sqlite3_stmt_isexplain(pStmt);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -7976,6 +7982,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_next_stmt", test_next_stmt ,0 },
|
||||
{ "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
|
||||
{ "sqlite3_stmt_isexplain", test_stmt_isexplain,0 },
|
||||
{ "sqlite3_stmt_mode", test_stmt_isexplain,0 },
|
||||
{ "sqlite3_stmt_busy", test_stmt_busy ,0 },
|
||||
{ "uses_stmt_journal", uses_stmt_journal ,0 },
|
||||
|
||||
|
||||
+17
-5
@@ -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]);
|
||||
|
||||
+18
-14
@@ -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,24 @@ 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 origExplain:2; /* The original value of explain */
|
||||
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 */
|
||||
@@ -497,6 +500,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*);
|
||||
|
||||
+32
-4
@@ -996,8 +996,17 @@ 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 */
|
||||
5 /* SQLITE_STMTMODE_TABLELIST */
|
||||
};
|
||||
Vdbe *pVm = (Vdbe *)pStmt;
|
||||
return pVm ? pVm->nResColumn : 0;
|
||||
if( pVm==0 ) return 0;
|
||||
assert( pVm->explain>=0 && pVm->explain<=3 );
|
||||
if( pVm->explain==0 ) return pVm->nResColumn;
|
||||
return (int)anColumn[pVm->explain];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1006,8 +1015,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 +1070,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 +1220,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]);
|
||||
@@ -1683,6 +1693,24 @@ int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
|
||||
return pStmt ? ((Vdbe*)pStmt)->explain : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Query or set the mode for a prepared statement.
|
||||
*/
|
||||
int sqlite3_stmt_mode(sqlite3_stmt *pStmt, int iNewMode){
|
||||
Vdbe *v;
|
||||
if( pStmt==0 ) return SQLITE_STMTMODE_RUN;
|
||||
v = (Vdbe*)pStmt;
|
||||
if( iNewMode==SQLITE_STMTMODE_EXPLAIN
|
||||
|| iNewMode==SQLITE_STMTMODE_TABLELIST
|
||||
|| iNewMode==v->origExplain
|
||||
){
|
||||
if( v->magic==VDBE_MAGIC_RUN && v->pc<0 ){
|
||||
v->explain = iNewMode;
|
||||
}
|
||||
}
|
||||
return v->explain;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the prepared statement is in need of being reset.
|
||||
*/
|
||||
|
||||
+148
-83
@@ -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,66 @@ 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",
|
||||
"schema", "name", "type", "rw", "src"
|
||||
};
|
||||
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 if( p->explain==SQLITE_STMTMODE_EQP ){
|
||||
iFirst = 8;
|
||||
cnt = 4;
|
||||
}else{
|
||||
iFirst = 12;
|
||||
cnt = 5;
|
||||
}
|
||||
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 +2036,13 @@ 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
|
||||
|| p->explain==SQLITE_STMTMODE_TABLELIST );
|
||||
assert( p->magic==VDBE_MAGIC_RUN );
|
||||
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
|
||||
|
||||
@@ -2002,8 +2050,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 +2073,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 +2087,7 @@ int sqlite3VdbeList(
|
||||
nRow += apSub[i]->nOp;
|
||||
}
|
||||
}
|
||||
p->pResultSet = pMem;
|
||||
|
||||
while(1){ /* Loop exits via break */
|
||||
i = p->pc++;
|
||||
@@ -2065,7 +2116,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 +2133,23 @@ 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 if( p->explain==SQLITE_STMTMODE_EQP ){
|
||||
/* 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;
|
||||
}else{
|
||||
/* TABLELIST wants OP_Open opcodes only */
|
||||
if( pOp->opcode==OP_OpenRead ) break;
|
||||
if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
|
||||
if( pOp->opcode==OP_ReopenIdx ) break;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2097,32 +2157,52 @@ int sqlite3VdbeList(
|
||||
p->rc = SQLITE_INTERRUPT;
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
|
||||
}else if( p->explain==SQLITE_STMTMODE_TABLELIST ){
|
||||
Schema *pSchema;
|
||||
HashElem *k;
|
||||
int iDb = pOp->p3;
|
||||
int iRoot = pOp->p2;
|
||||
const char *zName = 0;
|
||||
const char *zType = 0;
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
sqlite3VdbeMemSetStr(pMem++, db->aDb[iDb].zDbSName, -1,
|
||||
SQLITE_UTF8, SQLITE_STATIC);
|
||||
pSchema = db->aDb[iDb].pSchema;
|
||||
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||
Table *pTab = (Table*)sqliteHashData(k);
|
||||
if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
|
||||
zName = pTab->zName;
|
||||
zType = "table";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( zName==0 ){
|
||||
for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
|
||||
Index *pIdx = (Index*)sqliteHashData(k);
|
||||
if( pIdx->tnum==iRoot ){
|
||||
zName = pIdx->zName;
|
||||
zType = "index";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3VdbeMemSetStr(pMem++, zName, -1, SQLITE_UTF8, SQLITE_STATIC);
|
||||
sqlite3VdbeMemSetStr(pMem++, zType, 5, SQLITE_UTF8, SQLITE_STATIC);
|
||||
sqlite3VdbeMemSetInt64(pMem++, pOp->opcode==OP_OpenWrite);
|
||||
sqlite3VdbeMemSetInt64(pMem++, i<p->pc-1);
|
||||
p->nRes = 5;
|
||||
p->rc = SQLITE_OK;
|
||||
rc = SQLITE_ROW;
|
||||
}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 +2220,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 +2242,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 +2450,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 = p->origExplain = pParse->explain;
|
||||
}
|
||||
p->expired = 0;
|
||||
|
||||
@@ -2425,7 +2488,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 +2625,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 +3372,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 +3477,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
@@ -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];
|
||||
|
||||
@@ -288,6 +288,7 @@ static Keyword aKeywordTable[] = {
|
||||
{ "SELECT", "TK_SELECT", ALWAYS, 10 },
|
||||
{ "SET", "TK_SET", ALWAYS, 10 },
|
||||
{ "TABLE", "TK_TABLE", ALWAYS, 1 },
|
||||
{ "TABLES", "TK_TABLES", EXPLAIN, 10 },
|
||||
{ "TEMP", "TK_TEMP", ALWAYS, 1 },
|
||||
{ "TEMPORARY", "TK_TEMP", ALWAYS, 1 },
|
||||
{ "THEN", "TK_THEN", ALWAYS, 3 },
|
||||
|
||||
Reference in New Issue
Block a user