Skip to content

Commit

Permalink
add sqlite support
Browse files Browse the repository at this point in the history
  • Loading branch information
SockworkOrange committed Oct 17, 2024
1 parent b27064b commit ba3f073
Show file tree
Hide file tree
Showing 25 changed files with 409 additions and 25 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ SOURCE_WASM_FILE="WasmRunner/bin/Release/net8.0/wasi-wasm/AppBundle/WasmRunner.w
TESTS_CONTAINER_NAME="plugin-tests"
MYSQL_CONNECTION_STRING="server=mysqldb;database=tests;user=root"
POSTGRES_CONNECTION_STRING="host=postgresdb;database=tests;username=user;password=pass"
SQLITE_CONNECTION_STRING="Data Source=/app/plugin.db;Mode=ReadWrite"
SQLC_CI_FILE="sqlc.ci.yaml"
12 changes: 7 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
GeneratedProtobuf
MySqlConnectorExample
NpgsqlExample
SqliteExample
- name: Verify pushed Dockerfile is synced
run: |
Expand Down Expand Up @@ -108,6 +109,7 @@ jobs:

steps:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: wasm-file
Expand All @@ -125,6 +127,11 @@ jobs:
- name: Updating plugin sha
run: ./scripts/wasm/update_sha.sh ${SQLC_CI_FILE}

- name: Verify pushed generated code is synced
run: |
./scripts/wasm/update_sha.sh ${SQLC_CI_FILE}
sqlc -f ${SQLC_CI_FILE} diff
- name: Codegen Tests against matrix of configurations
run: ./scripts/tests/run_codegen_matrix.sh ${SQLC_CI_FILE}

Expand All @@ -148,11 +155,6 @@ jobs:
uses: xom9ikk/[email protected]
with:
load-mode: strict

- name: Verify pushed generated code is synced
run: |
./scripts/wasm/update_sha.sh ${SQLC_CI_FILE}
sqlc -f ${SQLC_CI_FILE} diff

- name: Docker compose
uses: hoverkraft-tech/[email protected]
Expand Down
1 change: 1 addition & 0 deletions CodeGenerator/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ private DbDriver InstantiateDriver()
{
DriverName.MySqlConnector => new MySqlConnectorDriver(Options.DotnetFramework),
DriverName.Npgsql => new NpgsqlDriver(Options.DotnetFramework),
DriverName.Sqlite => new SqliteDriver(Options.DotnetFramework),
_ => throw new ArgumentException($"unknown driver: {Options.DriverName}")
};
}
Expand Down
8 changes: 5 additions & 3 deletions CodeGenerator/Generators/CsprojGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public File GenerateFile()

