Skip to content

Commit b5b623d

Browse files
committed
Validate unmapped contract properties in SELECT
1 parent 734b775 commit b5b623d

5 files changed

Lines changed: 33 additions & 0 deletions

File tree

src/Dibix.Sdk.CodeGeneration/Parser/StatementOutputParser.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,16 @@ bool isFirstResult
335335
if (!(schema is ObjectSchema objectSchema))
336336
throw new NotSupportedException($"Unsupported return type for result validation: {returnType.GetType()}");
337337

338+
foreach (IGrouping<string, OutputColumnResult> duplicateGroups in columnGroup.GroupBy(x => x.ColumnName).Where(x => x.Count() > 1))
339+
{
340+
foreach (OutputColumnResult duplicateColumn in duplicateGroups.Skip(1))
341+
{
342+
logger.LogError($"Duplicate column name in SELECT '{duplicateColumn.ColumnName}'", duplicateColumn.ColumnNameSource, returnType.Location.Source);
343+
}
344+
}
345+
346+
ICollection<ObjectSchemaProperty> visitedProperties = [.. objectSchema.Properties.Where(x => IsPrimitiveType(x.Type, schemaRegistry) && !x.Type.IsEnumerable)];
347+
338348
foreach (OutputColumnResult columnResult in columnGroup)
339349
{
340350
// Validate alias
@@ -354,6 +364,8 @@ bool isFirstResult
354364
continue;
355365
}
356366

367+
visitedProperties.Remove(property);
368+
357369
if (!IsPrimitiveType(property.Type, schemaRegistry))
358370
{
359371
logger.LogError($"Column '{columnResult.ColumnName}' cannot be mapped. Only primitive types are supported.", returnElement.Location.Source, columnResult.ColumnNameSource.StartLine, columnResult.ColumnNameSource.StartColumn);
@@ -365,6 +377,11 @@ bool isFirstResult
365377
//if (columnResult.IsNullable.HasValue && columnResult.IsNullable.Value != property.Type.IsNullable)
366378
// logger.LogError(null, $"Nullability of column '{columnResult.ColumnName}' should match the target property", target.Source, columnResult.ColumnNameSource.StartLine, columnResult.ColumnNameSource.StartColumn);
367379
}
380+
381+
foreach (ObjectSchemaProperty property in visitedProperties)
382+
{
383+
logger.LogError($"Property '{property.Name}' on type '{schema.FullName}' not mapped", columnGroup[0].PrimarySource, returnType.Location.Source);
384+
}
368385
}
369386
}
370387

src/Dibix.Sdk.Sql/ScriptDomExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.ObjectModel;
44
using System.Linq;
55
using System.Text;
6+
using Dibix.Sdk.Abstractions;
67
using Microsoft.SqlServer.Dac;
78
using Microsoft.SqlServer.Dac.Model;
89
using Microsoft.SqlServer.TransactSql.ScriptDom;
@@ -11,6 +12,8 @@ namespace Dibix.Sdk.Sql
1112
{
1213
public static class ScriptDomExtensions
1314
{
15+
public static void LogError(this ILogger logger, string text, TSqlFragment fragment, string source) => logger.LogMessage(LogCategory.Error, subCategory: null, code: null, text, source, fragment.StartLine, fragment.StartColumn);
16+
1417
public static string Dump(this TSqlFragment fragment)
1518
{
1619
StringBuilder sb = new StringBuilder();

tests/Dibix.Sdk.Tests.Database/Dibix.Sdk.Tests.Database.sqlproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
<Build Include="Tests\Syntax\dbx_tests_syntax_singleconcreteresult_params_array.sql" />
155155
<Build Include="Tests\Syntax\dbx_tests_syntax_enum3.sql" />
156156
<Build Include="Tests\Syntax\dbx_tests_syntax_empty_params_udt.sql" />
157+
<Build Include="Tests\Syntax\dbx_tests_syntax_singleconcreteresult_missingcolumn.sql" />
157158
</ItemGroup>
158159
<ItemGroup>
159160
<Folder Include="CodeAnalysis" />
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- @Return ClrTypes:GenericContract Mode:Single
2+
CREATE PROCEDURE [dbo].[dbx_tests_syntax_singleconcreteresult_missingcolumn]
3+
AS
4+
SELECT [id] = 1
5+
, [name] = NULL
6+
, [parentid] = NULL
7+
, [role] = NULL
8+
, [creationtime] = NULL

tests/Dibix.Sdk.Tests/CodeGeneration/CodeGenerationTaskTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,16 +520,20 @@ public void Endpoint_WithValidationErrors_Error()
520520
, @"Types\dbx_codeanalysis_udt_int.sql"
521521
, @"Tests\Syntax\dbx_tests_syntax_empty_params.sql"
522522
, @"Tests\Syntax\dbx_tests_syntax_empty_params_udt.sql"
523+
, @"Tests\Syntax\dbx_tests_syntax_singleconcreteresult.sql"
524+
, @"Tests\Syntax\dbx_tests_syntax_singleconcreteresult_missingcolumn.sql"
523525
}
524526
, contracts: new[]
525527
{
526528
@"Contracts\Direction.json"
529+
, @"Contracts\GenericContract.json"
527530
, @"Contracts\Entry.json"
528531
, @"Contracts\Request.json"
529532
}
530533
, endpoints: new[] { @"Endpoints\GenericEndpointWithErrors.json" }
531534
, isEmbedded: false
532535
, expectedException: @"One or more errors occured during code generation:
536+
Tests\Syntax\dbx_tests_syntax_singleconcreteresult_missingcolumn.sql(4,12,4,12):error:Property 'ImageUrl' on type 'Dibix.Sdk.Tests.DomainModel.GenericContract' not mapped
533537
Endpoints\GenericEndpointWithErrors.json(8,15,8,15):error:Unknown property source 'WTF'
534538
Endpoints\GenericEndpointWithErrors.json(20,20,20,20):error:Property 'X' not found on contract 'Dibix.Sdk.Tests.DomainModel.Request'
535539
Endpoints\GenericEndpointWithErrors.json(21,23,21,23):error:Property 'Nm' not found on contract 'Dibix.Sdk.Tests.DomainModel.Entry'

0 commit comments

Comments
 (0)