System.Data.SQLite

Check-in [c16bb56cfd]
Login

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

Overview
Comment:Move the native memory allocation wrapper methods into the new SQLiteMemory class.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | virtualTables
Files: files | file ages | folders
SHA1: c16bb56cfd403ee3698c53b4f871f9ae7f57e220
User & Date: mistachkin 2013-06-21 05:39:00.085
Context
2013-06-21
06:06
Modularize various aspects of the virtual table handling in the example SQLiteVirtualTableCursorEnumerable class. check-in: 5033bacee1 user: mistachkin tags: virtualTables
05:39
Move the native memory allocation wrapper methods into the new SQLiteMemory class. check-in: c16bb56cfd user: mistachkin tags: virtualTables
05:14
Fix memory leak in the SQLiteModuleBase class. Add support for optionally tracking memory usage of the SQLiteMarshal class. Make sure sqlite3_*_interop() functions are only used when SQLITE_STANDARD is not defined. check-in: 4aab5f9721 user: mistachkin tags: virtualTables
Changes
Unified Diff Ignore Whitespace Patch
Changes to SQLite.NET.Settings.targets.
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
              These counts are intended to be used by the test suite to detect
              possible resource leaks.
    -->
    <CountHandle Condition="'$(CountHandle)' == ''">false</CountHandle>

    <!--
        NOTE: Enable tracking of all outstanding bytes allocated by the
              SQLiteMarshal class.  By default, this is disabled.  If this is
              enabled, this library will keep track of all outstanding bytes
              allocated by the SQLiteMarshal class.  This has the potential to
              slow down the library a bit.
    -->
    <TrackMarshalBytes Condition="'$(TrackMarshalBytes)' == ''">false</TrackMarshalBytes>

    <!--
        NOTE: For interaction with the native SQLite implementation, use the
              custom built interop DLL (i.e. "SQLite.Interop.dll")?  By default,
              this is enabled.  This property is mutually exclusive with the
              "UseSqliteStandard" one, below.  This should always be disabled in
              the project file that builds the NetModule target.







|

|


|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
              These counts are intended to be used by the test suite to detect
              possible resource leaks.
    -->
    <CountHandle Condition="'$(CountHandle)' == ''">false</CountHandle>

    <!--
        NOTE: Enable tracking of all outstanding bytes allocated by the
              SQLiteMemory class.  By default, this is disabled.  If this is
              enabled, this library will keep track of all outstanding bytes
              allocated by the SQLiteMemory class.  This has the potential to
              slow down the library a bit.
    -->
    <TrackMemoryBytes Condition="'$(TrackMemoryBytes)' == ''">false</TrackMemoryBytes>

    <!--
        NOTE: For interaction with the native SQLite implementation, use the
              custom built interop DLL (i.e. "SQLite.Interop.dll")?  By default,
              this is enabled.  This property is mutually exclusive with the
              "UseSqliteStandard" one, below.  This should always be disabled in
              the project file that builds the NetModule target.
Changes to Setup/set_user_mistachkin_Debug.bat.
13
14
15
16
17
18
19
20
REM NOTE: Enables the extra debug code helpful in troubleshooting issues.
REM
SET MSBUILD_ARGS=/p:CheckState=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:CountHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceConnection=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceStatement=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TrackMarshalBytes=true







|
13
14
15
16
17
18
19
20
REM NOTE: Enables the extra debug code helpful in troubleshooting issues.
REM
SET MSBUILD_ARGS=/p:CheckState=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:CountHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceConnection=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceStatement=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TrackMemoryBytes=true
Changes to System.Data.SQLite/SQLite3.cs.
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
                throw new SQLiteException(SQLiteErrorCode.Error, GetLastError());
            }
        }
        finally
        {
            if (pName != IntPtr.Zero)
            {
                SQLiteMarshal.Free(pName);
                pName = IntPtr.Zero;
            }
        }
    }

    /// <summary>
    /// Calls the native SQLite core library in order to cleanup the resources







|







