SCAN t1 USING COVERING INDEX t1_idx_01a7214e
}
+ifcapable fts5 {
+ do_setup_rec_test $tn.20.0 {
+ CREATE VIRTUAL TABLE ft USING fts5(a);
+ CREATE TABLE t1(x, y);
+ } {
+ SELECT * FROM ft, t1 WHERE a=x
+ } {
+ CREATE INDEX t1_idx_00000078 ON t1(x);
+ SCAN ft VIRTUAL TABLE INDEX 0:
+ SEARCH t1 USING INDEX t1_idx_00000078 (x=?)
+ }
+}
+
}
proc do_candidates_test {tn sql res} {
CREATE INDEX x1_idx_00000062 ON x1(b);
}
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 7.0 {
+ CREATE VIRTUAL TABLE ft USING fts5(a);
+ CREATE TABLE t1(x, y);
+}
+
+do_candidates_test 7.1 {
+ SELECT * FROM ft, t1 WHERE a=x
+} {
+ CREATE INDEX t1_idx_00000078 ON t1(x);
+}
+
+register_tcl_module db
+proc vtab_command {method args} {
+ global G
+
+ switch -- $method {
+ xConnect {
+ return "CREATE TABLE t1(a, b, c);"
+ }
+
+ xBestIndex {
+ return [list]
+ }
+
+ xFilter {
+ return [list sql "SELECT rowid, * FROM t0"]
+ }
+ }
+
+ return {}
+}
+
+do_execsql_test 7.2 {
+ CREATE TABLE t0(a, b, c);
+ INSERT INTO t0 VALUES(1, 2, 3), (11, 22, 33);
+ CREATE VIRTUAL TABLE t2 USING tcl(vtab_command);
+}
+
+do_execsql_test 7.3 {
+ SELECT * FROM t2
+} {
+ 1 2 3
+ 11 22 33
+}
+
+do_candidates_test 7.4 {
+ SELECT * FROM ft, t1 WHERE a=x
+} {
+ CREATE INDEX t1_idx_00000078 ON t1(x);
+}
+
+do_test 7.5 {
+ set expert [sqlite3_expert_new db]
+ list [catch { $expert sql "SELECT * FROM ft, t2 WHERE b=1" } msg] $msg
+} {1 {no such table: t2}}
+$expert destroy
+
finish_test
return rc;
}
+/*
+** This function tests if the schema of the main database of database handle
+** db contains an object named zTab. Assuming no error occurs, output parameter
+** (*pbContains) is set to true if zTab exists, or false if it does not.
+**
+** Or, if an error occurs, an SQLite error code is returned. The final value
+** of (*pbContains) is undefined in this case.
+*/
+static int expertDbContainsObject(
+ sqlite3 *db,
+ const char *zTab,
+ int *pbContains /* OUT: True if object exists */
+){
+ const char *zSql = "SELECT 1 FROM sqlite_schema WHERE name = ?";
+ sqlite3_stmt *pSql = 0;
+ int rc = SQLITE_OK;
+ int ret = 0;
+
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_text(pSql, 1, zTab, -1, SQLITE_STATIC);
+ if( SQLITE_ROW==sqlite3_step(pSql) ){
+ ret = 1;
+ }
+ rc = sqlite3_finalize(pSql);
+ }
+
+ *pbContains = ret;
+ return rc;
+}
+
+/*
+** Execute SQL command zSql using database handle db. If no error occurs,
+** set (*pzErr) to NULL and return SQLITE_OK.
+**
+** If an error does occur, return an SQLite error code and set (*pzErr) to
+** point to a buffer containing an English language error message. Except,
+** if the error message begins with "no such module:", then ignore the
+** error and return as if the SQL statement had succeeded.
+**
+** This is used to copy as much of the database schema as possible while
+** ignoring any errors related to missing virtual table modules.
+*/
+static int expertSchemaSql(sqlite3 *db, const char *zSql, char **pzErr){
+ int rc = SQLITE_OK;
+ char *zErr = 0;
+
+ rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
+ if( rc!=SQLITE_OK && zErr ){
+ int nErr = STRLEN(zErr);
+ if( nErr>=15 && memcmp(zErr, "no such module:", 15)==0 ){
+ sqlite3_free(zErr);
+ rc = SQLITE_OK;
+ zErr = 0;
+ }
+ }
+
+ *pzErr = zErr;
+ return rc;
+}
static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
int rc = idxRegisterVtab(p);
** 2) Create the equivalent virtual table in dbv.
*/
rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
- "SELECT type, name, sql, 1 FROM sqlite_schema "
+ "SELECT type, name, sql, 1, sql LIKE 'create virtual%' "
+ "FROM sqlite_schema "
"WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
" UNION ALL "
- "SELECT type, name, sql, 2 FROM sqlite_schema "
+ "SELECT type, name, sql, 2, 0 FROM sqlite_schema "
"WHERE type = 'trigger'"
" AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
- "ORDER BY 4, 1"
+ "ORDER BY 4, 5 DESC, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
+ int bVirtual = sqlite3_column_int(pSchema, 4);
+ int bExists = 0;
if( zType==0 || zName==0 ) continue;
- if( zType[0]=='v' || zType[1]=='r' ){
- if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
+ rc = expertDbContainsObject(p->dbv, zName, &bExists);
+ if( rc || bExists ) continue;
+
+ if( zType[0]=='v' || zType[1]=='r' || bVirtual ){
+ /* A view. Or a trigger on a view. */
+ if( zSql ) rc = expertSchemaSql(p->dbv, zSql, pzErrmsg);
}else{
IdxTable *pTab;
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
if( rc==SQLITE_OK ){
sqlite3_stmt *pSql = 0;
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
- "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
- " AND sql NOT LIKE 'CREATE VIRTUAL %%' ORDER BY rowid"
+ "SELECT sql, name "
+ " FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
+ " ORDER BY rowid"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
- if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
+ const char *zName = (const char*)sqlite3_column_text(pSql, 1);
+ int bExists = 0;
+ rc = expertDbContainsObject(pNew->dbm, zName, &bExists);
+ if( rc==SQLITE_OK && zSql && bExists==0 ){
+ rc = expertSchemaSql(pNew->dbm, zSql, pzErrmsg);
+ }
}
idxFinalize(&rc, pSql);
}
-C Additional\sclarification\sin\sthe\scomments\sto\ssqlite3_stdio.c.\s\sNo\schanges\nto\scode.
-D 2024-10-11T23:31:37.983
+C Allow\sthe\s".expert"\scommand\sto\sanalyze\sstatements\sthat\suse\sbuilt-in\svirtual\stables.
+D 2024-10-12T18:00:22.050
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test b10f9e20f64102a015c0fcf54cb7b7680266b397e91d93cdad45f57857cdfba6
-F ext/expert/sqlite3expert.c df417a6d91873a74d35daa9259171647c23c6601415e938e8a71702703f3d677
+F ext/expert/expert1.test e049c507d33f7a7cf92ea6b15ac630cbc22598e387ec6749c2c5e1a5405e15a7
+F ext/expert/sqlite3expert.c b7cbbd7cc109c66ebdf6091467d790abb9d7c25ae3b822bb76388509641d37de
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 9621c3b527702b47799538e028f96945b5697752dbb56078aa7f114c72fd4e1a
-R 659759ae0159a7655f5b52c1145c8c1c
-U drh
-Z 640899f5a3ac016602bbc301589aaa54
+P 2db24c5364808008fa503f37ca8ccf5d135e8f6bfac2efb29e509e26f7190470
+R 3ec70cb458fa17a25b97de6754d185ac
+T *branch * expert-vtab-fix
+T *sym-expert-vtab-fix *
+T -sym-trunk *
+U dan
+Z e6ab462e3ffdb8d19a80b4f488adc3f5
# Remove this line to create a well-formed Fossil manifest.