using Connected.Expressions.Formatters;
using Connected.Expressions.Translation;
using Connected.Expressions.Translation.Optimization;
using Connected.Expressions.Translation.Rewriters;
using System.Linq.Expressions;
namespace Connected.Expressions.Languages;
public class Linguist
{
///
/// Construct a
///
public Linguist(ExpressionCompilationContext context, QueryLanguage language, Translator translator)
{
Context = context;
Language = language;
Translator = translator;
}
protected ExpressionCompilationContext Context { get; }
public QueryLanguage Language { get; }
public Translator Translator { get; }
///
/// Provides language specific query translation. Use this to apply language specific rewrites or
/// to make assertions/validations about the query.
///
public virtual Expression Translate(Expression expression)
{
/*
* remove redundant layers again before cross apply rewrite
*/
expression = UnusedColumns.Remove(expression);
expression = RedundantColumns.Remove(expression);
expression = RedundantSubqueries.Remove(expression);
/*
* convert cross-apply and outer-apply joins into inner & left-outer-joins if possible
*/
var rewritten = CrossApplyRewriter.Rewrite(this.Language, expression);
/*
* convert cross joins into inner joins
*/
rewritten = CrossJoinRewriter.Rewrite(rewritten);
if (rewritten != expression)
{
expression = rewritten;
/*
* do final reduction
*/
expression = UnusedColumns.Remove(expression);
expression = RedundantSubqueries.Remove(expression);
expression = RedundantJoins.Remove(expression);
expression = RedundantColumns.Remove(expression);
}
return expression;
}
///
/// Converts the query expression into text of this query language
///
public virtual string Format(Expression expression)
{
/*
* use common SQL formatter by default
*/
return SqlFormatter.Format(expression);
}
///
/// Determine which sub-expressions must be parameters
///
public virtual Expression Parameterize(Expression expression)
{
return Parameterizer.Parameterize(Language, expression);
}
}