From 16759b9598980e3f8184b3041bc0938aa67d85ce Mon Sep 17 00:00:00 2001 From: Thomas Stocker Date: Mon, 6 Sep 2021 02:06:26 +0200 Subject: [PATCH 01/91] AOT Jit Compile Workaround --- src/SQLite.cs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/SQLite.cs b/src/SQLite.cs index ee172b39..a4dca86e 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -25,6 +25,7 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Diagnostics; #if !USE_SQLITEPCL_RAW using System.Runtime.InteropServices; @@ -35,6 +36,7 @@ using System.Linq.Expressions; using System.Text; using System.Threading; +using ExecutionEngineException = System.ExecutionEngineException; #if USE_CSHARP_SQLITE using Sqlite3 = Community.CsharpSqlite.Sqlite3; @@ -2139,6 +2141,14 @@ void OnTableChanged (TableMapping table, NotifyTableChangedAction action) } public event EventHandler TableChanged; + + public static void RegisterFastColumnSetter ( + Type type, + string name, + Action setter) + { + FastColumnSetter.RegisterFastColumnSetter (type, name, setter); + } } public class NotifyTableChangedEventArgs : EventArgs @@ -3038,7 +3048,16 @@ public IEnumerable ExecuteDeferredQuery (TableMapping map) continue; if (fastColumnSetters[i] != null) { - fastColumnSetters[i].Invoke (obj, stmt, i); + try { + fastColumnSetters[i].Invoke (obj, stmt, i); + } +#pragma warning disable CS0618 // Type or member is obsolete + catch (ExecutionEngineException) { +#pragma warning restore CS0618 // Type or member is obsolete + // Column setter as AOT Problem so don't use it. + fastColumnSetters[i] = null; + Trace.WriteLine($"FastMapper AOT Jit Exception on Type {map.MappedType.FullName} Column {cols[i].Name}"); + } } else { var colType = SQLite3.ColumnType (stmt, i); @@ -3365,6 +3384,14 @@ object ReadCol (Sqlite3Statement stmt, int index, SQLite3.ColType type, Type clr internal class FastColumnSetter { + private static ConcurrentDictionary<(Type, string), Action> customSetter = + new ConcurrentDictionary<(Type, string), Action> (); + + public static void RegisterFastColumnSetter(Type type, string name, Action setter) + { + customSetter[(type, name)] = setter; + } + /// /// Creates a delegate that can be used to quickly set object members from query columns. /// @@ -3381,7 +3408,9 @@ internal class FastColumnSetter /// internal static Action GetFastSetter (SQLiteConnection conn, TableMapping.Column column) { - Action fastSetter = null; + if (customSetter.TryGetValue ((typeof(T), column.Name), out var fastSetter)) { + return fastSetter; + } Type clrType = column.PropertyInfo.PropertyType; From de0e98e84b8294216af02d03803dab2108ea4139 Mon Sep 17 00:00:00 2001 From: Thomas Stocker Date: Mon, 6 Sep 2021 02:16:52 +0200 Subject: [PATCH 02/91] fixed spelling --- src/SQLite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SQLite.cs b/src/SQLite.cs index a4dca86e..8185ef78 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -3054,7 +3054,7 @@ public IEnumerable ExecuteDeferredQuery (TableMapping map) #pragma warning disable CS0618 // Type or member is obsolete catch (ExecutionEngineException) { #pragma warning restore CS0618 // Type or member is obsolete - // Column setter as AOT Problem so don't use it. + // Column setter has AOT Problem so don't use it. fastColumnSetters[i] = null; Trace.WriteLine($"FastMapper AOT Jit Exception on Type {map.MappedType.FullName} Column {cols[i].Name}"); } From 8352f4b20db912b64231bc3a4de4032e4c8e2b3f Mon Sep 17 00:00:00 2001 From: Thomas Stocker Date: Mon, 6 Sep 2021 02:18:37 +0200 Subject: [PATCH 03/91] Correct Name --- src/SQLite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SQLite.cs b/src/SQLite.cs index 8185ef78..6ab8b9be 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -3056,7 +3056,7 @@ public IEnumerable ExecuteDeferredQuery (TableMapping map) #pragma warning restore CS0618 // Type or member is obsolete // Column setter has AOT Problem so don't use it. fastColumnSetters[i] = null; - Trace.WriteLine($"FastMapper AOT Jit Exception on Type {map.MappedType.FullName} Column {cols[i].Name}"); + Trace.WriteLine($"FastColumnSetter AOT Jit Exception on Type {map.MappedType.FullName} Column {cols[i].Name}"); } } else { From a60a2645a0f282175fda9aac4e1d1d91544c7572 Mon Sep 17 00:00:00 2001 From: Thomas Stocker Date: Thu, 9 Sep 2021 11:26:07 +0200 Subject: [PATCH 04/91] Update SQLite.cs Read value that could not be read by default implmentation --- src/SQLite.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SQLite.cs b/src/SQLite.cs index 6ab8b9be..9f41f34a 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -3057,6 +3057,7 @@ public IEnumerable ExecuteDeferredQuery (TableMapping map) // Column setter has AOT Problem so don't use it. fastColumnSetters[i] = null; Trace.WriteLine($"FastColumnSetter AOT Jit Exception on Type {map.MappedType.FullName} Column {cols[i].Name}"); + i--; // go one back and read it with default implementation } } else { From 2464447e0d6b6bda6cb73364a382de2a1aaa790d Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Wed, 26 Jul 2023 16:27:53 +0200 Subject: [PATCH 05/91] retarget Tests to .NET 6.0 Because .NET 3.1 is end of life --- tests/SQLite.Tests/SQLite.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 1d9224f8..8c0db897 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net6.0 false From 647576547f46814ff020ce3e7819620c59283b69 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 14:59:27 +0100 Subject: [PATCH 06/91] roll forward last minor --- global.json | 1 + 1 file changed, 1 insertion(+) diff --git a/global.json b/global.json index 8a1056e1..8c95f992 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { "version": "8.0.100" + "rollForward": "latestMinor", } } \ No newline at end of file From 49ceeb970cb5a9cc486fc1e8a81aad7be2e5d479 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 15:01:36 +0100 Subject: [PATCH 07/91] fixing build --- SQLite.sln | 74 +++++++++++++++++++++++++++++------------------------ global.json | 4 +-- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/SQLite.sln b/SQLite.sln index a6329bc1..53e8e82e 100644 --- a/SQLite.sln +++ b/SQLite.sln @@ -1,108 +1,114 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34707.107 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0E59A10-7BD0-4554-B133-66FA850159BE}" ProjectSection(SolutionItems) = preProject + global.json = global.json Makefile = Makefile README.md = README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-std", "nuget\SQLite-net-std\SQLite-net-std.csproj", "{081D08D6-10F1-431B-88FE-469FD9FE898C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-std", "nuget\SQLite-net-std\SQLite-net-std.csproj", "{081D08D6-10F1-431B-88FE-469FD9FE898C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiDiff", "tests\ApiDiff\ApiDiff.csproj", "{1DEF735C-B973-4ED9-8446-7FFA6D0B410B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiDiff", "tests\ApiDiff\ApiDiff.csproj", "{1DEF735C-B973-4ED9-8446-7FFA6D0B410B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-base", "nuget\SQLite-net-base\SQLite-net-base.csproj", "{53D1953C-3641-47D0-BE08-14DB853CC576}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-base", "nuget\SQLite-net-base\SQLite-net-base.csproj", "{53D1953C-3641-47D0-BE08-14DB853CC576}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-sqlcipher", "nuget\SQLite-net-sqlcipher\SQLite-net-sqlcipher.csproj", "{59DB03EF-E28D-431E-9058-74AF316800EE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-sqlcipher", "nuget\SQLite-net-sqlcipher\SQLite-net-sqlcipher.csproj", "{59DB03EF-E28D-431E-9058-74AF316800EE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Tests", "tests\SQLite.Tests\SQLite.Tests.csproj", "{80B66A43-B358-4438-BF06-6351B86B121A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite.Tests", "tests\SQLite.Tests\SQLite.Tests.csproj", "{80B66A43-B358-4438-BF06-6351B86B121A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-static", "nuget\SQLite-net-static\SQLite-net-static.csproj", "{7CD60DAE-D505-4C2E-80B3-296556CE711E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-static", "nuget\SQLite-net-static\SQLite-net-static.csproj", "{7CD60DAE-D505-4C2E-80B3-296556CE711E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU + Debug|iPhone = Debug|iPhone Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|Any CPU = Release|Any CPU Release|iPhone = Release|iPhone Release|iPhoneSimulator = Release|iPhoneSimulator - Debug|iPhone = Debug|iPhone EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.Build.0 = Release|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.Build.0 = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.Build.0 = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhone.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhone.Build.0 = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.Build.0 = Release|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.Build.0 = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhone.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhone.Build.0 = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.Build.0 = Release|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.Build.0 = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhone.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhone.Build.0 = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.Build.0 = Release|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.Build.0 = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhone.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhone.Build.0 = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.Build.0 = Release|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.Build.0 = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhone.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhone.Build.0 = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.Build.0 = Release|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.Build.0 = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhone.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhone.Build.0 = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {1DEF735C-B973-4ED9-8446-7FFA6D0B410B} = {FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF} diff --git a/global.json b/global.json index 8c95f992..dd9af827 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { "version": "8.0.100" - "rollForward": "latestMinor", + "rollForward": "latestMinor" } -} \ No newline at end of file +} From 2f90c314272d448b025057d11bc40d0cd5f84b1b Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 15:01:54 +0100 Subject: [PATCH 08/91] fixing global.json --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index dd9af827..79379c18 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100" + "version": "8.0.100", "rollForward": "latestMinor" } } From accbe0efa3d29a687ab089b9954d5a638c95217f Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 15:10:13 +0100 Subject: [PATCH 09/91] update tests --- tests/SQLite.Tests/SQLite.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index bbb743fd..05ce2c74 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -9,7 +9,7 @@ - + From 7dddbd67aef5cff67741a96dab92ec78faff9cc5 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 15:10:59 +0100 Subject: [PATCH 10/91] increase version number --- Directory.Build.props | 2 +- SQLite.sln | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 28f8be5b..0dff1e8a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ 1.9 - + 1 Logo-low.png https://github.com/praeclarum/sqlite-net diff --git a/SQLite.sln b/SQLite.sln index 53e8e82e..586c3d13 100644 --- a/SQLite.sln +++ b/SQLite.sln @@ -5,6 +5,7 @@ VisualStudioVersion = 17.10.34707.107 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0E59A10-7BD0-4554-B133-66FA850159BE}" ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props global.json = global.json Makefile = Makefile README.md = README.md From ffa45b3d745afe496d923882f09bf311fbe0ed40 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 15:13:02 +0100 Subject: [PATCH 11/91] fixing version --- Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0dff1e8a..7e1aeec0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 1.9 - 1 + 1.9.1 + Logo-low.png https://github.com/praeclarum/sqlite-net From 2e2772c2956735b8328048074f464f9e3eb1f09c Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 28 Mar 2024 15:18:08 +0100 Subject: [PATCH 12/91] version number --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 7e1aeec0..b680839c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 1.9.1 + 1.9.173 Logo-low.png From ef58b8412d7b0aceeb32ec2ea6eab5c732b24a4a Mon Sep 17 00:00:00 2001 From: inforithmics Date: Wed, 5 Mar 2025 13:20:02 +0100 Subject: [PATCH 13/91] Revert Solution changes --- SQLite.sln | 75 +++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/SQLite.sln b/SQLite.sln index 586c3d13..a6329bc1 100644 --- a/SQLite.sln +++ b/SQLite.sln @@ -1,115 +1,108 @@  -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.10.34707.107 -MinimumVisualStudioVersion = 10.0.40219.1 +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0E59A10-7BD0-4554-B133-66FA850159BE}" ProjectSection(SolutionItems) = preProject - Directory.Build.props = Directory.Build.props - global.json = global.json Makefile = Makefile README.md = README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-std", "nuget\SQLite-net-std\SQLite-net-std.csproj", "{081D08D6-10F1-431B-88FE-469FD9FE898C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-std", "nuget\SQLite-net-std\SQLite-net-std.csproj", "{081D08D6-10F1-431B-88FE-469FD9FE898C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiDiff", "tests\ApiDiff\ApiDiff.csproj", "{1DEF735C-B973-4ED9-8446-7FFA6D0B410B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiDiff", "tests\ApiDiff\ApiDiff.csproj", "{1DEF735C-B973-4ED9-8446-7FFA6D0B410B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-base", "nuget\SQLite-net-base\SQLite-net-base.csproj", "{53D1953C-3641-47D0-BE08-14DB853CC576}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-base", "nuget\SQLite-net-base\SQLite-net-base.csproj", "{53D1953C-3641-47D0-BE08-14DB853CC576}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-sqlcipher", "nuget\SQLite-net-sqlcipher\SQLite-net-sqlcipher.csproj", "{59DB03EF-E28D-431E-9058-74AF316800EE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-sqlcipher", "nuget\SQLite-net-sqlcipher\SQLite-net-sqlcipher.csproj", "{59DB03EF-E28D-431E-9058-74AF316800EE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite.Tests", "tests\SQLite.Tests\SQLite.Tests.csproj", "{80B66A43-B358-4438-BF06-6351B86B121A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Tests", "tests\SQLite.Tests\SQLite.Tests.csproj", "{80B66A43-B358-4438-BF06-6351B86B121A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLite-net-static", "nuget\SQLite-net-static\SQLite-net-static.csproj", "{7CD60DAE-D505-4C2E-80B3-296556CE711E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-static", "nuget\SQLite-net-static\SQLite-net-static.csproj", "{7CD60DAE-D505-4C2E-80B3-296556CE711E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|iPhone = Debug|iPhone - Debug|iPhoneSimulator = Debug|iPhoneSimulator Release|Any CPU = Release|Any CPU + Debug|iPhoneSimulator = Debug|iPhoneSimulator Release|iPhone = Release|iPhone Release|iPhoneSimulator = Release|iPhoneSimulator + Debug|iPhone = Debug|iPhone EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.Build.0 = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.Build.0 = Release|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhone.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhone.Build.0 = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.Build.0 = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.Build.0 = Release|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhone.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhone.Build.0 = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.Build.0 = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.Build.0 = Release|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhone.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhone.Build.0 = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.Build.0 = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.Build.0 = Release|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhone.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhone.Build.0 = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.Build.0 = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.Build.0 = Release|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhone.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhone.Build.0 = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.Build.0 = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.Build.0 = Release|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhone.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhone.Build.0 = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {1DEF735C-B973-4ED9-8446-7FFA6D0B410B} = {FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF} From 00117c606bfecd63f24d192f146cd6a8805a0658 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Wed, 5 Mar 2025 13:24:51 +0100 Subject: [PATCH 14/91] undo changes --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index cdbb589e..d5bf446d 100644 --- a/global.json +++ b/global.json @@ -3,4 +3,4 @@ "version": "9.0.100", "rollForward": "latestFeature" } -} +} \ No newline at end of file From 390823e7d1b80aa7b24e976e402d416c3aa74fa6 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Wed, 5 Mar 2025 13:44:21 +0100 Subject: [PATCH 15/91] Added FastColumnSetter Unit Tests --- tests/SQLite.Tests/FastColumnSetterTest.cs | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/SQLite.Tests/FastColumnSetterTest.cs diff --git a/tests/SQLite.Tests/FastColumnSetterTest.cs b/tests/SQLite.Tests/FastColumnSetterTest.cs new file mode 100644 index 00000000..b2e0ca40 --- /dev/null +++ b/tests/SQLite.Tests/FastColumnSetterTest.cs @@ -0,0 +1,116 @@ +using System; +using System.Linq; +#if NETFX_CORE +using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; +using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; +using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; +using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#else +using NUnit.Framework; +#endif + +namespace SQLite.Tests +{ + [TestFixture] + class FastColumnSetterTest + { + public class TestSetter + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Data { get; set; } + + public DateTime Date { get; set; } + } + + public class TestDb : SQLiteConnection + { + public TestDb (String path) + : base (path) + { + CreateTable (); + } + } + + [Test] + public void SetFastColumnSetters_AndReadData() + { + FastColumnSetter.RegisterFastColumnSetter( + typeof(TestSetter), + nameof(TestSetter.Id), + (obj, stmt, index) => { ((TestSetter)obj).Id = SQLite3.ColumnInt(stmt, index); }); + + FastColumnSetter.RegisterFastColumnSetter ( + typeof (TestSetter), + nameof (TestSetter.Data), + (obj, stmt, index) => { ((TestSetter)obj).Data = SQLite3.ColumnString (stmt, index); }); + + FastColumnSetter.RegisterFastColumnSetter ( + typeof (TestSetter), + nameof (TestSetter.Date), + (obj, stmt, index) => { ((TestSetter)obj).Date = new DateTime (SQLite3.ColumnInt64 (stmt, index)); }); + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new TestSetter { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i) + }; + + var db = new TestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Data.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + } + + [Test] + public void SetFastColumnSetters_AndReadData_IsCalled() + { + int callCount = 0; + + FastColumnSetter.RegisterFastColumnSetter ( + typeof (TestSetter), + nameof (TestSetter.Id), + (obj, stmt, index) => { + ((TestSetter)obj).Id = SQLite3.ColumnInt (stmt, index); + callCount++; + }); + + FastColumnSetter.RegisterFastColumnSetter ( + typeof (TestSetter), + nameof (TestSetter.Data), + (obj, stmt, index) => { + ((TestSetter)obj).Data = SQLite3.ColumnString (stmt, index); + callCount++; + }); + + FastColumnSetter.RegisterFastColumnSetter ( + typeof (TestSetter), + nameof (TestSetter.Date), + (obj, stmt, index) => { + ((TestSetter)obj).Date = new DateTime (SQLite3.ColumnInt64 (stmt, index)); + callCount++; + }); + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new TestSetter { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i) + }; + + var db = new TestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Data.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + + Assert.IsTrue(callCount > 0); + } + } +} +} From 449e6e8efd05b6192057704bd600363d6e7e802d Mon Sep 17 00:00:00 2001 From: inforithmics Date: Wed, 5 Mar 2025 13:47:19 +0100 Subject: [PATCH 16/91] revert test changes --- tests/SQLite.Tests/SQLite.Tests.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 05ce2c74..d44f218a 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -2,14 +2,16 @@ net8.0 + false + - + From f08d9c9fe4284e78b95d0048de1bb006ccad9038 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Wed, 5 Mar 2025 13:48:13 +0100 Subject: [PATCH 17/91] fixed build --- tests/SQLite.Tests/FastColumnSetterTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/SQLite.Tests/FastColumnSetterTest.cs b/tests/SQLite.Tests/FastColumnSetterTest.cs index b2e0ca40..66efa0ba 100644 --- a/tests/SQLite.Tests/FastColumnSetterTest.cs +++ b/tests/SQLite.Tests/FastColumnSetterTest.cs @@ -12,7 +12,7 @@ namespace SQLite.Tests { [TestFixture] - class FastColumnSetterTest + public class FastColumnSetterTest { public class TestSetter { @@ -113,4 +113,3 @@ public void SetFastColumnSetters_AndReadData_IsCalled() } } } -} From 84cf28fb50c829794166de160184eb0a165a9940 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 00:46:22 +0200 Subject: [PATCH 18/91] Add Source Generator Project --- SQLite.sln | 78 ++++++++++++------- .../Sqlite_net.SourceGenerator.csproj | 16 ++++ 2 files changed, 66 insertions(+), 28 deletions(-) create mode 100644 nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj diff --git a/SQLite.sln b/SQLite.sln index a6329bc1..8c860d1f 100644 --- a/SQLite.sln +++ b/SQLite.sln @@ -1,6 +1,8 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36429.23 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0E59A10-7BD0-4554-B133-66FA850159BE}" ProjectSection(SolutionItems) = preProject Makefile = Makefile @@ -21,93 +23,113 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Tests", "tests\SQLit EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-static", "nuget\SQLite-net-static\SQLite-net-static.csproj", "{7CD60DAE-D505-4C2E-80B3-296556CE711E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sqlite_net.SourceGenerator", "nuget\Sqlite_net.SourceGenerator\Sqlite_net.SourceGenerator.csproj", "{8AFC8450-42E6-41AF-8E39-17EC7C13D695}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU + Debug|iPhone = Debug|iPhone Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|Any CPU = Release|Any CPU Release|iPhone = Release|iPhone Release|iPhoneSimulator = Release|iPhoneSimulator - Debug|iPhone = Debug|iPhone EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.Build.0 = Release|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.Build.0 = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|Any CPU.Build.0 = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhone.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhone.Build.0 = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {081D08D6-10F1-431B-88FE-469FD9FE898C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {081D08D6-10F1-431B-88FE-469FD9FE898C}.Debug|iPhone.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.Build.0 = Release|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.Build.0 = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|Any CPU.Build.0 = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhone.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhone.Build.0 = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {1DEF735C-B973-4ED9-8446-7FFA6D0B410B}.Debug|iPhone.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.Build.0 = Release|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.Build.0 = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|Any CPU.Build.0 = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhone.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhone.Build.0 = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {53D1953C-3641-47D0-BE08-14DB853CC576}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {53D1953C-3641-47D0-BE08-14DB853CC576}.Debug|iPhone.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.Build.0 = Release|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.Build.0 = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|Any CPU.Build.0 = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhone.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhone.Build.0 = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {59DB03EF-E28D-431E-9058-74AF316800EE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {59DB03EF-E28D-431E-9058-74AF316800EE}.Debug|iPhone.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.Build.0 = Release|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.Build.0 = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80B66A43-B358-4438-BF06-6351B86B121A}.Release|Any CPU.Build.0 = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhone.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhone.Build.0 = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {80B66A43-B358-4438-BF06-6351B86B121A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {80B66A43-B358-4438-BF06-6351B86B121A}.Debug|iPhone.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.Build.0 = Release|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.Build.0 = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|Any CPU.Build.0 = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhone.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhone.Build.0 = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {7CD60DAE-D505-4C2E-80B3-296556CE711E}.Debug|iPhone.Build.0 = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Debug|iPhone.Build.0 = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Release|Any CPU.Build.0 = Release|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Release|iPhone.ActiveCfg = Release|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Release|iPhone.Build.0 = Release|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {8AFC8450-42E6-41AF-8E39-17EC7C13D695}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {1DEF735C-B973-4ED9-8446-7FFA6D0B410B} = {FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF} {80B66A43-B358-4438-BF06-6351B86B121A} = {FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E4388666-648A-41A5-B10B-2598523000A1} + EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = tests\SQLite.Tests.csproj Policies = $0 diff --git a/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj b/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj new file mode 100644 index 00000000..96be9a54 --- /dev/null +++ b/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.0 + false + + + *$(MSBuildProjectFile)* + + + + + + + + From 29a43677f5931369dc6f535117b6943d6a0c3f43 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 01:52:13 +0200 Subject: [PATCH 19/91] Sqlite fist colum setters --- nuget/Sqlite_net.SourceGenerator/Pollyfill.cs | 5 + .../SQLiteFAstColumnSetterGenerator.cs | 231 ++++++++++++++++++ .../Sqlite_net.SourceGenerator.csproj | 7 +- 3 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 nuget/Sqlite_net.SourceGenerator/Pollyfill.cs create mode 100644 nuget/Sqlite_net.SourceGenerator/SQLiteFAstColumnSetterGenerator.cs diff --git a/nuget/Sqlite_net.SourceGenerator/Pollyfill.cs b/nuget/Sqlite_net.SourceGenerator/Pollyfill.cs new file mode 100644 index 00000000..dfa45ce1 --- /dev/null +++ b/nuget/Sqlite_net.SourceGenerator/Pollyfill.cs @@ -0,0 +1,5 @@ +// Polyfill for IsExternalInit to support record types in .NET Standard 2.0 +namespace System.Runtime.CompilerServices +{ + internal static class IsExternalInit { } +} diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFAstColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFAstColumnSetterGenerator.cs new file mode 100644 index 00000000..565de0c2 --- /dev/null +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFAstColumnSetterGenerator.cs @@ -0,0 +1,231 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Text; + +[Generator] +public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + // Find all classes with TableAttribute or properties with ColumnAttribute + var classDeclarations = context.SyntaxProvider + .CreateSyntaxProvider( + predicate: static (s, _) => IsCandidateClass(s), + transform: static (ctx, _) => GetClassInfo(ctx)) + .Where(static m => m is not null); + + // Combine with compilation + var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); + + context.RegisterSourceOutput(compilationAndClasses, + static (spc, source) => Execute(source.Left, source.Right, spc)); + } + + static bool IsCandidateClass(SyntaxNode node) + { + if (node is not ClassDeclarationSyntax classDecl) + return false; + + // Check if class has TableAttribute + if (classDecl.AttributeLists.Any(attrList => + attrList.Attributes.Any(attr => + attr.Name.ToString().Contains("Table")))) + { + return true; + } + + // Check if any property has ColumnAttribute + return classDecl.Members + .OfType() + .Any(prop => prop.AttributeLists.Any(attrList => + attrList.Attributes.Any(attr => + attr.Name.ToString().Contains("Column")))); + } + + static ClassInfo? GetClassInfo(GeneratorSyntaxContext context) + { + var classDecl = (ClassDeclarationSyntax)context.Node; + var semanticModel = context.SemanticModel; + + var classSymbol = semanticModel.GetDeclaredSymbol(classDecl); + if (classSymbol is null) + return null; + + var hasTableAttribute = classSymbol.GetAttributes() + .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); + + var properties = new List(); + + foreach (var member in classSymbol.GetMembers().OfType()) + { + var hasColumnAttribute = member.GetAttributes() + .Any(attr => attr.AttributeClass?.Name == "ColumnAttribute"); + + // Include property if class has TableAttribute or property has ColumnAttribute + if (hasTableAttribute || hasColumnAttribute) + { + var columnName = GetColumnName(member); + properties.Add(new PropertyInfo(member.Name, member.Type.ToDisplayString(), columnName)); + } + } + + if (properties.Count == 0) + return null; + + return new ClassInfo( + classSymbol.Name, + classSymbol.ContainingNamespace?.ToDisplayString() ?? string.Empty, + properties); + } + + static string GetColumnName(IPropertySymbol property) + { + // Check for ColumnAttribute with name parameter + var columnAttr = property.GetAttributes() + .FirstOrDefault(attr => attr.AttributeClass?.Name == "ColumnAttribute"); + + if (columnAttr?.ConstructorArguments.Length > 0) + { + var nameArg = columnAttr.ConstructorArguments[0]; + if (nameArg.Value is string columnName) + return columnName; + } + + // Default to property name + return property.Name; + } + + static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context) + { + if (classes.IsDefaultOrEmpty) + return; + + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("using System;"); + sb.AppendLine("using SQLite;"); + sb.AppendLine(); + sb.AppendLine("namespace SQLite.Generated"); + sb.AppendLine("{"); + sb.AppendLine(" internal static class FastColumnSetterRegistration"); + sb.AppendLine(" {"); + sb.AppendLine(" public static void RegisterAll()"); + sb.AppendLine(" {"); + + foreach (var classInfo in classes) + { + foreach (var property in classInfo.Properties) + { + var fullTypeName = string.IsNullOrEmpty(classInfo.Namespace) + ? classInfo.ClassName + : $"{classInfo.Namespace}.{classInfo.ClassName}"; + + sb.AppendLine($" SQLiteConnection.RegisterFastColumnSetter("); + sb.AppendLine($" typeof({fullTypeName}),"); + sb.AppendLine($" \"{property.ColumnName}\","); + sb.AppendLine($" (obj, stmt, index) => "); + sb.AppendLine($" {{"); + sb.AppendLine($" var typedObj = ({fullTypeName})obj;"); + sb.AppendLine($" var colType = SQLite3.ColumnType(stmt, index);"); + sb.AppendLine($" if (colType != SQLite3.ColType.Null)"); + sb.AppendLine($" {{"); + + // Generate appropriate setter based on property type + GeneratePropertySetter(sb, property); + + sb.AppendLine($" }}"); + sb.AppendLine($" }});"); + sb.AppendLine(); + } + } + + sb.AppendLine(" }"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + + context.AddSource("SQLiteFastColumnSetters.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + } + + static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) + { + var propertyType = property.TypeName; + + // Handle nullable types + var isNullable = propertyType.Contains("?"); + if (isNullable) + propertyType = propertyType.Replace("?", ""); + + switch (propertyType) + { + case "string": + case "String": + case "System.String": + sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnString(stmt, index);"); + break; + + case "int": + case "Int32": + case "System.Int32": + sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt(stmt, index);"); + break; + + case "long": + case "Int64": + case "System.Int64": + sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt64(stmt, index);"); + break; + + case "double": + case "Double": + case "System.Double": + sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); + break; + + case "float": + case "Single": + case "System.Single": + sb.AppendLine($" typedObj.{property.PropertyName} = (float)SQLite3.ColumnDouble(stmt, index);"); + break; + + case "bool": + case "Boolean": + case "System.Boolean": + sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt(stmt, index) == 1;"); + break; + + case "DateTime": + case "System.DateTime": + sb.AppendLine($" typedObj.{property.PropertyName} = new DateTime(SQLite3.ColumnInt64(stmt, index));"); + break; + + case "Guid": + case "System.Guid": + sb.AppendLine($" var text = SQLite3.ColumnString(stmt, index);"); + sb.AppendLine($" typedObj.{property.PropertyName} = new Guid(text);"); + break; + + case "byte[]": + sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index);"); + break; + + default: + // For other types, try to use a generic approach + sb.AppendLine($" // Generic setter for {propertyType}"); + sb.AppendLine($" var value = SQLite3.ColumnString(stmt, index);"); + sb.AppendLine($" if (value != null)"); + sb.AppendLine($" {{"); + sb.AppendLine($" typedObj.{property.PropertyName} = ({propertyType})Convert.ChangeType(value, typeof({propertyType}));"); + sb.AppendLine($" }}"); + break; + } + } + + record ClassInfo(string ClassName, string Namespace, List Properties); + record PropertyInfo(string PropertyName, string TypeName, string ColumnName); +} diff --git a/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj b/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj index 96be9a54..bb979d17 100644 --- a/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj +++ b/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj @@ -6,11 +6,14 @@ *$(MSBuildProjectFile)* + 9 + enable + true - - + + From 9736d7de0817f2230e041c812b8148296de490b9 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 01:52:43 +0200 Subject: [PATCH 20/91] fixing casing --- ...olumnSetterGenerator.cs => SQLiteFastColumnSetterGenerator.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename nuget/Sqlite_net.SourceGenerator/{SQLiteFAstColumnSetterGenerator.cs => SQLiteFastColumnSetterGenerator.cs} (100%) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFAstColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs similarity index 100% rename from nuget/Sqlite_net.SourceGenerator/SQLiteFAstColumnSetterGenerator.cs rename to nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs From 9ef1b1e33bfb58e3c20fdd76a1968782cabb112d Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 02:01:52 +0200 Subject: [PATCH 21/91] Improrove Source Generator --- .../SQLiteFastColumnSetterGenerator.cs | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 565de0c2..1c369fe3 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -24,7 +24,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); context.RegisterSourceOutput(compilationAndClasses, - static (spc, source) => Execute(source.Left, source.Right, spc)); + static (spc, source) => Execute(source.Left, source.Right!, spc)); } static bool IsCandidateClass(SyntaxNode node) @@ -105,17 +105,21 @@ static void Execute(Compilation compilation, ImmutableArray classes, { if (classes.IsDefaultOrEmpty) return; + + // Get the assembly name/namespace from the compilation + var assemblyName = compilation.AssemblyName ?? "Generated"; + var rootNamespace = GetRootNamespace(compilation) ?? assemblyName; var sb = new StringBuilder(); sb.AppendLine("// "); sb.AppendLine("using System;"); sb.AppendLine("using SQLite;"); sb.AppendLine(); - sb.AppendLine("namespace SQLite.Generated"); + sb.AppendLine($"namespace {rootNamespace}"); sb.AppendLine("{"); - sb.AppendLine(" internal static class FastColumnSetterRegistration"); + sb.AppendLine(" internal static class SQLite"); sb.AppendLine(" {"); - sb.AppendLine(" public static void RegisterAll()"); + sb.AppendLine(" public static void Init()"); sb.AppendLine(" {"); foreach (var classInfo in classes) @@ -151,6 +155,40 @@ static void Execute(Compilation compilation, ImmutableArray classes, context.AddSource("SQLiteFastColumnSetters.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } + + static string? GetRootNamespace(Compilation compilation) + { + // Try to get the default namespace from compilation options + if (compilation.Options is CSharpCompilationOptions csharpOptions) + { + // Check for global using statements or common namespace patterns + var globalUsings = compilation.SyntaxTrees + .SelectMany(tree => tree.GetRoot().DescendantNodes()) + .OfType() + .SelectMany(cu => cu.Usings) + .Where(u => u.GlobalKeyword.IsKind(SyntaxKind.GlobalKeyword)) + .ToList(); + } + + // Find the most common root namespace from existing types + var namespaces = compilation.GlobalNamespace + .GetNamespaceMembers() + .Where(ns => !string.IsNullOrEmpty(ns.Name) && + ns.Name != "System" && + ns.Name != "Microsoft" && + ns.Name != "SQLite") + .Select(ns => ns.Name) + .ToList(); + + if (namespaces.Any()) + { + return namespaces.First(); + } + + // Fallback to assembly name + return compilation.AssemblyName; + } + static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) { From 611aed25fad5cca3d8ec79f742cdce53115fe8f7 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 09:50:52 +0200 Subject: [PATCH 22/91] Generator improvements --- .../SQLiteFastColumnSetterGenerator.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 1c369fe3..12346301 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -11,6 +11,17 @@ [Generator] public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator { + private static HashSet SQLitePropertyAttributes = new() { + "ColumnAttribute", + "IndexedAttribute", + "IgnoreAttribute", + "UniqueAttribute", + "MaxLengthAttribute", + "CollationAttribute", + "NotNullAttribute", + "StoreAsTextAttribute", + }; + public void Initialize(IncrementalGeneratorInitializationContext context) { // Find all classes with TableAttribute or properties with ColumnAttribute @@ -35,17 +46,17 @@ static bool IsCandidateClass(SyntaxNode node) // Check if class has TableAttribute if (classDecl.AttributeLists.Any(attrList => attrList.Attributes.Any(attr => - attr.Name.ToString().Contains("Table")))) + attr.Name.ToString() == "TableAttribute"))) { return true; } - // Check if any property has ColumnAttribute + // Check if any property has SQLite Property Attribute return classDecl.Members .OfType() .Any(prop => prop.AttributeLists.Any(attrList => attrList.Attributes.Any(attr => - attr.Name.ToString().Contains("Column")))); + SQLitePropertyAttributes.Contains(attr.Name.ToString())))); } static ClassInfo? GetClassInfo(GeneratorSyntaxContext context) From 50128528bc9308bac174a2a545acbb66f9161af1 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 10:08:41 +0200 Subject: [PATCH 23/91] Added Unit Test --- .../SQLiteFastColumnSetterGenerator.cs | 2 +- tests/SQLite.Tests/SQLite.Tests.csproj | 14 ++++ tests/SQLite.Tests/SourceGeneratorTest.cs | 80 +++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/SQLite.Tests/SourceGeneratorTest.cs diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 12346301..eff588ad 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -128,7 +128,7 @@ static void Execute(Compilation compilation, ImmutableArray classes, sb.AppendLine(); sb.AppendLine($"namespace {rootNamespace}"); sb.AppendLine("{"); - sb.AppendLine(" internal static class SQLite"); + sb.AppendLine(" internal static class SQLiteInitializer"); sb.AppendLine(" {"); sb.AppendLine(" public static void Init()"); sb.AppendLine(" {"); diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index d44f218a..bc5d94e5 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -14,6 +14,20 @@ + + + + + + + + + true + $(BaseIntermediateOutputPath)Generated + + SQLite.cs diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs new file mode 100644 index 00000000..0c8395da --- /dev/null +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -0,0 +1,80 @@ +using System; +using System.Linq; +#if NETFX_CORE +using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; +using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; +using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; +using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#else +using NUnit.Framework; +#endif + +namespace SQLite.Tests +{ + [TestFixture] + public class SourceGeneratorTest + { + public class TestSetter + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Data { get; set; } + + public DateTime Date { get; set; } + } + + public class TestDb : SQLiteConnection + { + public TestDb (String path) + : base (path) + { + CreateTable (); + } + } + + [Test] + public void SqliteInitializer_AndReadData() + { + SQLiteInitializer.Init(); + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new TestSetter { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i) + }; + + var db = new TestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Data.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + } + + [Test] + public void SetFastColumnSetters_AndReadData_IsCalled() + { + SQLiteInitializer.Init (); + + int callCount = 0; + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new TestSetter { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i) + }; + + var db = new TestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Data.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + + Assert.IsTrue(callCount > 0); + } + } +} From 11fa1137324cb236bda59568943f0582c4a197b4 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 10:14:18 +0200 Subject: [PATCH 24/91] more debugging --- .../SQLiteFastColumnSetterGenerator.cs | 3 +++ tests/SQLite.Tests/SourceGeneratorTest.cs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index eff588ad..112f781a 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -24,6 +24,9 @@ public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator public void Initialize(IncrementalGeneratorInitializationContext context) { + // Stop Debugger for Debugging the Analyzer + System.Diagnostics.Debugger.Break(); + // Find all classes with TableAttribute or properties with ColumnAttribute var classDeclarations = context.SyntaxProvider .CreateSyntaxProvider( diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 0c8395da..fc854965 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -36,7 +36,7 @@ public TestDb (String path) [Test] public void SqliteInitializer_AndReadData() { - SQLiteInitializer.Init(); + //SQLiteInitializer.Init(); var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -56,7 +56,7 @@ public void SqliteInitializer_AndReadData() [Test] public void SetFastColumnSetters_AndReadData_IsCalled() { - SQLiteInitializer.Init (); + //SQLiteInitializer.Init (); int callCount = 0; From 743e25e308f8670898a325bdf5f2e6c375a5ceb0 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 10:30:09 +0200 Subject: [PATCH 25/91] Some more fixes --- .../SQLiteFastColumnSetterGenerator.cs | 28 ++++++++++--------- .../Sqlite_net.SourceGenerator.csproj | 4 +-- tests/SQLite.Tests/SourceGeneratorTest.cs | 5 ++-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 112f781a..dadd3357 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -12,23 +12,23 @@ public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator { private static HashSet SQLitePropertyAttributes = new() { - "ColumnAttribute", - "IndexedAttribute", - "IgnoreAttribute", - "UniqueAttribute", - "MaxLengthAttribute", - "CollationAttribute", - "NotNullAttribute", - "StoreAsTextAttribute", + "Column", + "Indexed", + "Ignore", + "Unique", + "MaxLength", + "Collation", + "NotNull", + "StoreAsText", }; public void Initialize(IncrementalGeneratorInitializationContext context) { // Stop Debugger for Debugging the Analyzer - System.Diagnostics.Debugger.Break(); + System.Diagnostics.Debugger.Launch(); - // Find all classes with TableAttribute or properties with ColumnAttribute - var classDeclarations = context.SyntaxProvider + // Find all classes with TableAttribute or properties with ColumnAttribute + var classDeclarations = context.SyntaxProvider .CreateSyntaxProvider( predicate: static (s, _) => IsCandidateClass(s), transform: static (ctx, _) => GetClassInfo(ctx)) @@ -48,8 +48,10 @@ static bool IsCandidateClass(SyntaxNode node) // Check if class has TableAttribute if (classDecl.AttributeLists.Any(attrList => - attrList.Attributes.Any(attr => - attr.Name.ToString() == "TableAttribute"))) + attrList.Attributes.Any(attr => { + var s = attr.Name.ToString (); + return s == "Table"; + }))) { return true; } diff --git a/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj b/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj index bb979d17..877156d9 100644 --- a/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj +++ b/nuget/Sqlite_net.SourceGenerator/Sqlite_net.SourceGenerator.csproj @@ -3,12 +3,10 @@ netstandard2.0 false - - - *$(MSBuildProjectFile)* 9 enable true + true diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index fc854965..9aa2ce55 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Newtonsoft; #if NETFX_CORE using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; @@ -36,7 +37,7 @@ public TestDb (String path) [Test] public void SqliteInitializer_AndReadData() { - //SQLiteInitializer.Init(); + SQLiteInitializer.Init(); var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -56,7 +57,7 @@ public void SqliteInitializer_AndReadData() [Test] public void SetFastColumnSetters_AndReadData_IsCalled() { - //SQLiteInitializer.Init (); + SQLiteInitializer.Init (); int callCount = 0; From da463ec7f0e22975fe81ecb15e9c177afc16f76b Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 10:57:00 +0200 Subject: [PATCH 26/91] Fixing Root Namespace --- .../SQLiteFastColumnSetterGenerator.cs | 51 +++++++------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index dadd3357..42ebb49b 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Text; +using Microsoft.CodeAnalysis.Diagnostics; [Generator] public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator @@ -34,11 +35,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context) transform: static (ctx, _) => GetClassInfo(ctx)) .Where(static m => m is not null); + // Get analyzer config options for accessing MSBuild properties + var configOptions = context.AnalyzerConfigOptionsProvider; + // Combine with compilation - var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); + var compilationAndClasses = context.CompilationProvider + .Combine(classDeclarations.Collect()) + .Combine(configOptions); context.RegisterSourceOutput(compilationAndClasses, - static (spc, source) => Execute(source.Left, source.Right!, spc)); + static (spc, source) => Execute(source.Left.Left, source.Left.Right!, source.Right, spc)); } static bool IsCandidateClass(SyntaxNode node) @@ -117,14 +123,18 @@ static string GetColumnName(IPropertySymbol property) return property.Name; } - static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context) + static void Execute( + Compilation compilation, + ImmutableArray classes, + AnalyzerConfigOptionsProvider configOptionsProvider, + SourceProductionContext context) { if (classes.IsDefaultOrEmpty) return; // Get the assembly name/namespace from the compilation var assemblyName = compilation.AssemblyName ?? "Generated"; - var rootNamespace = GetRootNamespace(compilation) ?? assemblyName; + var rootNamespace = GetRootNamespace(configOptionsProvider, compilation) ?? assemblyName; var sb = new StringBuilder(); sb.AppendLine("// "); @@ -169,38 +179,15 @@ static void Execute(Compilation compilation, ImmutableArray classes, sb.AppendLine(" }"); sb.AppendLine("}"); - context.AddSource("SQLiteFastColumnSetters.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + context.AddSource("SQLiteInitializer.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } - static string? GetRootNamespace(Compilation compilation) + static string? GetRootNamespace(AnalyzerConfigOptionsProvider configOptionsProvider, Compilation compilation) { - // Try to get the default namespace from compilation options - if (compilation.Options is CSharpCompilationOptions csharpOptions) - { - // Check for global using statements or common namespace patterns - var globalUsings = compilation.SyntaxTrees - .SelectMany(tree => tree.GetRoot().DescendantNodes()) - .OfType() - .SelectMany(cu => cu.Usings) - .Where(u => u.GlobalKeyword.IsKind(SyntaxKind.GlobalKeyword)) - .ToList(); + if (configOptionsProvider.GlobalOptions.TryGetValue ("build_property.RootNamespace", out var rootNs)) { + return rootNs; } - - // Find the most common root namespace from existing types - var namespaces = compilation.GlobalNamespace - .GetNamespaceMembers() - .Where(ns => !string.IsNullOrEmpty(ns.Name) && - ns.Name != "System" && - ns.Name != "Microsoft" && - ns.Name != "SQLite") - .Select(ns => ns.Name) - .ToList(); - - if (namespaces.Any()) - { - return namespaces.First(); - } - + // Fallback to assembly name return compilation.AssemblyName; } From 535e33a1f9c66ab5f89cd9eb97d5ed23cdaeb09b Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 11:04:31 +0200 Subject: [PATCH 27/91] Improved unit Test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 87 +++++++++++++++++++---- 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 9aa2ce55..7d9940da 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -12,10 +12,29 @@ namespace SQLite.Tests { + public class OuterTestSetter + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Data { get; set; } + + public DateTime Date { get; set; } + } + + public class OuterTestDb : SQLiteConnection + { + public OuterTestDb (String path) + : base (path) + { + CreateTable (); + } + } + [TestFixture] public class SourceGeneratorTest { - public class TestSetter + public class InnerTestSetter { [AutoIncrement, PrimaryKey] public int Id { get; set; } @@ -25,37 +44,37 @@ public class TestSetter public DateTime Date { get; set; } } - public class TestDb : SQLiteConnection + public class InnerTestDb : SQLiteConnection { - public TestDb (String path) + public InnerTestDb (String path) : base (path) { - CreateTable (); + CreateTable (); } } [Test] - public void SqliteInitializer_AndReadData() + public void SqliteInitializer_Inner_AndReadData() { SQLiteInitializer.Init(); var n = 20; var cq = from i in Enumerable.Range (1, n) - select new TestSetter { + select new InnerTestSetter { Data = Convert.ToString (i), Date = new DateTime (2013, 1, i) }; - var db = new TestDb (TestPath.GetTempFileName ()); + var db = new InnerTestDb (TestPath.GetTempFileName ()); db.InsertAll (cq); - var results = db.Table ().Where (o => o.Data.Equals ("10")); + var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); } [Test] - public void SetFastColumnSetters_AndReadData_IsCalled() + public void SetFastColumnSetters_Inner_AndReadData_IsCalled() { SQLiteInitializer.Init (); @@ -63,19 +82,63 @@ public void SetFastColumnSetters_AndReadData_IsCalled() var n = 20; var cq = from i in Enumerable.Range (1, n) - select new TestSetter { + select new InnerTestSetter { Data = Convert.ToString (i), Date = new DateTime (2013, 1, i) }; - var db = new TestDb (TestPath.GetTempFileName ()); + var db = new InnerTestDb (TestPath.GetTempFileName ()); db.InsertAll (cq); - var results = db.Table ().Where (o => o.Data.Equals ("10")); + var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); Assert.IsTrue(callCount > 0); } + + [Test] + public void SqliteInitializer_Outer_AndReadData () + { + SQLiteInitializer.Init (); + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new OuterTestSetter() { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i) + }; + + var db = new InnerTestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Data.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + } + + [Test] + public void SetFastColumnSetters_Outer_AndReadData_IsCalled () + { + SQLiteInitializer.Init (); + + int callCount = 0; + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new OuterTestSetter { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i) + }; + + var db = new InnerTestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Data.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + + Assert.IsTrue (callCount > 0); + } } } From 2372f1d9300e8a7c66938960d6e24b7e15172c48 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 11:46:35 +0200 Subject: [PATCH 28/91] Improve column setter --- .../SQLiteFastColumnSetterGenerator.cs | 80 +++++++++++-------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 42ebb49b..b775d510 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -12,7 +12,7 @@ [Generator] public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator { - private static HashSet SQLitePropertyAttributes = new() { + private static List SQLitePropertyAttributes = new() { "Column", "Indexed", "Ignore", @@ -54,56 +54,68 @@ static bool IsCandidateClass(SyntaxNode node) // Check if class has TableAttribute if (classDecl.AttributeLists.Any(attrList => - attrList.Attributes.Any(attr => { - var s = attr.Name.ToString (); - return s == "Table"; - }))) + attrList.Attributes.Any(attr => attr.Name.ToString ().Contains("Table")))) { return true; } // Check if any property has SQLite Property Attribute return classDecl.Members - .OfType() - .Any(prop => prop.AttributeLists.Any(attrList => - attrList.Attributes.Any(attr => - SQLitePropertyAttributes.Contains(attr.Name.ToString())))); + .OfType () + .Any (prop => prop.AttributeLists.Any (attrList => + attrList.Attributes.Any (attr => { + var attributeName = attr.Name.ToString (); + return SQLitePropertyAttributes.Any (f => attributeName.Contains (f)); + }))); } static ClassInfo? GetClassInfo(GeneratorSyntaxContext context) { - var classDecl = (ClassDeclarationSyntax)context.Node; - var semanticModel = context.SemanticModel; + var classDecl = (ClassDeclarationSyntax)context.Node; + var semanticModel = context.SemanticModel; - var classSymbol = semanticModel.GetDeclaredSymbol(classDecl); - if (classSymbol is null) - return null; + var classSymbol = semanticModel.GetDeclaredSymbol(classDecl); + if (classSymbol is null) + return null; - var hasTableAttribute = classSymbol.GetAttributes() - .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); + var hasTableAttribute = classSymbol.GetAttributes() + .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); - var properties = new List(); + var properties = new List(); - foreach (var member in classSymbol.GetMembers().OfType()) - { - var hasColumnAttribute = member.GetAttributes() - .Any(attr => attr.AttributeClass?.Name == "ColumnAttribute"); + foreach (var member in classSymbol.GetMembers().OfType()) + { + var hasColumnAttribute = member.GetAttributes() + .Any(attr => attr.AttributeClass?.Name == "ColumnAttribute"); - // Include property if class has TableAttribute or property has ColumnAttribute - if (hasTableAttribute || hasColumnAttribute) - { - var columnName = GetColumnName(member); - properties.Add(new PropertyInfo(member.Name, member.Type.ToDisplayString(), columnName)); - } - } + // Include property if class has TableAttribute or property has ColumnAttribute + if (hasTableAttribute || hasColumnAttribute) + { + var columnName = GetColumnName(member); + properties.Add(new PropertyInfo(member.Name, member.Type.ToDisplayString(), columnName)); + } + } + + if (properties.Count == 0) + return null; + + // Handle nested classes by building the full containing type path + var containingTypes = new List(); + var currentContaining = classSymbol.ContainingType; + while (currentContaining != null) + { + containingTypes.Insert(0, currentContaining.Name); + currentContaining = currentContaining.ContainingType; + } - if (properties.Count == 0) - return null; + var fullClassName = containingTypes.Count > 0 + ? $"{string.Join(".", containingTypes)}.{classSymbol.Name}" + : classSymbol.Name; - return new ClassInfo( - classSymbol.Name, - classSymbol.ContainingNamespace?.ToDisplayString() ?? string.Empty, - properties); + return new ClassInfo( + fullClassName, + classSymbol.ContainingNamespace?.ToDisplayString() ?? string.Empty, + properties); } static string GetColumnName(IPropertySymbol property) From 3849a7d76cc2262d20c45177b49b6c25a60aad3d Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:06:17 +0200 Subject: [PATCH 29/91] some more improvments --- .../SQLiteFastColumnSetterGenerator.cs | 34 ++++++++++++------- src/SQLite.cs | 3 +- tests/SQLite.Tests/SourceGeneratorTest.cs | 26 ++++++++++++++ 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index b775d510..609c7f04 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -12,16 +12,24 @@ [Generator] public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator { - private static List SQLitePropertyAttributes = new() { - "Column", - "Indexed", - "Ignore", - "Unique", - "MaxLength", - "Collation", - "NotNull", - "StoreAsText", - }; + private static List SQLitePropertyAttributes = default!; + private static ImmutableHashSet SQLitePropertyFullAttributes = default!; + + static SQLiteFastColumnSetterGenerator () + { + SQLitePropertyAttributes = new() { + "Column", + "Indexed", + "Ignore", + "Unique", + "MaxLength", + "Collation", + "NotNull", + "StoreAsText" + }; + + SQLitePropertyFullAttributes = SQLitePropertyAttributes.Select (f => f + "Attribute").ToImmutableHashSet(); + } public void Initialize(IncrementalGeneratorInitializationContext context) { @@ -85,11 +93,11 @@ static bool IsCandidateClass(SyntaxNode node) foreach (var member in classSymbol.GetMembers().OfType()) { - var hasColumnAttribute = member.GetAttributes() - .Any(attr => attr.AttributeClass?.Name == "ColumnAttribute"); + var hasSqliteAttributes = member.GetAttributes() + .Any(attr => attr.AttributeClass?.Name != null && SQLitePropertyFullAttributes.Contains(attr.AttributeClass?.Name!)); // Include property if class has TableAttribute or property has ColumnAttribute - if (hasTableAttribute || hasColumnAttribute) + if (hasTableAttribute || hasSqliteAttributes) { var columnName = GetColumnName(member); properties.Add(new PropertyInfo(member.Name, member.Type.ToDisplayString(), columnName)); diff --git a/src/SQLite.cs b/src/SQLite.cs index a5d36375..ec7be9c8 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -3942,8 +3942,7 @@ object ReadCol (Sqlite3Statement stmt, int index, SQLite3.ColType type, Type clr internal class FastColumnSetter { - private static ConcurrentDictionary<(Type, string), Action> customSetter = - new ConcurrentDictionary<(Type, string), Action> (); + internal static ConcurrentDictionary<(Type, string), Action> customSetter = new(); public static void RegisterFastColumnSetter(Type type, string name, Action setter) { diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 7d9940da..e8a311b0 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -44,6 +44,17 @@ public class InnerTestSetter public DateTime Date { get; set; } } + // Shouldn't generate Setter because it is not accessible + private class PrivateInnerTestSetter + { + [AutoIncrement, PrimaryKey] + public int Id { get; set; } + + public string Data { get; set; } + + public DateTime Date { get; set; } + } + public class InnerTestDb : SQLiteConnection { public InnerTestDb (String path) @@ -53,6 +64,21 @@ public InnerTestDb (String path) } } + [Test] + public void SqliteInitializer_PrivateInnerTestSetter () + { + SQLiteInitializer.Init (); + + if (!SQLite.FastColumnSetter.customSetter.TryGetValue(typeof(PrivateInnerTestSetter, nameof(PrivateInnerTestSetter.Id), out var setter)) + { + Assert.IsTrue(true, "Should not be registered"); + } + else + { + Assert.Fail("Should not be registered"); + } + } + [Test] public void SqliteInitializer_Inner_AndReadData() { From a9749f343e36b7243c805f1b67fdb6bab936f377 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:12:13 +0200 Subject: [PATCH 30/91] More source generator fixes --- .../SQLiteFastColumnSetterGenerator.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 609c7f04..a046b4c5 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -85,6 +85,10 @@ static bool IsCandidateClass(SyntaxNode node) var classSymbol = semanticModel.GetDeclaredSymbol(classDecl); if (classSymbol is null) return null; + + // Return null if the class is private + if (classSymbol.DeclaredAccessibility == Accessibility.Private) + return null; var hasTableAttribute = classSymbol.GetAttributes() .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); From 69be8be952889baa642d357fd43009037ecb255f Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:14:42 +0200 Subject: [PATCH 31/91] Disable debugging code --- .../SQLiteFastColumnSetterGenerator.cs | 4 ++-- tests/SQLite.Tests/SQLite.Tests.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a046b4c5..289fcd4a 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -33,8 +33,8 @@ static SQLiteFastColumnSetterGenerator () public void Initialize(IncrementalGeneratorInitializationContext context) { - // Stop Debugger for Debugging the Analyzer - System.Diagnostics.Debugger.Launch(); + // Launch Debugger for Debugging the Analyzer + // System.Diagnostics.Debugger.Launch(); // Find all classes with TableAttribute or properties with ColumnAttribute var classDeclarations = context.SyntaxProvider diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index bc5d94e5..787adec6 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -24,8 +24,8 @@ - true - $(BaseIntermediateOutputPath)Generated + From 27f1ad387ef2665e54c6c0809624e560395c513c Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:15:37 +0200 Subject: [PATCH 32/91] fixing unit tests --- tests/SQLite.Tests/SourceGeneratorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index e8a311b0..1cfc0151 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -69,7 +69,7 @@ public void SqliteInitializer_PrivateInnerTestSetter () { SQLiteInitializer.Init (); - if (!SQLite.FastColumnSetter.customSetter.TryGetValue(typeof(PrivateInnerTestSetter, nameof(PrivateInnerTestSetter.Id), out var setter)) + if (!SQLite.FastColumnSetter.customSetter.TryGetValue((typeof(PrivateInnerTestSetter), nameof(PrivateInnerTestSetter.Id)), out var setter)) { Assert.IsTrue(true, "Should not be registered"); } From 14148a2752527cdc3b96092f96f4a469a00dc5b2 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:16:19 +0200 Subject: [PATCH 33/91] fixing unit test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 1cfc0151..cf98dfa8 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -135,7 +135,7 @@ public void SqliteInitializer_Outer_AndReadData () Date = new DateTime (2013, 1, i) }; - var db = new InnerTestDb (TestPath.GetTempFileName ()); + var db = new OuterTestDb(TestPath.GetTempFileName ()); db.InsertAll (cq); var results = db.Table ().Where (o => o.Data.Equals ("10")); @@ -157,7 +157,7 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () Date = new DateTime (2013, 1, i) }; - var db = new InnerTestDb (TestPath.GetTempFileName ()); + var db = new OuterTestDb (TestPath.GetTempFileName ()); db.InsertAll (cq); var results = db.Table ().Where (o => o.Data.Equals ("10")); From 863ee547230c558fa8fd20ad2665a0246260ec7e Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:17:44 +0200 Subject: [PATCH 34/91] more unit tests --- tests/SQLite.Tests/SourceGeneratorTest.cs | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index cf98dfa8..6b8036d7 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -79,6 +79,32 @@ public void SqliteInitializer_PrivateInnerTestSetter () } } + [Test] + public void SqliteInitializer_InnerTestSetter () + { + SQLiteInitializer.Init (); + + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (PrivateInnerTestSetter), nameof (PrivateInnerTestSetter.Id)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + + [Test] + public void SqliteInitializer_OuterTestSetter () + { + SQLiteInitializer.Init (); + + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (PrivateInnerTestSetter), nameof (PrivateInnerTestSetter.Id)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + [Test] public void SqliteInitializer_Inner_AndReadData() { From efc72c4b7d90e87c2bd8381d27a699d94eef2a37 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:19:54 +0200 Subject: [PATCH 35/91] Fixing unit tests --- tests/SQLite.Tests/SourceGeneratorTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 6b8036d7..1caeed4b 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -84,7 +84,7 @@ public void SqliteInitializer_InnerTestSetter () { SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (PrivateInnerTestSetter), nameof (PrivateInnerTestSetter.Id)), out var setter)) { + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (InnerTestSetter), nameof (InnerTestSetter.Id)), out var setter)) { Assert.IsTrue (true, "Should be registered"); } else { @@ -97,7 +97,7 @@ public void SqliteInitializer_OuterTestSetter () { SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (PrivateInnerTestSetter), nameof (PrivateInnerTestSetter.Id)), out var setter)) { + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Id)), out var setter)) { Assert.IsTrue (true, "Should be registered"); } else { From 83eb160d40bf26cd74f4bc00a8b4c2fcfe4565b1 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:34:51 +0200 Subject: [PATCH 36/91] More bugfixes --- .../SQLiteFastColumnSetterGenerator.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 289fcd4a..53eb4aab 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -25,7 +25,10 @@ static SQLiteFastColumnSetterGenerator () "MaxLength", "Collation", "NotNull", - "StoreAsText" + "StoreAsText", + "AutoIncrement", + "PrimaryKey", + "NotNull" }; SQLitePropertyFullAttributes = SQLitePropertyAttributes.Select (f => f + "Attribute").ToImmutableHashSet(); @@ -34,7 +37,7 @@ static SQLiteFastColumnSetterGenerator () public void Initialize(IncrementalGeneratorInitializationContext context) { // Launch Debugger for Debugging the Analyzer - // System.Diagnostics.Debugger.Launch(); + System.Diagnostics.Debugger.Launch(); // Find all classes with TableAttribute or properties with ColumnAttribute var classDeclarations = context.SyntaxProvider From 1b632a89fd8c2b51ef54837ad4893ae8cb055369 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 12:37:27 +0200 Subject: [PATCH 37/91] disable debugging code --- .../SQLiteFastColumnSetterGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 53eb4aab..35614801 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -37,7 +37,7 @@ static SQLiteFastColumnSetterGenerator () public void Initialize(IncrementalGeneratorInitializationContext context) { // Launch Debugger for Debugging the Analyzer - System.Diagnostics.Debugger.Launch(); + // System.Diagnostics.Debugger.Launch(); // Find all classes with TableAttribute or properties with ColumnAttribute var classDeclarations = context.SyntaxProvider From 0d8f54e14b166fa524f8b8d1829ed1090e44e213 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 13:30:19 +0200 Subject: [PATCH 38/91] fixing build --- src/SQLite.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SQLite.cs b/src/SQLite.cs index ec7be9c8..bd95aa8a 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -3942,7 +3942,8 @@ object ReadCol (Sqlite3Statement stmt, int index, SQLite3.ColType type, Type clr internal class FastColumnSetter { - internal static ConcurrentDictionary<(Type, string), Action> customSetter = new(); + internal static ConcurrentDictionary<(Type, string), Action> customSetter = + new ConcurrentDictionary<(Type, string), Action>(); public static void RegisterFastColumnSetter(Type type, string name, Action setter) { From 58318a905fc88f4d3c75e36cdb986a38b5fe3085 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 13:33:56 +0200 Subject: [PATCH 39/91] Don't register generic types --- .../SQLiteFastColumnSetterGenerator.cs | 3 +++ tests/SQLite.Tests/SQLite.Tests.csproj | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 35614801..1deed5b5 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -93,6 +93,9 @@ static bool IsCandidateClass(SyntaxNode node) if (classSymbol.DeclaredAccessibility == Accessibility.Private) return null; + if (classSymbol.IsGenericType) + return null; + var hasTableAttribute = classSymbol.GetAttributes() .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 787adec6..bc5d94e5 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -24,8 +24,8 @@ - + true + $(BaseIntermediateOutputPath)Generated From 1b746ba0d8c925fc0677925f9fced8f2bb15f819 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 13:38:19 +0200 Subject: [PATCH 40/91] some fixes --- tests/SQLite.Tests/SourceGeneratorTest.cs | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 1caeed4b..3f5223ca 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Newtonsoft; #if NETFX_CORE using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; @@ -34,6 +35,16 @@ public OuterTestDb (String path) [TestFixture] public class SourceGeneratorTest { + public class StringTest : BaseTest + { + } + + public class BaseTest + { + [PrimaryKey] + public T Id { get; set; } + } + public class InnerTestSetter { [AutoIncrement, PrimaryKey] @@ -79,6 +90,19 @@ public void SqliteInitializer_PrivateInnerTestSetter () } } + [Test] + public void SqliteInitializer_StringTestSetter () + { + SQLiteInitializer.Init (); + + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (StringTest), nameof (StringTest.Id)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + [Test] public void SqliteInitializer_InnerTestSetter () { From 5299770df14e85299c95effddbde1ad56cffcb3d Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 13:43:59 +0200 Subject: [PATCH 41/91] Improve properties waling --- .../SQLiteFastColumnSetterGenerator.cs | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 1deed5b5..a71498a5 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -95,23 +95,36 @@ static bool IsCandidateClass(SyntaxNode node) if (classSymbol.IsGenericType) return null; - - var hasTableAttribute = classSymbol.GetAttributes() - .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); + + var hasTableAttribute = classSymbol.GetAttributes() + .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); var properties = new List(); - foreach (var member in classSymbol.GetMembers().OfType()) + // Iterate through the class hierarchy to get all properties + var currentType = classSymbol; + while (currentType != null) { - var hasSqliteAttributes = member.GetAttributes() - .Any(attr => attr.AttributeClass?.Name != null && SQLitePropertyFullAttributes.Contains(attr.AttributeClass?.Name!)); - - // Include property if class has TableAttribute or property has ColumnAttribute - if (hasTableAttribute || hasSqliteAttributes) - { - var columnName = GetColumnName(member); - properties.Add(new PropertyInfo(member.Name, member.Type.ToDisplayString(), columnName)); + foreach (var member in classSymbol.GetMembers ().OfType ()) { + var hasSqliteAttributes = member.GetAttributes () + .Any (attr => + attr.AttributeClass?.Name != null && + SQLitePropertyFullAttributes.Contains (attr.AttributeClass?.Name!)); + + // Include property if class has TableAttribute or property has ColumnAttribute + if (hasTableAttribute || hasSqliteAttributes) { + var columnName = GetColumnName (member); + properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName)); + } } + + // Move to base type + currentType = currentType.BaseType; + + // Stop at System.Object or if we hit a null base type + if (currentType?.SpecialType == SpecialType.System_Object) + break; + } if (properties.Count == 0) From 8ebae535e54a24997ba6eed66bcdbc974c00bc03 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 13:54:09 +0200 Subject: [PATCH 42/91] Fixing unit test --- .../SQLiteFastColumnSetterGenerator.cs | 2 +- tests/SQLite.Tests/SourceGeneratorTest.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a71498a5..e26b91dc 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -105,7 +105,7 @@ static bool IsCandidateClass(SyntaxNode node) var currentType = classSymbol; while (currentType != null) { - foreach (var member in classSymbol.GetMembers ().OfType ()) { + foreach (var member in currentType.GetMembers ().OfType ()) { var hasSqliteAttributes = member.GetAttributes () .Any (attr => attr.AttributeClass?.Name != null && diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 3f5223ca..0db4e121 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -35,6 +35,7 @@ public OuterTestDb (String path) [TestFixture] public class SourceGeneratorTest { + [Table("Test")] public class StringTest : BaseTest { } From 16c0926785caecc2972f26a19f681d44296a54f5 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 14:41:58 +0200 Subject: [PATCH 43/91] Adding sourcegenerator to nuget --- nuget/SQLite-net-base/SQLite-net-base.csproj | 6 ++++++ nuget/SQLite-net-sqlcipher/SQLite-net-sqlcipher.csproj | 6 ++++++ nuget/SQLite-net-static/SQLite-net-static.csproj | 6 ++++++ nuget/SQLite-net-std/SQLite-net-std.csproj | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/nuget/SQLite-net-base/SQLite-net-base.csproj b/nuget/SQLite-net-base/SQLite-net-base.csproj index 8fd9ae2e..d9a694ee 100644 --- a/nuget/SQLite-net-base/SQLite-net-base.csproj +++ b/nuget/SQLite-net-base/SQLite-net-base.csproj @@ -34,4 +34,10 @@ + + + + + + diff --git a/nuget/SQLite-net-sqlcipher/SQLite-net-sqlcipher.csproj b/nuget/SQLite-net-sqlcipher/SQLite-net-sqlcipher.csproj index 714af08a..5354fbc6 100644 --- a/nuget/SQLite-net-sqlcipher/SQLite-net-sqlcipher.csproj +++ b/nuget/SQLite-net-sqlcipher/SQLite-net-sqlcipher.csproj @@ -35,4 +35,10 @@ + + + + + + diff --git a/nuget/SQLite-net-static/SQLite-net-static.csproj b/nuget/SQLite-net-static/SQLite-net-static.csproj index f8c4d857..08a691d2 100644 --- a/nuget/SQLite-net-static/SQLite-net-static.csproj +++ b/nuget/SQLite-net-static/SQLite-net-static.csproj @@ -31,4 +31,10 @@ + + + + + + diff --git a/nuget/SQLite-net-std/SQLite-net-std.csproj b/nuget/SQLite-net-std/SQLite-net-std.csproj index 4a1e6d1b..23d2f776 100644 --- a/nuget/SQLite-net-std/SQLite-net-std.csproj +++ b/nuget/SQLite-net-std/SQLite-net-std.csproj @@ -33,4 +33,10 @@ + + + + + + From 330c327f72d2df4dce07cea0d80c5194245a9eb4 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 14:47:59 +0200 Subject: [PATCH 44/91] fixing unit test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 0db4e121..002fd958 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -211,7 +211,7 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () var db = new OuterTestDb (TestPath.GetTempFileName ()); db.InsertAll (cq); - var results = db.Table ().Where (o => o.Data.Equals ("10")); + var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); From c68845f39e287d56a57282775db008ec18a44a44 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 14:52:35 +0200 Subject: [PATCH 45/91] fixing unit test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 002fd958..5d72f20c 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -189,7 +189,7 @@ public void SqliteInitializer_Outer_AndReadData () var db = new OuterTestDb(TestPath.GetTempFileName ()); db.InsertAll (cq); - var results = db.Table ().Where (o => o.Data.Equals ("10")); + var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); } From 9184e119c5ec6f021d2d484af1852e2b999f4e32 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 15:13:55 +0200 Subject: [PATCH 46/91] comment out debug output --- tests/SQLite.Tests/SQLite.Tests.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index bc5d94e5..1621eda3 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -24,8 +24,10 @@ + From c9c13e02facb79efb5b24a7540fa0ea15dbdb249 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:11:12 +0200 Subject: [PATCH 47/91] fixing unit tests --- tests/SQLite.Tests/SourceGeneratorTest.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 5d72f20c..9e0dc924 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -155,8 +155,6 @@ public void SetFastColumnSetters_Inner_AndReadData_IsCalled() { SQLiteInitializer.Init (); - int callCount = 0; - var n = 20; var cq = from i in Enumerable.Range (1, n) select new InnerTestSetter { @@ -170,8 +168,6 @@ public void SetFastColumnSetters_Inner_AndReadData_IsCalled() var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); - - Assert.IsTrue(callCount > 0); } [Test] @@ -199,8 +195,6 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () { SQLiteInitializer.Init (); - int callCount = 0; - var n = 20; var cq = from i in Enumerable.Range (1, n) select new OuterTestSetter { @@ -214,8 +208,6 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); - - Assert.IsTrue (callCount > 0); } } } From 5440d2dcc43b45a2e10a1915d9b5ed9cb50c44a6 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:19:34 +0200 Subject: [PATCH 48/91] don^t map readonly properties --- .../SQLiteFastColumnSetterGenerator.cs | 21 +++++++++++-------- tests/SQLite.Tests/SourceGeneratorTest.cs | 17 ++++++++++++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index e26b91dc..4401df41 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Linq; using System.Reflection; +using System.Reflection.Metadata.Ecma335; using System.Text; using Microsoft.CodeAnalysis.Diagnostics; @@ -106,15 +107,17 @@ static bool IsCandidateClass(SyntaxNode node) while (currentType != null) { foreach (var member in currentType.GetMembers ().OfType ()) { - var hasSqliteAttributes = member.GetAttributes () - .Any (attr => - attr.AttributeClass?.Name != null && - SQLitePropertyFullAttributes.Contains (attr.AttributeClass?.Name!)); - - // Include property if class has TableAttribute or property has ColumnAttribute - if (hasTableAttribute || hasSqliteAttributes) { - var columnName = GetColumnName (member); - properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName)); + if (!member.IsReadOnly) { + var hasSqliteAttributes = member.GetAttributes () + .Any (attr => + attr.AttributeClass?.Name != null && + SQLitePropertyFullAttributes.Contains (attr.AttributeClass?.Name!)); + + // Include property if class has TableAttribute or property has ColumnAttribute + if (hasTableAttribute || hasSqliteAttributes) { + var columnName = GetColumnName (member); + properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName)); + } } } diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 9e0dc924..e723168c 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -21,6 +21,8 @@ public class OuterTestSetter public string Data { get; set; } public DateTime Date { get; set; } + + public string NotWritable { get; } } public class OuterTestDb : SQLiteConnection @@ -118,7 +120,7 @@ public void SqliteInitializer_InnerTestSetter () } [Test] - public void SqliteInitializer_OuterTestSetter () + public void SqliteInitializer_OuterTestSetter_NotWritable_NotRegistered() { SQLiteInitializer.Init (); @@ -130,6 +132,19 @@ public void SqliteInitializer_OuterTestSetter () } } + [Test] + public void SqliteInitializer_OuterTestSetter () + { + SQLiteInitializer.Init (); + + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.NotWritable)), out var setter)) { + Assert.IsTrue(true, "Should not be registered (not writable)"); + } + else { + Assert.Fail ("Should not be registered (not writable)"); + } + } + [Test] public void SqliteInitializer_Inner_AndReadData() { From 144454c231edf64d09481224fc0535291c9f437d Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:26:31 +0200 Subject: [PATCH 49/91] Don't register ignore Attributes --- .../SQLiteFastColumnSetterGenerator.cs | 1 + tests/SQLite.Tests/SourceGeneratorTest.cs | 28 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 4401df41..57e6e61b 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -111,6 +111,7 @@ static bool IsCandidateClass(SyntaxNode node) var hasSqliteAttributes = member.GetAttributes () .Any (attr => attr.AttributeClass?.Name != null && + attr.AttributeClass.Name != "IgnoreAttribute" && SQLitePropertyFullAttributes.Contains (attr.AttributeClass?.Name!)); // Include property if class has TableAttribute or property has ColumnAttribute diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index e723168c..0c7834c8 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -23,6 +23,9 @@ public class OuterTestSetter public DateTime Date { get; set; } public string NotWritable { get; } + + [Ignore] + public string Ignore { get; set; } } public class OuterTestDb : SQLiteConnection @@ -124,11 +127,24 @@ public void SqliteInitializer_OuterTestSetter_NotWritable_NotRegistered() { SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Id)), out var setter)) { - Assert.IsTrue (true, "Should be registered"); + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.NotWritable)), out var setter)) { + Assert.IsTrue (true, "Should not be registered (not writable)"); } else { - Assert.Fail ("Should be registered"); + Assert.Fail ("Should not be registered (not writable)"); + } + } + + [Test] + public void SqliteInitializer_OuterTestSetter_Ignore_NotRegistered () + { + SQLiteInitializer.Init (); + + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Ignore)), out var setter)) { + Assert.IsTrue (true, "Should not be registered (Ignore)"); + } + else { + Assert.Fail ("Should not be registered (Ignore)"); } } @@ -137,11 +153,11 @@ public void SqliteInitializer_OuterTestSetter () { SQLiteInitializer.Init (); - if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.NotWritable)), out var setter)) { - Assert.IsTrue(true, "Should not be registered (not writable)"); + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Id)), out var setter)) { + Assert.IsTrue(true, "Should not be registered"); } else { - Assert.Fail ("Should not be registered (not writable)"); + Assert.Fail ("Should not be registered"); } } From 72b38525120ca2f15db1f97023c2fa409d2e3b8a Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:29:49 +0200 Subject: [PATCH 50/91] Check SQLite Namespace for attributes --- .../SQLiteFastColumnSetterGenerator.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 57e6e61b..a21bd7db 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -98,7 +98,7 @@ static bool IsCandidateClass(SyntaxNode node) return null; var hasTableAttribute = classSymbol.GetAttributes() - .Any(attr => attr.AttributeClass?.Name == "TableAttribute"); + .Any(attr => attr.AttributeClass?.ContainingNamespace.Name == "SQLite" && attr.AttributeClass?.Name == "TableAttribute"); var properties = new List(); @@ -111,6 +111,7 @@ static bool IsCandidateClass(SyntaxNode node) var hasSqliteAttributes = member.GetAttributes () .Any (attr => attr.AttributeClass?.Name != null && + attr.AttributeClass.ContainingNamespace.Name == "SQLite" && attr.AttributeClass.Name != "IgnoreAttribute" && SQLitePropertyFullAttributes.Contains (attr.AttributeClass?.Name!)); @@ -157,7 +158,7 @@ static string GetColumnName(IPropertySymbol property) { // Check for ColumnAttribute with name parameter var columnAttr = property.GetAttributes() - .FirstOrDefault(attr => attr.AttributeClass?.Name == "ColumnAttribute"); + .FirstOrDefault(attr => attr.AttributeClass?.ContainingNamespace.Name == "SQLite" && attr.AttributeClass?.Name == "ColumnAttribute"); if (columnAttr?.ConstructorArguments.Length > 0) { From cc6603ac8a8c210bd5b9da10aa4151b97c60e48f Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:36:34 +0200 Subject: [PATCH 51/91] A renamed test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 0c7834c8..ee54e5e1 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -26,6 +26,9 @@ public class OuterTestSetter [Ignore] public string Ignore { get; set; } + + [Column("A")] + public string Z { get; set; } } public class OuterTestDb : SQLiteConnection @@ -122,6 +125,20 @@ public void SqliteInitializer_InnerTestSetter () } } + + [Test] + public void SqliteInitializer_OuterTestSetter_ZRenamedA() + { + SQLiteInitializer.Init (); + + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), "A"), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + [Test] public void SqliteInitializer_OuterTestSetter_NotWritable_NotRegistered() { @@ -221,6 +238,27 @@ public void SqliteInitializer_Outer_AndReadData () Assert.AreEqual (results.FirstOrDefault ().Data, "10"); } + [Test] + public void SqliteInitializer_Outer_AndReadData_ZRenamedA() + { + SQLiteInitializer.Init (); + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new OuterTestSetter () { + Data = Convert.ToString (i), + Date = new DateTime (2013, 1, i), + Z = Convert.ToString(i), + }; + + var db = new OuterTestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Z.Equals ("10")); + Assert.AreEqual (results.Count (), 1); + Assert.AreEqual (results.FirstOrDefault ().Z, "10"); + } + [Test] public void SetFastColumnSetters_Outer_AndReadData_IsCalled () { From b0f5391efcd2c7ae78cbfc2f21255d5bbd1cb3f2 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:46:40 +0200 Subject: [PATCH 52/91] fix build order --- SQLite.sln | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/SQLite.sln b/SQLite.sln index 8c860d1f..de464324 100644 --- a/SQLite.sln +++ b/SQLite.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.14.36429.23 d17.14 +VisualStudioVersion = 17.14.36429.23 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0E59A10-7BD0-4554-B133-66FA850159BE}" ProjectSection(SolutionItems) = preProject @@ -12,16 +12,28 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{FECC0E44-E626-49CB-BD8B-0CFBD93FBEFF}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-std", "nuget\SQLite-net-std\SQLite-net-std.csproj", "{081D08D6-10F1-431B-88FE-469FD9FE898C}" + ProjectSection(ProjectDependencies) = postProject + {8AFC8450-42E6-41AF-8E39-17EC7C13D695} = {8AFC8450-42E6-41AF-8E39-17EC7C13D695} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiDiff", "tests\ApiDiff\ApiDiff.csproj", "{1DEF735C-B973-4ED9-8446-7FFA6D0B410B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-base", "nuget\SQLite-net-base\SQLite-net-base.csproj", "{53D1953C-3641-47D0-BE08-14DB853CC576}" + ProjectSection(ProjectDependencies) = postProject + {8AFC8450-42E6-41AF-8E39-17EC7C13D695} = {8AFC8450-42E6-41AF-8E39-17EC7C13D695} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-sqlcipher", "nuget\SQLite-net-sqlcipher\SQLite-net-sqlcipher.csproj", "{59DB03EF-E28D-431E-9058-74AF316800EE}" + ProjectSection(ProjectDependencies) = postProject + {8AFC8450-42E6-41AF-8E39-17EC7C13D695} = {8AFC8450-42E6-41AF-8E39-17EC7C13D695} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite.Tests", "tests\SQLite.Tests\SQLite.Tests.csproj", "{80B66A43-B358-4438-BF06-6351B86B121A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLite-net-static", "nuget\SQLite-net-static\SQLite-net-static.csproj", "{7CD60DAE-D505-4C2E-80B3-296556CE711E}" + ProjectSection(ProjectDependencies) = postProject + {8AFC8450-42E6-41AF-8E39-17EC7C13D695} = {8AFC8450-42E6-41AF-8E39-17EC7C13D695} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sqlite_net.SourceGenerator", "nuget\Sqlite_net.SourceGenerator\Sqlite_net.SourceGenerator.csproj", "{8AFC8450-42E6-41AF-8E39-17EC7C13D695}" EndProject From 4d24c0ab3dc98036f919dbbaa75f11404a433c5a Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 16:50:07 +0200 Subject: [PATCH 53/91] fixing make --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 42cd34dd..6b0d5365 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,10 @@ PACKAGES_OUT=$(abspath PackagesOut) all: nuget -nuget: pclnuget basenuget sqlciphernuget staticnuget +nuget: sourcegenerator pclnuget basenuget sqlciphernuget staticnuget + +sourcegenerator: nuget\Sqlite_net.SourceGenerator\Sqlite_net.SourceGenerator.csproj $(SRC) + dotnet build -c Release $< pclnuget: nuget/SQLite-net-std/SQLite-net-std.csproj $(SRC) dotnet pack -c Release -o $(PACKAGES_OUT) $< From 6083ae4439ed1d1c2bdee45f8c3e07fd309a9dac Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 17:14:32 +0200 Subject: [PATCH 54/91] added decimal --- .../SQLiteFastColumnSetterGenerator.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a21bd7db..a177790b 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -276,7 +276,13 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); break; - case "float": + case "decimal": + case "Decimal": + case "System.Decimal": + sb.AppendLine ($" typedObj.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); + break; + + case "float": case "Single": case "System.Single": sb.AppendLine($" typedObj.{property.PropertyName} = (float)SQLite3.ColumnDouble(stmt, index);"); From ba2c4853ec6201d84af650b7da664959c02de694 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 17:29:20 +0200 Subject: [PATCH 55/91] Added Timespan --- .../SQLiteFastColumnSetterGenerator.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a177790b..ba9c5208 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -299,7 +299,12 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) sb.AppendLine($" typedObj.{property.PropertyName} = new DateTime(SQLite3.ColumnInt64(stmt, index));"); break; - case "Guid": + case "TimeSpan": + case "System.TimeSpan": + sb.AppendLine ($" typedObj.{property.PropertyName} = new TimeSpan(SQLite3.ColumnInt64(stmt, index));"); + break; + + case "Guid": case "System.Guid": sb.AppendLine($" var text = SQLite3.ColumnString(stmt, index);"); sb.AppendLine($" typedObj.{property.PropertyName} = new Guid(text);"); From f619bc6c435b16e500af556792d8225546d6c4ac Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:00:10 +0200 Subject: [PATCH 56/91] Make SqlInitializer public and initialize it only once --- .../SQLiteFastColumnSetterGenerator.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index ba9c5208..06f6c5dc 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -191,12 +191,16 @@ static void Execute( sb.AppendLine(); sb.AppendLine($"namespace {rootNamespace}"); sb.AppendLine("{"); - sb.AppendLine(" internal static class SQLiteInitializer"); + sb.AppendLine(" public static class SQLiteInitializer"); sb.AppendLine(" {"); - sb.AppendLine(" public static void Init()"); + sb.AppendLine(" private static bool initialized"); + sb.AppendLine(" public static void Init()"); sb.AppendLine(" {"); + sb.AppendLine (" if (initialized)"); + sb.AppendLine (" return;"); + sb.AppendLine (" initialized = true;"); - foreach (var classInfo in classes) + foreach (var classInfo in classes) { foreach (var property in classInfo.Properties) { From 572f0ff6b5de22e7f2ac0e2be9a46d69b92eedb1 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:02:33 +0200 Subject: [PATCH 57/91] fixing code generator --- .../SQLiteFastColumnSetterGenerator.cs | 2 +- tests/SQLite.Tests/SourceGeneratorTest.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 06f6c5dc..15e12704 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -193,7 +193,7 @@ static void Execute( sb.AppendLine("{"); sb.AppendLine(" public static class SQLiteInitializer"); sb.AppendLine(" {"); - sb.AppendLine(" private static bool initialized"); + sb.AppendLine(" private static bool initialized;"); sb.AppendLine(" public static void Init()"); sb.AppendLine(" {"); sb.AppendLine (" if (initialized)"); diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index ee54e5e1..56fc4526 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -242,6 +242,7 @@ public void SqliteInitializer_Outer_AndReadData () public void SqliteInitializer_Outer_AndReadData_ZRenamedA() { SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -257,6 +258,8 @@ public void SqliteInitializer_Outer_AndReadData_ZRenamedA() var results = db.Table ().Where (o => o.Z.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Z, "10"); + + Assert.AreEqual(mapperCount, FastColumnSetter.customSetter.Count); } [Test] From a8bb63083a91a2f86f2f0c4b8f2099b016a9d6c1 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:05:56 +0200 Subject: [PATCH 58/91] fixing vulnerability warning --- tests/SQLite.Tests/SQLite.Tests.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 1621eda3..68d130d7 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -11,7 +11,8 @@ - + + From 3091fccda82317e64fd14eabb1df71aaea5d2591 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:06:25 +0200 Subject: [PATCH 59/91] rever add sqlite green --- tests/SQLite.Tests/SQLite.Tests.csproj | 1 - tests/SQLite.Tests/SourceGeneratorTest.cs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 68d130d7..c6c89483 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -12,7 +12,6 @@ - diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 56fc4526..d4adc2c9 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -241,6 +241,7 @@ public void SqliteInitializer_Outer_AndReadData () [Test] public void SqliteInitializer_Outer_AndReadData_ZRenamedA() { + SQLitePCL.Batteries_V2.Init (); SQLiteInitializer.Init (); var mapperCount = FastColumnSetter.customSetter.Count; From 0ec43fbc68f07a03586b199542f5a0a2cf623372 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:16:07 +0200 Subject: [PATCH 60/91] remove debugging code --- tests/SQLite.Tests/SourceGeneratorTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index d4adc2c9..56fc4526 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -241,7 +241,6 @@ public void SqliteInitializer_Outer_AndReadData () [Test] public void SqliteInitializer_Outer_AndReadData_ZRenamedA() { - SQLitePCL.Batteries_V2.Init (); SQLiteInitializer.Init (); var mapperCount = FastColumnSetter.customSetter.Count; From 4837e6d7d3c871adc079306fefecce5441da92a9 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:17:41 +0200 Subject: [PATCH 61/91] test that no new mappers are created,. --- tests/SQLite.Tests/SourceGeneratorTest.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 56fc4526..799bc791 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -182,6 +182,7 @@ public void SqliteInitializer_OuterTestSetter () public void SqliteInitializer_Inner_AndReadData() { SQLiteInitializer.Init(); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -196,12 +197,14 @@ public void SqliteInitializer_Inner_AndReadData() var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); } [Test] public void SetFastColumnSetters_Inner_AndReadData_IsCalled() { SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -216,12 +219,14 @@ public void SetFastColumnSetters_Inner_AndReadData_IsCalled() var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); } [Test] public void SqliteInitializer_Outer_AndReadData () { SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -236,6 +241,7 @@ public void SqliteInitializer_Outer_AndReadData () var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); } [Test] @@ -258,7 +264,6 @@ public void SqliteInitializer_Outer_AndReadData_ZRenamedA() var results = db.Table ().Where (o => o.Z.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Z, "10"); - Assert.AreEqual(mapperCount, FastColumnSetter.customSetter.Count); } @@ -266,6 +271,7 @@ public void SqliteInitializer_Outer_AndReadData_ZRenamedA() public void SetFastColumnSetters_Outer_AndReadData_IsCalled () { SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; var cq = from i in Enumerable.Range (1, n) @@ -280,6 +286,7 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () var results = db.Table ().Where (o => o.Data.Equals ("10")); Assert.AreEqual (results.Count (), 1); Assert.AreEqual (results.FirstOrDefault ().Data, "10"); + Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); } } } From d3ab50020d0d468b8855f6757a183fe4e9198962 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Sun, 14 Sep 2025 22:50:34 +0200 Subject: [PATCH 62/91] Add Unit Tests for all basic types --- .../SQLiteFastColumnSetterGenerator.cs | 15 +++- tests/SQLite.Tests/SourceGeneratorTest.cs | 83 ++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 15e12704..a04c59f0 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -262,7 +262,20 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnString(stmt, index);"); break; - case "int": + case "byte": + case "Byte": + case "System.Byte": + sb.AppendLine ($" typedObj.{property.PropertyName} = (byte)SQLite3.ColumnInt(stmt, index);"); + break; + + case "short": + case "Int16": + case "System.Int16": + sb.AppendLine ($" typedObj.{property.PropertyName} = (short)SQLite3.ColumnInt(stmt, index);"); + break; + + + case "int": case "Int32": case "System.Int32": sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt(stmt, index);"); diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 799bc791..00487297 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -64,7 +64,35 @@ public class InnerTestSetter public DateTime Date { get; set; } } - // Shouldn't generate Setter because it is not accessible + public class AllBasicTypesSetter + { + [PrimaryKey] + public int Id { get; set; } + + public string String { get; set; } + + public byte Byte { get; set; } + + public short Short { get; set; } + + public int Int { get; set; } + + public long Long { get; set; } + + public float Float { get; set; } + + public double Double { get; set; } + + public decimal Decimal { get; set; } + + public TimeSpan TimeSpam { get; set; } + + public DateTime DateTime { get; set; } + + public Guid Guid { get; set; } + } + + // Shouldn't generate Setter because it is not accessible private class PrivateInnerTestSetter { [AutoIncrement, PrimaryKey] @@ -75,6 +103,15 @@ private class PrivateInnerTestSetter public DateTime Date { get; set; } } + public class AllBasicTypesTestDb : SQLiteConnection + { + public AllBasicTypesTestDb (String path) + : base (path) + { + CreateTable (); + } + } + public class InnerTestDb : SQLiteConnection { public InnerTestDb (String path) @@ -288,5 +325,49 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () Assert.AreEqual (results.FirstOrDefault ().Data, "10"); Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); } + + [Test] + public void SetFastColumnSetters_AllBasicTypes_Works () + { + SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new AllBasicTypesSetter() { + Id = i, + String = Convert.ToString(i), + Byte = (byte)i, + Short = (short)i, + Int = i, + Long = i, + Float = i, + Double = i, + Decimal = i, + DateTime = new DateTime(2000, 1, i), + TimeSpam = new TimeSpan(i, 0, 0), + Guid = new Guid (i, 0, 0, new byte[8]), + }; + + var db = new AllBasicTypesTestDb(TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Id.Equals (10)); + Assert.AreEqual (results.Count (), 1); + var data = results.FirstOrDefault (); + Assert.AreEqual (data.String, "10"); + Assert.AreEqual (data.Byte, (byte)10); + Assert.AreEqual (data.Short, (short)10); + Assert.AreEqual (data.Int, (int)10); + Assert.AreEqual (data.Long, (long)10); + Assert.AreEqual (data.Float, (float)10); + Assert.AreEqual (data.Double, (double)10); + Assert.AreEqual (data.Decimal, (decimal)10); + Assert.AreEqual (data.TimeSpam, new TimeSpan(10, 0, 0)); + Assert.AreEqual (data.DateTime, new DateTime(2000, 1, 10)); + Assert.AreEqual (data.Guid, new Guid (10, 0, 0, new byte[8])); + + Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); + } } } From 0aee315ec7397771f6dcf1b64e43c3ce0bb1d034 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Mon, 15 Sep 2025 22:09:40 +0200 Subject: [PATCH 63/91] Use ModuleInitializer for automatic Sqlite initialization --- .../SQLiteFastColumnSetterGenerator.cs | 6 ++++- tests/SQLite.Tests/SourceGeneratorTest.cs | 27 +++++-------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a04c59f0..84d7a197 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -191,9 +191,13 @@ static void Execute( sb.AppendLine(); sb.AppendLine($"namespace {rootNamespace}"); sb.AppendLine("{"); - sb.AppendLine(" public static class SQLiteInitializer"); + sb.AppendLine(" [SQLite.Preserve(AllMembers = true)]"); + sb.AppendLine(" public static class SQLiteInitializer"); sb.AppendLine(" {"); sb.AppendLine(" private static bool initialized;"); + sb.AppendLine("#if NET5_0_OR_GREATER"); + sb.AppendLine(" [System.Runtime.CompilerServices.ModuleInitializer]"); + sb.AppendLine("#endif"); sb.AppendLine(" public static void Init()"); sb.AppendLine(" {"); sb.AppendLine (" if (initialized)"); diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 00487297..f83cfb2c 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -48,6 +48,8 @@ public class StringTest : BaseTest { } +#if NET5_0_OR_GREATER +#endif public class BaseTest { [PrimaryKey] @@ -124,8 +126,6 @@ public InnerTestDb (String path) [Test] public void SqliteInitializer_PrivateInnerTestSetter () { - SQLiteInitializer.Init (); - if (!SQLite.FastColumnSetter.customSetter.TryGetValue((typeof(PrivateInnerTestSetter), nameof(PrivateInnerTestSetter.Id)), out var setter)) { Assert.IsTrue(true, "Should not be registered"); @@ -139,8 +139,6 @@ public void SqliteInitializer_PrivateInnerTestSetter () [Test] public void SqliteInitializer_StringTestSetter () { - SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (StringTest), nameof (StringTest.Id)), out var setter)) { Assert.IsTrue (true, "Should be registered"); } @@ -152,8 +150,6 @@ public void SqliteInitializer_StringTestSetter () [Test] public void SqliteInitializer_InnerTestSetter () { - SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (InnerTestSetter), nameof (InnerTestSetter.Id)), out var setter)) { Assert.IsTrue (true, "Should be registered"); } @@ -166,8 +162,6 @@ public void SqliteInitializer_InnerTestSetter () [Test] public void SqliteInitializer_OuterTestSetter_ZRenamedA() { - SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), "A"), out var setter)) { Assert.IsTrue (true, "Should be registered"); } @@ -179,8 +173,6 @@ public void SqliteInitializer_OuterTestSetter_ZRenamedA() [Test] public void SqliteInitializer_OuterTestSetter_NotWritable_NotRegistered() { - SQLiteInitializer.Init (); - if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.NotWritable)), out var setter)) { Assert.IsTrue (true, "Should not be registered (not writable)"); } @@ -192,8 +184,6 @@ public void SqliteInitializer_OuterTestSetter_NotWritable_NotRegistered() [Test] public void SqliteInitializer_OuterTestSetter_Ignore_NotRegistered () { - SQLiteInitializer.Init (); - if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Ignore)), out var setter)) { Assert.IsTrue (true, "Should not be registered (Ignore)"); } @@ -205,8 +195,6 @@ public void SqliteInitializer_OuterTestSetter_Ignore_NotRegistered () [Test] public void SqliteInitializer_OuterTestSetter () { - SQLiteInitializer.Init (); - if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Id)), out var setter)) { Assert.IsTrue(true, "Should not be registered"); } @@ -218,7 +206,6 @@ public void SqliteInitializer_OuterTestSetter () [Test] public void SqliteInitializer_Inner_AndReadData() { - SQLiteInitializer.Init(); var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; @@ -240,7 +227,7 @@ public void SqliteInitializer_Inner_AndReadData() [Test] public void SetFastColumnSetters_Inner_AndReadData_IsCalled() { - SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; @@ -262,7 +249,7 @@ public void SetFastColumnSetters_Inner_AndReadData_IsCalled() [Test] public void SqliteInitializer_Outer_AndReadData () { - SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; @@ -284,7 +271,7 @@ public void SqliteInitializer_Outer_AndReadData () [Test] public void SqliteInitializer_Outer_AndReadData_ZRenamedA() { - SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; @@ -307,7 +294,7 @@ public void SqliteInitializer_Outer_AndReadData_ZRenamedA() [Test] public void SetFastColumnSetters_Outer_AndReadData_IsCalled () { - SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; @@ -329,7 +316,7 @@ public void SetFastColumnSetters_Outer_AndReadData_IsCalled () [Test] public void SetFastColumnSetters_AllBasicTypes_Works () { - SQLiteInitializer.Init (); + var mapperCount = FastColumnSetter.customSetter.Count; var n = 20; From 29297881d2872c2579a5b05e429dad2a40acfe80 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 09:52:34 +0200 Subject: [PATCH 64/91] Improved Source Generator --- .../SQLiteFastColumnSetterGenerator.cs | 171 ++++++++++++++---- tests/SQLite.Tests/SQLite.Tests.csproj | 4 +- tests/SQLite.Tests/SourceGeneratorTest.cs | 36 +++- 3 files changed, 173 insertions(+), 38 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 84d7a197..5c9a7934 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -1,4 +1,5 @@ -using Microsoft.CodeAnalysis; +using System; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -71,6 +72,11 @@ static bool IsCandidateClass(SyntaxNode node) return true; } + // I need to analyse the base class in the semantic model + if (HasBaseClass (classDecl)) { + return true; + } + // Check if any property has SQLite Property Attribute return classDecl.Members .OfType () @@ -81,77 +87,174 @@ static bool IsCandidateClass(SyntaxNode node) }))); } - static ClassInfo? GetClassInfo(GeneratorSyntaxContext context) + static bool HasBaseClass (ClassDeclarationSyntax classDecl) { - var classDecl = (ClassDeclarationSyntax)context.Node; - var semanticModel = context.SemanticModel; + var baseList = classDecl.BaseList; + if (baseList == null) + return false; - var classSymbol = semanticModel.GetDeclaredSymbol(classDecl); + return baseList.Types.Count > 0; + } + + static ClassInfo? GetClassInfo (INamedTypeSymbol? classSymbol) + { if (classSymbol is null) return null; - + // Return null if the class is private if (classSymbol.DeclaredAccessibility == Accessibility.Private) return null; - if (classSymbol.IsGenericType) + if (classSymbol.IsGenericType) + return null; + + var hasSqliteAttributes = HasTableAttribute (classSymbol); + if (!hasSqliteAttributes) { + hasSqliteAttributes = HasSQLiteAttribute (classSymbol); + } + + if (!hasSqliteAttributes) { return null; - - var hasTableAttribute = classSymbol.GetAttributes() - .Any(attr => attr.AttributeClass?.ContainingNamespace.Name == "SQLite" && attr.AttributeClass?.Name == "TableAttribute"); + } - var properties = new List(); + var properties = new List (); // Iterate through the class hierarchy to get all properties var currentType = classSymbol; - while (currentType != null) - { + while (currentType != null) { foreach (var member in currentType.GetMembers ().OfType ()) { if (!member.IsReadOnly) { - var hasSqliteAttributes = member.GetAttributes () - .Any (attr => - attr.AttributeClass?.Name != null && - attr.AttributeClass.ContainingNamespace.Name == "SQLite" && - attr.AttributeClass.Name != "IgnoreAttribute" && - SQLitePropertyFullAttributes.Contains (attr.AttributeClass?.Name!)); - - // Include property if class has TableAttribute or property has ColumnAttribute - if (hasTableAttribute || hasSqliteAttributes) { + var ignore = member.GetAttributes () + .Any (attr => IsIgnoreAttribute (attr.AttributeClass)); + + // Include property if not ignored + if (!ignore) { var columnName = GetColumnName (member); properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName)); } } } - + // Move to base type currentType = currentType.BaseType; - + // Stop at System.Object or if we hit a null base type if (currentType?.SpecialType == SpecialType.System_Object) break; - } if (properties.Count == 0) return null; // Handle nested classes by building the full containing type path - var containingTypes = new List(); + var containingTypes = new List (); var currentContaining = classSymbol.ContainingType; - while (currentContaining != null) - { - containingTypes.Insert(0, currentContaining.Name); + while (currentContaining != null) { + containingTypes.Insert (0, currentContaining.Name); currentContaining = currentContaining.ContainingType; } - var fullClassName = containingTypes.Count > 0 - ? $"{string.Join(".", containingTypes)}.{classSymbol.Name}" + var fullClassName = containingTypes.Count > 0 + ? $"{string.Join (".", containingTypes)}.{classSymbol.Name}" : classSymbol.Name; - return new ClassInfo( + return new ClassInfo ( fullClassName, - classSymbol.ContainingNamespace?.ToDisplayString() ?? string.Empty, + classSymbol.ContainingNamespace?.ToDisplayString () ?? string.Empty, properties); + } + + private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) + { + while (true) { + if (classSymbol == null || classSymbol.SpecialType == SpecialType.System_Object) { + return false; + } + + var members = classSymbol.GetMembers(); + foreach (var member in members) { + if (member.GetAttributes().Any(attr => IsSQLiteAttribute (attr.AttributeClass))) + { + return true; + } + } + + classSymbol = classSymbol.BaseType; + } + } + + private static bool HasTableAttribute (INamedTypeSymbol? classSymbol) + { + while (true) { + if (classSymbol == null || classSymbol.SpecialType == SpecialType.System_Object) { + return false; + } + + var hasTableAttribute = classSymbol.GetAttributes () + .Any (attr => IsTableAttribute (attr.AttributeClass)); + if (hasTableAttribute) return true; + + classSymbol = classSymbol.BaseType; + } + } + + static ClassInfo? GetClassInfo(GeneratorSyntaxContext context) + { + var classDecl = (ClassDeclarationSyntax)context.Node; + var semanticModel = context.SemanticModel; + + var classSymbol = semanticModel.GetDeclaredSymbol(classDecl); + return GetClassInfo (classSymbol); + } + + private static bool IsTableAttribute (INamedTypeSymbol? attributeClass) + { + while (true) { + if (attributeClass == null) { + return false; + } + + if (IsSQLiteNamespace (attributeClass) && attributeClass.Name == "TableAttribute") { + return true; + } + + attributeClass = attributeClass.BaseType; + } + } + + private static bool IsIgnoreAttribute (INamedTypeSymbol? attributeClass) + { + while (true) { + if (attributeClass == null) { + return false; + } + + if (IsSQLiteNamespace (attributeClass) && attributeClass.Name == "IgnoreAttribute") { + return true; + } + + attributeClass = attributeClass.BaseType; + } + } + + private static bool IsSQLiteAttribute (INamedTypeSymbol? attributeClass) + { + while (true) { + if (attributeClass == null) { + return false; + } + + if (IsSQLiteNamespace (attributeClass) && SQLitePropertyFullAttributes.Contains (attributeClass.Name)) { + return true; + } + + attributeClass = attributeClass.BaseType; + } + } + + private static bool IsSQLiteNamespace (INamedTypeSymbol attributeClass) + { + return attributeClass.ContainingNamespace.Name == "SQLite"; } static string GetColumnName(IPropertySymbol property) @@ -300,7 +403,7 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) case "decimal": case "Decimal": case "System.Decimal": - sb.AppendLine ($" typedObj.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); + sb.AppendLine ($" typedObj.{property.PropertyName} = System.Convert.ToDecimal(SQLite3.ColumnDouble(stmt, index));"); break; case "float": diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index c6c89483..92d6ca85 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -24,10 +24,10 @@ - + diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index f83cfb2c..dc5a9321 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -13,6 +13,11 @@ namespace SQLite.Tests { + [AttributeUsage (AttributeTargets.Property, AllowMultiple = false, Inherited = true)] + class DerivedIgnoreAttribute : IgnoreAttribute + { + } + public class OuterTestSetter { [AutoIncrement, PrimaryKey] @@ -27,6 +32,9 @@ public class OuterTestSetter [Ignore] public string Ignore { get; set; } + [DerivedIgnore] + public string DerivedIgnore { get; set; } + [Column("A")] public string Z { get; set; } } @@ -48,8 +56,10 @@ public class StringTest : BaseTest { } -#if NET5_0_OR_GREATER -#endif + public class IntTest : BaseTest + { + } + public class BaseTest { [PrimaryKey] @@ -147,6 +157,17 @@ public void SqliteInitializer_StringTestSetter () } } + [Test] + public void SqliteInitializer_IntTestSetter () + { + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (IntTest), nameof (IntTest.Id)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + [Test] public void SqliteInitializer_InnerTestSetter () { @@ -192,6 +213,17 @@ public void SqliteInitializer_OuterTestSetter_Ignore_NotRegistered () } } + [Test] + public void SqliteInitializer_OuterTestSetter_DeriveIgnore_NotRegistered () + { + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.DerivedIgnore)), out var setter)) { + Assert.IsTrue (true, "Should not be registered (Ignore)"); + } + else { + Assert.Fail ("Should not be registered (Ignore)"); + } + } + [Test] public void SqliteInitializer_OuterTestSetter () { From 3cca10c3bfe7e057f34a140de2f13ca2e758bd9f Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 10:00:46 +0200 Subject: [PATCH 65/91] cache has sqlite attribute --- .../SQLiteFastColumnSetterGenerator.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 5c9a7934..a1089a17 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -14,6 +15,8 @@ [Generator] public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator { + private static ConcurrentDictionary cachedHasSqliteAttribute = new (); + private static ConcurrentDictionary cachedHasTableAttribute = new (); private static List SQLitePropertyAttributes = default!; private static ImmutableHashSet SQLitePropertyFullAttributes = default!; @@ -166,8 +169,15 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) { + if (classSymbol != null && cachedHasSqliteAttribute.TryGetValue(classSymbol, out var result)) { + return result; + } + while (true) { if (classSymbol == null || classSymbol.SpecialType == SpecialType.System_Object) { + if (classSymbol != null) { + cachedHasSqliteAttribute[classSymbol] = false; + } return false; } @@ -175,6 +185,7 @@ private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) foreach (var member in members) { if (member.GetAttributes().Any(attr => IsSQLiteAttribute (attr.AttributeClass))) { + cachedHasSqliteAttribute[classSymbol] = true; return true; } } @@ -185,14 +196,24 @@ private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) private static bool HasTableAttribute (INamedTypeSymbol? classSymbol) { - while (true) { + if (classSymbol != null && cachedHasTableAttribute.TryGetValue (classSymbol, out var result)) { + return result; + } + + while (true) { if (classSymbol == null || classSymbol.SpecialType == SpecialType.System_Object) { + if (classSymbol != null) { + cachedHasTableAttribute[classSymbol] = false; + } return false; } var hasTableAttribute = classSymbol.GetAttributes () .Any (attr => IsTableAttribute (attr.AttributeClass)); - if (hasTableAttribute) return true; + if (hasTableAttribute) { + cachedHasTableAttribute[classSymbol] = true; + return true; + } classSymbol = classSymbol.BaseType; } From 8356eccdb0833d82bdfabbe1eb667da303737182 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 10:02:37 +0200 Subject: [PATCH 66/91] fixing build --- .../SQLiteFastColumnSetterGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a1089a17..63a014cc 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -15,8 +15,8 @@ [Generator] public class SQLiteFastColumnSetterGenerator : IIncrementalGenerator { - private static ConcurrentDictionary cachedHasSqliteAttribute = new (); - private static ConcurrentDictionary cachedHasTableAttribute = new (); + private static ConcurrentDictionary, bool> cachedHasSqliteAttribute = new (); + private static ConcurrentDictionary, bool> cachedHasTableAttribute = new (); private static List SQLitePropertyAttributes = default!; private static ImmutableHashSet SQLitePropertyFullAttributes = default!; From 2845edce6ac2cb54f9b91adfc8dde05c2a301a5d Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 10:29:08 +0200 Subject: [PATCH 67/91] fixing enum --- .../SQLiteFastColumnSetterGenerator.cs | 29 +- tests/SQLite.Tests/EnumCacheTest.cs | 278 +++++++++--------- 2 files changed, 158 insertions(+), 149 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 63a014cc..1d8a7565 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -133,7 +133,7 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) // Include property if not ignored if (!ignore) { var columnName = GetColumnName (member); - properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName)); + properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, member.Type.TypeKind == TypeKind.Enum)); } } } @@ -460,17 +460,26 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) break; default: - // For other types, try to use a generic approach - sb.AppendLine($" // Generic setter for {propertyType}"); - sb.AppendLine($" var value = SQLite3.ColumnString(stmt, index);"); - sb.AppendLine($" if (value != null)"); - sb.AppendLine($" {{"); - sb.AppendLine($" typedObj.{property.PropertyName} = ({propertyType})Convert.ChangeType(value, typeof({propertyType}));"); - sb.AppendLine($" }}"); - break; + if (property.IsEnum) { + // For other types, try to use a generic approach + sb.AppendLine ($" // Enum setter for {propertyType}"); + sb.AppendLine ($" var value = SQLite3.ColumnInt(stmt, index);"); + sb.AppendLine ($" typedObj.{ property.PropertyName} = ({ propertyType})value;"); +} + else { + // For other types, try to use a generic approach + sb.AppendLine ($" // Generic setter for {propertyType}"); + sb.AppendLine ($" var value = SQLite3.ColumnString(stmt, index);"); + sb.AppendLine ($" if (value != null)"); + sb.AppendLine ($" {{"); + sb.AppendLine ($" typedObj.{property.PropertyName} = ({propertyType})Convert.ChangeType(value, typeof({propertyType}));"); + sb.AppendLine ($" }}"); + } + + break; } } record ClassInfo(string ClassName, string Namespace, List Properties); - record PropertyInfo(string PropertyName, string TypeName, string ColumnName); + record PropertyInfo(string PropertyName, string TypeName, string ColumnName, bool IsEnum); } diff --git a/tests/SQLite.Tests/EnumCacheTest.cs b/tests/SQLite.Tests/EnumCacheTest.cs index c6163f5d..e5c1ad8b 100644 --- a/tests/SQLite.Tests/EnumCacheTest.cs +++ b/tests/SQLite.Tests/EnumCacheTest.cs @@ -1,143 +1,143 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -#if NETFX_CORE -using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; -using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; -using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; -#else -using NUnit.Framework; -#endif - -namespace SQLite.Tests -{ - [TestFixture] - public class EnumCacheTests - { - [StoreAsText] - public enum TestEnumStoreAsText - { - Value1, - - Value2, - - Value3 - } - - public enum TestEnumStoreAsInt - { - Value1, - - Value2, - - Value3 +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +#if NETFX_CORE +using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; +using SetUp = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; +using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; +using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; +#else +using NUnit.Framework; +#endif + +namespace SQLite.Tests +{ + [TestFixture] + public class EnumCacheTests + { + [StoreAsText] + public enum TestEnumStoreAsText + { + Value1, + + Value2, + + Value3 + } + + public enum TestEnumStoreAsInt + { + Value1, + + Value2, + + Value3 + } + + public enum TestByteEnumStoreAsInt : byte + { + Value1, + + Value2, + + Value3 + } + + public enum TestEnumWithRepeats + { + Value1 = 1, + + Value2 = 2, + + Value2Again = 2, + + Value3 = 3, + } + + [StoreAsText] + public enum TestEnumWithRepeatsAsText + { + Value1 = 1, + + Value2 = 2, + + Value2Again = 2, + + Value3 = 3, + } + + public class TestClassThusNotEnum + { + + } + + [Test] + public void ShouldReturnTrueForEnumStoreAsText() + { + var info = EnumCache.GetInfo(); + + Assert.IsTrue(info.IsEnum); + Assert.IsTrue(info.StoreAsText); + Assert.IsNotNull(info.EnumValues); + + var values = Enum.GetValues(typeof(TestEnumStoreAsText)).Cast().ToList(); + + for (int i = 0; i < values.Count; i++) + { + Assert.AreEqual(values[i].ToString(), info.EnumValues[i]); + } } - public enum TestByteEnumStoreAsInt : byte - { - Value1, - - Value2, - - Value3 - } - - public enum TestEnumWithRepeats - { - Value1 = 1, - - Value2 = 2, - - Value2Again = 2, - - Value3 = 3, - } - - [StoreAsText] - public enum TestEnumWithRepeatsAsText - { - Value1 = 1, - - Value2 = 2, - - Value2Again = 2, - - Value3 = 3, - } - - public class TestClassThusNotEnum - { - - } - - [Test] - public void ShouldReturnTrueForEnumStoreAsText() - { - var info = EnumCache.GetInfo(); - - Assert.IsTrue(info.IsEnum); - Assert.IsTrue(info.StoreAsText); - Assert.IsNotNull(info.EnumValues); - - var values = Enum.GetValues(typeof(TestEnumStoreAsText)).Cast().ToList(); - - for (int i = 0; i < values.Count; i++) - { - Assert.AreEqual(values[i].ToString(), info.EnumValues[i]); - } - } - - [Test] - public void ShouldReturnTrueForEnumStoreAsInt() - { - var info = EnumCache.GetInfo(); - - Assert.IsTrue(info.IsEnum); - Assert.IsFalse(info.StoreAsText); - Assert.IsNull(info.EnumValues); + [Test] + public void ShouldReturnTrueForEnumStoreAsInt() + { + var info = EnumCache.GetInfo(); + + Assert.IsTrue(info.IsEnum); + Assert.IsFalse(info.StoreAsText); + Assert.IsNull(info.EnumValues); } - [Test] - public void ShouldReturnTrueForByteEnumStoreAsInt() - { - var info = EnumCache.GetInfo(); - - Assert.IsTrue(info.IsEnum); - Assert.IsFalse(info.StoreAsText); - } - - [Test] - public void ShouldReturnFalseForClass() - { - var info = EnumCache.GetInfo(); - - Assert.IsFalse(info.IsEnum); - Assert.IsFalse(info.StoreAsText); - Assert.IsNull(info.EnumValues); - } - - [Test] - public void Issue598_EnumsWithRepeatedValues () - { - var info = EnumCache.GetInfo (); - - Assert.IsTrue (info.IsEnum); - Assert.IsFalse (info.StoreAsText); - Assert.IsNull (info.EnumValues); - } - - [Test] - public void Issue598_EnumsWithRepeatedValuesAsText () - { - var info = EnumCache.GetInfo (); - - Assert.IsTrue (info.IsEnum); - Assert.IsTrue (info.StoreAsText); - Assert.IsNotNull (info.EnumValues); - } - } -} + [Test] + public void ShouldReturnTrueForByteEnumStoreAsInt() + { + var info = EnumCache.GetInfo(); + + Assert.IsTrue(info.IsEnum); + Assert.IsFalse(info.StoreAsText); + } + + [Test] + public void ShouldReturnFalseForClass() + { + var info = EnumCache.GetInfo(); + + Assert.IsFalse(info.IsEnum); + Assert.IsFalse(info.StoreAsText); + Assert.IsNull(info.EnumValues); + } + + [Test] + public void Issue598_EnumsWithRepeatedValues () + { + var info = EnumCache.GetInfo (); + + Assert.IsTrue (info.IsEnum); + Assert.IsFalse (info.StoreAsText); + Assert.IsNull (info.EnumValues); + } + + [Test] + public void Issue598_EnumsWithRepeatedValuesAsText () + { + var info = EnumCache.GetInfo (); + + Assert.IsTrue (info.IsEnum); + Assert.IsTrue (info.StoreAsText); + Assert.IsNotNull (info.EnumValues); + } + } +} From 34e833544208b44fd48795df87a15af48a32a077 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 10:39:57 +0200 Subject: [PATCH 68/91] some more fixes --- .../SQLiteFastColumnSetterGenerator.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 1d8a7565..cb859102 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -133,7 +133,7 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) // Include property if not ignored if (!ignore) { var columnName = GetColumnName (member); - properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, member.Type.TypeKind == TypeKind.Enum)); + properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, IsEnum(member))); } } } @@ -167,6 +167,22 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) properties); } + private static bool IsEnum (IPropertySymbol member) + { + + var type = member.Type; + if (type is INamedTypeSymbol named && + named.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { + type = named.TypeArguments[0]; + } + + if (type.TypeKind == TypeKind.Enum) { + return true; + } + + return false; + } + private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) { if (classSymbol != null && cachedHasSqliteAttribute.TryGetValue(classSymbol, out var result)) { From f545bbebded63707df2e065659fd055e8dcf9a9e Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 10:54:04 +0200 Subject: [PATCH 69/91] fix all unit tests --- .../SQLiteFastColumnSetterGenerator.cs | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index cb859102..6f860e21 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -133,7 +133,7 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) // Include property if not ignored if (!ignore) { var columnName = GetColumnName (member); - properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, IsEnum(member))); + properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, GetEnumInfo(member))); } } } @@ -167,9 +167,8 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) properties); } - private static bool IsEnum (IPropertySymbol member) + private static EnumInfo? GetEnumInfo (IPropertySymbol member) { - var type = member.Type; if (type is INamedTypeSymbol named && named.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { @@ -177,10 +176,12 @@ private static bool IsEnum (IPropertySymbol member) } if (type.TypeKind == TypeKind.Enum) { - return true; + var storeAsText = type.GetAttributes () + .Any (attr => IsStoreAsTextAttribute(attr.AttributeClass)); + return new EnumInfo (storeAsText); } - return false; + return null; } private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) @@ -210,7 +211,7 @@ private static bool HasSQLiteAttribute (INamedTypeSymbol? classSymbol) } } - private static bool HasTableAttribute (INamedTypeSymbol? classSymbol) + private static bool HasTableAttribute (INamedTypeSymbol? classSymbol) { if (classSymbol != null && cachedHasTableAttribute.TryGetValue (classSymbol, out var result)) { return result; @@ -259,6 +260,21 @@ private static bool IsTableAttribute (INamedTypeSymbol? attributeClass) } } + private static bool IsStoreAsTextAttribute (INamedTypeSymbol? attributeClass) + { + while (true) { + if (attributeClass == null) { + return false; + } + + if (IsSQLiteNamespace (attributeClass) && attributeClass.Name == "StoreAsTextAttribute") { + return true; + } + + attributeClass = attributeClass.BaseType; + } + } + private static bool IsIgnoreAttribute (INamedTypeSymbol? attributeClass) { while (true) { @@ -476,12 +492,21 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) break; default: - if (property.IsEnum) { + if (property.Enum != null) { // For other types, try to use a generic approach sb.AppendLine ($" // Enum setter for {propertyType}"); - sb.AppendLine ($" var value = SQLite3.ColumnInt(stmt, index);"); - sb.AppendLine ($" typedObj.{ property.PropertyName} = ({ propertyType})value;"); -} + if (property.Enum.StoreAsText) { + sb.AppendLine ($" var value = SQLite3.ColumnString(stmt, index);"); + sb.AppendLine ($" if (value != null)"); + sb.AppendLine ($" {{"); + sb.AppendLine ($" typedObj.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), value, ignoreCase: true);"); + sb.AppendLine ($" }}"); + } + else { + sb.AppendLine ($" var value = SQLite3.ColumnInt(stmt, index);"); + sb.AppendLine ($" typedObj.{property.PropertyName} = ({propertyType})value;"); + } + } else { // For other types, try to use a generic approach sb.AppendLine ($" // Generic setter for {propertyType}"); @@ -497,5 +522,6 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) } record ClassInfo(string ClassName, string Namespace, List Properties); - record PropertyInfo(string PropertyName, string TypeName, string ColumnName, bool IsEnum); + record PropertyInfo(string PropertyName, string TypeName, string ColumnName, EnumInfo? Enum); + record EnumInfo (bool StoreAsText); } From 4b95286b4780f634aa54b492b221433e7914e892 Mon Sep 17 00:00:00 2001 From: Inforithmics Date: Thu, 18 Sep 2025 10:54:38 +0200 Subject: [PATCH 70/91] use not vulnerable mstest version --- tests/SQLite.Tests/SQLite.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 92d6ca85..e7216f77 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -11,7 +11,7 @@ - + From 5852a064c47d05a4138bd732cc7e60d0a1d5ad8a Mon Sep 17 00:00:00 2001 From: inforithmics Date: Fri, 19 Sep 2025 19:17:20 +0200 Subject: [PATCH 71/91] ignore obsoelete and and don't use static or private properties --- .../SQLiteFastColumnSetterGenerator.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 6f860e21..1b4e5667 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -7,8 +7,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Reflection; -using System.Reflection.Metadata.Ecma335; using System.Text; using Microsoft.CodeAnalysis.Diagnostics; @@ -126,7 +124,7 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) var currentType = classSymbol; while (currentType != null) { foreach (var member in currentType.GetMembers ().OfType ()) { - if (!member.IsReadOnly) { + if (!member.IsReadOnly && !member.IsStatic && !member.IsIndexer && (member.DeclaredAccessibility != Accessibility.Private && member.DeclaredAccessibility != Accessibility.Protected) ) { var ignore = member.GetAttributes () .Any (attr => IsIgnoreAttribute (attr.AttributeClass)); @@ -344,13 +342,16 @@ static void Execute( sb.AppendLine("// "); sb.AppendLine("using System;"); sb.AppendLine("using SQLite;"); - sb.AppendLine(); + sb.AppendLine("#pragma warning disable CS0618 // Disable obsolete Warnings"); + sb.AppendLine(); sb.AppendLine($"namespace {rootNamespace}"); sb.AppendLine("{"); - sb.AppendLine(" [SQLite.Preserve(AllMembers = true)]"); + sb.AppendLine(" /// SQLite Initializer Class "); + sb.AppendLine(" [SQLite.Preserve(AllMembers = true)]"); sb.AppendLine(" public static class SQLiteInitializer"); sb.AppendLine(" {"); sb.AppendLine(" private static bool initialized;"); + sb.AppendLine(" /// Init SQLite Fast Column Setters "); sb.AppendLine("#if NET5_0_OR_GREATER"); sb.AppendLine(" [System.Runtime.CompilerServices.ModuleInitializer]"); sb.AppendLine("#endif"); From 720862475b6ce2a81c092d0e798a93de7471707b Mon Sep 17 00:00:00 2001 From: inforithmics Date: Fri, 19 Sep 2025 19:21:00 +0200 Subject: [PATCH 72/91] Added Unit Tests --- tests/SQLite.Tests/SourceGeneratorTest.cs | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index dc5a9321..7d609ebe 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -37,6 +37,9 @@ public class OuterTestSetter [Column("A")] public string Z { get; set; } + + private string Private { get; set; } + public static string StaticProperty {get; set; } } public class OuterTestDb : SQLiteConnection @@ -224,6 +227,28 @@ public void SqliteInitializer_OuterTestSetter_DeriveIgnore_NotRegistered () } } + [Test] + public void SqliteInitializer_OuterTestSetter_Private_NotRegistered () + { + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), "Private"), out var setter)) { + Assert.IsTrue (true, "Private properties Should not be registered"); + } + else { + Assert.Fail ("Private properties Should not be registered"); + } + } + + [Test] + public void SqliteInitializer_OuterTestSetter_StaticProperty_NotRegistered () + { + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof(OuterTestSetter.StaticProperty)), out var setter)) { + Assert.IsTrue (true, "Static properties Should not be registered"); + } + else { + Assert.Fail ("Static properties Should not be registered"); + } + } + [Test] public void SqliteInitializer_OuterTestSetter () { From 85c5a5b36bbec985c5920fecf1e8dc894c0de7c5 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Fri, 19 Sep 2025 19:40:49 +0200 Subject: [PATCH 73/91] more obsolete warning suppression --- .../SQLiteFastColumnSetterGenerator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 1b4e5667..fbc28dc5 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -343,6 +343,7 @@ static void Execute( sb.AppendLine("using System;"); sb.AppendLine("using SQLite;"); sb.AppendLine("#pragma warning disable CS0618 // Disable obsolete Warnings"); + sb.AppendLine("#pragma warning disable CS0612 // Disable obsolete Warnings"); sb.AppendLine(); sb.AppendLine($"namespace {rootNamespace}"); sb.AppendLine("{"); From bfaab789de85d47a6d673b66c85149884336b0ad Mon Sep 17 00:00:00 2001 From: inforithmics Date: Fri, 19 Sep 2025 19:43:13 +0200 Subject: [PATCH 74/91] added obsolete unit test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 7d609ebe..f168627b 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -11,6 +11,9 @@ using NUnit.Framework; #endif +#pragma warning disable CS0618 // Disable obsolete Warnings +#pragma warning disable CS0612 // Disable obsolete Warnings + namespace SQLite.Tests { [AttributeUsage (AttributeTargets.Property, AllowMultiple = false, Inherited = true)] @@ -40,6 +43,9 @@ public class OuterTestSetter private string Private { get; set; } public static string StaticProperty {get; set; } + + [Obsolete] + public string Obsolete { get; set; } } public class OuterTestDb : SQLiteConnection @@ -194,6 +200,17 @@ public void SqliteInitializer_OuterTestSetter_ZRenamedA() } } + [Test] + public void SqliteInitializer_OuterTestSetter_Obsolete_Property() + { + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof(OuterTestSetter.Obsolete)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + [Test] public void SqliteInitializer_OuterTestSetter_NotWritable_NotRegistered() { From bb8e2be182ec65bcff6a5d32a2765b4f5e1bd467 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Fri, 19 Sep 2025 20:02:27 +0200 Subject: [PATCH 75/91] Fixed Init and private set properties --- .../SQLiteFastColumnSetterGenerator.cs | 4 ++- tests/SQLite.Tests/SQLite.Tests.csproj | 4 +-- tests/SQLite.Tests/SourceGeneratorTest.cs | 26 +++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index fbc28dc5..4385f79b 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -124,7 +124,9 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) var currentType = classSymbol; while (currentType != null) { foreach (var member in currentType.GetMembers ().OfType ()) { - if (!member.IsReadOnly && !member.IsStatic && !member.IsIndexer && (member.DeclaredAccessibility != Accessibility.Private && member.DeclaredAccessibility != Accessibility.Protected) ) { + if (!member.IsReadOnly && !member.IsStatic && !member.IsIndexer && + (member.DeclaredAccessibility != Accessibility.Private && member.DeclaredAccessibility != Accessibility.Protected) && + (member.SetMethod?.DeclaredAccessibility != Accessibility.Private && member.SetMethod?.DeclaredAccessibility != Accessibility.Protected && member.SetMethod?.IsInitOnly != true)) { var ignore = member.GetAttributes () .Any (attr => IsIgnoreAttribute (attr.AttributeClass)); diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index e7216f77..0e2b5771 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -4,14 +4,14 @@ net8.0 false - + 9 - + diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index f168627b..a6d8ef6c 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -46,6 +46,10 @@ public class OuterTestSetter [Obsolete] public string Obsolete { get; set; } + + public string PrivateSet { get; private set; } + + public string Init { get; init; } } public class OuterTestDb : SQLiteConnection @@ -266,6 +270,28 @@ public void SqliteInitializer_OuterTestSetter_StaticProperty_NotRegistered () } } + [Test] + public void SqliteInitializer_OuterTestSetter_PrivateSet_NotRegistered () + { + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.PrivateSet)), out var setter)) { + Assert.IsTrue (true, "Private Set properties Should not be registered"); + } + else { + Assert.Fail ("Private Set properties Should not be registered"); + } + } + + [Test] + public void SqliteInitializer_OuterTestSetter_Init_NotRegistered () + { + if (!SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (OuterTestSetter), nameof (OuterTestSetter.Init)), out var setter)) { + Assert.IsTrue (true, "Init properties Should not be registered"); + } + else { + Assert.Fail ("Init properties Should not be registered"); + } + } + [Test] public void SqliteInitializer_OuterTestSetter () { From fcbf2d9e337e165f9418a7242a8ccd80b41c7947 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Fri, 19 Sep 2025 20:18:53 +0200 Subject: [PATCH 76/91] fixed vulnerability warning for mstest --- tests/SQLite.Tests/SQLite.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 0e2b5771..528b7baa 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -11,7 +11,7 @@ - + From a4978f2f3634ffdc8c9ac322e9cfe225a33d6662 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:11:00 +0200 Subject: [PATCH 77/91] Reduce variables --- .../SQLiteFastColumnSetterGenerator.cs | 37 +++++++++---------- tests/SQLite.Tests/SQLite.Tests.csproj | 2 +- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 4385f79b..58ffb66f 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -377,13 +377,12 @@ static void Execute( sb.AppendLine($" \"{property.ColumnName}\","); sb.AppendLine($" (obj, stmt, index) => "); sb.AppendLine($" {{"); - sb.AppendLine($" var typedObj = ({fullTypeName})obj;"); sb.AppendLine($" var colType = SQLite3.ColumnType(stmt, index);"); sb.AppendLine($" if (colType != SQLite3.ColType.Null)"); sb.AppendLine($" {{"); // Generate appropriate setter based on property type - GeneratePropertySetter(sb, property); + GeneratePropertySetter($"(({fullTypeName})obj)",sb, property); sb.AppendLine($" }}"); sb.AppendLine($" }});"); @@ -409,7 +408,7 @@ static void Execute( } - static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) + static void GeneratePropertySetter(string typedObject, StringBuilder sb, PropertyInfo property) { var propertyType = property.TypeName; @@ -423,76 +422,76 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) case "string": case "String": case "System.String": - sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnString(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnString(stmt, index);"); break; case "byte": case "Byte": case "System.Byte": - sb.AppendLine ($" typedObj.{property.PropertyName} = (byte)SQLite3.ColumnInt(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = (byte)SQLite3.ColumnInt(stmt, index);"); break; case "short": case "Int16": case "System.Int16": - sb.AppendLine ($" typedObj.{property.PropertyName} = (short)SQLite3.ColumnInt(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = (short)SQLite3.ColumnInt(stmt, index);"); break; case "int": case "Int32": case "System.Int32": - sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnInt(stmt, index);"); break; case "long": case "Int64": case "System.Int64": - sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt64(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnInt64(stmt, index);"); break; case "double": case "Double": case "System.Double": - sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); break; case "decimal": case "Decimal": case "System.Decimal": - sb.AppendLine ($" typedObj.{property.PropertyName} = System.Convert.ToDecimal(SQLite3.ColumnDouble(stmt, index));"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = System.Convert.ToDecimal(SQLite3.ColumnDouble(stmt, index));"); break; case "float": case "Single": case "System.Single": - sb.AppendLine($" typedObj.{property.PropertyName} = (float)SQLite3.ColumnDouble(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = (float)SQLite3.ColumnDouble(stmt, index);"); break; case "bool": case "Boolean": case "System.Boolean": - sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnInt(stmt, index) == 1;"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnInt(stmt, index) == 1;"); break; case "DateTime": case "System.DateTime": - sb.AppendLine($" typedObj.{property.PropertyName} = new DateTime(SQLite3.ColumnInt64(stmt, index));"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = new DateTime(SQLite3.ColumnInt64(stmt, index));"); break; case "TimeSpan": case "System.TimeSpan": - sb.AppendLine ($" typedObj.{property.PropertyName} = new TimeSpan(SQLite3.ColumnInt64(stmt, index));"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = new TimeSpan(SQLite3.ColumnInt64(stmt, index));"); break; case "Guid": case "System.Guid": sb.AppendLine($" var text = SQLite3.ColumnString(stmt, index);"); - sb.AppendLine($" typedObj.{property.PropertyName} = new Guid(text);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = new Guid(text);"); break; case "byte[]": - sb.AppendLine($" typedObj.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index);"); break; default: @@ -503,12 +502,12 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) sb.AppendLine ($" var value = SQLite3.ColumnString(stmt, index);"); sb.AppendLine ($" if (value != null)"); sb.AppendLine ($" {{"); - sb.AppendLine ($" typedObj.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), value, ignoreCase: true);"); + sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), value, ignoreCase: true);"); sb.AppendLine ($" }}"); } else { sb.AppendLine ($" var value = SQLite3.ColumnInt(stmt, index);"); - sb.AppendLine ($" typedObj.{property.PropertyName} = ({propertyType})value;"); + sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})value;"); } } else { @@ -517,7 +516,7 @@ static void GeneratePropertySetter(StringBuilder sb, PropertyInfo property) sb.AppendLine ($" var value = SQLite3.ColumnString(stmt, index);"); sb.AppendLine ($" if (value != null)"); sb.AppendLine ($" {{"); - sb.AppendLine ($" typedObj.{property.PropertyName} = ({propertyType})Convert.ChangeType(value, typeof({propertyType}));"); + sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})Convert.ChangeType(value, typeof({propertyType}));"); sb.AppendLine ($" }}"); } diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 528b7baa..8d645ec1 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -11,7 +11,7 @@ - + From 0ae89a43def207553a33a6458408ec3d37712720 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:16:12 +0200 Subject: [PATCH 78/91] more variable removal --- .../SQLiteFastColumnSetterGenerator.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 58ffb66f..35c05c3b 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -377,8 +377,7 @@ static void Execute( sb.AppendLine($" \"{property.ColumnName}\","); sb.AppendLine($" (obj, stmt, index) => "); sb.AppendLine($" {{"); - sb.AppendLine($" var colType = SQLite3.ColumnType(stmt, index);"); - sb.AppendLine($" if (colType != SQLite3.ColType.Null)"); + sb.AppendLine($" if (SQLite3.ColumnType(stmt, index) != SQLite3.ColType.Null)"); sb.AppendLine($" {{"); // Generate appropriate setter based on property type @@ -486,8 +485,7 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert case "Guid": case "System.Guid": - sb.AppendLine($" var text = SQLite3.ColumnString(stmt, index);"); - sb.AppendLine($" {typedObject}.{property.PropertyName} = new Guid(text);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = new Guid(SQLite3.ColumnString(stmt, index));"); break; case "byte[]": @@ -506,8 +504,7 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert sb.AppendLine ($" }}"); } else { - sb.AppendLine ($" var value = SQLite3.ColumnInt(stmt, index);"); - sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})value;"); + sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})SQLite3.ColumnInt(stmt, index);"); } } else { From 4e07a7c4d3bde5e519c0c147056b1faa9bce1bed Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:18:27 +0200 Subject: [PATCH 79/91] more variable reductions --- .../SQLiteFastColumnSetterGenerator.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 35c05c3b..a1459192 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -497,24 +497,16 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert // For other types, try to use a generic approach sb.AppendLine ($" // Enum setter for {propertyType}"); if (property.Enum.StoreAsText) { - sb.AppendLine ($" var value = SQLite3.ColumnString(stmt, index);"); - sb.AppendLine ($" if (value != null)"); - sb.AppendLine ($" {{"); - sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), value, ignoreCase: true);"); - sb.AppendLine ($" }}"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), SQLite3.ColumnString(stmt, index), ignoreCase: true);"); } else { - sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})SQLite3.ColumnInt(stmt, index);"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = ({propertyType})SQLite3.ColumnInt(stmt, index);"); } } else { // For other types, try to use a generic approach - sb.AppendLine ($" // Generic setter for {propertyType}"); - sb.AppendLine ($" var value = SQLite3.ColumnString(stmt, index);"); - sb.AppendLine ($" if (value != null)"); - sb.AppendLine ($" {{"); - sb.AppendLine ($" {typedObject}.{property.PropertyName} = ({propertyType})Convert.ChangeType(value, typeof({propertyType}));"); - sb.AppendLine ($" }}"); + sb.AppendLine($" // Generic setter for {propertyType}"); + sb.AppendLine($" {typedObject}.{property.PropertyName} = ({propertyType})Convert.ChangeType(SQLite3.ColumnString(stmt, index), typeof({propertyType}));"); } break; From a0c9a2071ebee791259fdfc29c61cb6e901554f6 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:23:05 +0200 Subject: [PATCH 80/91] add nullable test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 84 ++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index a6d8ef6c..4015f71e 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -117,7 +117,36 @@ public class AllBasicTypesSetter public Guid Guid { get; set; } } - // Shouldn't generate Setter because it is not accessible + + public class AllBasicTypesSetterNullable + { + [PrimaryKey] + public int Id { get; set; } + + public string String { get; set; } + + public byte? Byte { get; set; } + + public short? Short { get; set; } + + public int? Int { get; set; } + + public long? Long { get; set; } + + public float? Float { get; set; } + + public double? Double { get; set; } + + public decimal? Decimal { get; set; } + + public TimeSpan? TimeSpam { get; set; } + + public DateTime? DateTime { get; set; } + + public Guid? Guid { get; set; } + } + +// Shouldn't generate Setter because it is not accessible private class PrivateInnerTestSetter { [AutoIncrement, PrimaryKey] @@ -137,6 +166,15 @@ public AllBasicTypesTestDb (String path) } } + public class AllBasicTypesNullableTestDb : SQLiteConnection + { + public AllBasicTypesNullableTestDb (String path) + : base (path) + { + CreateTable (); + } + } + public class InnerTestDb : SQLiteConnection { public InnerTestDb (String path) @@ -456,5 +494,49 @@ public void SetFastColumnSetters_AllBasicTypes_Works () Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); } + + [Test] + public void SetFastColumnSetters_AllBasicTypesNullable_Works () + { + + var mapperCount = FastColumnSetter.customSetter.Count; + + var n = 20; + var cq = from i in Enumerable.Range (1, n) + select new AllBasicTypesSetterNullable() { + Id = i, + String = null, + Byte = null, + Short = null, + Int = null, + Long = null, + Float = null, + Double = null, + Decimal = null, + DateTime = null, + TimeSpam = null, + Guid = null, + }; + + var db = new AllBasicTypesNullableTestDb (TestPath.GetTempFileName ()); + db.InsertAll (cq); + + var results = db.Table ().Where (o => o.Id.Equals (10)); + Assert.AreEqual (results.Count (), 1); + var data = results.FirstOrDefault (); + Assert.AreEqual (data.String, "10"); + Assert.AreEqual (data.Byte, null); + Assert.AreEqual (data.Short, null); + Assert.AreEqual (data.Int, null); + Assert.AreEqual (data.Long, null); + Assert.AreEqual (data.Float, null); + Assert.AreEqual (data.Double, null); + Assert.AreEqual (data.Decimal, null); + Assert.AreEqual (data.TimeSpam, null); + Assert.AreEqual (data.DateTime, null); + Assert.AreEqual (data.Guid, null); + + Assert.AreEqual (mapperCount, FastColumnSetter.customSetter.Count); + } } } From ff95b32bfdb7f97e77a15155843bfa2377f9bba6 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:23:23 +0200 Subject: [PATCH 81/91] fix unit test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 4015f71e..86c2a52a 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -524,7 +524,7 @@ public void SetFastColumnSetters_AllBasicTypesNullable_Works () var results = db.Table ().Where (o => o.Id.Equals (10)); Assert.AreEqual (results.Count (), 1); var data = results.FirstOrDefault (); - Assert.AreEqual (data.String, "10"); + Assert.AreEqual (data.String, null); Assert.AreEqual (data.Byte, null); Assert.AreEqual (data.Short, null); Assert.AreEqual (data.Int, null); From 0eab04626d785a27ea8d28f8d0ceda31f8ecb7ff Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:34:51 +0200 Subject: [PATCH 82/91] improved generated code --- .../SQLiteFastColumnSetterGenerator.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index a1459192..30fdd470 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -133,7 +133,7 @@ static bool HasBaseClass (ClassDeclarationSyntax classDecl) // Include property if not ignored if (!ignore) { var columnName = GetColumnName (member); - properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, GetEnumInfo(member))); + properties.Add (new PropertyInfo (member.Name, member.Type.ToDisplayString (), columnName, GetEnumInfo(member))); } } } @@ -377,16 +377,9 @@ static void Execute( sb.AppendLine($" \"{property.ColumnName}\","); sb.AppendLine($" (obj, stmt, index) => "); sb.AppendLine($" {{"); - sb.AppendLine($" if (SQLite3.ColumnType(stmt, index) != SQLite3.ColType.Null)"); - sb.AppendLine($" {{"); - - // Generate appropriate setter based on property type - GeneratePropertySetter($"(({fullTypeName})obj)",sb, property); - - sb.AppendLine($" }}"); - sb.AppendLine($" }});"); - sb.AppendLine(); - } + GeneratePropertySetter ($"(({fullTypeName})obj)", sb, property); + sb.AppendLine($" }});"); + } } sb.AppendLine(" }"); @@ -416,6 +409,11 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert if (isNullable) propertyType = propertyType.Replace("?", ""); + if (isNullable) { + sb.AppendLine($" if (SQLite3.ColumnType(stmt, index) != SQLite3.ColType.Null)"); + sb.AppendLine($" {{"); + } + switch (propertyType) { case "string": @@ -511,6 +509,10 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert break; } + + if (isNullable) { + sb.AppendLine($" }}"); + } } record ClassInfo(string ClassName, string Namespace, List Properties); From 9d3f68c7659f8f58fbaab7a8767876fc028786ea Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:36:00 +0200 Subject: [PATCH 83/91] comment out debug output --- tests/SQLite.Tests/SQLite.Tests.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index 8d645ec1..f46fb8c9 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -24,9 +24,11 @@ - + + From 9ec0d37683ae0c6aa7154447822a80383cfc501c Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:46:11 +0200 Subject: [PATCH 84/91] fixed nullable byte arrays --- .../SQLiteFastColumnSetterGenerator.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 30fdd470..7848c5a8 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -409,6 +409,14 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert if (isNullable) propertyType = propertyType.Replace("?", ""); + switch (propertyType) { + case "byte[]": + case "Byte[]": + case "System.Byte[]": + isNullable = true; // need to handle nullable for byte arrays + break; + } + if (isNullable) { sb.AppendLine($" if (SQLite3.ColumnType(stmt, index) != SQLite3.ColType.Null)"); sb.AppendLine($" {{"); @@ -487,7 +495,9 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert break; case "byte[]": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index);"); + case "Byte[]": + case "System.Byte[]": + sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index);"); break; default: From 7ae777c17cd9c6341473b8ec9cd205e4dfc1a21a Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 12:48:29 +0200 Subject: [PATCH 85/91] added directory.build.props to solution --- SQLite.sln | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SQLite.sln b/SQLite.sln index de464324..8faf72b9 100644 --- a/SQLite.sln +++ b/SQLite.sln @@ -1,10 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.14.36429.23 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11012.119 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0E59A10-7BD0-4554-B133-66FA850159BE}" ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props Makefile = Makefile README.md = README.md EndProjectSection From c43bec5e688a4b8cfe44a7e83f5160472c0d55e7 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 13:32:14 +0200 Subject: [PATCH 86/91] Make Generated code more compact --- .../SQLiteFastColumnSetterGenerator.cs | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 7848c5a8..7631d7b4 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -375,10 +375,8 @@ static void Execute( sb.AppendLine($" SQLiteConnection.RegisterFastColumnSetter("); sb.AppendLine($" typeof({fullTypeName}),"); sb.AppendLine($" \"{property.ColumnName}\","); - sb.AppendLine($" (obj, stmt, index) => "); - sb.AppendLine($" {{"); + sb.Append($" (obj, stmt, index) => "); GeneratePropertySetter ($"(({fullTypeName})obj)", sb, property); - sb.AppendLine($" }});"); } } @@ -418,111 +416,117 @@ static void GeneratePropertySetter(string typedObject, StringBuilder sb, Propert } if (isNullable) { - sb.AppendLine($" if (SQLite3.ColumnType(stmt, index) != SQLite3.ColType.Null)"); + sb.AppendLine(""); + sb.AppendLine($" {{"); + sb.AppendLine($" if (SQLite3.ColumnType(stmt, index) != SQLite3.ColType.Null)"); sb.AppendLine($" {{"); - } + sb.Append($" "); +} switch (propertyType) { case "string": case "String": case "System.String": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnString(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = SQLite3.ColumnString(stmt, index)"); break; case "byte": case "Byte": case "System.Byte": - sb.AppendLine($" {typedObject}.{property.PropertyName} = (byte)SQLite3.ColumnInt(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = (byte)SQLite3.ColumnInt(stmt, index)"); break; case "short": case "Int16": case "System.Int16": - sb.AppendLine($" {typedObject}.{property.PropertyName} = (short)SQLite3.ColumnInt(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = (short)SQLite3.ColumnInt(stmt, index)"); break; case "int": case "Int32": case "System.Int32": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnInt(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = SQLite3.ColumnInt(stmt, index)"); break; case "long": case "Int64": case "System.Int64": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnInt64(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = SQLite3.ColumnInt64(stmt, index)"); break; case "double": case "Double": case "System.Double": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = SQLite3.ColumnDouble(stmt, index)"); break; case "decimal": case "Decimal": case "System.Decimal": - sb.AppendLine($" {typedObject}.{property.PropertyName} = System.Convert.ToDecimal(SQLite3.ColumnDouble(stmt, index));"); + sb.Append($"{typedObject}.{property.PropertyName} = System.Convert.ToDecimal(SQLite3.ColumnDouble(stmt, index))"); break; case "float": case "Single": case "System.Single": - sb.AppendLine($" {typedObject}.{property.PropertyName} = (float)SQLite3.ColumnDouble(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = (float)SQLite3.ColumnDouble(stmt, index)"); break; case "bool": case "Boolean": case "System.Boolean": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnInt(stmt, index) == 1;"); + sb.Append($"{typedObject}.{property.PropertyName} = SQLite3.ColumnInt(stmt, index) == 1"); break; case "DateTime": case "System.DateTime": - sb.AppendLine($" {typedObject}.{property.PropertyName} = new DateTime(SQLite3.ColumnInt64(stmt, index));"); + sb.Append($"{typedObject}.{property.PropertyName} = new DateTime(SQLite3.ColumnInt64(stmt, index))"); break; case "TimeSpan": case "System.TimeSpan": - sb.AppendLine($" {typedObject}.{property.PropertyName} = new TimeSpan(SQLite3.ColumnInt64(stmt, index));"); + sb.Append($"{typedObject}.{property.PropertyName} = new TimeSpan(SQLite3.ColumnInt64(stmt, index))"); break; case "Guid": case "System.Guid": - sb.AppendLine($" {typedObject}.{property.PropertyName} = new Guid(SQLite3.ColumnString(stmt, index));"); + sb.Append($"{typedObject}.{property.PropertyName} = new Guid(SQLite3.ColumnString(stmt, index))"); break; case "byte[]": case "Byte[]": case "System.Byte[]": - sb.AppendLine($" {typedObject}.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = SQLite3.ColumnByteArray(stmt, index)"); break; default: if (property.Enum != null) { // For other types, try to use a generic approach - sb.AppendLine ($" // Enum setter for {propertyType}"); if (property.Enum.StoreAsText) { - sb.AppendLine($" {typedObject}.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), SQLite3.ColumnString(stmt, index), ignoreCase: true);"); - } + sb.Append($"{typedObject}.{property.PropertyName} = ({propertyType})Enum.Parse(typeof({propertyType}), SQLite3.ColumnString(stmt, index), ignoreCase: true)"); + } else { - sb.AppendLine($" {typedObject}.{property.PropertyName} = ({propertyType})SQLite3.ColumnInt(stmt, index);"); + sb.Append($"{typedObject}.{property.PropertyName} = ({propertyType})SQLite3.ColumnInt(stmt, index)"); } } else { // For other types, try to use a generic approach - sb.AppendLine($" // Generic setter for {propertyType}"); - sb.AppendLine($" {typedObject}.{property.PropertyName} = ({propertyType})Convert.ChangeType(SQLite3.ColumnString(stmt, index), typeof({propertyType}));"); + sb.Append($"{typedObject}.{property.PropertyName} = ({propertyType})Convert.ChangeType(SQLite3.ColumnString(stmt, index), typeof({propertyType}))"); } - break; - } + break; + } if (isNullable) { - sb.AppendLine($" }}"); + sb.AppendLine($";"); + sb.AppendLine($" }}"); + sb.AppendLine($" }});"); } + else { + sb.AppendLine(");"); + } } record ClassInfo(string ClassName, string Namespace, List Properties); From 8478d15787438b45006e834cd5504f42cf983895 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 14:01:26 +0200 Subject: [PATCH 87/91] InitPerClass --- .../SQLiteFastColumnSetterGenerator.cs | 37 +++++++++++++------ tests/SQLite.Tests/SQLite.Tests.csproj | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 7631d7b4..26137aa6 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -360,32 +360,45 @@ static void Execute( sb.AppendLine("#endif"); sb.AppendLine(" public static void Init()"); sb.AppendLine(" {"); - sb.AppendLine (" if (initialized)"); - sb.AppendLine (" return;"); - sb.AppendLine (" initialized = true;"); + sb.AppendLine(" if (initialized)"); + sb.AppendLine(" return;"); + sb.AppendLine(" initialized = true;"); + + foreach (var classInfo in classes) { + var fullTypeName = FullTypeName (classInfo); + var initName = "Init" + fullTypeName.Replace (".", "_"); + sb.AppendLine($" {initName}();"); + } - foreach (var classInfo in classes) - { - foreach (var property in classInfo.Properties) - { - var fullTypeName = string.IsNullOrEmpty(classInfo.Namespace) - ? classInfo.ClassName - : $"{classInfo.Namespace}.{classInfo.ClassName}"; + sb.AppendLine (" }"); + foreach (var classInfo in classes) { + var fullTypeName = FullTypeName (classInfo); + var initName = "Init" + fullTypeName.Replace (".", "_"); + sb.AppendLine($" public static void {initName}()"); + sb.AppendLine(" {"); + foreach (var property in classInfo.Properties) { sb.AppendLine($" SQLiteConnection.RegisterFastColumnSetter("); sb.AppendLine($" typeof({fullTypeName}),"); sb.AppendLine($" \"{property.ColumnName}\","); sb.Append($" (obj, stmt, index) => "); GeneratePropertySetter ($"(({fullTypeName})obj)", sb, property); } - } + sb.AppendLine (" }"); + } - sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine("}"); context.AddSource("SQLiteInitializer.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } + + static string FullTypeName (ClassInfo classInfo) + { + return string.IsNullOrEmpty (classInfo.Namespace) + ? classInfo.ClassName + : $"{classInfo.Namespace}.{classInfo.ClassName}"; +} static string? GetRootNamespace(AnalyzerConfigOptionsProvider configOptionsProvider, Compilation compilation) { diff --git a/tests/SQLite.Tests/SQLite.Tests.csproj b/tests/SQLite.Tests/SQLite.Tests.csproj index f46fb8c9..7404f0bf 100644 --- a/tests/SQLite.Tests/SQLite.Tests.csproj +++ b/tests/SQLite.Tests/SQLite.Tests.csproj @@ -10,7 +10,7 @@ - + From 49903140a7d8d138ca786a070a898492c1bc7ad2 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 14:19:17 +0200 Subject: [PATCH 88/91] avoid duplicate initializations --- .../SQLiteFastColumnSetterGenerator.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 26137aa6..2257313f 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -335,7 +335,9 @@ static void Execute( { if (classes.IsDefaultOrEmpty) return; - + + classes = RemoveDuplicates(classes); + // Get the assembly name/namespace from the compilation var assemblyName = compilation.AssemblyName ?? "Generated"; var rootNamespace = GetRootNamespace(configOptionsProvider, compilation) ?? assemblyName; @@ -393,6 +395,25 @@ static void Execute( context.AddSource("SQLiteInitializer.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } + private static ImmutableArray RemoveDuplicates (ImmutableArray classes) + { + Dictionary existing = new(); + + foreach (var it in classes) { + var fullTypeName = FullTypeName (it); + if (existing.TryGetValue (fullTypeName, out var current)) { + if (it.Properties.Count > current.Properties.Count) { + existing[fullTypeName] = it; + } + } + else { + existing[fullTypeName] = it; + } + } + + return existing.Values.ToImmutableArray(); + } + static string FullTypeName (ClassInfo classInfo) { return string.IsNullOrEmpty (classInfo.Namespace) From 7b17f267c86f254d0d44eb03e75c8757a7cf892d Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 14:35:10 +0200 Subject: [PATCH 89/91] added partial test --- tests/SQLite.Tests/SourceGeneratorTest.cs | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/SQLite.Tests/SourceGeneratorTest.cs b/tests/SQLite.Tests/SourceGeneratorTest.cs index 86c2a52a..377942ca 100644 --- a/tests/SQLite.Tests/SourceGeneratorTest.cs +++ b/tests/SQLite.Tests/SourceGeneratorTest.cs @@ -73,6 +73,19 @@ public class IntTest : BaseTest { } + + public partial class PartialTest + { + [PrimaryKey] + public string Id { get; set; } + } + + public partial class PartialTest + { + [Column ("Test")] + public string Test { get; set; } + } + public class BaseTest { [PrimaryKey] @@ -208,6 +221,28 @@ public void SqliteInitializer_StringTestSetter () } } + [Test] + public void SqliteInitializer_PartialTestSetter () + { + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (PartialTest), nameof (PartialTest.Id)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + + [Test] + public void SqliteInitializer_PartialTestSetter_Test() + { + if (SQLite.FastColumnSetter.customSetter.TryGetValue ((typeof (PartialTest), nameof (PartialTest.Test)), out var setter)) { + Assert.IsTrue (true, "Should be registered"); + } + else { + Assert.Fail ("Should be registered"); + } + } + [Test] public void SqliteInitializer_IntTestSetter () { From 0f37b3444c3b046fb37c67b65aa2fbbc33143375 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 14:52:01 +0200 Subject: [PATCH 90/91] make new classes variable --- .../SQLiteFastColumnSetterGenerator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index 2257313f..f64cd111 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -329,14 +329,14 @@ static string GetColumnName(IPropertySymbol property) static void Execute( Compilation compilation, - ImmutableArray classes, + ImmutableArray classesDuplicates, AnalyzerConfigOptionsProvider configOptionsProvider, SourceProductionContext context) { - if (classes.IsDefaultOrEmpty) + if (classesDuplicates.IsDefaultOrEmpty) return; - classes = RemoveDuplicates(classes); + var classes = RemoveDuplicates(classesDuplicates); // Get the assembly name/namespace from the compilation var assemblyName = compilation.AssemblyName ?? "Generated"; From cd232354a52ede174cac032afda4cae30460c780 Mon Sep 17 00:00:00 2001 From: inforithmics Date: Mon, 22 Sep 2025 14:59:41 +0200 Subject: [PATCH 91/91] making class initializers private --- .../SQLiteFastColumnSetterGenerator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs index f64cd111..4985a350 100644 --- a/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs +++ b/nuget/Sqlite_net.SourceGenerator/SQLiteFastColumnSetterGenerator.cs @@ -377,7 +377,8 @@ static void Execute( foreach (var classInfo in classes) { var fullTypeName = FullTypeName (classInfo); var initName = "Init" + fullTypeName.Replace (".", "_"); - sb.AppendLine($" public static void {initName}()"); + sb.AppendLine($" /// Init SQLite Fast Column Setters for {fullTypeName}"); + sb.AppendLine($" private static void {initName}()"); sb.AppendLine(" {"); foreach (var property in classInfo.Properties) { sb.AppendLine($" SQLiteConnection.RegisterFastColumnSetter(");