System.Data.SQLite

Check-in [6660801c43]
Login

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

Overview
Comment:Stop using the transaction nesting level to build SAVEPOINT names.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | tkt-1f7bfff467
Files: files | file ages | folders
SHA1: 6660801c431f4a3e32496d41f8ffbda693af67cd
User & Date: mistachkin 2016-10-31 14:17:17.139
Context
2016-11-01
21:21
Add two tests that use three nested transactions. check-in: 676a8c8e5d user: mistachkin tags: tkt-1f7bfff467
2016-10-31
14:17
Stop using the transaction nesting level to build SAVEPOINT names. check-in: 6660801c43 user: mistachkin tags: tkt-1f7bfff467
01:23
Merge updates from trunk. check-in: 09c590c144 user: mistachkin tags: tkt-1f7bfff467
Changes
Unified Diff Ignore Whitespace Patch
Changes to System.Data.SQLite/SQLiteTransaction.cs.
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
        /// <summary>
        /// The original transaction level for the associated connection
        /// when this transaction was created (i.e. begun).
        /// </summary>
        private int _beginLevel;

        /// <summary>
        /// The SAVEPOINT names for each transaction level.

        /// </summary>
        private Dictionary<int, string> _savePointNames;

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

        /// <summary>
        /// Constructs the transaction object, binding it to the supplied connection
        /// </summary>
        /// <param name="connection">The connection to open a transaction on</param>







|
>

|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
        /// <summary>
        /// The original transaction level for the associated connection
        /// when this transaction was created (i.e. begun).
        /// </summary>
        private int _beginLevel;

        /// <summary>
        /// The SAVEPOINT name for this transaction, if any.  This will
        /// only be non-null if this transaction is a nested one.
        /// </summary>
        private string _savePointName;

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

        /// <summary>
        /// Constructs the transaction object, binding it to the supplied connection
        /// </summary>
        /// <param name="connection">The connection to open a transaction on</param>
90
91
92
93
94
95
96


97
98
99
100
101
102
103
104
105
106
            }
            else
            {
                try
                {
                    using (SQLiteCommand cmd = _cnn.CreateCommand())
                    {


                        cmd.CommandText = String.Format(
                            "SAVEPOINT {0};", GetSavePointName(
                            transactionLevel));

                        cmd.ExecuteNonQuery();

                        _beginLevel = transactionLevel;
                    }
                }
                catch (SQLiteException)







>
>

|
<







91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
            }
            else
            {
                try
                {
                    using (SQLiteCommand cmd = _cnn.CreateCommand())
                    {
                        _savePointName = GetSavePointName();

                        cmd.CommandText = String.Format(
                            "SAVEPOINT {0};", _savePointName);


                        cmd.ExecuteNonQuery();

                        _beginLevel = transactionLevel;
                    }
                }
                catch (SQLiteException)
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
                _cnn._transactionLevel = 0;
                _cnn = null;
            }
            else
            {
                using (SQLiteCommand cmd = _cnn.CreateCommand())
                {
                    int transactionLevel = _cnn._transactionLevel;


                    cmd.CommandText = String.Format(
                        "RELEASE {0};", GetSavePointName(
                        transactionLevel - 1));

                    cmd.ExecuteNonQuery();
                }

                _cnn._transactionLevel--;
                _cnn = null;
            }







|
>


|
<







189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
                _cnn._transactionLevel = 0;
                _cnn = null;
            }
            else
            {
                using (SQLiteCommand cmd = _cnn.CreateCommand())
                {
                    if (String.IsNullOrEmpty(_savePointName))
                        throw new SQLiteException("Cannot commit, unknown SAVEPOINT");

                    cmd.CommandText = String.Format(
                        "RELEASE {0};", _savePointName);


                    cmd.ExecuteNonQuery();
                }

                _cnn._transactionLevel--;
                _cnn = null;
            }
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
                }
                else
                {
                    try
                    {
                        using (SQLiteCommand cmd = cnn.CreateCommand())
                        {
                            int transactionLevel = cnn._transactionLevel;


                            cmd.CommandText = String.Format(
                                "ROLLBACK TO {0};", GetSavePointName(
                                transactionLevel - 1));

                            cmd.ExecuteNonQuery();
                        }

                        cnn._transactionLevel--;
                    }
                    catch
                    {
                        if (throwError)
                            throw;
                    }
                }
            }
        }

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

        /// <summary>
        /// Constructs the name of a new or existing savepoint.

        /// </summary>
        /// <param name="transactionLevel">
        /// The transaction level associated with the connection.
        /// </param>
        /// <returns>
        /// The name of the savepoint -OR- null if it cannot be constructed.
        /// </returns>
        private string GetSavePointName(
            int transactionLevel
            )
        {
            if (_savePointNames == null)
                _savePointNames = new Dictionary<int, string>();

            string name;

            if (!_savePointNames.TryGetValue(transactionLevel, out name))
            {
                int sequence = ++_cnn._transactionSequence;

                name = String.Format(
                    "sqlite_dotnet_savepoint_{0}_{1}",
                    transactionLevel, sequence);

                _savePointNames[transactionLevel] = name;
            }

            return name;
        }

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

        /// <summary>
        /// Checks the state of this transaction, optionally throwing an exception if a state inconsistency is found.
        /// </summary>







|
>


|
<


















|
>

<
<
<

|

|
<
<

<
<
<
<
<
<
<
|

|
|
<
<
<
<
<
<







285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317



318
319
320
321


322







323
324
325
326






327
328
329
330
331
332
333
                }
                else
                {
                    try
                    {
                        using (SQLiteCommand cmd = cnn.CreateCommand())
                        {
                            if (String.IsNullOrEmpty(_savePointName))
                                throw new SQLiteException("Cannot rollback, unknown SAVEPOINT");

                            cmd.CommandText = String.Format(
                                "ROLLBACK TO {0};", _savePointName);


                            cmd.ExecuteNonQuery();
                        }

                        cnn._transactionLevel--;
                    }
                    catch
                    {
                        if (throwError)
                            throw;
                    }
                }
            }
        }

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

        /// <summary>
        /// Constructs the name of a new savepoint for this transaction.  It
        /// should only be called from the constructor of this class.
        /// </summary>



        /// <returns>
        /// The name of the new savepoint -OR- null if it cannot be constructed.
        /// </returns>
        private string GetSavePointName()


        {







            int sequence = ++_cnn._transactionSequence;

            return String.Format(
                "sqlite_dotnet_savepoint_{0}", sequence);






        }

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

        /// <summary>
        /// Checks the state of this transaction, optionally throwing an exception if a state inconsistency is found.
        /// </summary>