aboutsummaryrefslogtreecommitdiff
path: root/lib/sql-providers
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sql-providers')
-rw-r--r--lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/README.md17
-rw-r--r--lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/build.readme.md0
-rw-r--r--lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/MYSqlExport.cs138
-rw-r--r--lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/VNLib.Plugins.Extensions.Loading.Sql.MYSql.csproj59
-rw-r--r--lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/README.md17
-rw-r--r--lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/build.readme.md0
-rw-r--r--lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/SQLiteExport.cs131
-rw-r--r--lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/VNLib.Plugins.Extensions.Loading.Sql.SQLite.csproj59
-rw-r--r--lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/README.md17
-rw-r--r--lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/build.readme.md0
-rw-r--r--lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/SqlServerExport.cs149
-rw-r--r--lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/VNLib.Plugins.Extensions.Loading.Sql.SQLServer.csproj59
12 files changed, 646 insertions, 0 deletions
diff --git a/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/README.md b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/README.md
new file mode 100644
index 0000000..2823281
--- /dev/null
+++ b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/README.md
@@ -0,0 +1,17 @@
+# VNLib.Plugins.Extensions.Sql.MySql
+*A runtime asset library that provides access to MySql database features for plugins that are configured to load the provider*
+
+**This library contains 3rd-party dependencies**
+
+## Builds
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below).
+
+## Docs and Guides
+Documentation, specifications, and setup guides are available on my website.
+
+[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_vnlib.plugins.Extensions.Sql.MySql)
+[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Plugins.Extensions)
+[Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules)
+
+## License
+Source files in for this project are licensed to you under the GNU Affero General Public License (or any later version). See the LICENSE files for more information. \ No newline at end of file
diff --git a/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/build.readme.md b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/build.readme.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/build.readme.md
diff --git a/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/MYSqlExport.cs b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/MYSqlExport.cs
new file mode 100644
index 0000000..26fd3a3
--- /dev/null
+++ b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/MYSqlExport.cs
@@ -0,0 +1,138 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Extensions.Loading.Sql.Mysql
+* File: MySqlExport.cs
+*
+* MySqlExport.cs is part of VNLib.Plugins.Extensions.Loading.Sql which
+* is part of the larger VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Extensions.Loading.Sql is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* VNLib.Plugins.Extensions.Loading.Sql is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see https://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Text.Json;
+using System.Data.Common;
+using System.Threading.Tasks;
+
+using Microsoft.EntityFrameworkCore;
+
+using MySql.Data.MySqlClient;
+
+using VNLib.Utils.Logging;
+using VNLib.Plugins.Extensions.Loading;
+
+namespace VNLib.Plugins.Extensions.Sql
+{
+
+ [ServiceExport]
+ [ConfigurationName("sql", Required = true)]
+ public sealed class MySqlExport(PluginBase plugin, IConfigScope config)
+ {
+ private async Task<string> BuildConnStringAsync()
+ {
+ //See if the user suggested a raw connection string
+ if (config.TryGetProperty("connection_string", ps => ps.GetString(), out string? conString))
+ {
+ return conString!;
+ }
+ else if (config.TryGetValue("json", out JsonElement value))
+ {
+ JsonSerializerOptions opt = new(JsonSerializerDefaults.General)
+ {
+ AllowTrailingCommas = true,
+ IgnoreReadOnlyFields = true,
+ DictionaryKeyPolicy = JsonNamingPolicy.SnakeCaseLower,
+ };
+
+ MySqlConnectionStringBuilder b = value.Deserialize<MySqlConnectionStringBuilder>(opt)!;
+
+ //Get the password from the secret manager
+ using ISecretResult? secret = await plugin.TryGetSecretAsync("db_password");
+
+ b.Password = secret?.Result.ToString();
+ return b.ConnectionString;
+ }
+ else
+ {
+ //Get the password from the secret manager
+ using ISecretResult? secret = await plugin.TryGetSecretAsync("db_password");
+
+ // Build connection strin
+ return new MySqlConnectionStringBuilder()
+ {
+ Server = config["hostname"].GetString(),
+ Database = config["catalog"].GetString(),
+ UserID = config["username"].GetString(),
+ Pooling = true,
+ MinimumPoolSize = config.GetValueOrDefault("min_pool_size", p => p.GetUInt32(), 10u),
+ MaximumPoolSize = config.GetValueOrDefault("max_pool_size", p => p.GetUInt32(), 50u),
+ AllowBatch = config.GetValueOrDefault("allow_batch", p => p.GetBoolean(), true),
+ ConnectionLifeTime = config.GetValueOrDefault("connection_lifetime", p => p.GetUInt32(), 0u),
+ ConnectionTimeout = config.GetValueOrDefault("connection_timeout", p => p.GetUInt32(), 15u),
+ Port = config.GetValueOrDefault("port", p => p.GetUInt32(), 3306u),
+ PipeName = config.GetValueOrDefault("pipe_name", p => p.GetString(), null),
+ AllowLoadLocalInfile = config.GetValueOrDefault("allow_load_local_infile", p => p.GetBoolean(), false),
+ AllowLoadLocalInfileInPath = config.GetValueOrDefault("allow_load_local_infile_in_path", p => p.GetString(), null),
+
+ Password = secret?.Result.ToString(),
+ }
+ .ConnectionString;
+ }
+ }
+
+ /*
+ * NOTICE:
+ * Function names must be public and must match the SqlConnectionLoader delegate names.
+ *
+ * GetDbConnection - A sync or async function that takes a configuration scope and
+ * returns a DbConnection factory
+ *
+ * GetDbOptions - A sync or async function that takes a configuration scope and
+ * returns a DbConnectionOptions instance
+ *
+ * GetProviderName - Returns a string that is the provider name for the connection
+ */
+
+ public string GetProviderName() => "mysql";
+
+ public async Task<Func<DbConnection>> GetDbConnectionAsync(IConfigScope sqlConfig)
+ {
+ //Store local copy of the connection string, probably not the best idea because of the password, but best for now
+ string connString = await BuildConnStringAsync();
+
+ return () => new MySqlConnection(connString);
+ }
+
+ public async Task<DbContextOptions> GetDbOptionsAsync(IConfigScope sqlConfig)
+ {
+ //Get the connection string from the configuration
+ string connString = await BuildConnStringAsync();
+
+ //Build the options using the mysql extension method
+ DbContextOptionsBuilder b = new();
+ b.UseMySQL(connString);
+
+ //Write debug loggin to the debug log if the user has it enabled or the plugin is in debug mode
+ if (sqlConfig.GetValueOrDefault("debug", p => p.GetBoolean(), false) || plugin.IsDebug())
+ {
+ //Write the SQL to the debug log
+ b.LogTo((v) => plugin.Log.Debug("MySql: {v}", v));
+ }
+
+ return b.Options;
+ }
+ }
+}
diff --git a/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/VNLib.Plugins.Extensions.Loading.Sql.MYSql.csproj b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/VNLib.Plugins.Extensions.Loading.Sql.MYSql.csproj
new file mode 100644
index 0000000..dcb4a5c
--- /dev/null
+++ b/lib/sql-providers/mysql/VNLib.Plugins.Extensions.Loading.Sql.MySql/src/VNLib.Plugins.Extensions.Loading.Sql.MYSql.csproj
@@ -0,0 +1,59 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net8.0</TargetFramework>
+ <AssemblyName>VNLib.Plugins.Extensions.Sql.MySql</AssemblyName>
+ <RootNamespace>VNLib.Plugins.Extensions.Sql</RootNamespace>
+ <Nullable>enable</Nullable>
+ <ImplicitUsings>disable</ImplicitUsings>
+ <GenerateDocumentationFile>True</GenerateDocumentationFile>
+ <!--Enable dynamic loading-->
+ <EnableDynamicLoading>true</EnableDynamicLoading>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <PackageId>VNLib.Plugins.Extensions.Sql.MySql</PackageId>
+ <Authors>Vaughn Nugent</Authors>
+ <Company>Vaughn Nugent</Company>
+ <Product>VNLib.Plugins.Extensions.Sql.MySql</Product>
+ <Copyright>Copyright © 2024 Vaughn Nugent</Copyright>
+ <PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Plugins.Extensions</PackageProjectUrl>
+ <RepositoryUrl>https://github.com/VnUgE/VNLib.Plugins.Extensions/tree/master/lib/sql-providers/VNLib.Plugins.Extensions.Sql.MySql</RepositoryUrl>
+ <Description>A runtime asset library that provides MySql interfaces for ADO and EFCore SQL server clients</Description>
+ <PackageReadmeFile>README.md</PackageReadmeFile>
+ <PackageLicenseFile>LICENSE</PackageLicenseFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <None Include="../../../../../LICENSE">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Include="..\README.md">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ </None>
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="ErrorProne.NET.Structs" Version="0.1.2">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="MySql.EntityFrameworkCore" Version="8.0.0" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\..\VNLib.Plugins.Extensions.Loading\src\VNLib.Plugins.Extensions.Loading.csproj" />
+ </ItemGroup>
+
+ <Target Condition="'$(BuildingInsideVisualStudio)' == true" Name="PostBuild" AfterTargets="PostBuildEvent">
+ <Exec Command="start xcopy &quot;$(TargetDir)&quot; &quot;$(SolutionDir)devplugins\RuntimeAssets\$(TargetName)&quot; /E /Y /R" />
+ </Target>
+
+</Project>
diff --git a/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/README.md b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/README.md
new file mode 100644
index 0000000..abf236f
--- /dev/null
+++ b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/README.md
@@ -0,0 +1,17 @@
+# VNLib.Plugins.Extensions.Sql.SQLite
+*A runtime asset library that provides access to SQLite database features for plugins that are configured to load the provider*
+
+**This library contains 3rd-party dependencies**
+
+## Builds
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below).
+
+## Docs and Guides
+Documentation, specifications, and setup guides are available on my website.
+
+[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_vnlib.plugins.Extensions.Sql.SQLite)
+[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Plugins.Extensions)
+[Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules)
+
+## License
+Source files in for this project are licensed to you under the GNU Affero General Public License (or any later version). See the LICENSE files for more information. \ No newline at end of file
diff --git a/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/build.readme.md b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/build.readme.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/build.readme.md
diff --git a/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/SQLiteExport.cs b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/SQLiteExport.cs
new file mode 100644
index 0000000..6f9455a
--- /dev/null
+++ b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/SQLiteExport.cs
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Extensions.Loading.Sql.SQLite
+* File: SQLiteExport.cs
+*
+* SQLiteExport.cs is part of VNLib.Plugins.Extensions.Loading.Sql.SQLite which
+* is part of the larger VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Extensions.Loading.Sql is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* VNLib.Plugins.Extensions.Loading.Sql is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see https://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Text.Json;
+using System.Data.Common;
+using System.Threading.Tasks;
+
+using Microsoft.EntityFrameworkCore;
+
+using Microsoft.Data.Sqlite;
+
+using VNLib.Utils.Logging;
+using VNLib.Plugins.Extensions.Loading;
+
+namespace VNLib.Plugins.Extensions.Sql
+{
+
+ [ServiceExport]
+ [ConfigurationName("sql", Required = true)]
+ public sealed class SQLiteExport(PluginBase plugin, IConfigScope config)
+ {
+
+ private async Task<string> BuildConnStringAsync()
+ {
+ //See if the user suggested a raw connection string
+ if (config.TryGetProperty("connection_string", ps => ps.GetString(), out string? conString))
+ {
+ return conString!;
+ }
+ else if (config.TryGetValue("json", out JsonElement value))
+ {
+ JsonSerializerOptions opt = new(JsonSerializerDefaults.General)
+ {
+ AllowTrailingCommas = true,
+ IgnoreReadOnlyFields = true,
+ DictionaryKeyPolicy = JsonNamingPolicy.SnakeCaseLower,
+ };
+
+ SqliteConnectionStringBuilder b = value.Deserialize<SqliteConnectionStringBuilder>(opt)!;
+
+ //Get the password from the secret manager
+ using ISecretResult? secret = await plugin.TryGetSecretAsync("db_password");
+
+ b.Password = secret?.Result.ToString();
+ return b.ConnectionString;
+ }
+ else
+ {
+ //Get the password from the secret manager
+ using ISecretResult? secret = await plugin.TryGetSecretAsync("db_password");
+
+ // Build connection strin
+ return new SqliteConnectionStringBuilder()
+ {
+ DataSource = config["source"].GetString(),
+ Pooling = true,
+ Cache = SqliteCacheMode.Default,
+ RecursiveTriggers = config.GetValueOrDefault("recursive_triggers", p => p.GetBoolean(), false),
+ DefaultTimeout = config.GetValueOrDefault("timeout", p => p.GetInt32(), 30),
+ Mode = config.GetValueOrDefault("mode", p => (SqliteOpenMode)p.GetInt32(), SqliteOpenMode.ReadWriteCreate),
+
+ Password = secret?.Result.ToString(),
+ }
+ .ConnectionString;
+ }
+ }
+
+ /*
+ * NOTICE:
+ * Function names must be public and must match the SqlConnectionLoader delegate names.
+ *
+ * GetDbConnection - A sync or async function that takes a configuration scope and
+ * returns a DbConnection factory
+ *
+ * GetDbOptions - A sync or async function that takes a configuration scope and
+ * returns a DbConnectionOptions instance
+ *
+ * GetProviderName - Returns a string that is the provider name for the connection
+ */
+
+ public string GetProviderName() => "sqlite"; //Use default handler for sqlite db creation
+
+ public async Task<Func<DbConnection>> GetDbConnectionAsync(IConfigScope sqlConfig)
+ {
+ //Store local copy of the connection string, probably not the best idea because of the password, but best for now
+ string connString = await BuildConnStringAsync();
+
+ return () => new SqliteConnection(connString);
+ }
+
+ public async Task<DbContextOptions> GetDbOptionsAsync(IConfigScope sqlConfig)
+ {
+ //Get the connection string from the configuration
+ string connString = await BuildConnStringAsync();
+
+ DbContextOptionsBuilder b = new();
+ b.UseSqlite(connString);
+
+ //Write debug loggin to the debug log if the user has it enabled or the plugin is in debug mode
+ if (sqlConfig.GetValueOrDefault("debug", p => p.GetBoolean(), false) || plugin.IsDebug())
+ {
+ //Write the SQL to the debug log
+ b.LogTo((v) => plugin.Log.Debug("SQLite: {v}", v));
+ }
+
+ return b.Options;
+ }
+ }
+}
diff --git a/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/VNLib.Plugins.Extensions.Loading.Sql.SQLite.csproj b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/VNLib.Plugins.Extensions.Loading.Sql.SQLite.csproj
new file mode 100644
index 0000000..b61f523
--- /dev/null
+++ b/lib/sql-providers/sqlite/VNLib.Plugins.Extensions.Loading.Sql.SQLite/src/VNLib.Plugins.Extensions.Loading.Sql.SQLite.csproj
@@ -0,0 +1,59 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net8.0</TargetFramework>
+ <AssemblyName>VNLib.Plugins.Extensions.Sql.SQLite</AssemblyName>
+ <RootNamespace>VNLib.Plugins.Extensions.Sql</RootNamespace>
+ <Nullable>enable</Nullable>
+ <ImplicitUsings>disable</ImplicitUsings>
+ <GenerateDocumentationFile>True</GenerateDocumentationFile>
+ <!--Enable dynamic loading-->
+ <EnableDynamicLoading>true</EnableDynamicLoading>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <PackageId>VNLib.Plugins.Extensions.Sql.SQLite</PackageId>
+ <Authors>Vaughn Nugent</Authors>
+ <Company>Vaughn Nugent</Company>
+ <Product>VNLib.Plugins.Extensions.Sql.SQLite</Product>
+ <Copyright>Copyright © 2024 Vaughn Nugent</Copyright>
+ <PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Plugins.Extensions</PackageProjectUrl>
+ <RepositoryUrl>https://github.com/VnUgE/VNLib.Plugins.Extensions/tree/master/lib/sql-providers/VNLib.Plugins.Extensions.Sql.SQLite</RepositoryUrl>
+ <Description>A runtime asset library that provides SQLite interfaces for ADO and EFCore SQL server clients</Description>
+ <PackageReadmeFile>README.md</PackageReadmeFile>
+ <PackageLicenseFile>LICENSE</PackageLicenseFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <None Include="../../../../../LICENSE">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Include="..\README.md">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ </None>
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="ErrorProne.NET.Structs" Version="0.1.2">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\..\VNLib.Plugins.Extensions.Loading\src\VNLib.Plugins.Extensions.Loading.csproj" />
+ </ItemGroup>
+
+ <Target Condition="'$(BuildingInsideVisualStudio)' == true" Name="PostBuild" AfterTargets="PostBuildEvent">
+ <Exec Command="start xcopy &quot;$(TargetDir)&quot; &quot;$(SolutionDir)devplugins\RuntimeAssets\$(TargetName)&quot; /E /Y /R" />
+ </Target>
+
+</Project>
diff --git a/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/README.md b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/README.md
new file mode 100644
index 0000000..89662e7
--- /dev/null
+++ b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/README.md
@@ -0,0 +1,17 @@
+# VNLib.Plugins.Extensions.Sql.SqlServer
+*A runtime asset library that provides access to SqlServer database features for plugins that are configured to load the provider*
+
+**This library contains 3rd-party dependencies**
+
+## Builds
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below).
+
+## Docs and Guides
+Documentation, specifications, and setup guides are available on my website.
+
+[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_vnlib.plugins.Extensions.Sql.SqlServer)
+[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Plugins.Extensions)
+[Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules)
+
+## License
+Source files in for this project are licensed to you under the GNU Affero General Public License (or any later version). See the LICENSE files for more information. \ No newline at end of file
diff --git a/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/build.readme.md b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/build.readme.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/build.readme.md
diff --git a/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/SqlServerExport.cs b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/SqlServerExport.cs
new file mode 100644
index 0000000..71f16bf
--- /dev/null
+++ b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/SqlServerExport.cs
@@ -0,0 +1,149 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Extensions.Loading.Sql.SQLServer
+* File: SQLServerExport.cs
+*
+* SQLServerExport.cs is part of VNLib.Plugins.Extensions.Loading.Sql.SQLServer which
+* is part of the larger VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Extensions.Loading.Sql is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* VNLib.Plugins.Extensions.Loading.Sql is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see https://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Text.Json;
+using System.Data.Common;
+using System.Threading.Tasks;
+
+using Microsoft.Data.SqlClient;
+
+using Microsoft.EntityFrameworkCore;
+
+using VNLib.Utils.Logging;
+using VNLib.Plugins.Extensions.Loading;
+
+namespace VNLib.Plugins.Extensions.Sql
+{
+
+ [ServiceExport]
+ [ConfigurationName("sql", Required = true)]
+ public sealed class SqlServerExport(PluginBase plugin, IConfigScope config)
+ {
+ private async Task<string> BuildConnStringAsync()
+ {
+ //See if the user suggested a raw connection string
+ if (config.TryGetProperty("connection_string", ps => ps.GetString(), out string? conString))
+ {
+ return conString!;
+ }
+ else if (config.TryGetValue("json", out JsonElement value))
+ {
+ JsonSerializerOptions opt = new(JsonSerializerDefaults.General)
+ {
+ AllowTrailingCommas = true,
+ IgnoreReadOnlyFields = true,
+ DictionaryKeyPolicy = JsonNamingPolicy.SnakeCaseLower,
+ };
+
+ SqlConnectionStringBuilder b = value.Deserialize<SqlConnectionStringBuilder>(opt)!;
+
+ //Get the password from the secret manager
+ using ISecretResult? secret = await plugin.TryGetSecretAsync("db_password");
+
+ b.Password = secret?.Result.ToString();
+ return b.ConnectionString;
+ }
+ else
+ {
+ //Get the password from the secret manager
+ using ISecretResult? secret = await plugin.TryGetSecretAsync("db_password");
+
+ // Build connection string
+ return new SqlConnectionStringBuilder()
+ {
+ DataSource = config["hostname"].GetString(),
+ InitialCatalog = config["catalog"].GetString(),
+ UserID = config["username"].GetString(),
+ Pooling = true,
+
+
+ ApplicationName = config.GetValueOrDefault("application_name", p => p.GetString(), string.Empty),
+ HostNameInCertificate = config.GetValueOrDefault("hostname_in_certificate", p => p.GetString(), string.Empty),
+ PacketSize = config.GetValueOrDefault("packet_size", p => p.GetInt32(), 8000),
+ Encrypt = config.GetValueOrDefault("encrypted", p => p.GetBoolean(), false),
+ IntegratedSecurity = config.GetValueOrDefault("integrated_security", p => p.GetBoolean(), false),
+ MultipleActiveResultSets = config.GetValueOrDefault("multiple_active_result_sets", p => p.GetBoolean(), false),
+ ConnectTimeout = config.GetValueOrDefault("connect_timeout", p => p.GetInt32(), 15),
+ LoadBalanceTimeout = config.GetValueOrDefault("load_balance_timeout", p => p.GetInt32(), 0),
+ MaxPoolSize = config.GetValueOrDefault("max_pool_size", p => p.GetInt32(), 100),
+ MinPoolSize = config.GetValueOrDefault("min_pool_size", p => p.GetInt32(), 0),
+ TransactionBinding = config.GetValueOrDefault("transaction_binding", p => p.GetString(), "Implicit Unbind"),
+ TypeSystemVersion = config.GetValueOrDefault("type_system_version", p => p.GetString(), "Latest"),
+ WorkstationID = config.GetValueOrDefault("workstation_id", p => p.GetString(), string.Empty),
+ CurrentLanguage = config.GetValueOrDefault("current_language", p => p.GetString(), "us_english"),
+ PersistSecurityInfo = config.GetValueOrDefault("persist_security_info", p => p.GetBoolean(), false),
+ Replication = config.GetValueOrDefault("replication", p => p.GetBoolean(), false),
+ TrustServerCertificate = config.GetValueOrDefault("trust_server_certificate", p => p.GetBoolean(), false),
+ UserInstance = config.GetValueOrDefault("user_instance", p => p.GetBoolean(), false),
+
+ Password = secret?.Result.ToString(),
+ }
+ .ConnectionString;
+ }
+ }
+
+ /*
+ * NOTICE:
+ * Function names must be public and must match the SqlConnectionLoader delegate names.
+ *
+ * GetDbConnection - A sync or async function that takes a configuration scope and
+ * returns a DbConnection factory
+ *
+ * GetDbOptions - A sync or async function that takes a configuration scope and
+ * returns a DbConnectionOptions instance
+ *
+ * GetProviderName - Returns a string that is the provider name for the connection
+ */
+
+ public string GetProviderName() => "sqlserver";
+
+ public async Task<Func<DbConnection>> GetDbConnectionAsync(IConfigScope sqlConfig)
+ {
+ //Store local copy of the connection string, probably not the best idea because of the password, but best for now
+ string connString = await BuildConnStringAsync();
+
+ return () => new SqlConnection(connString);
+ }
+
+ public async Task<DbContextOptions> GetDbOptionsAsync(IConfigScope sqlConfig)
+ {
+ //Get the connection string from the configuration
+ string connString = await BuildConnStringAsync();
+
+ //Build the options using the mysql extension method
+ DbContextOptionsBuilder b = new();
+ b.UseSqlServer(connString);
+
+ //Write debug loggin to the debug log if the user has it enabled or the plugin is in debug mode
+ if (sqlConfig.GetValueOrDefault("debug", p => p.GetBoolean(), false) || plugin.IsDebug())
+ {
+ //Write the SQL to the debug log
+ b.LogTo((v) => plugin.Log.Debug("SqlServer: {v}", v));
+ }
+
+ return b.Options;
+ }
+ }
+}
diff --git a/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/VNLib.Plugins.Extensions.Loading.Sql.SQLServer.csproj b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/VNLib.Plugins.Extensions.Loading.Sql.SQLServer.csproj
new file mode 100644
index 0000000..fea8eee
--- /dev/null
+++ b/lib/sql-providers/sqlserver/VNLib.Plugins.Extensions.Loading.Sql.SQLServer/src/VNLib.Plugins.Extensions.Loading.Sql.SQLServer.csproj
@@ -0,0 +1,59 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net8.0</TargetFramework>
+ <AssemblyName>VNLib.Plugins.Extensions.Sql.SqlServer</AssemblyName>
+ <RootNamespace>VNLib.Plugins.Extensions.Sql</RootNamespace>
+ <Nullable>enable</Nullable>
+ <ImplicitUsings>disable</ImplicitUsings>
+ <GenerateDocumentationFile>True</GenerateDocumentationFile>
+ <!--Enable dynamic loading-->
+ <EnableDynamicLoading>true</EnableDynamicLoading>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <PackageId>VNLib.Plugins.Extensions.Sql.SqlServer</PackageId>
+ <Authors>Vaughn Nugent</Authors>
+ <Company>Vaughn Nugent</Company>
+ <Product>VNLib.Plugins.Extensions.Sql.SqlServer</Product>
+ <Copyright>Copyright © 2024 Vaughn Nugent</Copyright>
+ <PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Plugins.Extensions</PackageProjectUrl>
+ <RepositoryUrl>https://github.com/VnUgE/VNLib.Plugins.Extensions/tree/master/lib/sql-providers/VNLib.Plugins.Extensions.Sql.SqlServer</RepositoryUrl>
+ <Description>A runtime asset library that provides SqlServer interfaces for ADO and EFCore SQL server clients</Description>
+ <PackageReadmeFile>README.md</PackageReadmeFile>
+ <PackageLicenseFile>LICENSE</PackageLicenseFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <None Include="../../../../../LICENSE">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Include="..\README.md">
+ <Pack>True</Pack>
+ <PackagePath>\</PackagePath>
+ </None>
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="ErrorProne.NET.Structs" Version="0.1.2">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\..\VNLib.Plugins.Extensions.Loading\src\VNLib.Plugins.Extensions.Loading.csproj" />
+ </ItemGroup>
+
+ <Target Condition="'$(BuildingInsideVisualStudio)' == true" Name="PostBuild" AfterTargets="PostBuildEvent">
+ <Exec Command="start xcopy &quot;$(TargetDir)&quot; &quot;$(SolutionDir)devplugins\RuntimeAssets\$(TargetName)&quot; /E /Y /R" />
+ </Target>
+
+</Project>