Skip to content

Commit 9f9cd5b

Browse files
committed
Switched back to the official SQLitePCLRaw.
1 parent 83d30d9 commit 9f9cd5b

13 files changed

+137
-37
lines changed

SQLite.Net.Tests/SQLite.Net2.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2121
</PackageReference>
2222
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
23-
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.3.1" />
23+
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.8" />
2424
</ItemGroup>
2525

2626
<ItemGroup>

SQLite.Net.Tests/SerializeTest.cs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
45
using NUnit.Framework;
56

6-
using System.Threading.Tasks;
7-
87
namespace SQLite.Net2.Tests
98
{
109
[TestFixture]
@@ -32,7 +31,7 @@ public SerializeTestDb(String path) : base(path)
3231
}
3332

3433
[Test]
35-
public async Task SerializeRoundTrip()
34+
public void SerializeRoundTrip()
3635
{
3736
var obj1 = new SerializeTestObj
3837
{
@@ -41,15 +40,15 @@ public async Task SerializeRoundTrip()
4140

4241
SQLiteConnection srcDb = new SerializeTestDb(":memory:");
4342

44-
int numIn1 = srcDb.Insert(obj1);
43+
var numIn1 = srcDb.Insert(obj1);
4544
Assert.AreEqual(1, numIn1);
4645

4746
List<SerializeTestObj> result1 = srcDb.Query<SerializeTestObj>("select * from SerializeTestObj").ToList();
4847
Assert.AreEqual(numIn1, result1.Count);
4948
Assert.AreEqual(obj1.Text, result1.First().Text);
5049

5150

52-
byte[] serialized = srcDb.Serialize();
51+
var serialized = srcDb.Serialize();
5352
srcDb.Close();
5453

5554
SQLiteConnection destDb = new SerializeTestDb(":memory");
@@ -61,5 +60,41 @@ public async Task SerializeRoundTrip()
6160

6261
destDb.Close();
6362
}
63+
64+
[Test]
65+
public void SerializeRoundTripStreams()
66+
{
67+
var obj1 = new SerializeTestObj
68+
{
69+
Text = "GLaDOS loves testing!"
70+
};
71+
72+
SQLiteConnection srcDb = new SerializeTestDb(":memory:");
73+
74+
var numIn1 = srcDb.Insert(obj1);
75+
Assert.AreEqual(1, numIn1);
76+
77+
List<SerializeTestObj> result1 = srcDb.Query<SerializeTestObj>("select * from SerializeTestObj").ToList();
78+
Assert.AreEqual(numIn1, result1.Count);
79+
Assert.AreEqual(obj1.Text, result1.First().Text);
80+
81+
82+
MemoryStream stream = new();
83+
var size = srcDb.Serialize(stream);
84+
Assert.That(size, Is.GreaterThan(0));
85+
srcDb.Close();
86+
87+
stream.Seek(0, SeekOrigin.Begin);
88+
89+
SQLiteConnection destDb = new SerializeTestDb(":memory");
90+
destDb.Deserialize(stream);
91+
Assert.That(stream.Position, Is.EqualTo(size));
92+
93+
result1 = destDb.Query<SerializeTestObj>("select * from SerializeTestObj").ToList();
94+
Assert.AreEqual(numIn1, result1.Count);
95+
Assert.AreEqual(obj1.Text, result1.First().Text);
96+
97+
destDb.Close();
98+
}
6499
}
65100
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

nuget.config

Lines changed: 0 additions & 6 deletions
This file was deleted.
-1.5 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.

src/SQLite.Net/Interop/SQLiteApi.cs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -315,34 +315,63 @@ public bool Equals(IDbBackupHandle other)
315315

316316
#region Serialize
317317

318-
public byte[] Serialize(IDbHandle db, string schema)
318+
/// <summary>
319+
/// Serialize the database, passing the memory to the given function to be copied as appropriate.
320+
/// <see cref="copy"/> will be called with a pointer to the serialized data and its size, and its
321+
/// return value or any exceptions will be passed through. The serialized memory is only valid
322+
/// during the callback, and will be freed immediately after regardless of success or failure.
323+
/// </summary>
324+
public T Serialize<T>(IDbHandle db, string schema, Func<IntPtr, long, T> copy)
319325
{
320326
var internalDbHandle = (DbHandle)db;
321-
return raw.sqlite3_serialize(internalDbHandle.DbPtr, schema);
322-
}
323327