1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
                throw new SQLiteException(SQLiteErrorCode.Error, GetLastError());
            }
        }
        finally
        {
            if (pName != IntPtr.Zero)
            {
                SQLiteMemory.Free(pName);
                pName = IntPtr.Zero;
            }
        }
    }

    /// <summary>
    /// Calls the native SQLite core library in order to cleanup the resources
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702

            return n;
        }
        finally
        {
            if (pSql != IntPtr.Zero)
            {
                SQLiteMarshal.Free(pSql);
                pSql = IntPtr.Zero;
            }
        }
    }

    /// <summary>
    /// Enables or disabled extension loading by SQLite.







|







1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702

            return n;
        }
        finally
        {
            if (pSql != IntPtr.Zero)
            {
                SQLiteMemory.Free(pSql);
                pSql = IntPtr.Zero;
            }
        }
    }

    /// <summary>
    /// Enables or disabled extension loading by SQLite.
Changes to System.Data.SQLite/SQLiteDefineConstants.cs.
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
            "TRACE_STATEMENT",
#endif

#if TRACE_WARNING
            "TRACE_WARNING",
#endif

#if TRACK_MARSHAL_BYTES
            "TRACK_MARSHAL_BYTES",
#endif

#if USE_INTEROP_DLL
            "USE_INTEROP_DLL",
#endif

#if USE_PREPARE_V2







|
|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
            "TRACE_STATEMENT",
#endif

#if TRACE_WARNING
            "TRACE_WARNING",
#endif

#if TRACK_MEMORY_BYTES
            "TRACK_MEMORY_BYTES",
#endif

#if USE_INTEROP_DLL
            "USE_INTEROP_DLL",
#endif