private string GetFileContents()
{
var nullableProperty = options.DotnetFramework.LatestDotnetSupported() ? "\n<Nullable>enable</Nullable>" : "";
var nullableProperty = options.DotnetFramework.LatestDotnetSupported() ? "<Nullable>enable</Nullable>" : "";
return $"""
<!--{Consts.AutoGeneratedComment}-->
<!--Run the following to add the project to the solution:
Expand All @@ -28,12 +28,13 @@ dotnet sln add {projectName}/{projectName}.csproj
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>{options.DotnetFramework.ToName()}</TargetFramework>{nullableProperty}
<TargetFramework>{options.DotnetFramework.ToName()}</TargetFramework>
{nullableProperty}
<OutputType>Library</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="{options.DriverName}" Version="{GetPackageVersion(options.DriverName)}"/>
<PackageReference Include="{options.DriverName.ToName()}" Version="{GetPackageVersion(options.DriverName)}"/>
</ItemGroup>

</Project>
Expand All @@ -46,6 +47,7 @@ private static string GetPackageVersion(DriverName driverName)
{
DriverName.Npgsql => "8.0.3",
DriverName.MySqlConnector => "2.3.6",
DriverName.Sqlite => "8.0.10",
_ => throw new NotSupportedException($"unsupported driver: {driverName}")
};
}
Expand Down
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ COPY MySqlConnectorExample/*.csproj ./MySqlConnectorExample/
COPY NpgsqlExample/*.csproj ./NpgsqlExample/
COPY PluginOptions/*.csproj ./PluginOptions/
COPY SqlcGenCsharp/*.csproj ./SqlcGenCsharp/
COPY SqliteExample/*.csproj ./SqliteExample/
COPY WasmRunner/*.csproj ./WasmRunner/

COPY CodeGenerator/ ./CodeGenerator/
Expand All @@ -26,6 +27,11 @@ COPY MySqlConnectorExample/ ./MySqlConnectorExample/
COPY NpgsqlExample/ ./NpgsqlExample/
COPY PluginOptions/ ./PluginOptions/
COPY SqlcGenCsharp/ ./SqlcGenCsharp/
COPY SqliteExample/ ./SqliteExample/
COPY WasmRunner/ ./WasmRunner/

RUN dotnet restore

RUN apt-get update && apt-get install -y sqlite3
COPY examples/authors/sqlite/schema.sql sqlite_schema.sql
RUN sqlite3 plugin.db < sqlite_schema.sql
72 changes: 72 additions & 0 deletions Drivers/SqliteDriver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Plugin;
using SqlcGenCsharp.Drivers.Generators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace SqlcGenCsharp.Drivers;

public partial class SqliteDriver(DotnetFramework dotnetFramework) : DbDriver(dotnetFramework)
{
protected override List<(string, Func<int, string>, HashSet<string>)> GetColumnMapping()
{
return
[
("byte[]", ordinal => $"Utils.GetBytes(reader, {ordinal})", ["blob"]),
("string", ordinal => $"reader.GetString({ordinal})", ["text"]),
("int", ordinal => $"reader.GetInt32({ordinal})", ["integer"]),
("float", ordinal => $"reader.GetFloat({ordinal})", ["real"]),
];
}

public override UsingDirectiveSyntax[] GetUsingDirectives()
{
return base.GetUsingDirectives()
.Append(UsingDirective(ParseName("Microsoft.Data.Sqlite")))
.Append(UsingDirective(ParseName("System")))
.ToArray();
}

public override (string, string) EstablishConnection(Query query)
{
return (
$"var {Variable.Connection.Name()} = new SqliteConnection({Variable.ConnectionString.Name()})",
$"{Variable.Connection.Name()}.Open()"
);
}

public override string CreateSqlCommand(string sqlTextConstant)
{
return $"var {Variable.Command.Name()} = new SqliteCommand({sqlTextConstant}, {Variable.Connection.Name()})";
}

public override string TransformQueryText(Query query)
{
return query.Params
.Aggregate(query.Text, (current, currentParameter) => BindParameterRegex()
.Replace(current, $"@{currentParameter.Column.Name.FirstCharToLower()}", 1));
}

public override MemberDeclarationSyntax OneDeclare(string queryTextConstant, string argInterface,
string returnInterface, Query query)
{
return new OneDeclareGen(this).Generate(queryTextConstant, argInterface, returnInterface, query);
}

public override MemberDeclarationSyntax ExecDeclare(string queryTextConstant, string argInterface, Query query)
{
return new ExecDeclareGen(this).Generate(queryTextConstant, argInterface, query);
}

public override MemberDeclarationSyntax ManyDeclare(string queryTextConstant, string argInterface,
string returnInterface, Query query)
{
return new ManyDeclareGen(this).Generate(queryTextConstant, argInterface, returnInterface, query);
}

[GeneratedRegex(@"\?")]
private static partial Regex BindParameterRegex();
}
1 change: 1 addition & 0 deletions EndToEndTests/EndToEndTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\MySqlConnectorExample\MySqlConnectorExample.csproj"/>
<ProjectReference Include="..\NpgsqlExample\NpgsqlExample.csproj"/>
<ProjectReference Include="..\SqliteExample\SqliteExample.csproj" />
</ItemGroup>

</Project>
80 changes: 80 additions & 0 deletions EndToEndTests/SqliteTester.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using NUnit.Framework;
using NUnit.Framework.Legacy;
using SqliteExample;
using System;
using System.Threading.Tasks;

namespace SqlcGenCsharpTests;

public class SqliteTester : SqlDriverTester
{
private static string ConnectionStringEnv => "SQLITE_CONNECTION_STRING";

private QuerySql QuerySql { get; } =
new(Environment.GetEnvironmentVariable(ConnectionStringEnv)!);

protected override async Task<long> CreateFirstAuthorAndTest()
{
var createAuthorArgs = new QuerySql.CreateAuthorArgs
{
Name = DataGenerator.BojackAuthor,
Bio = DataGenerator.BojackTheme
};
await QuerySql.CreateAuthor(createAuthorArgs);

var actualAuthors = await QuerySql.ListAuthors();
Assert.That(actualAuthors[0] is
{
Id: 1,
Name: DataGenerator.BojackAuthor,
Bio: DataGenerator.BojackTheme
});
var insertedId = actualAuthors[0].Id;
var getBojackAuthorArgs = new QuerySql.GetAuthorArgs { Id = insertedId };
var bojackAuthor = await QuerySql.GetAuthor(getBojackAuthorArgs);
Assert.That(bojackAuthor is
{
Name: DataGenerator.BojackAuthor,
Bio: DataGenerator.BojackTheme
});
return insertedId;
}

protected override async Task CreateSecondAuthorAndTest()
{
var createAuthorArgs = new QuerySql.CreateAuthorArgs
{
Name = DataGenerator.DrSeussAuthor,
Bio = DataGenerator.DrSeussQuote
};
await QuerySql.CreateAuthor(createAuthorArgs);
var actualAuthors = await QuerySql.ListAuthors();
Assert.That(actualAuthors[0] is
{
Name: DataGenerator.BojackAuthor,
Bio: DataGenerator.BojackTheme
});
Assert.That(actualAuthors[1] is
{
Name: DataGenerator.DrSeussAuthor,
Bio: DataGenerator.DrSeussQuote
});
ClassicAssert.AreEqual(2, actualAuthors.Count);
}

protected override async Task DeleteFirstAuthorAndTest(long idToDelete)
{
var deleteAuthorArgs = new QuerySql.DeleteAuthorArgs
{
Id = Convert.ToInt32(idToDelete)
};
await QuerySql.DeleteAuthor(deleteAuthorArgs);
var authorRows = await QuerySql.ListAuthors();
Assert.That(authorRows[0] is
{
Name: DataGenerator.DrSeussAuthor,
Bio: DataGenerator.DrSeussQuote
});
ClassicAssert.AreEqual(1, authorRows.Count);
}
}
7 changes: 7 additions & 0 deletions EndToEndTests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,11 @@ public async Task TestFlowOnPostgres()
await tester.TestBasicFlow();
await tester.TestCopyFlow();
}

[Test]
public async Task TestFlowOnSqlite()
{
var tester = new SqliteTester();
await tester.TestBasicFlow();
}
}
9 changes: 5 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ dotnet-format:
dotnet format \
--exclude GeneratedProtobuf \
--exclude MySqlConnectorExample \
--exclude NpgsqlExample
--exclude NpgsqlExample \
--exclude SqliteExample

dockerfile-generate:
./scripts/generate_dockerfile.sh Dockerfile

protobuf-generate:
./scripts/generate_protobuf.sh
#./scripts/generate_protobuf.sh

run-end2end-tests:
./scripts/tests/run_end2end.sh
Expand All @@ -29,7 +30,7 @@ run-codegen-tests-process:
sqlc-generate-process: dotnet-publish-process
sqlc -f sqlc.local.yaml generate

test-process-plugin: sqlc-generate-process dockerfile-generate run-codegen-tests-process run-end2end-tests
test-process-plugin: sqlc-generate-process dockerfile-generate run-end2end-tests

# WASM type plugin
dotnet-publish-wasm: protobuf-generate
Expand All @@ -45,4 +46,4 @@ sqlc-generate-wasm: dotnet-publish-wasm update-wasm-plugin
run-codegen-tests-wasm:
./scripts/tests/run_codegen_matrix.sh sqlc.ci.yaml

test-wasm-plugin: sqlc-generate-wasm update-wasm-plugin dockerfile-generate run-codegen-tests-wasm run-end2end-tests
test-wasm-plugin: sqlc-generate-wasm update-wasm-plugin dockerfile-generate run-end2end-tests
4 changes: 2 additions & 2 deletions MySqlConnectorExample/MySqlConnectorExample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
</PropertyGroup>

Expand Down
4 changes: 2 additions & 2 deletions NpgsqlExample/NpgsqlExample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
</PropertyGroup>

Expand Down
27 changes: 27 additions & 0 deletions PluginOptions/DriverName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Linq;

namespace SqlcGenCsharp;

public enum DriverName
{
MySqlConnector,
Npgsql,
Sqlite
}


public static class DriverNameExtensions
{
private static readonly Dictionary<DriverName, string> EnumToString = new()
{
{ DriverName.MySqlConnector, "MySqlConnector" },
{ DriverName.Npgsql, "Npgsql" },
{ DriverName.Sqlite, "Microsoft.Data.Sqlite" }
};

public static string ToName(this DriverName me)
{
return EnumToString[me];
}
}
6 changes: 0 additions & 6 deletions PluginOptions/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@

namespace SqlcGenCsharp;

public enum DriverName
{
MySqlConnector,
Npgsql
}

public class Options
{
public Options(GenerateRequest generateRequest)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
### Options
| Option | Possible values | Optional | Info |
|-----------------|----------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| driver | values: `MySqlConnector`,`Npgsql` | No | Choosing the driver to use - refer to the [above](#supported-sql-engines) section on supported SQL engines. |
| driver | values: `MySqlConnector`,`Npgsql`, `Sqlite` | No | Choosing the driver to use - refer to the [examples](docs/Examples.md) to see the supported SQL engines and their drivers |
| targetFramework | default: `net8.0`<br/>values: `netstandard2.0`, `netstandard2.1`, `net8.0` | Yes | Determines the target framework for your generated code, meaning the generated code will be compiled to the specified runtime.<br/>For more information and help deciding on the right value, refer to the [Microsoft .NET Standard documentation](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-1-0). |
| generateCsproj | default: `true`<br/>values: `false`,`true` | Yes | Assists you with the integration of SQLC and csharp by generating a `.csproj` file. This converts the generated output to a .dll, a project that you can easily incorporate into your build process. |
| generateCsproj | default: `true`<br/>values: `false`,`true` | Yes | Assists you with the integration of SQLC and csharp by generating a `.csproj` file. This converts the generated output to a .dll, a project that you can easily incorporate into your build process. |

### Configuration
```yaml
Expand Down
Loading

0 comments on commit ba3f073

Please sign in to comment.