System.Data.SQLite

Check-in [7d50138407]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Attempt to limit the number of times GetSettingValue is called from the SQLiteConnection class. Pursuant to ticket [25d53b48f6].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7d50138407b6992b2ff54d13a0e3998eef29207d
User & Date: mistachkin 2016-07-01 22:58:33.004
Original Comment: Attempt to limit the number of times GetSettingsValue is called from the SQLiteConnection class. Pursuant to ticket [25d53b48f6].
Context
2016-07-01
23:18
Update version history docs. check-in: b21adfaffa user: mistachkin tags: trunk
22:58
Attempt to limit the number of times GetSettingValue is called from the SQLiteConnection class. Pursuant to ticket [25d53b48f6]. check-in: 7d50138407 user: mistachkin tags: trunk
21:30
Pedantic: update the XML configuration file with the new settings as well, despite the fact that they cannot be effectively set from there. check-in: 8571817993 user: mistachkin tags: trunk
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteConnection.cs.
1406
1407
1408
1409
1410
1411
1412









1413
1414
1415
1416
1417
1418
1419
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428







+
+
+
+
+
+
+
+
+







    private static event SQLiteConnectionEventHandler _handlers;

    /// <summary>
    /// The extra connection flags to be used for all opened connections.
    /// </summary>
    private static SQLiteConnectionFlags _sharedFlags;

    /// <summary>
    /// The <see cref="SQLiteConnection" /> instance (for this thread) that
    /// had the most recent call to <see cref="SQLiteConnection.Open" />.
    /// </summary>
#if !PLATFORM_COMPACTFRAMEWORK
    [ThreadStatic()]
#endif
    private static SQLiteConnection _lastConnectionInOpen;

#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Used to hold the active library version number of SQLite.
    /// </summary>
    private static int _versionNumber;
#endif
    #endregion
2023
2024
2025
2026
2027
2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2032
2033
2034
2035
2036
2037
2038

2039
2040
2041
2042
2043
2044
2045
2046