#if USE_PREPARE_V2
Changes to System.Data.SQLite/SQLiteModuleBase.cs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Joe Mistachkin (joe@mistachkin.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;

#if TRACK_MARSHAL_BYTES
using System.Threading;
#endif

namespace System.Data.SQLite
{
    #region SQLite Context Helper Class
    public sealed class SQLiteContext












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Joe Mistachkin (joe@mistachkin.com)
 *
 * Released to the public domain, use at your own risk!
 ********************************************************/

using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;

#if TRACK_MEMORY_BYTES
using System.Threading;
#endif

namespace System.Data.SQLite
{
    #region SQLite Context Helper Class
    public sealed class SQLiteContext
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529












1530
1531











































































































1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
            int savepoint             /* in */
            );
    }
    #endregion

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

    #region SQLiteMarshal Class
    internal static class SQLiteMarshal
    {
        #region Private Constants
        private static int ThirtyBits = 0x3fffffff;
        private static readonly Encoding Utf8Encoding = Encoding.UTF8;
        #endregion

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

        #region Private Data
#if TRACK_MARSHAL_BYTES
        private static int bytesAllocated;
        private static int maximumBytesAllocated;
#endif
        #endregion

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

        #region IntPtr Helper Methods
        internal static IntPtr IntPtrForOffset(
            IntPtr pointer,
            int offset
            )
        {
            return new IntPtr(pointer.ToInt64() + offset);
        }
        #endregion

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

        #region Marshal Read Helper Methods
        internal static int ReadInt32(
            IntPtr pointer,
            int offset
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return Marshal.ReadInt32(pointer, offset);
#else
            return Marshal.ReadInt32(IntPtrForOffset(pointer, offset));
#endif
        }

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

        internal static double ReadDouble(
            IntPtr pointer,
            int offset
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return BitConverter.Int64BitsToDouble(Marshal.ReadInt64(
                pointer, offset));
#else
            return BitConverter.ToDouble(BitConverter.GetBytes(
                Marshal.ReadInt64(IntPtrForOffset(pointer, offset))), 0);
#endif
        }

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

        internal static IntPtr ReadIntPtr(
            IntPtr pointer,
            int offset
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return Marshal.ReadIntPtr(pointer, offset);
#else
            return Marshal.ReadIntPtr(IntPtrForOffset(pointer, offset));
#endif
        }
        #endregion

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

        #region Marshal Write Helper Methods
        internal static void WriteInt32(
            IntPtr pointer,
            int offset,
            int value
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            Marshal.WriteInt32(pointer, offset, value);
#else
            Marshal.WriteInt32(IntPtrForOffset(pointer, offset), value);
#endif
        }

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

        internal static void WriteDouble(
            IntPtr pointer,
            int offset,
            double value
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            Marshal.WriteInt64(pointer, offset,
                BitConverter.DoubleToInt64Bits(value));
#else
            Marshal.WriteInt64(IntPtrForOffset(pointer, offset),
                BitConverter.ToInt64(BitConverter.GetBytes(value), 0));
#endif
        }

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

        internal static void WriteIntPtr(
            IntPtr pointer,
            int offset,
            IntPtr value
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            Marshal.WriteIntPtr(pointer, offset, value);
#else
            Marshal.WriteIntPtr(IntPtrForOffset(pointer, offset), value);
#endif
        }
        #endregion

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

        #region Memory Allocation Helper Methods
        internal static IntPtr Allocate(int size)
        {
            IntPtr pMemory = UnsafeNativeMethods.sqlite3_malloc(size);

#if TRACK_MARSHAL_BYTES
            if (pMemory != IntPtr.Zero)
            {
                int blockSize = Size(pMemory);

                if (blockSize > 0)
                {
                    Interlocked.Add(ref bytesAllocated, blockSize);
                    Interlocked.Add(ref maximumBytesAllocated, blockSize);
                }
            }
#endif

            return pMemory;
        }

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

        internal static int Size(IntPtr pMemory)
        {
#if !SQLITE_STANDARD
            try
            {
                return UnsafeNativeMethods.sqlite3_malloc_size_interop(
                    pMemory);
            }
            catch
            {
                // do nothing.
            }
#endif

            return 0;

        }

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

        internal static void Free(IntPtr pMemory)
        {
#if TRACK_MARSHAL_BYTES
            if (pMemory != IntPtr.Zero)
            {
                int blockSize = Size(pMemory);

                if (blockSize > 0)
                    Interlocked.Add(ref bytesAllocated, -blockSize);
            }
#endif

            UnsafeNativeMethods.sqlite3_free(pMemory);
        }
        #endregion













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












































































































        #region Byte Array Helper Methods
        internal static byte[] BytesFromIntPtr(
            IntPtr pValue,
            int length
            )
        {
            if (pValue == IntPtr.Zero)
                return null;

            if (length == 0)
                return new byte[0];

            byte[] result = new byte[length];

            Marshal.Copy(pValue, result, 0, length);

            return result;
        }

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

        internal static IntPtr BytesToIntPtr(
            byte[] value
            )
        {
            if (value == null)
                return IntPtr.Zero;

            int length = value.Length;

            if (length == 0)
                return IntPtr.Zero;

            IntPtr result = Allocate(length);

            if (result == IntPtr.Zero)
                return IntPtr.Zero;

            Marshal.Copy(value, 0, result, length);

            return result;
        }
        #endregion

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

        #region UTF-8 Encoding Helper Methods
        internal static byte[] GetUtf8BytesFromString(
            string value
            )
        {
            if (value == null)
                return null;

            return Utf8Encoding.GetBytes(value);
        }

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

        internal static string GetStringFromUtf8Bytes(
            byte[] bytes
            )
        {
            if (bytes == null)
                return null;

#if !PLATFORM_COMPACTFRAMEWORK
            return Utf8Encoding.GetString(bytes);
#else
            return Utf8Encoding.GetString(bytes, 0, bytes.Length);
#endif
        }
        #endregion

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

        #region UTF-8 String Helper Methods
        internal static int ProbeForUtf8ByteLength(
            IntPtr pValue,
            int limit
            )
        {
            int length = 0;

            if (pValue != IntPtr.Zero)







|
|

<
<
<
<
<
<
<

|







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|



|

















|


<
<
|
<
<
<
<
<
<
|
<

>




|

|












|
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|



















|











|













|











|

















|







1339
1340
1341
1342
1343
1344
1345
1346
1347
1348







1349
1350
1351
1352
1353
1354
1355
1356
1357











































































































1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383


1384






1385

1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
            int savepoint             /* in */
            );
    }
    #endregion

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

    #region SQLiteMemory Class
    internal static class SQLiteMemory
    {







        #region Private Data
#if TRACK_MEMORY_BYTES
        private static int bytesAllocated;
        private static int maximumBytesAllocated;
#endif
        #endregion

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












































































































        #region Memory Allocation Helper Methods
        public static IntPtr Allocate(int size)
        {
            IntPtr pMemory = UnsafeNativeMethods.sqlite3_malloc(size);

#if TRACK_MEMORY_BYTES
            if (pMemory != IntPtr.Zero)
            {
                int blockSize = Size(pMemory);

                if (blockSize > 0)
                {
                    Interlocked.Add(ref bytesAllocated, blockSize);
                    Interlocked.Add(ref maximumBytesAllocated, blockSize);
                }
            }
#endif

            return pMemory;
        }

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

        public static int Size(IntPtr pMemory)
        {
#if !SQLITE_STANDARD


            return UnsafeNativeMethods.sqlite3_malloc_size_interop(pMemory);






#else

            return 0;
#endif
        }

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

        public static void Free(IntPtr pMemory)
        {
#if TRACK_MEMORY_BYTES
            if (pMemory != IntPtr.Zero)
            {
                int blockSize = Size(pMemory);

                if (blockSize > 0)
                    Interlocked.Add(ref bytesAllocated, -blockSize);
            }
#endif

            UnsafeNativeMethods.sqlite3_free(pMemory);
        }
        #endregion
    }
    #endregion

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

    #region SQLiteMarshal Class
    internal static class SQLiteMarshal
    {
        #region Private Constants
        private static int ThirtyBits = 0x3fffffff;
        private static readonly Encoding Utf8Encoding = Encoding.UTF8;
        #endregion

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

        #region IntPtr Helper Methods
        public static IntPtr IntPtrForOffset(
            IntPtr pointer,
            int offset
            )
        {
            return new IntPtr(pointer.ToInt64() + offset);
        }
        #endregion

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

        #region Marshal Read Helper Methods
        public static int ReadInt32(
            IntPtr pointer,
            int offset
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return Marshal.ReadInt32(pointer, offset);
#else
            return Marshal.ReadInt32(IntPtrForOffset(pointer, offset));
#endif
        }

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

        public static double ReadDouble(
            IntPtr pointer,
            int offset
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return BitConverter.Int64BitsToDouble(Marshal.ReadInt64(
                pointer, offset));
#else
            return BitConverter.ToDouble(BitConverter.GetBytes(
                Marshal.ReadInt64(IntPtrForOffset(pointer, offset))), 0);
#endif
        }

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

        public static IntPtr ReadIntPtr(
            IntPtr pointer,
            int offset
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            return Marshal.ReadIntPtr(pointer, offset);
#else
            return Marshal.ReadIntPtr(IntPtrForOffset(pointer, offset));
#endif
        }
        #endregion

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

        #region Marshal Write Helper Methods
        public static void WriteInt32(
            IntPtr pointer,
            int offset,
            int value
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            Marshal.WriteInt32(pointer, offset, value);
#else
            Marshal.WriteInt32(IntPtrForOffset(pointer, offset), value);
#endif
        }

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

        public static void WriteDouble(
            IntPtr pointer,
            int offset,
            double value
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            Marshal.WriteInt64(pointer, offset,
                BitConverter.DoubleToInt64Bits(value));
#else
            Marshal.WriteInt64(IntPtrForOffset(pointer, offset),
                BitConverter.ToInt64(BitConverter.GetBytes(value), 0));
#endif
        }

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

        public static void WriteIntPtr(
            IntPtr pointer,
            int offset,
            IntPtr value
            )
        {
#if !PLATFORM_COMPACTFRAMEWORK
            Marshal.WriteIntPtr(pointer, offset, value);
#else
            Marshal.WriteIntPtr(IntPtrForOffset(pointer, offset), value);
#endif
        }
        #endregion

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

        #region Byte Array Helper Methods
        public static byte[] BytesFromIntPtr(
            IntPtr pValue,
            int length
            )
        {
            if (pValue == IntPtr.Zero)
                return null;

            if (length == 0)
                return new byte[0];

            byte[] result = new byte[length];

            Marshal.Copy(pValue, result, 0, length);

            return result;
        }

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

        public static IntPtr BytesToIntPtr(
            byte[] value
            )
        {
            if (value == null)
                return IntPtr.Zero;

            int length = value.Length;

            if (length == 0)
                return IntPtr.Zero;

            IntPtr result = SQLiteMemory.Allocate(length);

            if (result == IntPtr.Zero)
                return IntPtr.Zero;

            Marshal.Copy(value, 0, result, length);

            return result;
        }
        #endregion

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

        #region UTF-8 Encoding Helper Methods
        public static byte[] GetUtf8BytesFromString(
            string value
            )
        {
            if (value == null)
                return null;

            return Utf8Encoding.GetBytes(value);
        }

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

        public static string GetStringFromUtf8Bytes(
            byte[] bytes
            )
        {
            if (bytes == null)
                return null;

#if !PLATFORM_COMPACTFRAMEWORK
            return Utf8Encoding.GetString(bytes);
#else
            return Utf8Encoding.GetString(bytes, 0, bytes.Length);
#endif
        }
        #endregion

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

        #region UTF-8 String Helper Methods
        public static int ProbeForUtf8ByteLength(
            IntPtr pValue,
            int limit
            )
        {
            int length = 0;

            if (pValue != IntPtr.Zero)
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
            }

            return length;
        }

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

        internal static string StringFromUtf8IntPtr(
            IntPtr pValue
            )
        {
            return StringFromUtf8IntPtr(pValue,
                ProbeForUtf8ByteLength(pValue, ThirtyBits));
        }

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

        internal static string StringFromUtf8IntPtr(
            IntPtr pValue,
            int length
            )
        {
            if (pValue == IntPtr.Zero)
                return null;








|









|







1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
            }

            return length;
        }

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

        public static string StringFromUtf8IntPtr(
            IntPtr pValue
            )
        {
            return StringFromUtf8IntPtr(pValue,
                ProbeForUtf8ByteLength(pValue, ThirtyBits));
        }

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

        public static string StringFromUtf8IntPtr(
            IntPtr pValue,
            int length
            )
        {
            if (pValue == IntPtr.Zero)
                return null;

1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
            }

            return String.Empty;
        }

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

        internal static IntPtr Utf8IntPtrFromString(
            string value
            )
        {
            if (value == null)
                return IntPtr.Zero;

            IntPtr result = IntPtr.Zero;
            byte[] bytes = GetUtf8BytesFromString(value);

            if (bytes == null)
                return IntPtr.Zero;

            int length = bytes.Length;

            result = Allocate(length + 1);

            if (result == IntPtr.Zero)
                return IntPtr.Zero;

            Marshal.Copy(bytes, 0, result, length);
            Marshal.WriteByte(result, length, 0);

            return result;
        }
        #endregion

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

        #region UTF-8 String Array Helper Methods
        internal static string[] StringArrayFromUtf8IntPtrArray(
            IntPtr[] pValues
            )
        {
            if (pValues == null)
                return null;

            string[] result = new string[pValues.Length];

            for (int index = 0; index < result.Length; index++)
                result[index] = StringFromUtf8IntPtr(pValues[index]);

            return result;
        }

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

        internal static IntPtr[] Utf8IntPtrArrayFromStringArray(
            string[] values
            )
        {
            if (values == null)
                return null;

            IntPtr[] result = new IntPtr[values.Length];

            for (int index = 0; index < result.Length; index++)
                result[index] = Utf8IntPtrFromString(values[index]);

            return result;
        }
        #endregion

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

        #region SQLiteValue Helper Methods
        internal static SQLiteValue[] ValueArrayFromSizeAndIntPtr(
            int nData,
            IntPtr apData
            )
        {
            if (nData < 0)
                return null;








|














|














|
















|


















|







1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
            }

            return String.Empty;
        }

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

        public static IntPtr Utf8IntPtrFromString(
            string value
            )
        {
            if (value == null)
                return IntPtr.Zero;

            IntPtr result = IntPtr.Zero;
            byte[] bytes = GetUtf8BytesFromString(value);

            if (bytes == null)
                return IntPtr.Zero;

            int length = bytes.Length;

            result = SQLiteMemory.Allocate(length + 1);

            if (result == IntPtr.Zero)
                return IntPtr.Zero;

            Marshal.Copy(bytes, 0, result, length);
            Marshal.WriteByte(result, length, 0);

            return result;
        }
        #endregion

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

        #region UTF-8 String Array Helper Methods
        public static string[] StringArrayFromUtf8IntPtrArray(
            IntPtr[] pValues
            )
        {
            if (pValues == null)
                return null;

            string[] result = new string[pValues.Length];

            for (int index = 0; index < result.Length; index++)
                result[index] = StringFromUtf8IntPtr(pValues[index]);

            return result;
        }

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

        public static IntPtr[] Utf8IntPtrArrayFromStringArray(
            string[] values
            )
        {
            if (values == null)
                return null;

            IntPtr[] result = new IntPtr[values.Length];

            for (int index = 0; index < result.Length; index++)
                result[index] = Utf8IntPtrFromString(values[index]);

            return result;
        }
        #endregion

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

        #region SQLiteValue Helper Methods
        public static SQLiteValue[] ValueArrayFromSizeAndIntPtr(
            int nData,
            IntPtr apData
            )
        {
            if (nData < 0)
                return null;

1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
            }

            return result;
        }

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

        internal static SQLiteValue[] ValueArrayFromIntPtrArray(
            IntPtr[] values
            )
        {
            if (values == null)
                return null;

            SQLiteValue[] result = new SQLiteValue[values.Length];

            for (int index = 0; index < result.Length; index++)
                result[index] = new SQLiteValue(values[index]);

            return result;
        }
        #endregion

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

        #region SQLiteIndex Helper Methods
        internal static void IndexFromIntPtr(
            IntPtr pIndex,
            ref SQLiteIndex index
            )
        {
            if (pIndex == IntPtr.Zero)
                return;








|


















|







1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
            }

            return result;
        }

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

        public static SQLiteValue[] ValueArrayFromIntPtrArray(
            IntPtr[] values
            )
        {
            if (values == null)
                return null;

            SQLiteValue[] result = new SQLiteValue[values.Length];

            for (int index = 0; index < result.Length; index++)
                result[index] = new SQLiteValue(values[index]);

            return result;
        }
        #endregion

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

        #region SQLiteIndex Helper Methods
        public static void IndexFromIntPtr(
            IntPtr pIndex,
            ref SQLiteIndex index
            )
        {
            if (pIndex == IntPtr.Zero)
                return;

1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
                index.Outputs.ConstraintUsages[iConstraint] =
                    new SQLiteIndexConstraintUsage(constraintUsage);
            }
        }

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

        internal static void IndexToIntPtr(
            SQLiteIndex index,
            IntPtr pIndex
            )
        {
            if ((index == null) || (index.Inputs == null) ||
                (index.Inputs.Constraints == null) ||
                (index.Inputs.OrderBys == null) || (index.Outputs == null) ||







|







1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
                index.Outputs.ConstraintUsages[iConstraint] =
                    new SQLiteIndexConstraintUsage(constraintUsage);
            }
        }

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

        public static void IndexToIntPtr(
            SQLiteIndex index,
            IntPtr pIndex
            )
        {
            if ((index == null) || (index.Inputs == null) ||
                (index.Inputs.Constraints == null) ||
                (index.Inputs.OrderBys == null) || (index.Outputs == null) ||
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
        #region Protected Members
        #region Native Table Helper Methods
        protected virtual IntPtr AllocateTable()
        {
            int size = Marshal.SizeOf(typeof(
                UnsafeNativeMethods.sqlite3_vtab));

            return SQLiteMarshal.Allocate(size);
        }

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

        protected virtual void ZeroTable(IntPtr pVtab)
        {
            if (pVtab == IntPtr.Zero)







|







2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
        #region Protected Members
        #region Native Table Helper Methods
        protected virtual IntPtr AllocateTable()
        {
            int size = Marshal.SizeOf(typeof(
                UnsafeNativeMethods.sqlite3_vtab));

            return SQLiteMemory.Allocate(size);
        }

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

        protected virtual void ZeroTable(IntPtr pVtab)
        {
            if (pVtab == IntPtr.Zero)
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
        }

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

        protected virtual void FreeTable(IntPtr pVtab)
        {
            SetTableError(pVtab, null);
            SQLiteMarshal.Free(pVtab);
        }
        #endregion

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

        #region Native Cursor Helper Methods
        protected virtual IntPtr AllocateCursor()
        {
            int size = Marshal.SizeOf(typeof(
                UnsafeNativeMethods.sqlite3_vtab_cursor));

            return SQLiteMarshal.Allocate(size);
        }

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

        protected virtual void FreeCursor(IntPtr pCursor)
        {
            SQLiteMarshal.Free(pCursor);
        }
        #endregion

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

        #region Table Lookup Methods
        protected virtual IntPtr TableFromCursor(







|











|






|







2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
        }

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

        protected virtual void FreeTable(IntPtr pVtab)
        {
            SetTableError(pVtab, null);
            SQLiteMemory.Free(pVtab);
        }
        #endregion

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

        #region Native Cursor Helper Methods
        protected virtual IntPtr AllocateCursor()
        {
            int size = Marshal.SizeOf(typeof(
                UnsafeNativeMethods.sqlite3_vtab_cursor));

            return SQLiteMemory.Allocate(size);
        }

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

        protected virtual void FreeCursor(IntPtr pCursor)
        {
            SQLiteMemory.Free(pCursor);
        }
        #endregion

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

        #region Table Lookup Methods
        protected virtual IntPtr TableFromCursor(
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
                return false;

            int offset = IntPtr.Size + sizeof(int);
            IntPtr pError = SQLiteMarshal.ReadIntPtr(pVtab, offset);

            if (pError != IntPtr.Zero)
            {
                SQLiteMarshal.Free(pError); pError = IntPtr.Zero;
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
            }

            if (error == null)
                return true;

            bool success = false;

            try
            {
                pError = SQLiteMarshal.Utf8IntPtrFromString(error);
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
                success = true;
            }
            finally
            {
                if (!success && (pError != IntPtr.Zero))
                {
                    SQLiteMarshal.Free(pError);
                    pError = IntPtr.Zero;
                }
            }

            return success;
        }








|


















|







2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
                return false;

            int offset = IntPtr.Size + sizeof(int);
            IntPtr pError = SQLiteMarshal.ReadIntPtr(pVtab, offset);

            if (pError != IntPtr.Zero)
            {
                SQLiteMemory.Free(pError); pError = IntPtr.Zero;
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
            }

            if (error == null)
                return true;

            bool success = false;

            try
            {
                pError = SQLiteMarshal.Utf8IntPtrFromString(error);
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
                success = true;
            }
            finally
            {
                if (!success && (pError != IntPtr.Zero))
                {
                    SQLiteMemory.Free(pError);
                    pError = IntPtr.Zero;
                }
            }

            return success;
        }

Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
      NOTE: Enable counting of the CriticalHandle derived object instances?
  -->
  <PropertyGroup Condition="'$(CountHandle)' != 'false'">
    <DefineConstants>$(DefineConstants);COUNT_HANDLE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: Enable tracking of bytes allocated by the SQLiteMarshal class?
  -->
  <PropertyGroup Condition="'$(TrackMarshalBytes)' != 'false'">
    <DefineConstants>$(DefineConstants);TRACK_MARSHAL_BYTES</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: For interaction with the native SQLite implementation, use the
            custom build interop DLL (i.e. "SQLite.Interop.DLL")?
  -->
  <PropertyGroup Condition="'$(UseInteropDll)' != 'false'">







|

|
|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
      NOTE: Enable counting of the CriticalHandle derived object instances?
  -->
  <PropertyGroup Condition="'$(CountHandle)' != 'false'">
    <DefineConstants>$(DefineConstants);COUNT_HANDLE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: Enable tracking of bytes allocated by the SQLiteMemory class?
  -->
  <PropertyGroup Condition="'$(TrackMemoryBytes)' != 'false'">
    <DefineConstants>$(DefineConstants);TRACK_MEMORY_BYTES</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: For interaction with the native SQLite implementation, use the
            custom build interop DLL (i.e. "SQLite.Interop.DLL")?
  -->
  <PropertyGroup Condition="'$(UseInteropDll)' != 'false'">
Changes to Tests/common.eagle.
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
    }

    proc reportSQLiteResources { channel {quiet false} {collect true} } {
      #
      # NOTE: Skip all output if we are running in "quiet" mode.
      #
      if {[haveConstraint \
              defineConstant.System.Data.SQLite.TRACK_MARSHAL_BYTES]} then {
        if {!$quiet} then {
          tputs $channel "---- current memory in use by SQLiteMarshal... "
        }

        if {[catch {object invoke -flags +NonPublic \
                System.Data.SQLite.SQLiteMarshal \
                bytesAllocated} memory] == 0} then {
          if {!$quiet} then {
            tputs $channel [appendArgs $memory " bytes\n"]
          }
        } else {
          set memory unknown

          if {!$quiet} then {
            tputs $channel [appendArgs $memory \n]
          }
        }

        if {!$quiet} then {
          tputs $channel "---- maximum memory in use by SQLiteMarshal... "
        }

        if {[catch {object invoke -flags +NonPublic \
                System.Data.SQLite.SQLiteMarshal \
                maximumBytesAllocated} memory] == 0} then {
          if {!$quiet} then {
            tputs $channel [appendArgs $memory " bytes\n"]
          }
        } else {
          set memory unknown








|

|



|













|



|







1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
    }

    proc reportSQLiteResources { channel {quiet false} {collect true} } {
      #
      # NOTE: Skip all output if we are running in "quiet" mode.
      #
      if {[haveConstraint \
              defineConstant.System.Data.SQLite.TRACK_MEMORY_BYTES]} then {
        if {!$quiet} then {
          tputs $channel "---- current memory in use by SQLiteMemory... "
        }

        if {[catch {object invoke -flags +NonPublic \
                System.Data.SQLite.SQLiteMemory \
                bytesAllocated} memory] == 0} then {
          if {!$quiet} then {
            tputs $channel [appendArgs $memory " bytes\n"]
          }
        } else {
          set memory unknown

          if {!$quiet} then {
            tputs $channel [appendArgs $memory \n]
          }
        }

        if {!$quiet} then {
          tputs $channel "---- maximum memory in use by SQLiteMemory... "
        }

        if {[catch {object invoke -flags +NonPublic \
                System.Data.SQLite.SQLiteMemory \
                maximumBytesAllocated} memory] == 0} then {
          if {!$quiet} then {
            tputs $channel [appendArgs $memory " bytes\n"]
          }
        } else {
          set memory unknown

1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
        foreach defineConstant [list \
            CHECK_STATE COUNT_HANDLE DEBUG INTEROP_CODEC INTEROP_DEBUG \
            INTEROP_EXTENSION_FUNCTIONS INTEROP_LEGACY_CLOSE INTEROP_LOG \
            INTEROP_TEST_EXTENSION NET_20 NET_35 NET_40 NET_45 NET_COMPACT_20 \
            PLATFORM_COMPACTFRAMEWORK PRELOAD_NATIVE_LIBRARY RETARGETABLE \
            SQLITE_STANDARD THROW_ON_DISPOSED TRACE TRACE_CONNECTION \
            TRACE_HANDLE TRACE_PRELOAD TRACE_STATEMENT TRACE_WARNING \
            TRACK_MARSHAL_BYTES USE_INTEROP_DLL USE_PREPARE_V2 WINDOWS] {
          #
          # NOTE: Check if the compile-time option is listed in the list of
          #       "define constants" kept track of by the managed assembly.
          #
          checkForSQLiteDefineConstant $::test_channel $defineConstant
        }








|







1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
        foreach defineConstant [list \
            CHECK_STATE COUNT_HANDLE DEBUG INTEROP_CODEC INTEROP_DEBUG \
            INTEROP_EXTENSION_FUNCTIONS INTEROP_LEGACY_CLOSE INTEROP_LOG \
            INTEROP_TEST_EXTENSION NET_20 NET_35 NET_40 NET_45 NET_COMPACT_20 \
            PLATFORM_COMPACTFRAMEWORK PRELOAD_NATIVE_LIBRARY RETARGETABLE \
            SQLITE_STANDARD THROW_ON_DISPOSED TRACE TRACE_CONNECTION \
            TRACE_HANDLE TRACE_PRELOAD TRACE_STATEMENT TRACE_WARNING \
            TRACK_MEMORY_BYTES USE_INTEROP_DLL USE_PREPARE_V2 WINDOWS] {
          #
          # NOTE: Check if the compile-time option is listed in the list of
          #       "define constants" kept track of by the managed assembly.
          #
          checkForSQLiteDefineConstant $::test_channel $defineConstant
        }