diff --git a/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs b/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs index 521e59616a..683f0b672c 100644 --- a/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs +++ b/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs @@ -243,6 +243,7 @@ public static string GetGraphQLTypeForColumnType(Type type) "Decimal" => DECIMAL_TYPE, "Boolean" => BOOLEAN_TYPE, "DateTime" => DATETIME_TYPE, + "DateTimeOffset" => DATETIME_TYPE, "Byte[]" => BYTEARRAY_TYPE, _ => throw new DataApiBuilderException( message: $"Column type {type} not handled by case. Please add a case resolving {type} to the appropriate GraphQL type", diff --git a/src/Service.Tests/DatabaseSchema-MsSql.sql b/src/Service.Tests/DatabaseSchema-MsSql.sql index f8dfb7a171..a49516bff9 100644 --- a/src/Service.Tests/DatabaseSchema-MsSql.sql +++ b/src/Service.Tests/DatabaseSchema-MsSql.sql @@ -143,7 +143,11 @@ CREATE TABLE type_table( float_types float, decimal_types decimal(38, 19), boolean_types bit, + date_types date, datetime_types datetime, + datetime2_types datetime2, + datetimeoffset_types datetimeoffset, + smalldatetime_types smalldatetime, bytearray_types varbinary(max), guid_types uniqueidentifier DEFAULT newid() ); @@ -359,12 +363,27 @@ INSERT INTO reviews(id, book_id, content) VALUES (567, 1, 'Indeed a great book') SET IDENTITY_INSERT reviews OFF SET IDENTITY_INSERT type_table ON -INSERT INTO type_table(id, byte_types, short_types, int_types, long_types, string_types, single_types, float_types, decimal_types, boolean_types, datetime_types, bytearray_types) VALUES - (1, 1, 1, 1, 1, '', 0.33, 0.33, 0.333333, 1, '1999-01-08 10:23:54', 0xABCDEF0123), - (2, 0, -1, -1, -1, 'lksa;jdflasdf;alsdflksdfkldj', -9.2, -9.2, -9.292929, 0, '1999-01-08 10:23:00', 0x98AB7511AABB1234), - (3, 0, -32768, -2147483648, -9223372036854775808, 'null', -3.4E38, -1.7E308, 2.929292E-19, 1, '1753-01-01 00:00:00.000', 0x00000000), - (4, 255, 32767, 2147483647, 9223372036854775807, 'null', 3.4E38, 1.7E308, 2.929292E-14, 1, '9999-12-31 23:59:59', 0xFFFFFFFF), - (5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO type_table(id, +byte_types, short_types, int_types, long_types, +string_types, +single_types, float_types, decimal_types, +boolean_types, +date_types, datetime_types, datetime2_types, datetimeoffset_types, smalldatetime_types, +bytearray_types) +VALUES + (1, 1, 1, 1, 1, '', 0.33, 0.33, 0.333333, 1, + '1999-01-08', '1999-01-08 10:23:54', '1999-01-08 10:23:54.9999999', '1999-01-08 10:23:54.9999999-14:00', '1999-01-08 10:23:54', + 0xABCDEF0123), + (2, 0, -1, -1, -1, 'lksa;jdflasdf;alsdflksdfkldj', -9.2, -9.2, -9.292929, 0, + '1999-01-08', '1999-01-08 10:23:00', '1999-01-08 10:23:00.9999999', '1999-01-08 10:23:00.9999999+13:00', '1999-01-08 10:23:00', + 0x98AB7511AABB1234), + (3, 0, -32768, -2147483648, -9223372036854775808, 'null', -3.4E38, -1.7E308, 2.929292E-19, 1, + '0001-01-01', '1753-01-01 00:00:00.000', '0001-01-01 00:00:00.0000000', '0001-01-01 00:00:00.0000000+0:00', '1900-01-01 00:00:00', + 0x00000000), + (4, 255, 32767, 2147483647, 9223372036854775807, 'null', 3.4E38, 1.7E308, 2.929292E-14, 1, + '9999-12-31', '9999-12-31 23:59:59', '9999-12-31 23:59:59.9999999', '9999-12-31 23:59:59.9999999+14:00', '2079-06-06', + 0xFFFFFFFF), + (5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); SET IDENTITY_INSERT type_table OFF SET IDENTITY_INSERT sales ON diff --git a/src/Service.Tests/GraphQLBuilder/Sql/SchemaConverterTests.cs b/src/Service.Tests/GraphQLBuilder/Sql/SchemaConverterTests.cs index 20bf8d158a..b4dae0bd36 100644 --- a/src/Service.Tests/GraphQLBuilder/Sql/SchemaConverterTests.cs +++ b/src/Service.Tests/GraphQLBuilder/Sql/SchemaConverterTests.cs @@ -226,6 +226,7 @@ public void MultipleColumnsAllMapped() [DataRow(typeof(decimal), DECIMAL_TYPE)] [DataRow(typeof(bool), BOOLEAN_TYPE)] [DataRow(typeof(DateTime), DATETIME_TYPE)] + [DataRow(typeof(DateTimeOffset), DATETIME_TYPE)] [DataRow(typeof(byte[]), BYTEARRAY_TYPE)] public void SystemTypeMapsToCorrectGraphQLType(Type systemType, string graphQLType) { diff --git a/src/Service.Tests/SqlTests/GraphQLPaginationTests/MsSqlGraphQLPaginationTests.cs b/src/Service.Tests/SqlTests/GraphQLPaginationTests/MsSqlGraphQLPaginationTests.cs index 31023fdc72..1a958ce783 100644 --- a/src/Service.Tests/SqlTests/GraphQLPaginationTests/MsSqlGraphQLPaginationTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLPaginationTests/MsSqlGraphQLPaginationTests.cs @@ -43,9 +43,21 @@ public static async Task SetupAsync(TestContext context) DisplayName = "Test after token for decimal values.")] [DataRow("boolean_types", "false", "true", 2, 4, DisplayName = "Test after token for boolean values.")] + [DataRow("date_types", "\"0001-01-01\"", + "\"9999-12-31\"", 3, 4, + DisplayName = "Test after token for date values.")] [DataRow("datetime_types", "\"1753-01-01T00:00:00.000\"", "\"9999-12-31T23:59:59\"", 3, 4, DisplayName = "Test after token for datetime values.")] + [DataRow("datetime2_types", "\"0001-01-01 00:00:00.0000000\"", + "\"9999-12-31T23:59:59.9999999\"", 3, 4, + DisplayName = "Test after token for datetime2 values.")] + [DataRow("datetimeoffset_types", "\"0001-01-01 00:00:00.0000000+0:00\"", + "\"9999-12-31T23:59:59.9999999+14:00\"", 3, 4, + DisplayName = "Test after token for datetimeoffset values.")] + [DataRow("smalldatetime_types", "\"1900-01-01 00:00:00\"", + "\"2079-06-06T00:00:00\"", 3, 4, + DisplayName = "Test after token for smalldate values.")] [DataRow("bytearray_types", "\"AAAAAA==\"", "\"/////w==\"", 3, 4, DisplayName = "Test after token for bytearray values.")] [TestMethod] diff --git a/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs b/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs index 6765b0caa0..c8e6313ce4 100644 --- a/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs +++ b/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs @@ -55,7 +55,16 @@ public static async Task SetupAsync(TestContext context) [DataRow("float_types eq 65535.9", "([float_types] = @param1)", DisplayName = "Equate float types.")] [DataRow("decimal_types eq 25.5", "([decimal_types] = @param1)", DisplayName = "Equate decimal types.")] [DataRow("boolean_types eq true", "([boolean_types] = @param1)", DisplayName = "Equate boolean types.")] - [DataRow("datetime_types eq 2023-01-24T12:51:59Z", "([datetime_types] = @param1)", DisplayName = "Equate datetime types.")] + [DataRow("date_types eq 9999-12-31", "([date_types] = @param1)", + DisplayName = "Equate date types.")] + [DataRow("datetime_types eq 2023-01-24T12:51:59Z", "([datetime_types] = @param1)", + DisplayName = "Equate datetime types.")] + [DataRow("datetime2_types eq 9998-12-31T21:59:59.99999Z", "([datetime2_types] = @param1)", + DisplayName = "Equate datetime2 types.")] + [DataRow("datetimeoffset_types eq 9998-12-31T21:59:59.99999-14:00", + "([datetimeoffset_types] = @param1)", DisplayName = "Equate datetimeoffset types.")] + [DataRow("smalldatetime_types eq 2079-06-06", "([smalldatetime_types] = @param1)", + DisplayName = "Equate smalldatetime types.")] [DataRow("bytearray_types eq 1000", "([bytearray_types] = @param1)", DisplayName = "Equate bytearray types.")] [DataRow("guid_types eq 9A19103F-16F7-4668-BE54-9A1E7A4F7556", "([guid_types] = @param1)", DisplayName = "Equate guid types.")] [TestMethod] diff --git a/src/Service/Parsers/EdmModelBuilder.cs b/src/Service/Parsers/EdmModelBuilder.cs index 1279c4817a..92de91423f 100644 --- a/src/Service/Parsers/EdmModelBuilder.cs +++ b/src/Service/Parsers/EdmModelBuilder.cs @@ -110,6 +110,7 @@ SourceDefinition sourceDefinition type = EdmPrimitiveTypeKind.Boolean; break; case "DateTime": + case "DateTimeOffset": type = EdmPrimitiveTypeKind.DateTimeOffset; break; case "Date": diff --git a/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs b/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs index f98d30b5c8..28cacf0650 100644 --- a/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs +++ b/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs @@ -353,6 +353,8 @@ protected object ParseParamAsSystemType(string param, Type systemType) "Decimal" => decimal.Parse(param), "Boolean" => bool.Parse(param), "DateTime" => DateTimeOffset.Parse(param), + "DateTimeOffset" => DateTimeOffset.Parse(param), + "Date" => DateOnly.Parse(param), "Guid" => Guid.Parse(param), _ => throw new NotSupportedException($"{systemType.Name} is not supported") };