-
+







    /// the value of <paramref name="default" /> is stored here.
    /// </param>
    /// <returns>
    /// Non-zero if the cached setting was found; otherwise, zero.
    /// </returns>
    internal bool TryGetCachedSetting(
        string name,     /* in */
        string @default, /* in */
        object @default, /* in */
        out object value /* out */
        )
    {
        if ((name == null) || (_cachedSettings == null))
        {
            value = @default;
            return false;
2451
2452
2453
2454
2455
2456
2457
2458




































2459
2460
2461


2462
2463
2464
2465
2466
2467
2468
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504


2505
2506
2507
2508
2509
2510
2511
2512
2513








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+







    /// within the connection string.
    /// </returns>
    internal static SortedList<string, string> ParseConnectionString(
        string connectionString,
        bool parseViaFramework,
        bool allowNameOnly
        )
    {
        return ParseConnectionString(
            null, connectionString, parseViaFramework, allowNameOnly);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// 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.
    /// </summary>
    /// <param name="connection">
    /// The connection that will be using the parsed connection string.
    /// </param>
    /// <param name="connectionString">
    /// The connection string to parse.
    /// </param>
    /// <param name="parseViaFramework">
    /// 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.
    /// </param>
    /// <param name="allowNameOnly">
    /// Non-zero if names are allowed without values.
    /// </param>
    /// <returns>
    /// The list of key/value pairs corresponding to the parameters specified
    /// within the connection string.
    /// </returns>
    private static SortedList<string, string> 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<string, string> opts)
    {
        object enumValue;
2967
2968
2969
2970
2971
2972
2973
2974
2975































2976
2977
2978
2979


























2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990

2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003

3004
3005
3006
3007
3008
3009
3010
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
3113









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











+












-
+







      else if (path.StartsWith ("file:", StringComparison.OrdinalIgnoreCase))
            return path.Substring (5);
      else if (path.StartsWith ("/", StringComparison.OrdinalIgnoreCase))
            return path;
      else
            throw new InvalidOperationException ("Invalid connection string: invalid URI");
    }

    /// <summary>
    /// Determines if the legacy connection string parser should be used.
    /// </summary>
    /// <param name="connection">
    /// The connection that will be using the parsed connection string.
    /// </param>
    /// <returns>
    /// Non-zero if the legacy connection string parser should be used.
    /// </returns>
    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);
    }

    /// <summary>
    /// 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.
    /// </summary>
    /// <param name="connectionString">
    /// The connection string to parse.
    /// </param>
    /// <param name="allowNameOnly">
    /// Non-zero if names are allowed without values.
    /// </param>
    /// <returns>
    /// The list of key/value pairs corresponding to the parameters specified
    /// within the connection string.
    /// </returns>
    private static SortedList<string, string> ParseConnectionString(
        string connectionString,
        bool allowNameOnly
        )
    {
        return ParseConnectionString(null, connectionString, allowNameOnly);
    }

    /// <summary>
    /// 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.
    /// </summary>
    /// <param name="connection">
    /// The connection that will be using the parsed connection string.
    /// </param>
    /// <param name="connectionString">
    /// The connection string to parse.
    /// </param>
    /// <param name="allowNameOnly">
    /// Non-zero if names are allowed without values.
    /// </param>
    /// <returns>
    /// The list of key/value pairs corresponding to the parameters specified
    /// within the connection string.
    /// </returns>
    private static SortedList<string, string> ParseConnectionString(
        SQLiteConnection connection,
        string connectionString,
        bool allowNameOnly
        )
    {
      string s = connectionString;
      int n;
      SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);

      // 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)
      {
          throw new ArgumentException(HelperMethods.StringFormat(
3041
3042
3043
3044
3045
3046
3047



3048
3049
3050
3051
3052
3053
3054
3055
3056
3057

3058
3059
3060
3061
3062
3063
3064
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171







+
+
+










+







    /// Parses a connection string using the built-in (i.e. framework provided)
    /// connection string parser class and returns the key/value pairs.  An
    /// 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.
    /// </summary>
    /// <param name="connection">
    /// The connection that will be using the parsed connection string.
    /// </param>
    /// <param name="connectionString">
    /// The connection string to parse.
    /// </param>
    /// <param name="strict">
    /// Non-zero to throw an exception if any connection string values are not of
    /// the <see cref="String" /> type.  This is not applicable when running on
    /// the .NET Compact Framework.
    /// </param>
    /// <returns>The list of key/value pairs.</returns>
    private static SortedList<string, string> ParseConnectionStringViaFramework(
        SQLiteConnection connection,
        string connectionString,
        bool strict
        )
    {
#if !PLATFORM_COMPACTFRAMEWORK
        DbConnectionStringBuilder connectionStringBuilder
            = new DbConnectionStringBuilder();
3094
3095
3096
3097
3098
3099
3100
3101

3102
3103
3104
3105
3106
3107
3108
3201
3202
3203
3204
3205
3206
3207

3208
3209
3210
3211
3212
3213
3214
3215







-
+







        return result;
#else
        //
        // 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
    /// <summary>
    /// Manual distributed transaction enlistment support
    /// </summary>
3494
3495
3496
3497
3498
3499
3500


3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511

3512
3513
3514
3515
3516
3517
3518
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619

3620
3621
3622
3623
3624
3625
3626
3627







+
+










-
+







    /// <summary>
    /// Opens the connection using the parameters found in the <see cref="ConnectionString" />.
    /// </summary>
    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)
        throw new InvalidOperationException();

      Close();

      SortedList<string, string> opts = ParseConnectionString(
          _connectionString, _parseViaFramework, false);
          this, _connectionString, _parseViaFramework, false);

      OnChanged(this, new ConnectionEventArgs(
          SQLiteConnectionEventType.ConnectionString, null, null, null, null,
          null, _connectionString, new object[] { opts }));

      object enumValue;

4395
4396
4397
4398
4399
4400
4401



































4402
4403
4404
4405
4406
4407
4408
4409
4410

4411

4412
4413
4414
4415








4416
4417
4418
4419
4420
4421
4422
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555

4556
4557



4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
-
+

-
-
-
+
+
+
+
+
+
+
+







            }
            else
            {
                return null;
            }
        }
    }

    /// <summary>
    /// Queries and returns the value of the specified setting, using the
    /// cached setting names and values for the last connection that used
    /// by the <see cref="SQLiteConnection.Open" /> method, when available.
    /// </summary>
    /// <param name="name">
    /// The name of the setting.
    /// </param>
    /// <param name="default">
    /// The value to be returned if the setting has not been set explicitly
    /// or cannot be determined.
    /// </param>
    /// <param name="value">
    /// The value of the cached setting is stored here if found; otherwise,
    /// the value of <paramref name="default" /> is stored here.
    /// </param>
    /// <returns>
    /// Non-zero if the cached setting was found; otherwise, zero.
    /// </returns>
    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);
    }

    /// <summary>
    /// The default connection flags to be used for all opened connections
    /// when they are not present in the connection string.
    /// </summary>
    public static SQLiteConnectionFlags DefaultFlags
    {
        get
        {
            string name = "DefaultFlags_SQLiteConnection";
            object enumValue;
            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;
        }
    }