From af90a6678e19a56c48706ac0ec39fea70ee1b6cd Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 28 Oct 2024 07:54:56 +0100 Subject: [PATCH] Allow SqlFragmentExpression to have a type/type mapping --- .../Query/ISqlExpressionFactory.cs | 4 +++- src/EFCore.Relational/Query/SqlExpressionFactory.cs | 4 ++-- .../Query/SqlExpressions/SelectExpression.cs | 2 +- .../Query/SqlExpressions/SqlFragmentExpression.cs | 13 +++++++++---- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs index 7308836e749..2712bec47ed 100644 --- a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs @@ -435,6 +435,8 @@ SqlExpression NiladicFunction( /// Creates a new which represents a SQL token. /// /// A string token to print in SQL tree. + /// The of the expression. Defaults to . + /// The associated with the expression. /// An expression representing a SQL token. - SqlExpression Fragment(string sql); + SqlExpression Fragment(string sql, Type? type = null, RelationalTypeMapping? typeMapping = null); } diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 976d024e282..064e97cbe74 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -956,8 +956,8 @@ public virtual SqlExpression Like(SqlExpression match, SqlExpression pattern, Sq => ApplyDefaultTypeMapping(new LikeExpression(match, pattern, escapeChar, null)); /// - public virtual SqlExpression Fragment(string sql) - => new SqlFragmentExpression(sql); + public virtual SqlExpression Fragment(string sql, Type? type = null, RelationalTypeMapping? typeMapping = null) + => new SqlFragmentExpression(sql, type, typeMapping); /// public virtual SqlExpression Constant(object value, RelationalTypeMapping? typeMapping = null) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index d3931c36b7b..25540603495 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2915,7 +2915,7 @@ private void AddJoin( ? innerSelect.Orderings : innerSelect._identifier.Count > 0 ? innerSelect._identifier.Select(e => new OrderingExpression(e.Column, true)) - : new[] { new OrderingExpression(new SqlFragmentExpression("(SELECT 1)"), true) }; + : new[] { new OrderingExpression(new SqlFragmentExpression("(SELECT 1)", typeof(int)), true) }; var rowNumberExpression = new RowNumberExpression( partitions, orderings.ToList(), (limit ?? offset)!.TypeMapping); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs index d5e2fae4d10..f34680715aa 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs @@ -20,8 +20,10 @@ public class SqlFragmentExpression : SqlExpression /// Creates a new instance of the class. /// /// A string token to print in SQL tree. - public SqlFragmentExpression(string sql) - : base(typeof(string), null) + /// The of the expression. Defaults to . + /// The associated with the expression. + public SqlFragmentExpression(string sql, Type? type = null, RelationalTypeMapping? typeMapping = null) + : base(type ?? typeof(object), typeMapping) => Sql = sql; /// @@ -36,8 +38,11 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// public override Expression Quote() => New( - _quotingConstructor ??= typeof(SqlFragmentExpression).GetConstructor([typeof(string)])!, - Constant(Sql)); // TODO: The new type mapping once that's merged + _quotingConstructor ??= + typeof(SqlFragmentExpression).GetConstructor([typeof(string), typeof(Type), typeof(RelationalTypeMapping)])!, + Constant(Sql), + Constant(Type), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(TypeMapping)); /// protected override void Print(ExpressionPrinter expressionPrinter)