Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -1408,10 +1408,19 @@ /// /// The extra connection flags to be used for all opened connections. /// private static SQLiteConnectionFlags _sharedFlags; + /// + /// The instance (for this thread) that + /// had the most recent call to . + /// +#if !PLATFORM_COMPACTFRAMEWORK + [ThreadStatic()] +#endif + private static SQLiteConnection _lastConnectionInOpen; + #if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK /// /// Used to hold the active library version number of SQLite. /// private static int _versionNumber; @@ -2025,11 +2034,11 @@ /// /// Non-zero if the cached setting was found; otherwise, zero. /// internal bool TryGetCachedSetting( string name, /* in */ - string @default, /* in */ + object @default, /* in */ out object value /* out */ ) { if ((name == null) || (_cachedSettings == null)) { @@ -2453,14 +2462,50 @@ internal static SortedList ParseConnectionString( string connectionString, bool parseViaFramework, bool allowNameOnly ) + { + return ParseConnectionString( + null, connectionString, parseViaFramework, allowNameOnly); + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + + /// + /// Parses a connection string into component parts using the custom + /// connection string parser. An exception may be thrown if the syntax + /// of the connection string is incorrect. + /// + /// + /// The connection that will be using the parsed connection string. + /// + /// + /// The connection string to parse. + /// + /// + /// Non-zero to parse the connection string using the algorithm provided + /// by the framework itself. This is not applicable when running on the + /// .NET Compact Framework. + /// + /// + /// Non-zero if names are allowed without values. + /// + /// + /// The list of key/value pairs corresponding to the parameters specified + /// within the connection string. + /// + private static SortedList ParseConnectionString( + SQLiteConnection connection, + string connectionString, + bool parseViaFramework, + bool allowNameOnly + ) { return parseViaFramework ? - ParseConnectionStringViaFramework(connectionString, false) : - ParseConnectionString(connectionString, allowNameOnly); + ParseConnectionStringViaFramework(connection, connectionString, false) : + ParseConnectionString(connection, connectionString, allowNameOnly); } /////////////////////////////////////////////////////////////////////////////////////////////// private void SetupSQLiteBase(SortedList opts) @@ -2969,16 +3014,73 @@ else if (path.StartsWith ("/", StringComparison.OrdinalIgnoreCase)) return path; else throw new InvalidOperationException ("Invalid connection string: invalid URI"); } + + /// + /// Determines if the legacy connection string parser should be used. + /// + /// + /// The connection that will be using the parsed connection string. + /// + /// + /// Non-zero if the legacy connection string parser should be used. + /// + private static bool ShouldUseLegacyConnectionStringParser( + SQLiteConnection connection + ) + { + string name = "No_SQLiteConnectionNewParser"; + object value; /* NOT USED */ + + if ((connection != null) && + connection.TryGetCachedSetting(name, null, out value)) + { + return true; + } + + if ((connection == null) && + TryGetLastCachedSetting(name, null, out value)) + { + return true; + } + + return (UnsafeNativeMethods.GetSettingValue(name, null) != null); + } + + /// + /// Parses a connection string into component parts using the custom + /// connection string parser. An exception may be thrown if the syntax + /// of the connection string is incorrect. + /// + /// + /// The connection string to parse. + /// + /// + /// Non-zero if names are allowed without values. + /// + /// + /// The list of key/value pairs corresponding to the parameters specified + /// within the connection string. + /// + private static SortedList ParseConnectionString( + string connectionString, + bool allowNameOnly + ) + { + return ParseConnectionString(null, connectionString, allowNameOnly); + } /// /// Parses a connection string into component parts using the custom /// connection string parser. An exception may be thrown if the syntax /// of the connection string is incorrect. /// + /// + /// The connection that will be using the parsed connection string. + /// /// /// The connection string to parse. /// /// /// Non-zero if names are allowed without values. @@ -2986,10 +3088,11 @@ /// /// The list of key/value pairs corresponding to the parameters specified /// within the connection string. /// private static SortedList ParseConnectionString( + SQLiteConnection connection, string connectionString, bool allowNameOnly ) { string s = connectionString; @@ -2998,11 +3101,11 @@ // First split into semi-colon delimited values. string error = null; string[] arParts; - if (UnsafeNativeMethods.GetSettingValue("No_SQLiteConnectionNewParser", null) != null) + if (ShouldUseLegacyConnectionStringParser(connection)) arParts = SQLiteConvert.Split(s, ';'); else arParts = SQLiteConvert.NewSplit(s, ';', true, ref error); if (arParts == null) @@ -3043,10 +3146,13 @@ /// exception may be thrown if the connection string is invalid or cannot be /// parsed. When compiled for the .NET Compact Framework, the custom /// connection string parser is always used instead because the framework /// provided one is unavailable there. /// + /// + /// The connection that will be using the parsed connection string. + /// /// /// The connection string to parse. /// /// /// Non-zero to throw an exception if any connection string values are not of @@ -3053,10 +3159,11 @@ /// the type. This is not applicable when running on /// the .NET Compact Framework. /// /// The list of key/value pairs. private static SortedList ParseConnectionStringViaFramework( + SQLiteConnection connection, string connectionString, bool strict ) { #if !PLATFORM_COMPACTFRAMEWORK @@ -3096,11 +3203,11 @@ // // NOTE: On the .NET Compact Framework, always use our custom connection // string parser as the built-in (i.e. framework provided) one is // unavailable. // - return ParseConnectionString(connectionString, false); + return ParseConnectionString(connection, connectionString, false); #endif } #if !PLATFORM_COMPACTFRAMEWORK /// @@ -3496,10 +3603,12 @@ /// public override void Open() { CheckDisposed(); + _lastConnectionInOpen = this; /* THREAD-SAFE: per-thread datum. */ + OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.Opening, null, null, null, null, null, null, null)); if (_connectionState != ConnectionState.Closed) @@ -3506,11 +3615,11 @@ throw new InvalidOperationException(); Close(); SortedList opts = ParseConnectionString( - _connectionString, _parseViaFramework, false); + this, _connectionString, _parseViaFramework, false); OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.ConnectionString, null, null, null, null, null, _connectionString, new object[] { opts })); @@ -4397,24 +4506,65 @@ { return null; } } } + + /// + /// Queries and returns the value of the specified setting, using the + /// cached setting names and values for the last connection that used + /// by the method, when available. + /// + /// + /// The name of the setting. + /// + /// + /// The value to be returned if the setting has not been set explicitly + /// or cannot be determined. + /// + /// + /// The value of the cached setting is stored here if found; otherwise, + /// the value of is stored here. + /// + /// + /// Non-zero if the cached setting was found; otherwise, zero. + /// + private static bool TryGetLastCachedSetting( + string name, + object @default, + out object value + ) + { + if (_lastConnectionInOpen == null) + { + value = @default; + return false; + } + + return _lastConnectionInOpen.TryGetCachedSetting( + name, @default, out value); + } /// /// The default connection flags to be used for all opened connections /// when they are not present in the connection string. /// public static SQLiteConnectionFlags DefaultFlags { get { - object enumValue; + string name = "DefaultFlags_SQLiteConnection"; + object value; - enumValue = TryParseEnum(typeof(SQLiteConnectionFlags), - UnsafeNativeMethods.GetSettingValue( - "DefaultFlags_SQLiteConnection", null), true); + if (!TryGetLastCachedSetting(name, null, out value)) + value = UnsafeNativeMethods.GetSettingValue(name, null); + + if (value == null) + return FallbackDefaultFlags; + + object enumValue = TryParseEnum( + typeof(SQLiteConnectionFlags), value.ToString(), true); if (enumValue is SQLiteConnectionFlags) return (SQLiteConnectionFlags)enumValue; return FallbackDefaultFlags;