Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding ability to configure extensions for Sqlite #428

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

aaronpowell
Copy link
Member

@aaronpowell aaronpowell commented Jan 29, 2025

Adding the ability to specify SQLite extensions that you want to load on the database. Extensions can be shipped as NuGet packages (https://www.nuget.org/packages/mod_spatialite is an example) or you can specify a path to the extension binary (an absolute path).

This is done in the app host and the info is projected as part of the connection string for the client.

In the client library, it'll read the extensions from the connection string (then delete that value so it is a valid connection string) and load the extensions using the SqliteConnection. Since SQLite needs the extension to be in PATH (see this doc) there is a bit of code to ensure the path for the binary is loaded correctly.

I've added some tests for observing that the extension loads, but it's a hard one to write tests for as you have to have a bunch of different binaries checked into the repo (I'd use mod_spatialite but it only ships Windows binaries in the nuget package). Because if this, I've marked the feature as experimental.

This doesn't support the EF SQLite integration as there's no way I can find using the EF API in which you can add extensions, you have to do it manually when the DbContext is created.

@aaronpowell aaronpowell requested a review from Copilot January 29, 2025 23:56
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 5 out of 9 changed files in this pull request and generated 2 comments.

Files not reviewed (4)
  • src/CommunityToolkit.Aspire.Hosting.Sqlite/PublicAPI.Unshipped.txt: Language not supported
  • src/CommunityToolkit.Aspire.Microsoft.Data.Sqlite/PublicAPI.Unshipped.txt: Language not supported
  • src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteResource.cs: Evaluated as low risk
  • src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteResourceBuilderExtensions.cs: Evaluated as low risk

Copy link

github-actions bot commented Feb 3, 2025

Code Coverage

Package Line Rate Branch Rate Complexity Health
CommunityToolkit.Aspire.EventStore 100% 100% 46
CommunityToolkit.Aspire.GoFeatureFlag 100% 97% 74
CommunityToolkit.Aspire.Hosting.ActiveMQ 70% 27% 144
CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit 1% 0% 14
CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder 100% 100% 22
CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps 100% 100% 28
CommunityToolkit.Aspire.Hosting.Bun 81% 71% 54
CommunityToolkit.Aspire.Hosting.Dapr 60% 51% 560
CommunityToolkit.Aspire.Hosting.Dapr.AzureRedis 93% 71% 54
CommunityToolkit.Aspire.Hosting.Deno 84% 75% 72
CommunityToolkit.Aspire.Hosting.EventStore 90% 71% 62
CommunityToolkit.Aspire.Hosting.GoFeatureFlag 59% 11% 62
CommunityToolkit.Aspire.Hosting.Golang 94% 50% 16
CommunityToolkit.Aspire.Hosting.Java 69% 72% 120
CommunityToolkit.Aspire.Hosting.Meilisearch 61% 27% 94
CommunityToolkit.Aspire.Hosting.Ngrok 59% 50% 58
CommunityToolkit.Aspire.Hosting.NodeJS.Extensions 90% 68% 92
CommunityToolkit.Aspire.Hosting.Ollama 65% 64% 198
CommunityToolkit.Aspire.Hosting.PapercutSmtp 92% 50% 10
CommunityToolkit.Aspire.Hosting.Python.Extensions 69% 50% 86
CommunityToolkit.Aspire.Hosting.Rust 94% 83% 16
CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects 74% 61% 114
CommunityToolkit.Aspire.Hosting.Sqlite 96% 96% 50
CommunityToolkit.Aspire.MassTransit.RabbitMQ 100% 100% 30
CommunityToolkit.Aspire.Meilisearch 97% 92% 68
CommunityToolkit.Aspire.Microsoft.Data.Sqlite 39% 27% 194
CommunityToolkit.Aspire.Microsoft.EntityFrameworkCore.Sqlite 51% 50% 92
CommunityToolkit.Aspire.OllamaSharp 87% 82% 68
Summary 72% (4133 / 5758) 56% (1201 / 2140) 2498

Minimum allowed line rate is 60%

Copy link
Member

@Alirexaa Alirexaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aaronpowell, I understand that writing functional tests for this situation is challenging, but I believe we need to proceed with it. For now, we could create tests that run only on Windows, but we should definitely include some functional tests. Additionally, we might want to update the example project to utilize the one extension, which I could then attempt to test locally.

/// <param name="PackageName">The name of the NuGet package. Only required if <paramref name="IsNuGetPackage"/> is <see langword="true" />.</param>
/// <param name="IsNuGetPackage">Indicates if the extension will be loaded from a NuGet package.</param>
/// <param name="ExtensionFolder">The folder for the extension. Only required if <paramref name="IsNuGetPackage"/> is <see langword="false" />.</param>
public record ExtensionMetadata(string Extension, string? PackageName, bool IsNuGetPackage, string? ExtensionFolder);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public record ExtensionMetadata(string Extension, string? PackageName, bool IsNuGetPackage, string? ExtensionFolder);
public record SqliteExtensionMetadata(string Extension, string? PackageName, bool IsNuGetPackage, string? ExtensionFolder);

I prefer SqliteExtensionMetadata to ExtensionMetadata because it prevents feature conflicts (e.g., PostgreSQL extensions like pgvector).

Comment on lines +27 to +34
/// <summary>
/// Represents metadata for an extension to be loaded into a database.
/// </summary>
/// <param name="Extension">The name of the extension binary, eg: vec0</param>
/// <param name="PackageName">The name of the NuGet package. Only required if <paramref name="IsNuGetPackage"/> is <see langword="true" />.</param>
/// <param name="IsNuGetPackage">Indicates if the extension will be loaded from a NuGet package.</param>
/// <param name="ExtensionFolder">The folder for the extension. Only required if <paramref name="IsNuGetPackage"/> is <see langword="false" />.</param>
public record ExtensionMetadata(string Extension, string? PackageName, bool IsNuGetPackage, string? ExtensionFolder);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems duplicate. Can we use a shared file (like dbgate)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah could do

@aaronpowell
Copy link
Member Author

I'll have to think about a functional test because yes, it needs to run on Windows only (which means I can't actually run the tests myself).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants