Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -2965,8 +2965,22 @@ while( zFilename[0] ){ int x = strcmp(zFilename, zParam); zFilename += sqlite3Strlen30(zFilename) + 1; if( x==0 ) return zFilename; zFilename += sqlite3Strlen30(zFilename) + 1; + } + return 0; +} + +/* +** Return the filename of the database associated with a database +** connection. +*/ +const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ + int i; + for(i=0; inDb; i++){ + if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){ + return sqlite3BtreeGetFilename(db->aDb[i].pBt); + } } return 0; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -4371,10 +4371,21 @@ ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +/* +** CAPI3REF: Return The Filename For A Database Connection +** +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database +** connection D, or if database N is a temporary or in-memory database, then +** a NULL pointer is returned. +*/ +const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); + /* ** CAPI3REF: Find the next prepared statement ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -4615,10 +4615,33 @@ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_release_memory(db); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } + +/* +** Usage: sqlite3_db_filename DB DBNAME +** +** Return the name of a file associated with a database. +*/ +static int test_db_filename( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + const char *zDbName; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zDbName = Tcl_GetString(objv[2]); + Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0); + return TCL_OK; +} /* ** Usage: sqlite3_soft_heap_limit ?N? ** ** Query or set the soft heap limit for the current thread. The @@ -5939,10 +5962,11 @@ { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, { "uses_stmt_journal", uses_stmt_journal ,0 }, { "sqlite3_release_memory", test_release_memory, 0}, { "sqlite3_db_release_memory", test_db_release_memory, 0}, + { "sqlite3_db_filename", test_db_filename, 0}, { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, { "sqlite3_load_extension", test_load_extension, 0}, Index: test/attach.test ================================================================== --- test/attach.test +++ test/attach.test @@ -49,10 +49,29 @@ execsql { ATTACH DATABASE 'test2.db' AS two; SELECT * FROM two.t2; } } {1 x 2 y} + +# Tests for the sqlite3_db_filename interface +# +do_test attach-1.3.1 { + file tail [sqlite3_db_filename db main] +} {test.db} +do_test attach-1.3.2 { + file tail [sqlite3_db_filename db MAIN] +} {test.db} +do_test attach-1.3.3 { + file tail [sqlite3_db_filename db temp] +} {} +do_test attach-1.3.4 { + file tail [sqlite3_db_filename db two] +} {test2.db} +do_test attach-1.3.5 { + file tail [sqlite3_db_filename db three] +} {} + do_test attach-1.4 { execsql { SELECT * FROM t2; } } {1 x 2 y}