324-
public long Serialize(IDbHandle db, string schema, System.IO.Stream stream)
325-
{
326-
var internalDbHandle = (DbHandle)db;
327-
return raw.sqlite3_serialize(internalDbHandle.DbPtr, schema, stream);
328-
}
328+
var bytesPtr = raw.sqlite3_serialize(internalDbHandle.DbPtr, schema, out var size, 0);
329+
if (bytesPtr == IntPtr.Zero)
330+
{
331+
throw new SQLiteException(Result.NoMem, Errmsg16(internalDbHandle));
332+
}
329333

330-
public void Deserialize(IDbHandle db, string schema, byte[] data)
331-
{
332-
var internalDbHandle = (DbHandle)db;
333-
var r = (Result)raw.sqlite3_deserialize(internalDbHandle.DbPtr, schema, data);
334-
if (r != Result.OK)
334+
try
335335
{
336-
throw new SQLiteException(r, Errmsg16(internalDbHandle));
336+
return copy(bytesPtr, size);
337+
}
338+
finally
339+
{
340+
raw.sqlite3_free(bytesPtr);
337341
}
338342
}
339343

340-
public void Deserialize(IDbHandle db, string schema, System.IO.Stream stream)
344+
/// <summary>
345+
/// Deserialize a database. A buffer of the requested <see cref="size"/> will be allocated and
346+
/// passed with the size to the given function to be filled as appropriate. Any exceptions will
347+
/// be passed through. The buffer is only valid during the callback, and will be freed or passed
348+
/// to sqlite immediately after depending on success.
349+
/// </summary>
350+
public void Deserialize(IDbHandle db, string schema, long size, Action<IntPtr, long> copy)
341351
{
342352
var internalDbHandle = (DbHandle)db;
343-
var r = (Result)raw.sqlite3_deserialize(internalDbHandle.DbPtr, schema, stream);
353+
354+
var bytesPtr = raw.sqlite3_malloc64(size);
355+
if (bytesPtr == IntPtr.Zero)
356+
{
357+
throw new SQLiteException(Result.NoMem, Errmsg16(internalDbHandle));
358+
}
359+
360+
try
361+
{
362+
copy(bytesPtr, size);
363+
}
364+
catch
365+
{
366+
raw.sqlite3_free(bytesPtr);
367+
throw;
368+
}
369+
370+
const int flags = raw.SQLITE_DESERIALIZE_RESIZEABLE | raw.SQLITE_DESERIALIZE_FREEONCLOSE;
371+
var r = (Result)raw.sqlite3_deserialize(internalDbHandle.DbPtr, schema, bytesPtr, size, size, flags);
344372
if (r != Result.OK)
345373
{
374+
// note: sqlite will free the buffer on error, thanks to SQLITE_DESERIALIZE_FREEONCLOSE
346375
throw new SQLiteException(r, Errmsg16(internalDbHandle));
347376
}
348377
}
@@ -380,4 +409,4 @@ public bool Equals(IDbStatement other)
380409
}
381410
}
382411
}
383-
}
412+
}

src/SQLite.Net/SQLite.Net2.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<AssemblyCopyright>Copyright ©2022 Benjamin Mayrargue</AssemblyCopyright>
1111
<LangVersion>Latest</LangVersion>
1212
<Nullable>enable</Nullable>
13+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1314
</PropertyGroup>
1415

