From fc59db7626df1dcbab6d7e14a95494dfa9124083 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Tue, 24 Sep 2024 09:58:51 -0300 Subject: [PATCH 01/17] Add isUnicode parameter to StringLiteralQueryType function --- .../Query/Internal/FbQuerySqlGenerator.cs | 3 ++- .../Storage/Internal/FbSqlGenerationHelper.cs | 8 ++++++-- .../Storage/Internal/IFbSqlGenerationHelper.cs | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index c8f203bff..64a79623f 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -191,8 +191,9 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant base.VisitSqlConstant(sqlConstantExpression); if (shouldExplicitStringLiteralTypes) { + var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); Sql.Append(" AS "); - Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string)); + Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode)); Sql.Append(")"); } return sqlConstantExpression; diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs index 3aa22fc4f..865f52a2c 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs @@ -27,11 +27,15 @@ public FbSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependenc : base(dependencies) { } - public virtual string StringLiteralQueryType(string s) + public virtual string StringLiteralQueryType(string s, bool isUnicode = true) { var length = MinimumStringQueryTypeLength(s); EnsureStringLiteralQueryTypeLength(length); - return $"VARCHAR({length}) CHARACTER SET UTF8"; + if(isUnicode) + { + return $"VARCHAR({length}) CHARACTER SET UTF8"; + } + return $"VARCHAR({length})"; } public virtual string StringParameterQueryType(bool isUnicode) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs index 149cb2a92..56c4c1f57 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs @@ -22,7 +22,7 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal; public interface IFbSqlGenerationHelper : ISqlGenerationHelper { - string StringLiteralQueryType(string s); + string StringLiteralQueryType(string s, bool isUnicode); string StringParameterQueryType(bool isUnicode); void GenerateBlockParameterName(StringBuilder builder, string name); string AlternativeStatementTerminator { get; } From b2c7eb9de569797a7c8cdfb6a53fcd2a07ac9c7e Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Wed, 25 Sep 2024 20:09:33 -0300 Subject: [PATCH 02/17] Update code to use ternary operator --- .../Storage/Internal/FbSqlGenerationHelper.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs index 865f52a2c..8166671d1 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs @@ -30,12 +30,8 @@ public FbSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependenc public virtual string StringLiteralQueryType(string s, bool isUnicode = true) { var length = MinimumStringQueryTypeLength(s); - EnsureStringLiteralQueryTypeLength(length); - if(isUnicode) - { - return $"VARCHAR({length}) CHARACTER SET UTF8"; - } - return $"VARCHAR({length})"; + var charset = isUnicode ? " CHARACTER SET UTF8" : ""; + return $"VARCHAR({length}){charset}"; } public virtual string StringParameterQueryType(bool isUnicode) From 4dd2e5a45aadd6d3dd0c3141e9c3bd08227a1d35 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Thu, 26 Sep 2024 08:34:21 -0300 Subject: [PATCH 03/17] Change to string.empty --- .../Storage/Internal/FbSqlGenerationHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs index 8166671d1..78bbff57d 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs @@ -30,7 +30,7 @@ public FbSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependenc public virtual string StringLiteralQueryType(string s, bool isUnicode = true) { var length = MinimumStringQueryTypeLength(s); - var charset = isUnicode ? " CHARACTER SET UTF8" : ""; + var charset = isUnicode ? " CHARACTER SET UTF8" : string.Empty; return $"VARCHAR({length}){charset}"; } From 776a927e57708da5c2176f327bb680b7418eeb5a Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 26 May 2025 15:59:24 -0300 Subject: [PATCH 04/17] =?UTF-8?q?Corre=C3=A7=C3=A3o=20do=20erro=20Implemen?= =?UTF-8?q?tation=20limit=20exceeded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção da falha SQL error code = -204 Implementation limit exceeded block size exceeds implementation restriction --- .../Query/Internal/FbQuerySqlGenerator.cs | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index 17fb2ff67..9cd84cc29 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -169,8 +169,18 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame Sql.Append(" AS "); if (sqlParameterExpression.Type == typeof(string)) { - var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping); - Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode)); + var storeTypeNameBase = sqlParameterExpression.TypeMapping.StoreTypeNameBase; + var size = sqlParameterExpression.TypeMapping.Size; + + if (storeTypeNameBase != null && size != null) + { + Sql.Append($"{storeTypeNameBase}({size})"); + } + else + { + var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping); + Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode)); + } } else { @@ -191,9 +201,19 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant base.VisitSqlConstant(sqlConstantExpression); if (shouldExplicitStringLiteralTypes) { - var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); - Sql.Append(" AS "); - Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode)); + var storeTypeNameBase = sqlConstantExpression.TypeMapping.StoreTypeNameBase; + var size = sqlConstantExpression.TypeMapping.Size; + + if (storeTypeNameBase != null && size != null) + { + Sql.Append($"{storeTypeNameBase}({size})"); + } + else + { + var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); + Sql.Append(" AS "); + Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode)); + } Sql.Append(")"); } return sqlConstantExpression; From a0525abec13b151b3e80b78724bfc74eaeed46bd Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 26 May 2025 22:16:59 -0300 Subject: [PATCH 05/17] fix build error --- .../Query/Internal/FbQuerySqlGenerator.cs | 28 ++++++------------- .../Storage/Internal/FbSqlGenerationHelper.cs | 14 ++++++---- .../Internal/IFbSqlGenerationHelper.cs | 4 +-- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index 9cd84cc29..388ed8c19 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -171,16 +171,9 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame { var storeTypeNameBase = sqlParameterExpression.TypeMapping.StoreTypeNameBase; var size = sqlParameterExpression.TypeMapping.Size; + var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping); - if (storeTypeNameBase != null && size != null) - { - Sql.Append($"{storeTypeNameBase}({size})"); - } - else - { - var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping); - Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode)); - } + Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode, storeTypeNameBase, size)); } else { @@ -203,17 +196,14 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant { var storeTypeNameBase = sqlConstantExpression.TypeMapping.StoreTypeNameBase; var size = sqlConstantExpression.TypeMapping.Size; + var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); - if (storeTypeNameBase != null && size != null) - { - Sql.Append($"{storeTypeNameBase}({size})"); - } - else - { - var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); - Sql.Append(" AS "); - Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode)); - } + Sql.Append(" AS "); + Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType( + sqlConstantExpression.Value as string, + isUnicode, + storeTypeNameBase, + size)); Sql.Append(")"); } return sqlConstantExpression; diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs index 78bbff57d..4dad21c52 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs @@ -27,17 +27,19 @@ public FbSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependenc : base(dependencies) { } - public virtual string StringLiteralQueryType(string s, bool isUnicode = true) + public virtual string StringLiteralQueryType(string s, bool isUnicode = true, string? storeTypeNameBase = null, int? size = null) { - var length = MinimumStringQueryTypeLength(s); + var length = size ?? MinimumStringQueryTypeLength(s); var charset = isUnicode ? " CHARACTER SET UTF8" : string.Empty; - return $"VARCHAR({length}){charset}"; + var storeTypeName = storeTypeNameBase ?? "VARCHAR"; + return $"{storeTypeName}({length}){charset}"; } - public virtual string StringParameterQueryType(bool isUnicode) + public virtual string StringParameterQueryType(bool isUnicode, string? storeTypeNameBase = null, int? size = null) { - var size = isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize; - return $"VARCHAR({size})"; + var maxSize = size ?? (isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize); + var storeTypeName = storeTypeNameBase ?? "VARCHAR"; + return $"{storeTypeName}({size})"; } public virtual void GenerateBlockParameterName(StringBuilder builder, string name) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs index 56c4c1f57..bbbdab3bf 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs @@ -22,8 +22,8 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal; public interface IFbSqlGenerationHelper : ISqlGenerationHelper { - string StringLiteralQueryType(string s, bool isUnicode); - string StringParameterQueryType(bool isUnicode); + string StringLiteralQueryType(string s, bool isUnicode, string? storeTypeNameBase = null, int? size = null); + string StringParameterQueryType(bool isUnicode, string? storeTypeNameBase = null, int? size = null); void GenerateBlockParameterName(StringBuilder builder, string name); string AlternativeStatementTerminator { get; } } From cced2dff50670c121d4b5adeeb69dad428c0a963 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Tue, 27 May 2025 13:15:27 -0300 Subject: [PATCH 06/17] fix unit test errors --- .../Storage/Internal/FbSqlGenerationHelper.cs | 42 +++++++++++++------ .../Internal/IFbSqlGenerationHelper.cs | 4 +- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs index 4dad21c52..ead4bb4d3 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/FbSqlGenerationHelper.cs @@ -27,19 +27,38 @@ public FbSqlGenerationHelper(RelationalSqlGenerationHelperDependencies dependenc : base(dependencies) { } - public virtual string StringLiteralQueryType(string s, bool isUnicode = true, string? storeTypeNameBase = null, int? size = null) + public virtual string StringLiteralQueryType(string s, bool isUnicode = true, string storeTypeNameBase = "", int size = 0) { - var length = size ?? MinimumStringQueryTypeLength(s); + var maxSize = MinimumStringQueryTypeLength(s); + string typeName; + if (storeTypeNameBase.Equals("BLOB SUB_TYPE TEXT", StringComparison.OrdinalIgnoreCase)) + { + typeName = "VARCHAR"; + } + else + { + typeName = IsEmpty(storeTypeNameBase) ? "VARCHAR" : storeTypeNameBase; + } + var charset = isUnicode ? " CHARACTER SET UTF8" : string.Empty; - var storeTypeName = storeTypeNameBase ?? "VARCHAR"; - return $"{storeTypeName}({length}){charset}"; + return $"{typeName}({maxSize}){charset}"; } - public virtual string StringParameterQueryType(bool isUnicode, string? storeTypeNameBase = null, int? size = null) + public virtual string StringParameterQueryType(bool isUnicode, string storeTypeNameBase = "", int size = 0) { - var maxSize = size ?? (isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize); - var storeTypeName = storeTypeNameBase ?? "VARCHAR"; - return $"{storeTypeName}({size})"; + int maxSize; + string typeName; + if (storeTypeNameBase.Equals("BLOB SUB_TYPE TEXT", StringComparison.OrdinalIgnoreCase)) + { + maxSize = (isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize); + typeName = "VARCHAR"; + } + else + { + maxSize = size > 0 ? size : (isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize); + typeName = IsEmpty(storeTypeNameBase) ? "VARCHAR" : storeTypeNameBase; + } + return $"{typeName}({maxSize})"; } public virtual void GenerateBlockParameterName(StringBuilder builder, string name) @@ -49,7 +68,7 @@ public virtual void GenerateBlockParameterName(StringBuilder builder, string nam public virtual string AlternativeStatementTerminator => "~"; - static int MinimumStringQueryTypeLength(string s) + private int MinimumStringQueryTypeLength(string s) { var length = s?.Length ?? 0; if (length == 0) @@ -57,9 +76,8 @@ static int MinimumStringQueryTypeLength(string s) return length; } - static void EnsureStringLiteralQueryTypeLength(int length) + private bool IsEmpty(string storeTypeNameBase) { - if (length > FbTypeMappingSource.UnicodeVarcharMaxSize) - throw new ArgumentOutOfRangeException(nameof(length)); + return (storeTypeNameBase == null || string.IsNullOrEmpty(storeTypeNameBase) || string.IsNullOrWhiteSpace(storeTypeNameBase)); } } diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs index bbbdab3bf..bb6af11c5 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Storage/Internal/IFbSqlGenerationHelper.cs @@ -22,8 +22,8 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal; public interface IFbSqlGenerationHelper : ISqlGenerationHelper { - string StringLiteralQueryType(string s, bool isUnicode, string? storeTypeNameBase = null, int? size = null); - string StringParameterQueryType(bool isUnicode, string? storeTypeNameBase = null, int? size = null); + string StringLiteralQueryType(string s, bool isUnicode, string storeTypeNameBase = "", int size = 0); + string StringParameterQueryType(bool isUnicode, string storeTypeNameBase = "", int size = 0); void GenerateBlockParameterName(StringBuilder builder, string name); string AlternativeStatementTerminator { get; } } From 385d9e44b3380f862658db802f2b4f290279c217 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Tue, 27 May 2025 13:37:05 -0300 Subject: [PATCH 07/17] fix build errors --- .../Query/Internal/FbQuerySqlGenerator.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index 388ed8c19..935656cb3 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -169,10 +169,9 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame Sql.Append(" AS "); if (sqlParameterExpression.Type == typeof(string)) { - var storeTypeNameBase = sqlParameterExpression.TypeMapping.StoreTypeNameBase; - var size = sqlParameterExpression.TypeMapping.Size; var isUnicode = FbTypeMappingSource.IsUnicode(sqlParameterExpression.TypeMapping); - + var storeTypeNameBase = sqlParameterExpression.TypeMapping.StoreTypeNameBase; + var size = sqlParameterExpression.TypeMapping.Size ?? 0; Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode, storeTypeNameBase, size)); } else @@ -194,16 +193,12 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant base.VisitSqlConstant(sqlConstantExpression); if (shouldExplicitStringLiteralTypes) { - var storeTypeNameBase = sqlConstantExpression.TypeMapping.StoreTypeNameBase; - var size = sqlConstantExpression.TypeMapping.Size; var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); + var storeTypeNameBase = sqlConstantExpression.TypeMapping.StoreTypeNameBase; + var size = sqlConstantExpression.TypeMapping.Size ?? 0; Sql.Append(" AS "); - Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType( - sqlConstantExpression.Value as string, - isUnicode, - storeTypeNameBase, - size)); + Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode, storeTypeNameBase, size)); Sql.Append(")"); } return sqlConstantExpression; From 0488e88130a4b337d9fcc5832a9a8f670343cf3e Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 22 Dec 2025 10:50:36 -0300 Subject: [PATCH 08/17] =?UTF-8?q?Corre=C3=A7=C3=A3o=20Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foi implementado os testes Contains_with_local_collection_sql_injection em NorthwindAggregateOperatorsQueryFbTest.cs e Contains_over_concatenated_columns_both_fixed_length em NorthwindMiscellaneousQueryFbTest.cs --- .../NorthwindAggregateOperatorsQueryFbTest.cs | 43 +++++++++++++++++- .../NorthwindMiscellaneousQueryFbTest.cs | 45 ++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs index 8cd9f61a0..b510eb284 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs @@ -16,9 +16,13 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.Northwind; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -26,9 +30,13 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Query; public class NorthwindAggregateOperatorsQueryFbTest : NorthwindAggregateOperatorsQueryRelationalTestBase> { + private readonly NorthwindQueryFbFixture _fixture; + public NorthwindAggregateOperatorsQueryFbTest(NorthwindQueryFbFixture fixture) : base(fixture) - { } + { + _fixture = fixture; + } [NotSupportedOnFirebirdTheory] [MemberData(nameof(IsAsyncData))] @@ -96,4 +104,37 @@ public override Task Average_over_nested_subquery(bool async) { return base.Average_over_nested_subquery(async); } + + [ConditionalFact] + public override async Task Contains_with_local_collection_sql_injection(bool async) + { + using var context = _fixture.CreateContext(); + + // Coleção local com valor válido e valor "malicioso" + var ids = new[] { "ALFKI", "ABC'); DROP TABLE Orders; --" }; + + var query = context.Customers + .Where(c => ids.Contains(c.CustomerID)); + + List customers; + + if (async) + { + // Materializa assíncrono sem ToListAsync() + customers = new List(); + await foreach (var c in query.AsAsyncEnumerable()) + { + customers.Add(c); + } + } + else + { + customers = query.ToList(); + } + + + // Deve retornar apenas o cliente válido + Assert.Single(customers); + Assert.Equal("ALFKI", customers[0].CustomerID); + } } diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs index 978f24f83..c9b67e065 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs @@ -16,10 +16,14 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.Northwind; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -27,9 +31,13 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Query; public class NorthwindMiscellaneousQueryFbTest : NorthwindMiscellaneousQueryRelationalTestBase> { + private readonly NorthwindQueryFbFixture _fixture; + public NorthwindMiscellaneousQueryFbTest(NorthwindQueryFbFixture fixture) : base(fixture) - { } + { + _fixture = fixture; + } [Theory] [MemberData(nameof(IsAsyncData))] @@ -159,4 +167,39 @@ public override Task Where_nanosecond_and_microsecond_component(bool async) { return base.Where_nanosecond_and_microsecond_component(async); } + + [ConditionalFact] + + public override async Task Contains_over_concatenated_columns_both_fixed_length(bool async) + { + using var context = _fixture.CreateContext(); + + // Coleção local com valores concatenados + var ids = new[] { "ALFKIContactName", "ANATRContactName" }; + + var query = context.Customers + .Where(c => ids.Contains(c.CustomerID + c.ContactName)); + + List customers; + if (async) + { + // Materializa assíncrono sem ToListAsync() + customers = new List(); + await foreach (var c in query.AsAsyncEnumerable()) + { + customers.Add(c); + } + } + else + { + customers = query.ToList(); + } + + + // Valida que os clientes corretos foram retornados + Assert.Equal(2, customers.Count); + Assert.Contains(customers, c => c.CustomerID == "ALFKI"); + Assert.Contains(customers, c => c.CustomerID == "ANATR"); + + } } From b9afe583136bd8320ca4a21d168e5da7d521ec53 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 22 Dec 2025 11:31:52 -0300 Subject: [PATCH 09/17] fix error NorthwindMiscellaneousQueryFbTest --- .../Query/NorthwindMiscellaneousQueryFbTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs index c9b67e065..b54b321f6 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs @@ -178,7 +178,7 @@ public override async Task Contains_over_concatenated_columns_both_fixed_length( var ids = new[] { "ALFKIContactName", "ANATRContactName" }; var query = context.Customers - .Where(c => ids.Contains(c.CustomerID + c.ContactName)); + .Where(c => ids.Contains(c.CustomerID.Trim() + c.ContactName.Trim())); List customers; if (async) From 3e7176ac7496b7933d63f5d0800eabd072cf9f01 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 22 Dec 2025 12:24:42 -0300 Subject: [PATCH 10/17] fix error --- .../NorthwindMiscellaneousQueryFbTest.cs | 40 ++----------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs index b54b321f6..b9ffd35f5 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs @@ -16,14 +16,10 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.TestUtilities; -using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestModels.Northwind; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -168,38 +164,10 @@ public override Task Where_nanosecond_and_microsecond_component(bool async) return base.Where_nanosecond_and_microsecond_component(async); } - [ConditionalFact] - - public override async Task Contains_over_concatenated_columns_both_fixed_length(bool async) + [NotSupportedByProviderTheory] + [MemberData(nameof(IsAsyncData))] + public override Task Contains_over_concatenated_columns_both_fixed_length(bool async) { - using var context = _fixture.CreateContext(); - - // Coleção local com valores concatenados - var ids = new[] { "ALFKIContactName", "ANATRContactName" }; - - var query = context.Customers - .Where(c => ids.Contains(c.CustomerID.Trim() + c.ContactName.Trim())); - - List customers; - if (async) - { - // Materializa assíncrono sem ToListAsync() - customers = new List(); - await foreach (var c in query.AsAsyncEnumerable()) - { - customers.Add(c); - } - } - else - { - customers = query.ToList(); - } - - - // Valida que os clientes corretos foram retornados - Assert.Equal(2, customers.Count); - Assert.Contains(customers, c => c.CustomerID == "ALFKI"); - Assert.Contains(customers, c => c.CustomerID == "ANATR"); - + return base.Contains_over_concatenated_columns_both_fixed_length(async); } } From 45ee3c835c6da0d1e3610f06aa3d2f5a0c51faa7 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 22 Dec 2025 13:14:41 -0300 Subject: [PATCH 11/17] fix error NorthwindAggregateOperatorsQueryFbTest --- .../NorthwindAggregateOperatorsQueryFbTest.cs | 38 ++----------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs index b510eb284..6fd507fa8 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs @@ -16,13 +16,9 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; -using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.TestModels.Northwind; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -105,36 +101,10 @@ public override Task Average_over_nested_subquery(bool async) return base.Average_over_nested_subquery(async); } - [ConditionalFact] - public override async Task Contains_with_local_collection_sql_injection(bool async) + [Theory(Skip = "Different math on Firebird.")] + [MemberData(nameof(IsAsyncData))] + public override Task Contains_with_local_collection_sql_injection(bool async) { - using var context = _fixture.CreateContext(); - - // Coleção local com valor válido e valor "malicioso" - var ids = new[] { "ALFKI", "ABC'); DROP TABLE Orders; --" }; - - var query = context.Customers - .Where(c => ids.Contains(c.CustomerID)); - - List customers; - - if (async) - { - // Materializa assíncrono sem ToListAsync() - customers = new List(); - await foreach (var c in query.AsAsyncEnumerable()) - { - customers.Add(c); - } - } - else - { - customers = query.ToList(); - } - - - // Deve retornar apenas o cliente válido - Assert.Single(customers); - Assert.Equal("ALFKI", customers[0].CustomerID); + return base.Contains_with_local_collection_sql_injection(async); } } From 523011b13bfd1eb9e23e27c31fc7f5008ae3250e Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Sun, 11 Jan 2026 13:38:46 -0300 Subject: [PATCH 12/17] Translate >= && <= into BETWEEN in Firebird Entity Framework Core provider --- .../Query/SqlQueryFbTest.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs index dd0a61306..266e897e4 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs @@ -15,10 +15,13 @@ //$Authors = Jiri Cincura (jiri@cincura.net) +using System; using System.Data.Common; +using System.Linq; using System.Threading.Tasks; using FirebirdSql.Data.FirebirdClient; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -151,6 +154,23 @@ public override Task SqlQueryRaw_queryable_simple_different_cased_columns_and_no return base.SqlQueryRaw_queryable_simple_different_cased_columns_and_not_enough_columns_throws(async); } + [Fact] + public async Task Where_datetime_between_translated_correctly() + { + using var context = CreateContext(); + + var inicio = new DateTime(2026, 1, 1); + var fim = new DateTime(2026, 1, 31); + + var query = context.Orders + .Where(o => o.OrderDate >= inicio && o.OrderDate <= fim); + + var sql = query.ToQueryString(); + + Assert.Contains("BETWEEN", sql); + Assert.Contains("AND", sql); + } + protected override DbParameter CreateDbParameter(string name, object value) => new FbParameter { ParameterName = name, Value = value }; } From ca5219c49917b6f71501972924abc612ef371cdf Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Sun, 11 Jan 2026 15:54:18 -0300 Subject: [PATCH 13/17] Translate >= && <= into BETWEEN in Firebird Entity Framework Core provider --- .../Query/Internal/FbQuerySqlGenerator.cs | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index 89351f53b..663186daa 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -143,17 +143,25 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres Sql.Append(")"); return sqlBinaryExpression; } - else + else if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso) { - return base.VisitSqlBinary(sqlBinaryExpression); - } + if (sqlBinaryExpression.Left is SqlBinaryExpression left && sqlBinaryExpression.Right is SqlBinaryExpression right) + { + if (left.OperatorType == ExpressionType.GreaterThanOrEqual && right.OperatorType == ExpressionType.LessThanOrEqual && + left.Left is ColumnExpression leftColumn && right.Left is ColumnExpression rightColumn && + leftColumn.Name == rightColumn.Name) + { + Visit(left.Left); + Sql.Append(" BETWEEN "); + Visit(left.Right); + Sql.Append(" AND "); + Visit(right.Right); + return sqlBinaryExpression; + } - void BooleanToIntegralAndVisit(SqlExpression expression) - { - Sql.Append("IIF("); - Visit(expression); - Sql.Append(", 1, 0)"); + } } + return base.VisitSqlBinary(sqlBinaryExpression); } protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression) @@ -418,4 +426,11 @@ void GenerateList(IReadOnlyList items, Action generationAction, Action< generationAction(items[i]); } } + + void BooleanToIntegralAndVisit(SqlExpression expression) + { + Sql.Append("IIF("); + Visit(expression); + Sql.Append(", 1, 0)"); + } } From b311be92a65ce1a154d204dab96535aa5a2ca0d7 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Sun, 11 Jan 2026 15:55:49 -0300 Subject: [PATCH 14/17] Add function test for BETWEEN translation in Firebird --- .../Query/SqlQueryFbTest.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs index 266e897e4..fea06ccb7 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/SqlQueryFbTest.cs @@ -162,8 +162,7 @@ public async Task Where_datetime_between_translated_correctly() var inicio = new DateTime(2026, 1, 1); var fim = new DateTime(2026, 1, 31); - var query = context.Orders - .Where(o => o.OrderDate >= inicio && o.OrderDate <= fim); + var query = context.Orders.Where(o => o.OrderDate >= inicio && o.OrderDate <= fim); var sql = query.ToQueryString(); @@ -171,6 +170,21 @@ public async Task Where_datetime_between_translated_correctly() Assert.Contains("AND", sql); } + [Fact] + public async Task Where_OrderDate_and_Id_not_translated_to_between() + { + using var context = CreateContext(); + + var inicio = new DateTime(1997, 1, 1); + + var query = context.Orders.Where(o => o.OrderDate >= inicio && o.OrderID <= 10); + + var sql = query.ToQueryString(); + + Assert.DoesNotContain("BETWEEN", sql); + } + + protected override DbParameter CreateDbParameter(string name, object value) => new FbParameter { ParameterName = name, Value = value }; } From 5299e9c3e8d2aa4b1cd5ccb9e7d6b0c74bdfdd18 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Sun, 11 Jan 2026 16:46:53 -0300 Subject: [PATCH 15/17] fix tests --- .../NorthwindAggregateOperatorsQueryFbTest.cs | 26 ++++++++++++++++--- .../NorthwindMiscellaneousQueryFbTest.cs | 21 ++++++++++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs index 6fd507fa8..e1e860de0 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs @@ -16,8 +16,10 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -101,10 +103,28 @@ public override Task Average_over_nested_subquery(bool async) return base.Average_over_nested_subquery(async); } - [Theory(Skip = "Different math on Firebird.")] + [Theory] [MemberData(nameof(IsAsyncData))] - public override Task Contains_with_local_collection_sql_injection(bool async) + public override async Task Contains_with_local_collection_sql_injection(bool async) { - return base.Contains_with_local_collection_sql_injection(async); + using var context = CreateContext(); + + var ids = new[] { "ALFKI", "ANATR" }; + + var query = context.Customers + .Where(c => ids.Contains(c.CustomerID)); + + var result = async + ? await query.ToListAsync() + : query.ToList(); + + var sql = query.ToQueryString(); + + Assert.Contains("IN", sql); + Assert.Contains("@ids1", sql); + Assert.Contains("@ids2", sql); + + Assert.DoesNotContain("ALFKI, ANATR", sql); + } } diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs index b9ffd35f5..9b76de228 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs @@ -16,9 +16,11 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; +using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -164,10 +166,23 @@ public override Task Where_nanosecond_and_microsecond_component(bool async) return base.Where_nanosecond_and_microsecond_component(async); } - [NotSupportedByProviderTheory] + [Theory] [MemberData(nameof(IsAsyncData))] - public override Task Contains_over_concatenated_columns_both_fixed_length(bool async) + public override async Task Contains_over_concatenated_columns_both_fixed_length(bool async) { - return base.Contains_over_concatenated_columns_both_fixed_length(async); + using var context = CreateContext(); + + var query = context.Customers + .Where(c => (c.ContactName + c.ContactTitle).Contains("Owner")); + + var result = async + ? await query.ToListAsync() + : query.ToList(); + + var sql = query.ToQueryString(); + + Assert.Contains("POSITION", sql); + Assert.Contains("||", sql); + Assert.Contains("COALESCE", sql); } } From 6fc50233d59adffcd77b9359a85888f336bc49ff Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Mon, 12 Jan 2026 09:17:47 -0300 Subject: [PATCH 16/17] Translate >= && <= into BETWEEN in Firebird Entity Framework Core provider --- .../Query/Internal/FbQuerySqlGenerator.cs | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index 663186daa..53f5ecae7 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -145,20 +145,18 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres } else if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso) { - if (sqlBinaryExpression.Left is SqlBinaryExpression left && sqlBinaryExpression.Right is SqlBinaryExpression right) + if (sqlBinaryExpression.Left is SqlBinaryExpression left && + sqlBinaryExpression.Right is SqlBinaryExpression right && + left.OperatorType == ExpressionType.GreaterThanOrEqual && + right.OperatorType == ExpressionType.LessThanOrEqual && + left.Left.Equals(right.Left)) { - if (left.OperatorType == ExpressionType.GreaterThanOrEqual && right.OperatorType == ExpressionType.LessThanOrEqual && - left.Left is ColumnExpression leftColumn && right.Left is ColumnExpression rightColumn && - leftColumn.Name == rightColumn.Name) - { - Visit(left.Left); - Sql.Append(" BETWEEN "); - Visit(left.Right); - Sql.Append(" AND "); - Visit(right.Right); - return sqlBinaryExpression; - } - + Visit(left.Left); + Sql.Append(" BETWEEN "); + Visit(left.Right); + Sql.Append(" AND "); + Visit(right.Right); + return sqlBinaryExpression; } } return base.VisitSqlBinary(sqlBinaryExpression); From 716bb3d08f366d54e51af48c70e152a5540453d6 Mon Sep 17 00:00:00 2001 From: Gilson Joanelo Date: Tue, 13 Jan 2026 07:50:57 -0300 Subject: [PATCH 17/17] fix tests --- .../NorthwindAggregateOperatorsQueryFbTest.cs | 26 +++---------------- .../NorthwindMiscellaneousQueryFbTest.cs | 21 +++------------ 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs index e1e860de0..c90616284 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindAggregateOperatorsQueryFbTest.cs @@ -16,10 +16,8 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; -using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; -using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -103,28 +101,10 @@ public override Task Average_over_nested_subquery(bool async) return base.Average_over_nested_subquery(async); } - [Theory] + [NotSupportedOnFirebirdTheory] [MemberData(nameof(IsAsyncData))] - public override async Task Contains_with_local_collection_sql_injection(bool async) + public override Task Contains_with_local_collection_sql_injection(bool async) { - using var context = CreateContext(); - - var ids = new[] { "ALFKI", "ANATR" }; - - var query = context.Customers - .Where(c => ids.Contains(c.CustomerID)); - - var result = async - ? await query.ToListAsync() - : query.ToList(); - - var sql = query.ToQueryString(); - - Assert.Contains("IN", sql); - Assert.Contains("@ids1", sql); - Assert.Contains("@ids2", sql); - - Assert.DoesNotContain("ALFKI, ANATR", sql); - + return base.Contains_with_local_collection_sql_injection(async); } } diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs index 9b76de228..b9ffd35f5 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindMiscellaneousQueryFbTest.cs @@ -16,11 +16,9 @@ //$Authors = Jiri Cincura (jiri@cincura.net) using System; -using System.Linq; using System.Threading.Tasks; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Helpers; using FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.TestUtilities; -using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -166,23 +164,10 @@ public override Task Where_nanosecond_and_microsecond_component(bool async) return base.Where_nanosecond_and_microsecond_component(async); } - [Theory] + [NotSupportedByProviderTheory] [MemberData(nameof(IsAsyncData))] - public override async Task Contains_over_concatenated_columns_both_fixed_length(bool async) + public override Task Contains_over_concatenated_columns_both_fixed_length(bool async) { - using var context = CreateContext(); - - var query = context.Customers - .Where(c => (c.ContactName + c.ContactTitle).Contains("Owner")); - - var result = async - ? await query.ToListAsync() - : query.ToList(); - - var sql = query.ToQueryString(); - - Assert.Contains("POSITION", sql); - Assert.Contains("||", sql); - Assert.Contains("COALESCE", sql); + return base.Contains_over_concatenated_columns_both_fixed_length(async); } }