Skip to content

Commit

Permalink
Fixed properties to be nullable.
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Irwin committed Apr 22, 2024
1 parent 12bb71b commit 1688d1a
Show file tree
Hide file tree
Showing 16 changed files with 769 additions and 3 deletions.
8 changes: 6 additions & 2 deletions SQuiL.SourceGenerator/SQuiL/Models/SQuiLDataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ void SwitchStatements()
foreach (var item in block.Properties)
{
writer.WriteLine(comma);
if (item.IsNullable)
writer.Write($"""reader.IsDBNull(reader.GetOrdinal("{item.Identifier.Value}")) ? default! : """);
writer.Write($"""{item.DataReader()}(reader.GetOrdinal("{item.Identifier.Value}"))""");
comma = ",";
}
Expand Down Expand Up @@ -312,7 +314,9 @@ void LoopProperties(string switchCase, string model, List<CodeItem> properties)
foreach (var item in properties)
{
writer.WriteLine(comma);
writer.Write($"""reader.IsDBNull(index{item.Identifier.Value}) ? default! : {item.DataReader()}(index{item.Identifier.Value})""");
if (item.IsNullable)
writer.Write($"""reader.IsDBNull(index{item.Identifier.Value}) ? default! : """);
writer.Write($"""{item.DataReader()}(index{item.Identifier.Value})""");
comma = ",";
}
writer.Indent--;
Expand Down Expand Up @@ -427,7 +431,7 @@ string TableDeclaration(string name, CodeBlock block)
Declare {block.DatabaseType.Original}(
[{SQuiLTableTypeDatabaseTagName}{name}__] varchar(max) default('{name}'),
{string.Join($",{writer.NewLine}\t", block.Properties.Select(p
=> $"[{p.Identifier.Value}] {p.Type.Original}"))});
=> $"[{p.Identifier.Value}] {p.Type.Original}{(p.IsNullable ? " Null" : "")}"))});
""";
}
Expand Down
1 change: 1 addition & 0 deletions SQuiL.SourceGenerator/SQuiL/Models/SQuiLTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using SQuiL.SourceGenerator.Parser;

using System;
using System.CodeDom.Compiler;
using System.Collections.Immutable;

Expand Down
2 changes: 1 addition & 1 deletion SQuiL.SourceGenerator/SQuiL/Parser/CodeItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public record CodeItem(Token Identifier, Token Type)

public string DataReader() => Type.DataReader();

public string CSharpType(Func<string>? callback = default) => Type.CSharpType(callback);
public string CSharpType(Func<string>? callback = default) => Type.CSharpType(callback) + (IsNullable ? "?" : "");

public static Func<CodeItem, int, string> SqlProperty(string classname, string model)
=> (p, i) => p.Type.SqlProperty(classname, model, i, p.Identifier.Value, $"item.{p.Identifier.Value}");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//HintName: ObjectPropertyNullableDataContext.g.cs
// <auto-generated />

#nullable enable

using Microsoft.Data.SqlClient;

using SQuiL;

namespace TestCase;

partial class TestQueryParamsAndReturnsDataContext : SQuiLBaseDataContext
{
public async Task<ObjectPropertyNullableResponse> ProcessObjectPropertyNullableAsync(
ObjectPropertyNullableRequest request,
CancellationToken cancellationToken = default!)
{
var builder = ConnectionStringBuilder("SQuiLDatabase");
using SqlConnection connection = new(builder.ConnectionString);
var command = connection.CreateCommand();

List<SqlParameter> parameters = new()
{
new("@EnvironmentName", System.Data.SqlDbType.VarChar, EnvironmentName.Length) { Value = EnvironmentName },
new("@Debug", System.Data.SqlDbType.Bit) { Value = EnvironmentName != "Production" },
};

command.CommandText = Query(parameters);
command.Parameters.AddRange(parameters.ToArray());

await connection.OpenAsync(cancellationToken);

ObjectPropertyNullableResponse response = new();

var isStudent = false;
var isParents = false;

using var reader = await command.ExecuteReaderAsync(cancellationToken);

do
{
var tableTag = reader.GetName(0);
if(tableTag.StartsWith("__SQuiL__Table__Type__"))
{
switch (tableTag)
{
case "__SQuiL__Table__Type__Error__":
{
if (!await reader.ReadAsync(cancellationToken)) break;

break;
}
case "__SQuiL__Table__Type__Return_Student__":
{
if (isStudent) throw new Exception(
"Already returned value for `Student`");

isStudent = true;

if (!await reader.ReadAsync(cancellationToken)) break;

if (response.Student is not null)
throw new Exception("Student was already set.");

if (reader.GetString(0) == "Return_Student")
{
response.Student = new(
reader.GetInt32(reader.GetOrdinal("ID")),
reader.IsDBNull(reader.GetOrdinal("FirstName")) ? default! : reader.GetString(reader.GetOrdinal("FirstName")),
reader.GetString(reader.GetOrdinal("LastName")),
reader.IsDBNull(reader.GetOrdinal("Age")) ? default! : reader.GetInt32(reader.GetOrdinal("Age")));
}
else
{
continue;
}

if (await reader.ReadAsync(cancellationToken))
throw new Exception(
"Return object results in more than one object. Consider using a return table instead.");

break;
}
case "__SQuiL__Table__Type__Returns_Parents__":
{
isParents = true;

if (!await reader.ReadAsync(cancellationToken)) break;

var indexID = reader.GetOrdinal("ID");
var indexFirstName = reader.GetOrdinal("FirstName");
var indexLastName = reader.GetOrdinal("LastName");
var indexAge = reader.GetOrdinal("Age");

do
{
if (reader.GetString(0) == "Returns_Parents")
{
response.Parents.Add(new(
reader.GetInt32(indexID),
reader.IsDBNull(indexFirstName) ? default! : reader.GetString(indexFirstName),
reader.GetString(indexLastName),
reader.IsDBNull(indexAge) ? default! : reader.GetInt32(indexAge)));
}
}
while (await reader.ReadAsync(cancellationToken));
break;
}
}
}
}
while (await reader.NextResultAsync(cancellationToken));

if (!isStudent) throw new Exception("Expected return object `Student`)");
if (!isParents) throw new Exception("Expected return table `Parents`)");

return response;

string Query(List<SqlParameter> parameters) => $"""
Declare @Return_Student table(
[__SQuiL__Table__Type__Return_Student__] varchar(max) default('Return_Student'),
[ID] int,
[FirstName] varchar(100) Null,
[LastName] varchar(100),
[Age] int Null);

