Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ architecture test in the same change and explain why.
A driver that doesn't implement an interface fails at runtime with a wrapped `SystemException`, not at compile time.
- **Drivers -> generated code**: drivers return C# source as strings / `MemberDeclarationSyntax`. Hooks return
fragments (`ConnectionGenCommands`, `CommandGenCommands`, `GenCommand.WrapBlock`), never whole files.
- **Opt-in contract**: every option that is off by default (e.g. `withCancellationToken`, `useProperSingularization`)
- **Opt-in contract**: every option that is off by default (e.g. `useCancellationToken`, `useProperSingularization`)
must leave generated output **byte-identical** when off. `sqlc diff` on the examples is the check.

### Code generation flow
Expand Down Expand Up @@ -198,18 +198,21 @@ CI fails if any of the generated artifacts above is stale (`sqlc diff`, `git dif
| Option | Default | Notes |
|-------------------------------|----------------------------------------------------------------|-------|
| `targetFramework` | `net8.0` | `netstandard2.0`, `netstandard2.1`, `net8.0`, `net9.0`, `net10.0` |
| `overrideDriverVersion` | `2.4.0` MySqlConnector, `8.0.6` Npgsql, `10.0.13` Microsoft.Data.Sqlite | constants in each driver |
| `driverVersion` | `2.4.0` MySqlConnector, `8.0.6` Npgsql, `10.0.13` Microsoft.Data.Sqlite | constants in each driver |
| `generateCsproj` | `true` | |
| `namespaceName` | output directory name | |
| `useDapper` | `false` | |
| `overrideDapperVersion` | `2.1.66` | `DbDriver.DefaultDapperVersion` |
| `dapperVersion` | `2.1.66` | `DbDriver.DefaultDapperVersion` |
| `useCentralPackageManagement` | `false` | omits `Version=` in the generated csproj |
| `withAsyncSuffix` | `true` | |
| `withCancellationToken` | `false` | must be byte-identical when off |
| `useAsyncSuffix` | `true` | |
| `useCancellationToken` | `false` | must be byte-identical when off |
| `useAsyncEnumerable` | `false` | `:many` returns `IAsyncEnumerable<Row>`; not supported on `netstandard2.0` |
| `useProperSingularization` | `false` | renames models when on |
| `overrides` | - | `Query:column` / `*:column`, see section 3 |
| `debugRequest` | `false` | internal: dumps the request; not allowed with WASM |

**Renamed options:** `overrideDriverVersion` -> `driverVersion`, `overrideDapperVersion` -> `dapperVersion`, `withAsyncSuffix` -> `useAsyncSuffix`, `withCancellationToken` -> `useCancellationToken`. The old names are deprecated but still accepted; setting both spellings to different values is an error.

### Annotation support
| Annotation / macro | PostgreSQL | MySQL | SQLite | Implementation |
|--------------------|-----------|-------|--------|----------------|
Expand Down
6 changes: 3 additions & 3 deletions Drivers/DbDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public abstract class DbDriver

public Options Options { get; }

public CancellationGen Cancellation => new(Options.WithCancellationToken);
public CancellationGen Cancellation => new(Options.UseCancellationToken);

public string DefaultSchema { get; }

Expand Down Expand Up @@ -158,7 +158,7 @@ private static Dictionary<string, Dictionary<string, Table>> ConstructTablesLook
public virtual IDictionary<string, string> GetPackageReferences()
{
return new Dictionary<string, string> {
{ "Dapper", Options.OverrideDapperVersion != string.Empty ? Options.OverrideDapperVersion : DefaultDapperVersion }
{ "Dapper", Options.DapperVersion != string.Empty ? Options.DapperVersion : DefaultDapperVersion }
}
.MergeIf(new Dictionary<string, string>
{
Expand All @@ -185,7 +185,7 @@ public virtual ISet<string> GetUsingDirectivesForQueries()
], Options.UseDapper)
.AddRangeIf([
"System.Runtime.CompilerServices"
], Options.UseAsyncEnumerable && Options.WithCancellationToken)
], Options.UseAsyncEnumerable && Options.UseCancellationToken)
.AddRangeExcludeNulls(GetUsingDirectivesForColumnMappings());
}

Expand Down
2 changes: 1 addition & 1 deletion Drivers/Generators/CopyFromDeclareGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class CopyFromDeclareGen(DbDriver dbDriver)
public MemberDeclarationSyntax Generate(string queryTextConstant, string argInterface, Query query)
{
return ParseMemberDeclaration($$"""
public async Task {{query.Name.ToMethodName(dbDriver.Options.WithAsyncSuffix)}}(List<{{argInterface}}> args{{dbDriver.Cancellation.TrailingMethodParameter()}})
public async Task {{query.Name.ToMethodName(dbDriver.Options.UseAsyncSuffix)}}(List<{{argInterface}}> args{{dbDriver.Cancellation.TrailingMethodParameter()}})
{
{{((ICopyFrom)dbDriver).GetCopyFromImpl(query, queryTextConstant)}}
}
Expand Down
2 changes: 1 addition & 1 deletion Drivers/Generators/ExecDeclareGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte
{
var parametersStr = CommonGen.GetMethodParameterList(argInterface, query.Params, dbDriver.Cancellation.MethodParameter());
return ParseMemberDeclaration($$"""
public async Task {{query.Name.ToMethodName(dbDriver.Options.WithAsyncSuffix)}}({{parametersStr}})
public async Task {{query.Name.ToMethodName(dbDriver.Options.UseAsyncSuffix)}}({{parametersStr}})
{
{{GetMethodBody(queryTextConstant, query)}}
}
Expand Down
2 changes: 1 addition & 1 deletion Drivers/Generators/ExecLastIdDeclareGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte
{
var parametersStr = CommonGen.GetMethodParameterList(argInterface, query.Params, dbDriver.Cancellation.MethodParameter());
return ParseMemberDeclaration($$"""
public async Task<{{dbDriver.GetIdColumnType(query)}}> {{query.Name.ToMethodName(dbDriver.Options.WithAsyncSuffix)}}({{parametersStr}})
public async Task<{{dbDriver.GetIdColumnType(query)}}> {{query.Name.ToMethodName(dbDriver.Options.UseAsyncSuffix)}}({{parametersStr}})
{
{{GetMethodBody(queryTextConstant, query)}}
}
Expand Down
2 changes: 1 addition & 1 deletion Drivers/Generators/ExecRowsDeclareGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte
{
var parametersStr = CommonGen.GetMethodParameterList(argInterface, query.Params, dbDriver.Cancellation.MethodParameter());
return ParseMemberDeclaration($$"""
public async Task<long> {{query.Name.ToMethodName(dbDriver.Options.WithAsyncSuffix)}}({{parametersStr}})
public async Task<long> {{query.Name.ToMethodName(dbDriver.Options.UseAsyncSuffix)}}({{parametersStr}})
{
{{GetMethodBody(queryTextConstant, query)}}
}
Expand Down
2 changes: 1 addition & 1 deletion Drivers/Generators/ManyDeclareGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte
var parametersStr = CommonGen.GetMethodParameterList(argInterface, query.Params, cancellationParam);
var returnType = asyncEnumerable ? $"IAsyncEnumerable<{returnInterface}>" : $"Task<List<{returnInterface}>>";
return ParseMemberDeclaration($$"""
public async {{returnType}} {{query.Name.ToMethodName(dbDriver.Options.WithAsyncSuffix)}}({{parametersStr}})
public async {{returnType}} {{query.Name.ToMethodName(dbDriver.Options.UseAsyncSuffix)}}({{parametersStr}})
{
{{GetMethodBody(queryTextConstant, returnInterface, query)}}
}
Expand Down
2 changes: 1 addition & 1 deletion Drivers/Generators/OneDeclareGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public MemberDeclarationSyntax Generate(string queryTextConstant, string argInte
var returnType = $"Task<{dbDriver.AddNullableSuffixIfNeeded(returnInterface, false)}>";
var parametersStr = CommonGen.GetMethodParameterList(argInterface, query.Params, dbDriver.Cancellation.MethodParameter());
return ParseMemberDeclaration($$"""
public async {{returnType}} {{query.Name.ToMethodName(dbDriver.Options.WithAsyncSuffix)}}({{parametersStr}})
public async {{returnType}} {{query.Name.ToMethodName(dbDriver.Options.UseAsyncSuffix)}}({{parametersStr}})
{
{{GetMethodBody(queryTextConstant, returnInterface, query)}}
}
Expand Down
2 changes: 1 addition & 1 deletion Drivers/MySqlConnectorDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public override IDictionary<string, string> GetPackageReferences()
.GetPackageReferences()
.Merge(new Dictionary<string, string>
{
{ "MySqlConnector", Options.OverrideDriverVersion != string.Empty ? Options.OverrideDriverVersion : DefaultMysqlConnectorVersion }
{ "MySqlConnector", Options.DriverVersion != string.Empty ? Options.DriverVersion : DefaultMysqlConnectorVersion }
})
.MergeIf(new Dictionary<string, string>
{
Expand Down
2 changes: 1 addition & 1 deletion Drivers/NpgsqlDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ public override IDictionary<string, string> GetPackageReferences()
.GetPackageReferences()
.Merge(new Dictionary<string, string>
{
{ "Npgsql", Options.OverrideDriverVersion != string.Empty ? Options.OverrideDriverVersion : DefaultNpgsqlVersion }
{ "Npgsql", Options.DriverVersion != string.Empty ? Options.DriverVersion : DefaultNpgsqlVersion }
});
}

Expand Down
2 changes: 1 addition & 1 deletion Drivers/SqliteDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public override IDictionary<string, string> GetPackageReferences()
.GetPackageReferences()
.Merge(new Dictionary<string, string>
{
{ "Microsoft.Data.Sqlite", Options.OverrideDriverVersion != string.Empty ? Options.OverrideDriverVersion : DefaultSqliteVersion }
{ "Microsoft.Data.Sqlite", Options.DriverVersion != string.Empty ? Options.DriverVersion : DefaultSqliteVersion }
});
}

Expand Down
27 changes: 19 additions & 8 deletions PluginOptions/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public Options(GenerateRequest generateRequest)
var rawOptions = JsonSerializer.Deserialize<RawOptions>(text) ?? throw new InvalidOperationException();

DriverName = EngineToDriverMapping[generateRequest.Settings.Engine];
OverrideDriverVersion = rawOptions.OverrideDriverVersion;
DriverVersion = Resolve(rawOptions.DriverVersion, rawOptions.OverrideDriverVersion, "driverVersion", "overrideDriverVersion") ?? string.Empty;
GenerateCsproj = rawOptions.GenerateCsproj;
UseDapper = rawOptions.UseDapper;
OverrideDapperVersion = rawOptions.OverrideDapperVersion;
DapperVersion = Resolve(rawOptions.DapperVersion, rawOptions.OverrideDapperVersion, "dapperVersion", "overrideDapperVersion") ?? string.Empty;
NamespaceName = rawOptions.NamespaceName;
DotnetFramework = DotnetFrameworkExtensions.ParseName(rawOptions.TargetFramework);
Overrides = rawOptions.Overrides ?? [];
WithAsyncSuffix = rawOptions.WithAsyncSuffix;
WithCancellationToken = rawOptions.WithCancellationToken;
UseAsyncSuffix = Resolve(rawOptions.UseAsyncSuffix, rawOptions.WithAsyncSuffix, "useAsyncSuffix", "withAsyncSuffix") ?? true;
UseCancellationToken = Resolve(rawOptions.UseCancellationToken, rawOptions.WithCancellationToken, "useCancellationToken", "withCancellationToken") ?? false;
UseCentralPackageManagement = rawOptions.UseCentralPackageManagement;
UseProperSingularization = rawOptions.UseProperSingularization;
UseAsyncEnumerable = rawOptions.UseAsyncEnumerable;
Expand All @@ -39,15 +39,15 @@ public Options(GenerateRequest generateRequest)

public DriverName DriverName { get; }

public string OverrideDriverVersion { get; }
public string DriverVersion { get; }

public DotnetFramework DotnetFramework { get; }

public bool GenerateCsproj { get; }

public bool UseDapper { get; }

public string OverrideDapperVersion { get; }
public string DapperVersion { get; }

public string NamespaceName { get; }

Expand All @@ -61,12 +61,12 @@ public Options(GenerateRequest generateRequest)
/// </summary>
public bool UseCentralPackageManagement { get; }

public bool WithAsyncSuffix { get; }
public bool UseAsyncSuffix { get; }

/// <summary>
/// When true, generated methods take an optional CancellationToken threaded into every async DB call.
/// </summary>
public bool WithCancellationToken { get; }
public bool UseCancellationToken { get; }

/// <summary>
/// When true, :many queries return IAsyncEnumerable&lt;Row&gt; (streamed with yield return) instead of Task&lt;List&lt;Row&gt;&gt;.
Expand All @@ -88,6 +88,17 @@ public Options(GenerateRequest generateRequest)
{ "sqlite", DriverName.Sqlite }
};

/// <summary>
/// Resolves an option that was renamed: the new name wins, the deprecated name is still honored,
/// and setting both to different values is rejected.
/// </summary>
private static T? Resolve<T>(T? current, T? deprecated, string currentName, string deprecatedName)
{
if (current is not null && deprecated is not null && !EqualityComparer<T>.Default.Equals(current, deprecated))
throw new ArgumentException($"Options '{currentName}' and '{deprecatedName}' (deprecated) are both set with different values");
return current ?? deprecated;
}

private static bool NoOptionsProvided(string optionsText)
{
return optionsText.Trim() == string.Empty;
Expand Down
32 changes: 28 additions & 4 deletions PluginOptions/RawOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ namespace SqlcGenCsharp;

public record RawOptions
{
[JsonPropertyName("driverVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? DriverVersion { get; init; }

/// <summary>Deprecated alias of <see cref="DriverVersion"/>.</summary>
[JsonPropertyName("overrideDriverVersion")]
public string OverrideDriverVersion { get; init; } = string.Empty;
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? OverrideDriverVersion { get; init; }

[JsonPropertyName("generateCsproj")]
public bool GenerateCsproj { get; init; } = true;
Expand All @@ -20,8 +26,14 @@ public record RawOptions
[JsonPropertyName("useDapper")]
public bool UseDapper { get; init; }

[JsonPropertyName("dapperVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? DapperVersion { get; init; }

/// <summary>Deprecated alias of <see cref="DapperVersion"/>.</summary>
[JsonPropertyName("overrideDapperVersion")]
public string OverrideDapperVersion { get; init; } = string.Empty;
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? OverrideDapperVersion { get; init; }

[JsonPropertyName("overrides")]
public List<OverrideOption>? Overrides { get; init; }
Expand All @@ -32,11 +44,23 @@ public record RawOptions
[JsonPropertyName("useCentralPackageManagement")]
public bool UseCentralPackageManagement { get; init; }

[JsonPropertyName("useAsyncSuffix")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? UseAsyncSuffix { get; init; }

/// <summary>Deprecated alias of <see cref="UseAsyncSuffix"/>.</summary>
[JsonPropertyName("withAsyncSuffix")]
public bool WithAsyncSuffix { get; init; } = true;
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? WithAsyncSuffix { get; init; }

[JsonPropertyName("useCancellationToken")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? UseCancellationToken { get; init; }

/// <summary>Deprecated alias of <see cref="UseCancellationToken"/>.</summary>
[JsonPropertyName("withCancellationToken")]
public bool WithCancellationToken { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? WithCancellationToken { get; init; }

[JsonPropertyName("useAsyncEnumerable")]
public bool UseAsyncEnumerable { get; init; }
Expand Down
Loading
Loading