From 7bcfe7e8b0158345918489b3a0103b6321b5156d Mon Sep 17 00:00:00 2001 From: gilzoide Date: Sat, 28 Jun 2025 13:57:34 -0300 Subject: [PATCH 1/2] Add ".sql" scripted importers There are two importers: the default one imports SQL files as TextAssets, the other one imports them as SQLiteAssets --- CHANGELOG.md | 2 + Editor/SQLAssetDatabaseImporter.cs | 56 +++++++++++++++++++++++++ Editor/SQLAssetDatabaseImporter.cs.meta | 11 +++++ Editor/SQLAssetTextImporter.cs | 39 +++++++++++++++++ Editor/SQLAssetTextImporter.cs.meta | 11 +++++ README.md | 1 + Runtime/SQLiteConnectionExtensions.cs | 9 ++++ Runtime/SQLiteExtensions.cs | 3 ++ 8 files changed, 132 insertions(+) create mode 100644 Editor/SQLAssetDatabaseImporter.cs create mode 100644 Editor/SQLAssetDatabaseImporter.cs.meta create mode 100644 Editor/SQLAssetTextImporter.cs create mode 100644 Editor/SQLAssetTextImporter.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 8afe488..6b8be6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ ".csv" files can be imported as SQLite database assets by changing the importer to `SQLite.Editor.Csv.SQLiteAssetCsvImporter` in the Inspector. - `SQLiteConnection.SerializeToAsset` extension method for serializing a database to an instance of `SQLiteAsset`. - `SQLiteConnection.ImportCsvToTable` extension method for importing a CSV text stream as a new table inside the database. +- Support for importing ".sql" files as either a `TextAsset` or a `SQLiteAsset`. +- `SQLiteConnection.Exec` extension method for executing a SQL script with multiple statements with a single call. ### Changed - Update SQLite to 3.50.1 diff --git a/Editor/SQLAssetDatabaseImporter.cs b/Editor/SQLAssetDatabaseImporter.cs new file mode 100644 index 0000000..69590fb --- /dev/null +++ b/Editor/SQLAssetDatabaseImporter.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Gil Barbosa Reis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +using System.IO; +using UnityEditor.AssetImporters; +using UnityEngine; + +namespace SQLite.Editor +{ + [ScriptedImporter(0, null, new[] { "sql" })] + public class SQLAssetDatabaseImporter : ScriptedImporter + { + [Header("SQLite asset options")] + [Tooltip("Flags controlling how the SQLite connection should be opened. 'ReadWrite' and 'Create' flags will be ignored, since SQLite assets are read-only.")] + [SerializeField] private SQLiteOpenFlags _openFlags = SQLiteOpenFlags.ReadOnly; + + [Tooltip("Whether to store DateTime properties as ticks (true) or strings (false).")] + [SerializeField] private bool _storeDateTimeAsTicks = true; + + [Tooltip("Name of the file created for the database inside Streaming Assets folder during builds.\n\n" + + "If empty, the database bytes will be stored in the asset itself.\n\n" + + "Loading databases from Streaming Assets is not supported in Android and WebGL platforms.")] + [SerializeField] private string _streamingAssetsPath; + + public override void OnImportAsset(AssetImportContext ctx) + { + SQLiteAsset asset; + using (var tempDb = new SQLiteConnection("")) + { + string contents = File.ReadAllText(assetPath); + tempDb.ExecuteScript(contents); + asset = tempDb.SerializeToAsset(null, _openFlags, _storeDateTimeAsTicks, _streamingAssetsPath); + } + ctx.AddObjectToAsset("main", asset); + ctx.SetMainObject(asset); + } + } +} diff --git a/Editor/SQLAssetDatabaseImporter.cs.meta b/Editor/SQLAssetDatabaseImporter.cs.meta new file mode 100644 index 0000000..88cfbc2 --- /dev/null +++ b/Editor/SQLAssetDatabaseImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73f952aa6f2394d23a56915dfa8295a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/SQLAssetTextImporter.cs b/Editor/SQLAssetTextImporter.cs new file mode 100644 index 0000000..0bffbc5 --- /dev/null +++ b/Editor/SQLAssetTextImporter.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Gil Barbosa Reis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +using System.IO; +using UnityEditor.AssetImporters; +using UnityEngine; + +namespace SQLite.Editor +{ + [ScriptedImporter(0, "sql")] + public class SQLAssetTextImporter : ScriptedImporter + { + public override void OnImportAsset(AssetImportContext ctx) + { + string contents = File.ReadAllText(assetPath); + TextAsset asset = new(contents); + ctx.AddObjectToAsset("main", asset); + ctx.SetMainObject(asset); + } + } +} diff --git a/Editor/SQLAssetTextImporter.cs.meta b/Editor/SQLAssetTextImporter.cs.meta new file mode 100644 index 0000000..3ff1197 --- /dev/null +++ b/Editor/SQLAssetTextImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba03993677dd740da91b9a13653538e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md index c589291..b7f9f1e 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ This package provides the excelent [SQLite-net](https://github.com/praeclarum/sq - [SQLiteAsset](Runtime/SQLiteAsset.cs): read-only SQLite database Unity assets. + Files with the extensions ".sqlite", ".sqlite2" and ".sqlite3" will be imported as SQLite database assets. + ".csv" files can be imported as SQLite database assets by changing the importer to `SQLite.Editor.Csv.SQLiteAssetCsvImporter` in the Inspector. + + ".sql" files are imported as Text assets by default, but can be imported as SQLite database assets by changing the importer to `SQLite.Editor.SQLAssetDatabaseImporter`. + Use the `CreateConnection()` method for connecting to the database provided by the asset. Make sure to `Dispose()` of any connections you create. + SQLite assets may be loaded from Streaming Assets folder or from memory, depending on the value of their "Streaming Assets Path" property. diff --git a/Runtime/SQLiteConnectionExtensions.cs b/Runtime/SQLiteConnectionExtensions.cs index 0d1b812..025859a 100644 --- a/Runtime/SQLiteConnectionExtensions.cs +++ b/Runtime/SQLiteConnectionExtensions.cs @@ -117,6 +117,15 @@ public static SQLiteConnection Deserialize(this SQLiteConnection db, ReadOnlySpa return db; } + public static void ExecuteScript(this SQLiteConnection db, string sql) + { + SQLite3.Result result = SQLite3.Exec(db.Handle, sql, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + if (result != SQLite3.Result.OK) + { + throw SQLiteException.New(result, SQLite3.GetErrmsg(db.Handle)); + } + } + /// /// Import a CSV data stream into the table named inside the database. /// The table will be created if it doesn't exist yet. diff --git a/Runtime/SQLiteExtensions.cs b/Runtime/SQLiteExtensions.cs index 56bc6fc..be6bc3b 100644 --- a/Runtime/SQLiteExtensions.cs +++ b/Runtime/SQLiteExtensions.cs @@ -69,6 +69,9 @@ public enum DeserializeFlags : uint [DllImport(LibraryPath, EntryPoint = "sqlite3_column_bytes16", CallingConvention = CallingConvention.Cdecl)] public static extern int ColumnBytes16(IntPtr stmt, int index); + [DllImport(LibraryPath, EntryPoint = "sqlite3_exec", CallingConvention = CallingConvention.Cdecl)] + public static extern Result Exec(IntPtr db, [MarshalAs(UnmanagedType.LPStr)] string sql, IntPtr callback, IntPtr userdata, IntPtr errorMessagePtr); + #if UNITY_WEBGL && !UNITY_EDITOR [DllImport(LibraryPath, CallingConvention = CallingConvention.Cdecl)] public static extern int idbvfs_register(int makeDefault); From d3025c9f255e7fdae206323b81a2e90bd2e827e4 Mon Sep 17 00:00:00 2001 From: gilzoide Date: Sat, 28 Jun 2025 13:59:40 -0300 Subject: [PATCH 2/2] Fix CHANGELOG [skip ci] --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b8be6c..fe596d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - `SQLiteConnection.SerializeToAsset` extension method for serializing a database to an instance of `SQLiteAsset`. - `SQLiteConnection.ImportCsvToTable` extension method for importing a CSV text stream as a new table inside the database. - Support for importing ".sql" files as either a `TextAsset` or a `SQLiteAsset`. -- `SQLiteConnection.Exec` extension method for executing a SQL script with multiple statements with a single call. +- `SQLiteConnection.ExecuteScript` extension method for executing a SQL script with multiple statements with a single call. ### Changed - Update SQLite to 3.50.1