diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs
index 4f5bb991039..709d03848a5 100644
--- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs
+++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs
@@ -413,10 +413,7 @@ protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression)
_relationalCommandBuilder.AppendLine("(");
- if (!_composableSql.IsMatch(fromSqlExpression.Sql))
- {
- throw new InvalidOperationException(RelationalStrings.FromSqlNonComposable);
- }
+ CheckComposableSql(fromSqlExpression.Sql);
using (_relationalCommandBuilder.Indent())
{
@@ -430,6 +427,20 @@ protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression)
return fromSqlExpression;
}
+ ///
+ /// Checks whether a given SQL string is composable, i.e. can be embedded as a subquery within a
+ /// larger SQL query.
+ ///
+ /// An SQL string to be checked for composability.
+ /// The given SQL isn't composable.
+ protected virtual void CheckComposableSql([NotNull] string sql)
+ {
+ if (_composableSql.IsMatch(sql))
+ {
+ throw new InvalidOperationException(RelationalStrings.FromSqlNonComposable);
+ }
+ }
+
///
protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
{