From 1688d1a2403b0e2ff579bbe59a64bf1490e78cb8 Mon Sep 17 00:00:00 2001 From: Paul Irwin Date: Mon, 22 Apr 2024 11:01:47 -0400 Subject: [PATCH] Fixed properties to be nullable. --- .../SQuiL/Models/SQuiLDataContext.cs | 8 +- .../SQuiL/Models/SQuiLTable.cs | 1 + .../SQuiL/Parser/CodeItem.cs | 2 +- ...tPropertyNullableDataContext.g.verified.cs | 140 ++++++ ...bjectPropertyNullableRequest.g.verified.cs | 11 + ...jectPropertyNullableResponse.g.verified.cs | 13 + ...ropertyNullable#ParentsTable.g.verified.cs | 12 + ...ullable#SQuiLBaseDataContext.g.verified.cs | 48 ++ ...ertyNullable#SQuiLExtensions.g.verified.cs | 19 + ...Nullable#SQuiLQueryAttribute.g.verified.cs | 22 + ...Nullable#SQuiLQueryFilesEnum.g.verified.cs | 11 + ...tyNullable#SQuiLTableAttribute.verified.cs | 17 + ...yNullable#SQuiLTableTypeEnum.g.verified.cs | 12 + ...opertyNullable#StudentObject.g.verified.cs | 12 + ...eturns.ObjectPropertyNullable.verified.txt | 434 ++++++++++++++++++ .../TestQueryParamsAndReturns.cs | 10 + 16 files changed, 769 insertions(+), 3 deletions(-) create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableDataContext.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableRequest.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableResponse.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ParentsTable.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLBaseDataContext.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLExtensions.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryAttribute.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryFilesEnum.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableAttribute.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableTypeEnum.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#StudentObject.g.verified.cs create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable.verified.txt create mode 100644 SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.cs diff --git a/SQuiL.SourceGenerator/SQuiL/Models/SQuiLDataContext.cs b/SQuiL.SourceGenerator/SQuiL/Models/SQuiLDataContext.cs index 92009ab..a5b5613 100644 --- a/SQuiL.SourceGenerator/SQuiL/Models/SQuiLDataContext.cs +++ b/SQuiL.SourceGenerator/SQuiL/Models/SQuiLDataContext.cs @@ -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 = ","; } @@ -312,7 +314,9 @@ void LoopProperties(string switchCase, string model, List 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--; @@ -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" : "")}"))}); """; } diff --git a/SQuiL.SourceGenerator/SQuiL/Models/SQuiLTable.cs b/SQuiL.SourceGenerator/SQuiL/Models/SQuiLTable.cs index 32dbf8f..566ff4e 100644 --- a/SQuiL.SourceGenerator/SQuiL/Models/SQuiLTable.cs +++ b/SQuiL.SourceGenerator/SQuiL/Models/SQuiLTable.cs @@ -3,6 +3,7 @@ using SQuiL.SourceGenerator.Parser; +using System; using System.CodeDom.Compiler; using System.Collections.Immutable; diff --git a/SQuiL.SourceGenerator/SQuiL/Parser/CodeItem.cs b/SQuiL.SourceGenerator/SQuiL/Parser/CodeItem.cs index 61da399..6c147a3 100644 --- a/SQuiL.SourceGenerator/SQuiL/Parser/CodeItem.cs +++ b/SQuiL.SourceGenerator/SQuiL/Parser/CodeItem.cs @@ -10,7 +10,7 @@ public record CodeItem(Token Identifier, Token Type) public string DataReader() => Type.DataReader(); - public string CSharpType(Func? callback = default) => Type.CSharpType(callback); + public string CSharpType(Func? callback = default) => Type.CSharpType(callback) + (IsNullable ? "?" : ""); public static Func SqlProperty(string classname, string model) => (p, i) => p.Type.SqlProperty(classname, model, i, p.Identifier.Value, $"item.{p.Identifier.Value}"); diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableDataContext.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableDataContext.g.verified.cs new file mode 100644 index 0000000..883a614 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableDataContext.g.verified.cs @@ -0,0 +1,140 @@ +//HintName: ObjectPropertyNullableDataContext.g.cs +// + +#nullable enable + +using Microsoft.Data.SqlClient; + +using SQuiL; + +namespace TestCase; + +partial class TestQueryParamsAndReturnsDataContext : SQuiLBaseDataContext +{ + public async Task ProcessObjectPropertyNullableAsync( + ObjectPropertyNullableRequest request, + CancellationToken cancellationToken = default!) + { + var builder = ConnectionStringBuilder("SQuiLDatabase"); + using SqlConnection connection = new(builder.ConnectionString); + var command = connection.CreateCommand(); + + List 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 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}]; + + + + """; + } +} diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableRequest.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableRequest.g.verified.cs new file mode 100644 index 0000000..9d6379e --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableRequest.g.verified.cs @@ -0,0 +1,11 @@ +//HintName: ObjectPropertyNullableRequest.g.cs +// + +#nullable enable + +namespace TestCase; + +public partial record ObjectPropertyNullableRequest +{ + public bool Debug { get; set; } +} diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableResponse.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableResponse.g.verified.cs new file mode 100644 index 0000000..f1f7084 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ObjectPropertyNullableResponse.g.verified.cs @@ -0,0 +1,13 @@ +//HintName: ObjectPropertyNullableResponse.g.cs +// + +#nullable enable + +namespace TestCase; + +public partial record ObjectPropertyNullableResponse +{ + public StudentObject? Student { get; set; } = default!; + + public System.Collections.Generic.List Parents { get; set; } = []; +} diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ParentsTable.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ParentsTable.g.verified.cs new file mode 100644 index 0000000..5ee8cb2 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#ParentsTable.g.verified.cs @@ -0,0 +1,12 @@ +//HintName: ParentsTable.g.cs +// + +#nullable enable + +namespace TestCase; + +public partial record ParentsTable( + int ID, + string? FirstName, + string LastName, + int? Age); diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLBaseDataContext.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLBaseDataContext.g.verified.cs new file mode 100644 index 0000000..a300a0d --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLBaseDataContext.g.verified.cs @@ -0,0 +1,48 @@ +//HintName: SQuiLBaseDataContext.g.cs +// + +#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 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. + """) + }); + } +} \ No newline at end of file diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLExtensions.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLExtensions.g.verified.cs new file mode 100644 index 0000000..a04959b --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLExtensions.g.verified.cs @@ -0,0 +1,19 @@ +//HintName: SQuiLExtensions.g.cs +// + +#nullable enable + +namespace Microsoft.Extensions.DependencyInjection; + +public static class SQuiLExtensions +{ + public static bool IsLoaded => true; + + public static IServiceCollection AddSQuiL( + this IServiceCollection services) + { + services.AddSingleton(); + + return services; + } +} diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryAttribute.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryAttribute.g.verified.cs new file mode 100644 index 0000000..4322a14 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryAttribute.g.verified.cs @@ -0,0 +1,22 @@ +//HintName: SQuiLQueryAttribute.g.cs +// + +#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; + } +} \ No newline at end of file diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryFilesEnum.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryFilesEnum.g.verified.cs new file mode 100644 index 0000000..21dbede --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLQueryFilesEnum.g.verified.cs @@ -0,0 +1,11 @@ +//HintName: SQuiLQueryFilesEnum.g.cs +// + +#nullable enable + +namespace SQuiL; + +public enum QueryFiles +{ + ObjectPropertyNullable +} diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableAttribute.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableAttribute.verified.cs new file mode 100644 index 0000000..c9d0cd7 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableAttribute.verified.cs @@ -0,0 +1,17 @@ +//HintName: SQuiLTableAttribute.cs +// + +#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; + } +} \ No newline at end of file diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableTypeEnum.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableTypeEnum.g.verified.cs new file mode 100644 index 0000000..7156942 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#SQuiLTableTypeEnum.g.verified.cs @@ -0,0 +1,12 @@ +//HintName: SQuiLTableTypeEnum.g.cs +// + +#nullable enable + +namespace SQuiL; + +public enum TableType +{ + Parents, + Student +} diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#StudentObject.g.verified.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#StudentObject.g.verified.cs new file mode 100644 index 0000000..727c398 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable#StudentObject.g.verified.cs @@ -0,0 +1,12 @@ +//HintName: StudentObject.g.cs +// + +#nullable enable + +namespace TestCase; + +public partial record StudentObject( + int ID, + string? FirstName, + string LastName, + int? Age); diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable.verified.txt b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable.verified.txt new file mode 100644 index 0000000..d45edd7 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.ObjectPropertyNullable.verified.txt @@ -0,0 +1,434 @@ +{ + Diagnostics: [ + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: CodeBlock { CodeType = OUTPUT_OBJECT, DatabaseType = Token { Type = TYPE_OBJECT, Offset = 0, Value = Student, Original = @Return_Student table }, Name = Student, DefaultValue = , IsObject = True, IsTable = False, IsRequired = False, IsNullable = True, Size = , Properties = System.Collections.Generic.List`1[SQuiL.SourceGenerator.Parser.CodeItem] }, + Message: CodeBlock { CodeType = OUTPUT_OBJECT, DatabaseType = Token { Type = TYPE_OBJECT, Offset = 0, Value = Student, Original = @Return_Student table }, Name = Student, DefaultValue = , IsObject = True, IsTable = False, IsRequired = False, IsNullable = True, Size = , Properties = System.Collections.Generic.List`1[SQuiL.SourceGenerator.Parser.CodeItem] }, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: CodeBlock { CodeType = OUTPUT_TABLE, DatabaseType = Token { Type = TYPE_TABLE, Offset = 106, Value = Parents, Original = @Returns_Parents table }, Name = Parents, DefaultValue = , IsObject = False, IsTable = True, IsRequired = False, IsNullable = False, Size = , Properties = System.Collections.Generic.List`1[SQuiL.SourceGenerator.Parser.CodeItem] }, + Message: CodeBlock { CodeType = OUTPUT_TABLE, DatabaseType = Token { Type = TYPE_TABLE, Offset = 106, Value = Parents, Original = @Returns_Parents table }, Name = Parents, DefaultValue = , IsObject = False, IsTable = True, IsRequired = False, IsNullable = False, Size = , Properties = System.Collections.Generic.List`1[SQuiL.SourceGenerator.Parser.CodeItem] }, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: CodeBlock { CodeType = USING, DatabaseType = Token { Type = IDENTIFIER, Offset = 217, Value = Database, Original = [Database] }, Name = Database, DefaultValue = , IsObject = False, IsTable = False, IsRequired = True, IsNullable = True, Size = , Properties = }, + Message: CodeBlock { CodeType = USING, DatabaseType = Token { Type = IDENTIFIER, Offset = 217, Value = Database, Original = [Database] }, Name = Database, DefaultValue = , IsObject = False, IsTable = False, IsRequired = True, IsNullable = True, Size = , Properties = }, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: CodeBlock { CodeType = BODY, DatabaseType = Token { Type = BODY, Offset = 228, Value = , Original = }, Name = , DefaultValue = , IsObject = False, IsTable = False, IsRequired = True, IsNullable = True, Size = , Properties = }, + Message: CodeBlock { CodeType = BODY, DatabaseType = Token { Type = BODY, Offset = 228, Value = , Original = }, Name = , DefaultValue = , IsObject = False, IsTable = False, IsRequired = True, IsNullable = True, Size = , Properties = }, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: KEYWORD_DECLARE => , + Message: KEYWORD_DECLARE => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: VARIABLE => Return_Student, + Message: VARIABLE => Return_Student, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_TABLE => , + Message: TYPE_TABLE => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_LPREN => , + Message: SYMBOL_LPREN => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => ID, + Message: IDENTIFIER => ID, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_INT => , + Message: TYPE_INT => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_COMMA => , + Message: SYMBOL_COMMA => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => FirstName, + Message: IDENTIFIER => FirstName, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_STRING => 100, + Message: TYPE_STRING => 100, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: LITERAL_NULL => , + Message: LITERAL_NULL => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_COMMA => , + Message: SYMBOL_COMMA => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => LastName, + Message: IDENTIFIER => LastName, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_STRING => 100, + Message: TYPE_STRING => 100, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_COMMA => , + Message: SYMBOL_COMMA => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => Age, + Message: IDENTIFIER => Age, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_INT => , + Message: TYPE_INT => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: LITERAL_NULL => , + Message: LITERAL_NULL => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_RPREN => , + Message: SYMBOL_RPREN => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: KEYWORD_DECLARE => , + Message: KEYWORD_DECLARE => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: VARIABLE => Returns_Parents, + Message: VARIABLE => Returns_Parents, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_TABLE => , + Message: TYPE_TABLE => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_LPREN => , + Message: SYMBOL_LPREN => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => ID, + Message: IDENTIFIER => ID, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_INT => , + Message: TYPE_INT => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_COMMA => , + Message: SYMBOL_COMMA => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => FirstName, + Message: IDENTIFIER => FirstName, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_STRING => 100, + Message: TYPE_STRING => 100, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: LITERAL_NULL => , + Message: LITERAL_NULL => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_COMMA => , + Message: SYMBOL_COMMA => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => LastName, + Message: IDENTIFIER => LastName, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_STRING => 100, + Message: TYPE_STRING => 100, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_COMMA => , + Message: SYMBOL_COMMA => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => Age, + Message: IDENTIFIER => Age, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: TYPE_INT => , + Message: TYPE_INT => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: LITERAL_NULL => , + Message: LITERAL_NULL => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: SYMBOL_RPREN => , + Message: SYMBOL_RPREN => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: KEYWORD_USE => , + Message: KEYWORD_USE => , + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: IDENTIFIER => Database, + Message: IDENTIFIER => Database, + Category: Logger + }, + { + Id: SP0000, + Title: Development Data, + Severity: Warning, + WarningLevel: 1, + Location: : (0,0)-(0,0), + MessageFormat: BODY => , + Message: BODY => , + Category: Logger + } + ] +} \ No newline at end of file diff --git a/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.cs b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.cs new file mode 100644 index 0000000..4151464 --- /dev/null +++ b/SQuiL.Tests/TestQueryParamsAndReturns/TestQueryParamsAndReturns.cs @@ -0,0 +1,10 @@ +namespace SQuiL.Tests.TestQueryParamsAndReturns; + +public class TestQueryParamsAndReturns : BaseTest +{ + [Fact] + public Task ObjectPropertyNullable() => TestQueryParamsAndReturns($""" + Declare @Return_Student table(ID int, FirstName varchar(100) Null, LastName varchar(100), Age int Null); + Declare @Returns_Parents table(ID int, FirstName varchar(100) Null, LastName varchar(100), Age int Null); + """); +}