Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fc59db7
Add isUnicode parameter to StringLiteralQueryType function
gilsonjoanelo Sep 24, 2024
b2c7eb9
Update code to use ternary operator
gilsonjoanelo Sep 25, 2024
4dd2e5a
Change to string.empty
gilsonjoanelo Sep 26, 2024
7b69cd2
Merge branch 'FirebirdSQL:master' into master
gilsonjoanelo Sep 26, 2024
a7574a0
Merge branch 'FirebirdSQL:master' into master
gilsonjoanelo Jan 12, 2025
751080c
Merge branch 'FirebirdSQL:master' into master
gilsonjoanelo May 25, 2025
776a927
Correção do erro Implementation limit exceeded
gilsonjoanelo May 26, 2025
a0525ab
fix build error
gilsonjoanelo May 27, 2025
cced2df
fix unit test errors
gilsonjoanelo May 27, 2025
385d9e4
fix build errors
gilsonjoanelo May 27, 2025
2029080
Merge branch 'FirebirdSQL:master' into master
gilsonjoanelo Nov 11, 2025
91f30fc
Merge branch 'master' of https://github.com/gilsonjoanelo/NETProvider
gilsonjoanelo Dec 18, 2025
0488e88
Correção Tests
gilsonjoanelo Dec 22, 2025
b9afe58
fix error NorthwindMiscellaneousQueryFbTest
gilsonjoanelo Dec 22, 2025
3e7176a
fix error
gilsonjoanelo Dec 22, 2025
45ee3c8
fix error NorthwindAggregateOperatorsQueryFbTest
gilsonjoanelo Dec 22, 2025
00ddffc
Merge branch 'FirebirdSQL:master' into master
gilsonjoanelo Jan 11, 2026
523011b
Translate >= && <= into BETWEEN in Firebird Entity Framework Core pro…
gilsonjoanelo Jan 11, 2026
ca5219c
Translate >= && <= into BETWEEN in Firebird Entity Framework Core pro…
gilsonjoanelo Jan 11, 2026
b311be9
Add function test for BETWEEN translation in Firebird
gilsonjoanelo Jan 11, 2026
5299e9c
fix tests
gilsonjoanelo Jan 11, 2026
6fc5023
Translate >= && <= into BETWEEN in Firebird Entity Framework Core pro…
gilsonjoanelo Jan 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
//$Authors = Jiri Cincura ([email protected])

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;
Expand All @@ -26,9 +28,13 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Query;

public class NorthwindAggregateOperatorsQueryFbTest : NorthwindAggregateOperatorsQueryRelationalTestBase<NorthwindQueryFbFixture<NoopModelCustomizer>>
{
private readonly NorthwindQueryFbFixture<NoopModelCustomizer> _fixture;

public NorthwindAggregateOperatorsQueryFbTest(NorthwindQueryFbFixture<NoopModelCustomizer> fixture)
: base(fixture)
{ }
{
_fixture = fixture;
}

[NotSupportedOnFirebirdTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -96,4 +102,29 @@ public override Task Average_over_nested_subquery(bool async)
{
return base.Average_over_nested_subquery(async);
}

[Theory]
[MemberData(nameof(IsAsyncData))]
public override async 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);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
//$Authors = Jiri Cincura ([email protected])

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;
Expand All @@ -27,9 +29,13 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests.Query;

public class NorthwindMiscellaneousQueryFbTest : NorthwindMiscellaneousQueryRelationalTestBase<NorthwindQueryFbFixture<NoopModelCustomizer>>
{
private readonly NorthwindQueryFbFixture<NoopModelCustomizer> _fixture;

public NorthwindMiscellaneousQueryFbTest(NorthwindQueryFbFixture<NoopModelCustomizer> fixture)
: base(fixture)
{ }
{
_fixture = fixture;
}

[Theory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -159,4 +165,24 @@ public override Task Where_nanosecond_and_microsecond_component(bool async)
{
return base.Where_nanosecond_and_microsecond_component(async);
}

[Theory]
[MemberData(nameof(IsAsyncData))]
public override async 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@

//$Authors = Jiri Cincura ([email protected])

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;
Expand Down Expand Up @@ -151,6 +154,37 @@ 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);
}

[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 };
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,23 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres
Sql.Append(")");
return sqlBinaryExpression;
}
else
else if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso)
{
return base.VisitSqlBinary(sqlBinaryExpression);
}

void BooleanToIntegralAndVisit(SqlExpression expression)
{
Sql.Append("IIF(");
Visit(expression);
Sql.Append(", 1, 0)");
if (sqlBinaryExpression.Left is SqlBinaryExpression left &&
sqlBinaryExpression.Right is SqlBinaryExpression right &&
left.OperatorType == ExpressionType.GreaterThanOrEqual &&
right.OperatorType == ExpressionType.LessThanOrEqual &&
left.Left.Equals(right.Left))
{
Visit(left.Left);
Sql.Append(" BETWEEN ");
Visit(left.Right);
Sql.Append(" AND ");
Visit(right.Right);
return sqlBinaryExpression;
}
}
return base.VisitSqlBinary(sqlBinaryExpression);
}

protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression)
Expand All @@ -170,7 +176,9 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame
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 ?? 0;
Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType(isUnicode, storeTypeNameBase, size));
}
else
{
Expand All @@ -192,8 +200,11 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant
if (shouldExplicitStringLiteralTypes)
{
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));
Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode, storeTypeNameBase, size));
Sql.Append(")");
}
return sqlConstantExpression;
Expand Down Expand Up @@ -413,4 +424,11 @@ void GenerateList<T>(IReadOnlyList<T> items, Action<T> generationAction, Action<
generationAction(items[i]);
}
}

void BooleanToIntegralAndVisit(SqlExpression expression)
{
Sql.Append("IIF(");
Visit(expression);
Sql.Append(", 1, 0)");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,38 @@ 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 = "", int size = 0)
{
var length = 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;
return $"VARCHAR({length}){charset}";
return $"{typeName}({maxSize}){charset}";
}

public virtual string StringParameterQueryType(bool isUnicode)
public virtual string StringParameterQueryType(bool isUnicode, string storeTypeNameBase = "", int size = 0)
{
var size = isUnicode ? FbTypeMappingSource.UnicodeVarcharMaxSize : FbTypeMappingSource.VarcharMaxSize;
return $"VARCHAR({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)
Expand All @@ -47,17 +68,16 @@ 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)
length = 1;
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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "", int size = 0);
string StringParameterQueryType(bool isUnicode, string storeTypeNameBase = "", int size = 0);
void GenerateBlockParameterName(StringBuilder builder, string name);
string AlternativeStatementTerminator { get; }
}
Loading