From d1a1c23423560f4cac2cab305d92bb2d67a04d57 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 3 Nov 2014 16:35:55 +0000 Subject: [PATCH] Refactor the interface to make it more easily extensible. FossilOrigin-Name: 7955342da4a35b57e4ae26690b8d40f7bba20e8f --- manifest | 18 +++++----- manifest.uuid | 2 +- src/sqlite.h.in | 93 ++++++++++++++++++++++++++++++------------------- src/test1.c | 8 +++-- src/vdbeapi.c | 46 +++++++++++++++--------- 5 files changed, 102 insertions(+), 65 deletions(-) diff --git a/manifest b/manifest index 5c51df5fcc..134366e0aa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sfurther\stests.\sFixes\sso\sthat\scompilation\swithout\sENABLE_STMT_SCANSTATUS\sworks. -D 2014-11-03T15:33:17.869 +C Refactor\sthe\sinterface\sto\smake\sit\smore\seasily\sextensible. +D 2014-11-03T16:35:55.977 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 282f8f5278e0c78eb442217531172ec9e1538796 -F src/sqlite.h.in aeba29025ba5fc721a11c1b81ed8745f93029590 +F src/sqlite.h.in a110c6320b3af8d7c0660fa1adbc530b6caa2d95 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h 4f86ac648ea398c1bb3db036062934cde257ea23 @@ -237,7 +237,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc F src/tclsqlite.c 7cdd4dd3c2a4183483feca260070d73d6e22cd47 -F src/test1.c b53f4da2f386efa5c248716cd4bdc8344a87e952 +F src/test1.c 5890094c09691fe9564cf0f0d5b22d35b3218c47 F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712 F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df @@ -292,7 +292,7 @@ F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a F src/vdbe.c 175a360c56e75ce4eb2b60704fd7c011b93926f5 F src/vdbe.h d412bd01e89f0d69991b8f46601f96bc169d28f4 F src/vdbeInt.h 539ba284790e871f98be74a78cbdfcedfae22639 -F src/vdbeapi.c addf446ecade237bebd7e9fe769bdfb9db8d9fb1 +F src/vdbeapi.c 76d62888455e3d3ffeaf70911cefa94e76a4678a F src/vdbeaux.c cf6b8152dd22155201d57c216e6266866b61da59 F src/vdbeblob.c 8b5442ff0954c44b45cbabbe2e94091a2e16fdef F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f @@ -1211,7 +1211,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f5313e0c680d9baebefb1cf50ddadedd4418a334 -R b9cde6c71acdc4fef0c5c1ac03d62018 -U dan -Z f0600457ea98c0c998694790015a9674 +P a2303c719222f1effb51acc6b37930561148c00c +R cbd06b886fdee03f70c2bf18e1342ca1 +U drh +Z 0328a60e2b5415c07361c47ade3f21c5 diff --git a/manifest.uuid b/manifest.uuid index fe7315da12..5fd1f91e84 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a2303c719222f1effb51acc6b37930561148c00c \ No newline at end of file +7955342da4a35b57e4ae26690b8d40f7bba20e8f \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 51383426d9..30ef4afb60 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7406,54 +7406,75 @@ int sqlite3_vtab_on_conflict(sqlite3 *); /* #define SQLITE_ABORT 4 // Also an error code */ #define SQLITE_REPLACE 5 +/* CAPI3REF: Prepared Statement Scan Status Opcodes +** KEYWORDS: {scanstatus option} +** +** The following constants can be used for the T parameter to the +** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a +** different metric for sqlite3_stmt_scanstatus() to return. +** +**
+** [[SQLITE_SCANSTAT_NLOOP]] SQLITE_SCANSTAT_NLOOP +**
The [sqlite3_int64] variable pointed to by the T parameter will be set to the +** total number of times that the X-th loop has run.
+** +** [[SQLITE_SCANSTAT_NVISIT]] SQLITE_SCANSTAT_NVISIT +**
The [sqlite3_int64] variable pointed to by the T parameter will be set to the +** total number of rows visited by the X-th loop.
+** +** [[SQLITE_SCANSTAT_EST]] SQLITE_SCANSTAT_EST +**
The [sqlite3_int64] variable pointed to by the T parameter will be set to the +** query planner's estimate for the number of rows visited for each +** iteration of the X-th loop. If the query planner's estimate was accurate, +** then this value should be approximately NVISIT/NLOOP. +** +** [[SQLITE_SCANSTAT_NAME]] SQLITE_SCANSTAT_NAME +**
The "const char *" variable pointed to by the T parameter will be set to +** a zero-terminated UTF-8 string containing the name of the index or table used +** for the X-th loop. +** +** [[SQLITE_SCANSTAT_EXPLAIN]] SQLITE_SCANSTAT_EXPLAIN +**
The "const char *" variable pointed to by the T parameter will be set to +** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description +** for the X-th loop. +**
+*/ +#define SQLITE_SCANSTAT_NLOOP 0 +#define SQLITE_SCANSTAT_NVISIT 1 +#define SQLITE_SCANSTAT_NEST 2 +#define SQLITE_SCANSTAT_NAME 3 +#define SQLITE_SCANSTAT_EXPLAIN 4 /* -** CAPI3REF: Prepared Statement Scan Statuses +** CAPI3REF: Prepared Statement Scan Status ** ** Return status data for a single loop within query pStmt. ** +** The "iScanStatusOp" parameter determines which status information to return. +** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of +** this interface is undefined. +** The requested measurement is written into a variable pointed to by +** the "pOut" parameter. ** Parameter "idx" identifies the specific loop to retrieve statistics for. ** Loops are numbered starting from zero. If idx is out of range - less than ** zero or greater than or equal to the total number of loops used to implement -** the statement - a non-zero value is returned. In this case the final value -** of all five output parameters is undefined. Otherwise, if idx is in range, -** zero is returned and the output parameters set as follows: +** the statement - a non-zero value is returned and the variable that pOut +** points to is unchanged. ** -** -** -** Output parameters *pzName and *pzExplain are set to point to buffers -** managed by the statement object. Both of these pointers may be invalidated -** by any API call on the same statement object, including an sqlite3_step() -** sqlite3_bind_*() call. -** -** Statistics may not be available for all loops in all statements. In cases -** where there exist loops with no available statistics, this function ignores -** them completely. +** Statistics might not be available for all loops in all statements. In cases +** where there exist loops with no available statistics, this function behaves +** as if the loop did not exist - it returns non-zero and leave the variable +** that pOut points to unchanged. ** ** This API is only available if the library is built with pre-processor -** symbol SQLITE_ENABLE_STMT_SCANSTATUS defined. +** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, - int idx, /* Index of loop to report on */ - sqlite3_int64 *pnLoop, /* OUT: Number of times loop was run */ - sqlite3_int64 *pnVisit, /* OUT: Number of rows visited (all loops) */ - sqlite3_int64 *pnEst, /* OUT: Number of rows estimated (per loop) */ - const char **pzName, /* OUT: Object name (table or index) */ - const char **pzExplain /* OUT: EQP string */ -); - + sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ + int idx, /* Index of loop to report on */ + int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ + void *pOut /* Result written here */ +); /* ** CAPI3REF: Zero Scan-Status Counters @@ -7461,7 +7482,7 @@ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( ** Zero all sqlite3_stmt_scanstatus() related event counters. ** ** This API is only available if the library is built with pre-processor -** symbol SQLITE_ENABLE_STMT_SCANSTATUS defined. +** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); diff --git a/src/test1.c b/src/test1.c index 72e70513bc..5e526b3013 100644 --- a/src/test1.c +++ b/src/test1.c @@ -2328,19 +2328,21 @@ static int test_stmt_scanstatus( if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; - res = sqlite3_stmt_scanstatus( - pStmt, idx, &nLoop, &nVisit, &nEst, &zName, &zExplain - ); + res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop); if( res==0 ){ Tcl_Obj *pRet = Tcl_NewObj(); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop)); + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit)); + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&nEst); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nEst)); + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1)); + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1)); Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1)); Tcl_SetObjResult(interp, pRet); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index e6eb034ae9..d3ba4e95d2 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1481,27 +1481,42 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ ** Return status data for a single loop within query pStmt. */ int sqlite3_stmt_scanstatus( - sqlite3_stmt *pStmt, + sqlite3_stmt *pStmt, /* Prepared statement being queried */ int idx, /* Index of loop to report on */ - sqlite3_int64 *pnLoop, /* OUT: Number of times loop was run */ - sqlite3_int64 *pnVisit, /* OUT: Number of rows visited (all loops) */ - sqlite3_int64 *pnEst, /* OUT: Number of rows estimated (per loop) */ - const char **pzName, /* OUT: Object name (table or index) */ - const char **pzExplain /* OUT: EQP string */ + int iScanStatusOp, /* Which metric to return */ + void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; ScanStatus *pScan; if( idx<0 || idx>=p->nScan ) return 1; pScan = &p->aScan[idx]; - if( pnLoop ) *pnLoop = p->anExec[pScan->addrLoop]; - if( pnVisit ) *pnVisit = p->anExec[pScan->addrVisit]; - if( pnEst ) *pnEst = pScan->nEst; - if( *pzName ) *pzName = pScan->zName; - if( *pzExplain ){ - if( pScan->addrExplain ){ - *pzExplain = p->aOp[ pScan->addrExplain ].p4.z; - }else{ - *pzExplain = 0; + switch( iScanStatusOp ){ + case SQLITE_SCANSTAT_NLOOP: { + *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop]; + break; + } + case SQLITE_SCANSTAT_NVISIT: { + *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit]; + break; + } + case SQLITE_SCANSTAT_EST: { + *(sqlite3_int64*)pOut = pScan->nEst; + break; + } + case SQLITE_SCANSTAT_NAME: { + *(const char**)pOut = pScan->zName + break; + } + case SQLITE_SCANSTAT_EXPLAIN: { + if( pScan->addrExplain ){ + *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; + }else{ + *(const char**)pOut = 0; + } + break; + } + default: { + return 1; } } return 0; @@ -1515,4 +1530,3 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ memset(p->anExec, 0, p->nOp * sizeof(i64)); } #endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ - -- 2.47.2