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); } }