Index: System.Data.SQLite/SQLite3.cs ================================================================== --- System.Data.SQLite/SQLite3.cs +++ System.Data.SQLite/SQLite3.cs @@ -854,10 +854,46 @@ /// internal override bool IsOpen() { return (_sql != null) && !_sql.IsInvalid && !_sql.IsClosed; } + + /// + /// Returns the fully qualified path and file name for the currently open + /// database, if any. + /// + /// + /// The name of the attached database to query. + /// + /// + /// The fully qualified path and file name for the currently open database, + /// if any. + /// + internal override string GetFileName(string dbName) + { + if (_sql == null) + return null; + + IntPtr pDbName = IntPtr.Zero; + + try + { + pDbName = (dbName != null) ? + SQLiteString.Utf8IntPtrFromString(dbName) : IntPtr.Zero; + + return UTF8ToString(UnsafeNativeMethods.sqlite3_db_filename( + _sql, pDbName), -1); + } + finally + { + if (pDbName != IntPtr.Zero) + { + SQLiteMemory.Free(pDbName); + pDbName = IntPtr.Zero; + } + } + } internal override void Open(string strFilename, string vfsName, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool) { // // NOTE: If the database connection is currently open, attempt to Index: System.Data.SQLite/SQLiteBase.cs ================================================================== --- System.Data.SQLite/SQLiteBase.cs +++ System.Data.SQLite/SQLiteBase.cs @@ -90,10 +90,22 @@ /// /// /// Non-zero if a database connection is open. /// internal abstract bool IsOpen(); + /// + /// Returns the fully qualified path and file name for the currently open + /// database, if any. + /// + /// + /// The name of the attached database to query. + /// + /// + /// The fully qualified path and file name for the currently open database, + /// if any. + /// + internal abstract string GetFileName(string dbName); /// /// Opens a database. /// /// /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -2026,10 +2026,31 @@ { CheckDisposed(); return _dataSource; } } + + /// + /// Returns the fully qualified path and file name for the currently open + /// database, if any. + /// +#if !PLATFORM_COMPACTFRAMEWORK + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] +#endif + public string FileName + { + get + { + CheckDisposed(); + + if (_sql == null) + throw new InvalidOperationException( + "Database connection not valid for getting file name."); + + return _sql.GetFileName("main"); + } + } /// /// Returns the string "main". /// #if !PLATFORM_COMPACTFRAMEWORK @@ -2725,11 +2746,11 @@ fileName = MemoryFileName; else { #if PLATFORM_COMPACTFRAMEWORK if (fileName.StartsWith("./") || fileName.StartsWith(".\\")) - fileName = Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1); + fileName = Path.GetDirectoryName(Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1); #endif bool toFullPath = SQLiteConvert.ToBoolean(FindKey(opts, "ToFullPath", DefaultToFullPath.ToString())); fileName = ExpandFileName(fileName, toFullPath); } } @@ -3793,10 +3814,34 @@ // // NOTE: No match, return the input string verbatim. // return value; } + + /// + /// Determines the directory to be used when dealing with the "|DataDirectory|" + /// macro in a database file name. + /// + /// + /// The directory to use in place of the "|DataDirectory|" macro -OR- null if it + /// cannot be determined. + /// + private static string GetDataDirectory() + { +#if PLATFORM_COMPACTFRAMEWORK + string result = Path.GetDirectoryName( + Assembly.GetCallingAssembly().GetName().CodeBase); +#else + string result = AppDomain.CurrentDomain.GetData( + "DataDirectory") as string; + + if (String.IsNullOrEmpty(result)) + result = AppDomain.CurrentDomain.BaseDirectory; +#endif + + return result; + } /// /// Expand the filename of the data source, resolving the |DataDirectory| /// macro as appropriate. /// @@ -3804,41 +3849,33 @@ /// /// Non-zero if the returned file name should be converted to a full path /// (except when using the .NET Compact Framework). /// /// The expanded path and filename of the filename - private string ExpandFileName(string sourceFile, bool toFullPath) - { - if (String.IsNullOrEmpty(sourceFile)) return sourceFile; - - if (sourceFile.StartsWith(_dataDirectory, StringComparison.OrdinalIgnoreCase)) - { - string dataDirectory; - -#if PLATFORM_COMPACTFRAMEWORK - dataDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase); -#else - dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string; - if (String.IsNullOrEmpty(dataDirectory)) - dataDirectory = AppDomain.CurrentDomain.BaseDirectory; -#endif - - if (sourceFile.Length > _dataDirectory.Length) - { - if (sourceFile[_dataDirectory.Length] == Path.DirectorySeparatorChar || - sourceFile[_dataDirectory.Length] == Path.AltDirectorySeparatorChar) - sourceFile = sourceFile.Remove(_dataDirectory.Length, 1); - } - sourceFile = Path.Combine(dataDirectory, sourceFile.Substring(_dataDirectory.Length)); - } - -#if !PLATFORM_COMPACTFRAMEWORK - if (toFullPath) - sourceFile = Path.GetFullPath(sourceFile); -#endif - - return sourceFile; + private static string ExpandFileName(string sourceFile, bool toFullPath) + { + if (String.IsNullOrEmpty(sourceFile)) return sourceFile; + + if (sourceFile.StartsWith(_dataDirectory, StringComparison.OrdinalIgnoreCase)) + { + string dataDirectory = GetDataDirectory(); + + if (sourceFile.Length > _dataDirectory.Length) + { + if (sourceFile[_dataDirectory.Length] == Path.DirectorySeparatorChar || + sourceFile[_dataDirectory.Length] == Path.AltDirectorySeparatorChar) + sourceFile = sourceFile.Remove(_dataDirectory.Length, 1); + } + sourceFile = Path.Combine(dataDirectory, sourceFile.Substring(_dataDirectory.Length)); + } + +#if !PLATFORM_COMPACTFRAMEWORK + if (toFullPath) + sourceFile = Path.GetFullPath(sourceFile); +#endif + + return sourceFile; } /// /// The following commands are used to extract schema information out of the database. Valid schema types are: /// Index: Tests/basic.eagle ================================================================== --- Tests/basic.eagle +++ Tests/basic.eagle @@ -3852,10 +3852,37 @@ rename getMyFuncArgs "" } -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\ System.Data.SQLite} -match regexp -result {^0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 \{1\ 2 3 A a M m Z z\} True 1 True 1 True 1 True 1 True 1 True 1 True 1 True 1\ \{(?:-)?\d+ (?:-)?\d+\}$}} + +############################################################################### + +set fileName(1) [file nativename \ + [file join [getDatabaseDirectory] data-1.76.db]] + +############################################################################### + +runTest {test data-1.76 {SQLiteConnection.FileName property} -setup { + setupDb [set fileName(2) data-1.76.db] +} -body { + set connection [getDbConnection] + $connection FileName +} -cleanup { + freeDbConnection + + unset -nocomplain connection + + cleanupDb $fileName(2) + + unset -nocomplain db +} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\ +System.Data.SQLite} -result $fileName(1)} + +############################################################################### + +unset -nocomplain fileName ############################################################################### reportSQLiteResources $test_channel