1516
<!-- nuget configurable properties -->
@@ -31,7 +32,7 @@
3132
<Title>sqlite-net2 light ORM for SQLite</Title>
3233
<Description>sqlite-net2 allows applications to manage data in SQLite databases using Entity Framework like queries, but much lighter</Description>
3334
<Product>$(AssemblyName) ($(TargetFramework))</Product>
34-
<VersionSuffix>.7</VersionSuffix>
35+
<VersionSuffix>.8</VersionSuffix>
3536
<PackageVersion>$(Version)$(VersionSuffix)</PackageVersion>
3637
<Authors>Benjamin Mayrargue</Authors>
3738
<Owners>Benjamin Mayrargue</Owners>
@@ -47,7 +48,7 @@
4748
</PropertyGroup>
4849

4950
<ItemGroup>
50-
<PackageReference Include="SQLitePCLRaw.core" Version="2.1.3.1" />
51+
<PackageReference Include="SQLitePCLRaw.core" Version="2.1.8" />
5152
<None Include="..\..\LICENSE.md" Pack="true" PackagePath="" />
5253
</ItemGroup>
5354

src/SQLite.Net/SQLiteConnection.cs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using System.Collections.Concurrent;
2424
using System.Collections.Generic;
2525
using System.Diagnostics;
26+
using System.IO;
2627
using System.Linq;
2728
using System.Linq.Expressions;
2829
using System.Reflection;
@@ -1806,24 +1807,64 @@ public async Task<string> CreateDatabaseBackup()
18061807

18071808
#region Serialize
18081809

1810+
/// <summary>
1811+
/// Get the serialization of the database.
1812+
/// (This is the same sequence of bytes as would be written to a .db file.)
1813+
/// </summary>
18091814
public byte[] Serialize(string databaseName = "main")
18101815
{
1811-
return sqlite.Serialize(Handle, databaseName);
1816+
return sqlite.Serialize(Handle, databaseName, (bytesPtr, size) =>
1817+
{
1818+
unsafe
1819+
{
1820+
return new ReadOnlySpan<byte>(bytesPtr.ToPointer(), checked((int)size)).ToArray();
1821+
}
1822+
});
18121823
}
18131824

1814-
public long Serialize(System.IO.Stream stream, string databaseName = "main")
1825+
/// <summary>
1826+
/// Write the serialization of the database to the given stream.
1827+
/// (This is the same sequence of bytes as would be written to a .db file.)
1828+
/// </summary>
1829+
/// <returns>The number of bytes written to the stream.</returns>
1830+
public long Serialize(Stream stream, string databaseName = "main")
18151831
{
1816-
return sqlite.Serialize(Handle, databaseName, stream);
1832+
return sqlite.Serialize(Handle, databaseName, (bytesPtr, size) =>
1833+
{
1834+
unsafe
1835+
{
1836+
new UnmanagedMemoryStream((byte*)bytesPtr, size).CopyTo(stream);
1837+
}
1838+
return size;
1839+
});
18171840
}
18181841

1842+
/// <summary>
1843+
/// Load the serialization (.db file contents) of a database from the given byte array.
1844+
/// </summary>
18191845
public void Deserialize(byte[] dbData, string databaseName = "main")
18201846
{
1821-
sqlite.Deserialize(Handle, databaseName, dbData);
1847+
sqlite.Deserialize(Handle, databaseName, dbData.Length, (bytesPtr, size) =>
1848+
{
1849+
unsafe
1850+
{
1851+
dbData.CopyTo(new Span<byte>(bytesPtr.ToPointer(), checked((int)size)));
1852+
}
1853+
});
18221854
}
18231855

1824-
public void Deserialize(System.IO.Stream stream, string databaseName = "main")
1856+
/// <summary>
1857+
/// Load the serialization (.db file contents) of a database from the given stream.
1858+
/// </summary>
1859+
public void Deserialize(Stream stream, string databaseName = "main")
18251860
{
1826-
sqlite.Deserialize(Handle, databaseName, stream);
1861+
sqlite.Deserialize(Handle, databaseName, stream.Length, (bytesPtr, size) =>
1862+
{
1863+
unsafe
1864+
{
1865+
stream.CopyTo(new UnmanagedMemoryStream((byte*)bytesPtr, size, size, FileAccess.Write));
1866+
}
1867+
});
18271868
}
18281869

18291870
#endregion

0 commit comments

Comments
 (0)