diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 4f5bb991039..d6b20755f4f 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,22 @@ 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) + { + Check.NotNull(sql, nameof(sql)); + + if (!_composableSql.IsMatch(sql)) + { + throw new InvalidOperationException(RelationalStrings.FromSqlNonComposable); + } + } + /// protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression) {