if( rc==SQLITE_OK ){
int nQuery = sqlite3_expert_count(p);
+ if( iVerbose>0 ){
+ const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
+ fprintf(stdout, "-- Candidates -------------------------------\n");
+ fprintf(stdout, "%s\n", zCand);
+ }
for(i=0; i<nQuery; i++){
const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
+ if( zIdx==0 ) zIdx = "(no new indexes)";
if( iVerbose>0 ){
- fprintf(stdout, "-- query %d ----------------------------------\n",i+1);
+ fprintf(stdout, "-- Query %d ----------------------------------\n",i+1);
fprintf(stdout, "%s\n\n", zSql);
}
fprintf(stdout, "%s\n%s\n", zIdx, zEQP);
set result [list]
for {set i 0} {$i < [$expert count]} {incr i} {
- lappend result [string trim [$expert report $i indexes]]
+ set idx [string trim [$expert report $i indexes]]
+ if {$idx==""} {set idx "(no new indexes)"}
+ lappend result $idx
lappend result [string trim [$expert report $i plan]]
}
struct sqlite3expert {
sqlite3 *db; /* User database */
sqlite3 *dbm; /* In-memory db for this analysis */
- int bRun; /* True once analysis has run */
- char **pzErrmsg;
IdxScan *pScan; /* List of scan objects */
IdxStatement *pStatement; /* List of IdxStatement objects */
+ int bRun; /* True once analysis has run */
+ char **pzErrmsg;
int rc; /* Error code from whereinfo hook */
IdxHash hIdx; /* Hash containing all candidate indexes */
+ char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */
};
for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
}
- if( pStmt->zIdx==0 ){
- pStmt->zIdx = idxAppendText(&rc, 0, "(no new indexes)\n");
- }
idxFinalize(&rc, pExplain);
}
int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
int rc;
+ IdxHashEntry *pEntry;
/* Create candidate indexes within the in-memory database file */
rc = idxCreateCandidates(p, pzErr);
+ for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
+ p->zCandidates = idxAppendText(&rc, p->zCandidates, "%s;\n", pEntry->zVal);
+ }
+
/* Figure out which of the candidate indexes are preferred by the query
** planner and report the results to the user. */
if( rc==SQLITE_OK ){
if( p->bRun==0 ) return 0;
for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
- if( pStmt ){
- switch( eReport ){
- case EXPERT_REPORT_SQL:
- zRet = pStmt->zSql;
- break;
- case EXPERT_REPORT_INDEXES:
- zRet = pStmt->zIdx;
- break;
- case EXPERT_REPORT_PLAN:
- zRet = pStmt->zEQP;
- break;
- }
+ switch( eReport ){
+ case EXPERT_REPORT_SQL:
+ if( pStmt ) zRet = pStmt->zSql;
+ break;
+ case EXPERT_REPORT_INDEXES:
+ if( pStmt ) zRet = pStmt->zIdx;
+ break;
+ case EXPERT_REPORT_PLAN:
+ if( pStmt ) zRet = pStmt->zEQP;
+ break;
+ case EXPERT_REPORT_CANDIDATES:
+ zRet = p->zCandidates;
+ break;
}
return zRet;
}
/*
** Create a new sqlite3expert object.
+**
+** If successful, a pointer to the new object is returned and (*pzErr) set
+** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
+** an English-language error message. In this case it is the responsibility
+** of the caller to eventually free the error message buffer using
+** sqlite3_free().
*/
sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
/*
-** Add an SQL statement to the analysis.
+** Specify zero or more SQL statements to be included in the analysis.
+**
+** Buffer zSql must contain zero or more complete SQL statements. This
+** function parses all statements contained in the buffer and adds them
+** to the internal list of statements to analyze. If successful, SQLITE_OK
+** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
+** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
+** may be set to point to an English language error message. In this case
+** the caller is responsible for eventually freeing the error message buffer
+** using sqlite3_free().
+**
+** If an error does occur while processing one of the statements in the
+** buffer passed as the second argument, none of the statements in the
+** buffer are added to the analysis.
+**
+** This function must be called before sqlite3_expert_analyze(). If a call
+** to this function is made on an sqlite3expert object that has already
+** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
+** immediately and no statements are added to the analysis.
*/
int sqlite3_expert_sql(
- sqlite3expert *p, /* From sqlite3_expert_new() */
- const char *zSql, /* SQL statement to add */
+ sqlite3expert *p, /* From a successful sqlite3_expert_new() */
+ const char *zSql, /* SQL statement(s) to add */
char **pzErr /* OUT: Error message (if any) */
);
+/*
+** This function is called after the sqlite3expert object has been configured
+** with all SQL statements using sqlite3_expert_sql() to actually perform
+** the analysis. Once this function has been called, it is not possible to
+** add further SQL statements to the analysis.
+**
+** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
+** an error occurs, an SQLite error code is returned and (*pzErr) set to
+** point to a buffer containing an English language error message. In this
+** case it is the responsibility of the caller to eventually free the buffer
+** using sqlite3_free().
+**
+** If an error does occur within this function, the sqlite3expert object
+** is no longer useful for any purpose. At that point it is no longer
+** possible to add further SQL statements to the object or to re-attempt
+** the analysis. The sqlite3expert object must still be freed using a call
+** sqlite3_expert_destroy().
+*/
int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
/*
-** Return the total number of SQL queries loaded via sqlite3_expert_sql().
+** Return the total number of statements loaded using sqlite3_expert_sql().
+** The total number of SQL statements may be different from the total number
+** to calls to sqlite3_expert_sql().
*/
int sqlite3_expert_count(sqlite3expert*);
/*
** Return a component of the report.
+**
+** This function is called after sqlite3_expert_analyze() to extract the
+** results of the analysis. Each call to this function returns either a
+** NULL pointer or a pointer to a buffer containing a nul-terminated string.
+** The value passed as the third argument must be one of the EXPERT_REPORT_*
+** #define constants defined below.
+**
+** For some EXPERT_REPORT_* parameters, the buffer returned contains
+** information relating to a specific SQL statement. In these cases that
+** SQL statement is identified by the value passed as the second argument.
+** SQL statements are numbered from 0 in the order in which they are parsed.
+** If an out-of-range value (less than zero or equal to or greater than the
+** value returned by sqlite3_expert_count()) is passed as the second argument
+** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
+**
+** EXPERT_REPORT_SQL:
+** Return the text of SQL statement iStmt.
+**
+** EXPERT_REPORT_INDEXES:
+** Return a buffer containing the CREATE INDEX statements for all recommended
+** indexes for statement iStmt. If there are no new recommeded indexes, NULL
+** is returned.
+**
+** EXPERT_REPORT_PLAN:
+** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
+** iStmt after the proposed indexes have been added to the database schema.
+**
+** EXPERT_REPORT_CANDIDATES:
+** Return a pointer to a buffer containing the CREATE INDEX statements
+** for all indexes that were tested (for all SQL statements). The iStmt
+** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
*/
const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
#define EXPERT_REPORT_SQL 1
#define EXPERT_REPORT_INDEXES 2
#define EXPERT_REPORT_PLAN 3
+#define EXPERT_REPORT_CANDIDATES 4
/*
-** Free an (sqlite3expert*) handle allocated by sqlite3-expert_new().
+** Free an (sqlite3expert*) handle and all associated resources. There
+** should be one call to this function for each successful call to
+** sqlite3-expert_new().
*/
void sqlite3_expert_destroy(sqlite3expert*);
-C Add\sext/expert/README.md.
-D 2017-04-10T20:00:26.414
+C Add\sheader\scomments\sto\sthe\sAPI\sfunctions\sin\ssqlite3expert.h.\sInclude\sa\slist\sof\nall\scandidate\sindexes\sin\sthe\sreport\soutput\sby\sthe\ssqlite3_expert\sprogram.
+D 2017-04-11T17:43:12.842
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
F ext/expert/README.md 9f15075ec5ad772808eff55ef044c31140fd1146aa0a3c47eafd155e71851b01
-F ext/expert/expert.c bf0fd71921cb7b807cda9a76fb380e3d6e6b980d6167093b2952b41ec9ad8f46
-F ext/expert/expert1.test d4451ccdca910ec3652a7a1994210fe2b7bc8f56431ed0cf2ff3dee798c89084
-F ext/expert/sqlite3expert.c 8bcb83b3723239dc6a2a199e7a030741b7ecf47814828a1da7ea559aa42f094a
-F ext/expert/sqlite3expert.h feeaee4ab73ba52426329781bbb28032ce18cf5abd2bf6221bac2df4c32b3013
+F ext/expert/expert.c 5bcc2fba8509fd1ddeb755df9273e9667ce82cda97b0dd6240792d9b9e86a873
+F ext/expert/expert1.test cc33f9390f205bfeb6a30c7618b24a5675f4b9cb844c9154c11398a7f1477e81
+F ext/expert/sqlite3expert.c 2b22a5fbd093a7020ea9625928292265f31b8e78f6feabb987e71a79b2a29089
+F ext/expert/sqlite3expert.h b1c9eedeb647fd734c4206ae6851635284cfbfa5fb688eff74c3265c9f949b4d
F ext/expert/test_expert.c bad0611732d07180d586bd589cbb7713dc3ab0338c52bff29680eb2007678c05
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 5dd9831721b70a89a26728adcd49c7f6103ef8266891a79c2db34d913702709e
-R 119e273740189bcdef018d8609f3a756
+P 9318f1b9ed2d8da3a82ea69179e2d56a99d326c7721642665f87f6a4534e7bf0
+R 15f16c821c74aae47eac0f21fc6788f2
U dan
-Z 664c10ad907cc8fb129a4f4feaf498a1
+Z 914bc7396f378320666a7fa77328351c
-9318f1b9ed2d8da3a82ea69179e2d56a99d326c7721642665f87f6a4534e7bf0
\ No newline at end of file
+0c45c5eb9f0f171b8d7c5f0d2973f9f59915467506cdff1450f3e4b2134a01ca
\ No newline at end of file