Declare @Returns_Parents table(
[__SQuiL__Table__Type__Returns_Parents__] varchar(max) default('Returns_Parents'),
[ID] int,
[FirstName] varchar(100) Null,
[LastName] varchar(100),
[Age] int Null);

Use [{builder.InitialCatalog}];



""";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//HintName: ObjectPropertyNullableRequest.g.cs
// <auto-generated />

#nullable enable

namespace TestCase;

public partial record ObjectPropertyNullableRequest
{
public bool Debug { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//HintName: ObjectPropertyNullableResponse.g.cs
// <auto-generated />

#nullable enable

namespace TestCase;

public partial record ObjectPropertyNullableResponse
{
public StudentObject? Student { get; set; } = default!;

public System.Collections.Generic.List<ParentsTable> Parents { get; set; } = [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//HintName: ParentsTable.g.cs
// <auto-generated />

#nullable enable

namespace TestCase;

public partial record ParentsTable(
int ID,
string? FirstName,
string LastName,
int? Age);
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//HintName: SQuiLBaseDataContext.g.cs
// <auto-generated />

#nullable enable

namespace SQuiL;

using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;

using System.Collections.Generic;
using System;

public abstract partial class SQuiLBaseDataContext(IConfiguration Configuration)
{
//public virtual string SettingName { get; } = "SQuiLDatabase";

protected string EnvironmentName { get; } = Configuration.GetSection("EnvironmentName")?.Value
?? Environment.GetEnvironmentVariable(Configuration.GetSection("EnvironmentVariable")?.Value ?? "ASPNETCORE_ENVIRONMENT")
?? "Development";

protected SqlConnectionStringBuilder ConnectionStringBuilder(string settingName)
{
return new SqlConnectionStringBuilder(Configuration.GetConnectionString(settingName)
?? throw new Exception($"Cannot find a connection string in the appsettings for {settingName}."));
}

protected void AddParams(System.Text.StringBuilder query, List<SqlParameter> parameters, int index, string table, string name, System.Data.SqlDbType type, object value, int size = 0)
{
var parameter = $"@{table}_{index}_{name}";
query.Append(parameter);

if (size == 0)
{
parameters.Add(new(parameter, type) { Value = value });
return;
}

parameters.Add(new(parameter, type, size) {
Value = value is null || ((string)value).Length <= size
? (value ?? "Null")
: throw new Exception($"""
ParamsTable model table property at index [{index}] has a string property [{name}]
with more than {size} characters.
""")
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//HintName: SQuiLExtensions.g.cs
// <auto-generated />

#nullable enable

namespace Microsoft.Extensions.DependencyInjection;

public static class SQuiLExtensions
{
public static bool IsLoaded => true;

public static IServiceCollection AddSQuiL(
this IServiceCollection services)
{
services.AddSingleton<TestCase.TestQueryParamsAndReturnsDataContext>();

return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//HintName: SQuiLQueryAttribute.g.cs
// <auto-generated />

#nullable enable

namespace SQuiL;

[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = true)]
public class SQuiLQueryAttribute : System.Attribute
{
public QueryFiles Type { get; }

public string Setting { get; }

public SQuiLQueryAttribute(
QueryFiles type,
string setting = "SQuiLDatabase")
{
Type = type;
Setting = setting;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//HintName: SQuiLQueryFilesEnum.g.cs
// <auto-generated />

#nullable enable

namespace SQuiL;

public enum QueryFiles
{
ObjectPropertyNullable
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//HintName: SQuiLTableAttribute.cs
// <auto-generated />

#nullable enable

namespace SQuiL;

[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = true)]
public class SQuiLTableAttribute : System.Attribute
{
public TableType Type { get; }

public SQuiLTableAttribute(TableType type)
{
Type = type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//HintName: SQuiLTableTypeEnum.g.cs
// <auto-generated />

#nullable enable

namespace SQuiL;

public enum TableType
{
Parents,
Student
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//HintName: StudentObject.g.cs
// <auto-generated />

#nullable enable

namespace TestCase;

public partial record StudentObject(
int ID,
string? FirstName,
string LastName,
int? Age);

0 comments on commit 1688d1a

Please sign in to comment.