/// <summary> /// Provides language specific query translation. Use this to apply language specific rewrites or /// to make assertions/validations about the query. /// </summary> /// <param name="expression"></param> /// <returns></returns> public virtual Expression Translate(Expression expression) { // remove redundant layers again before cross apply rewrite expression = UnusedColumnRemover.Remove(expression); expression = RedundantColumnRemover.Remove(expression); expression = RedundantSubqueryRemover.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 = UnusedColumnRemover.Remove(expression); expression = RedundantSubqueryRemover.Remove(expression); expression = RedundantJoinRemover.Remove(expression); expression = RedundantColumnRemover.Remove(expression); } return(expression); }
/// <summary> /// Apply mapping translations to this expression /// </summary> /// <param name="expression"></param> /// <returns></returns> public virtual Expression Translate(Expression expression) { // convert references to LINQ operators into query specific nodes expression = QueryBinder.Bind(this, expression); // move aggregate computations so they occur in same select as group-by expression = AggregateRewriter.Rewrite(this.Translator.Linguist.Language, expression); // do reduction so duplicate association's are likely to be clumped together expression = UnusedColumnRemover.Remove(expression); expression = RedundantColumnRemover.Remove(expression); expression = RedundantSubqueryRemover.Remove(expression); expression = RedundantJoinRemover.Remove(expression); // convert references to association properties into correlated queries var bound = RelationshipBinder.Bind(this, expression); if (bound != expression) { expression = bound; // clean up after ourselves! (multiple references to same association property) expression = RedundantColumnRemover.Remove(expression); expression = RedundantJoinRemover.Remove(expression); } // rewrite comparision checks between entities and multi-valued constructs expression = ComparisonRewriter.Rewrite(this.Mapping, expression); return(expression); }
/// <summary> /// Provides policy specific query translations. This is where choices about inclusion of related objects and how /// heirarchies are materialized affect the definition of the queries. /// </summary> /// <param name="expression"></param> /// <returns></returns> public virtual Expression Translate(Expression expression) { // add included relationships to client projection var rewritten = RelationshipIncluder.Include(this.translator.Mapper, expression); if (rewritten != expression) { expression = rewritten; expression = UnusedColumnRemover.Remove(expression); expression = RedundantColumnRemover.Remove(expression); expression = RedundantSubqueryRemover.Remove(expression); expression = RedundantJoinRemover.Remove(expression); } // convert any singleton (1:1 or n:1) projections into server-side joins (cardinality is preserved) rewritten = SingletonProjectionRewriter.Rewrite(this.translator.Linguist.Language, expression); if (rewritten != expression) { expression = rewritten; expression = UnusedColumnRemover.Remove(expression); expression = RedundantColumnRemover.Remove(expression); expression = RedundantSubqueryRemover.Remove(expression); expression = RedundantJoinRemover.Remove(expression); } // convert projections into client-side joins rewritten = ClientJoinedProjectionRewriter.Rewrite(this.policy, this.translator.Linguist.Language, expression); if (rewritten != expression) { expression = rewritten; expression = UnusedColumnRemover.Remove(expression); expression = RedundantColumnRemover.Remove(expression); expression = RedundantSubqueryRemover.Remove(expression); expression = RedundantJoinRemover.Remove(expression); } return(expression); }