diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindJoinQueryFbTest.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindJoinQueryFbTest.cs index 072b8cae..752c804f 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindJoinQueryFbTest.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/NorthwindJoinQueryFbTest.cs @@ -29,21 +29,21 @@ public NorthwindJoinQueryFbTest(NorthwindQueryFbFixture fix : base(fixture) { } - [NotSupportedOnFirebirdTheory] + [Theory] [MemberData(nameof(IsAsyncData))] public override Task GroupJoin_as_final_operator(bool async) { return base.GroupJoin_as_final_operator(async); } - [NotSupportedOnFirebirdTheory] + [Theory] [MemberData(nameof(IsAsyncData))] public override Task GroupJoin_SelectMany_subquery_with_filter_orderby(bool async) { return base.GroupJoin_SelectMany_subquery_with_filter_orderby(async); } - [NotSupportedOnFirebirdTheory] + [Theory] [MemberData(nameof(IsAsyncData))] public override Task GroupJoin_SelectMany_subquery_with_filter_orderby_and_DefaultIfEmpty(bool async) { @@ -99,14 +99,14 @@ public override Task Take_in_collection_projection_with_FirstOrDefault_on_top_le return base.Take_in_collection_projection_with_FirstOrDefault_on_top_level(async); } - [NotSupportedOnFirebirdTheory] + [Theory] [MemberData(nameof(IsAsyncData))] public override Task Unflattened_GroupJoin_composed(bool async) { return base.Unflattened_GroupJoin_composed(async); } - [NotSupportedOnFirebirdTheory] + [Theory] [MemberData(nameof(IsAsyncData))] public override Task Unflattened_GroupJoin_composed_2(bool async) { diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/UdfDbFunctionFbTests.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/UdfDbFunctionFbTests.cs index 937a842d..c524c8b3 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/UdfDbFunctionFbTests.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird.FunctionalTests/Query/UdfDbFunctionFbTests.cs @@ -51,7 +51,7 @@ public override void Udf_with_argument_being_comparison_of_nullable_columns() base.Udf_with_argument_being_comparison_of_nullable_columns(); } - [NotSupportedOnFirebirdFact] + [Fact] public override void QF_Select_Correlated_Subquery_In_Anonymous_MultipleCollections() { base.QF_Select_Correlated_Subquery_In_Anonymous_MultipleCollections(); diff --git a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs index 17fb2ff6..2e899cea 100644 --- a/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs +++ b/src/FirebirdSql.EntityFrameworkCore.Firebird/Query/Internal/FbQuerySqlGenerator.cs @@ -191,7 +191,7 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant base.VisitSqlConstant(sqlConstantExpression); if (shouldExplicitStringLiteralTypes) { - var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); + var isUnicode = FbTypeMappingSource.IsUnicode(sqlConstantExpression.TypeMapping); Sql.Append(" AS "); Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string, isUnicode)); Sql.Append(")"); @@ -280,6 +280,60 @@ protected override void GenerateOrderings(SelectExpression selectExpression) } } + // Adapted from Npgsql Entity Framework Core provider + // (https://github.com/npgsql/efcore.pg) + // Copyright (c) 2002-2021, Npgsql + protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression) + { + Sql.Append("JOIN LATERAL "); + + if (crossApplyExpression.Table is TableExpression table) + { + // Firebird doesn't support LATERAL JOIN over table, and it doesn't really make sense to do it - but EF Core + // will sometimes generate that. + Sql + .Append("(SELECT * FROM ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table.Name, table.Schema)) + .Append(")") + .Append(AliasSeparator) + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table.Alias)); + } + else + { + Visit(crossApplyExpression.Table); + } + + Sql.Append(" ON TRUE"); + return crossApplyExpression; + } + + // Adapted from Npgsql Entity Framework Core provider + // (https://github.com/npgsql/efcore.pg) + // Copyright (c) 2002-2021, Npgsql + protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression) + { + Sql.Append("LEFT JOIN LATERAL "); + + if (outerApplyExpression.Table is TableExpression table) + { + // Firebird doesn't support LATERAL JOIN over table, and it doesn't really make sense to do it - but EF Core + // will sometimes generate that. + Sql + .Append("(SELECT * FROM ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table.Name, table.Schema)) + .Append(")") + .Append(AliasSeparator) + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table.Alias)); + } + else + { + Visit(outerApplyExpression.Table); + } + + Sql.Append(" ON TRUE"); + return outerApplyExpression; + } + protected override void GeneratePseudoFromClause() { Sql.Append(" FROM RDB$DATABASE");