protected override SqlStatement ProcessQuery(SqlStatement statement) { if (statement.IsInsert() && statement.RequireInsertClause().Into.Name == "Parent") { var expr = QueryVisitor.Find(statement.RequireInsertClause(), e => { if (e.ElementType == QueryElementType.SetExpression) { var se = (SqlSetExpression)e; return(((SqlField)se.Column).Name == "ParentID"); } return(false); }) as SqlSetExpression; if (expr != null) { var value = ConvertTo <int> .From(((IValueContainer)expr.Expression).Value); if (value == 555) { var tableName = "Parent1"; var dic = new Dictionary <IQueryElement, IQueryElement>(); statement = new QueryVisitor().Convert(statement, e => { if (e.ElementType == QueryElementType.SqlTable) { var oldTable = (SqlTable)e; if (oldTable.Name == "Parent") { var newTable = new SqlTable(oldTable) { Name = tableName, PhysicalName = tableName }; foreach (var field in oldTable.Fields.Values) { dic.Add(field, newTable.Fields[field.Name]); } return(newTable); } } IQueryElement ex; return(dic.TryGetValue(e, out ex) ? ex : null); }); } } return(statement); } return(statement); }
public async Task BasicOperationsAsync([IncludeDataSources(ProviderName.SQLiteMS)] string context, [Values("Value1", "Value2")] string columnName) { var ms = CreateMappingSchema(columnName); using (var db = GetDataContext(context, ms)) using (var table = db.CreateLocalTable <SampleClass>()) using (db.CreateLocalTable <SampleClassWithIdentity>()) { await db.InsertAsync(new SampleClass() { Id = 1, StrKey = "K1", Value = "V1" }); await db.InsertAsync(new SampleClass() { Id = 2, StrKey = "K2", Value = "V2" }); await db.InsertOrReplaceAsync(new SampleClass() { Id = 3, StrKey = "K3", Value = "V3" }); await db.InsertWithIdentityAsync(new SampleClassWithIdentity() { Value = "V4" }); await db.DeleteAsync(new SampleClass() { Id = 1, StrKey = "K1" }); await db.UpdateAsync(new SampleClass() { Id = 2, StrKey = "K2", Value = "VU" }); var found = null != QueryVisitor.Find(table.GetSelectQuery(), e => e is SqlField f && f.PhysicalName == columnName); var foundKey = null != QueryVisitor.Find(table.GetSelectQuery(), e => e is SqlField f && f.PhysicalName == columnName); Assert.IsTrue(found); Assert.IsTrue(foundKey); var result = await table.ToArrayAsync(); } }
static bool CheckColumn(SelectQuery.Column column, ISqlExpression expr, SelectQuery query, bool optimizeValues, bool optimizeColumns) { if (expr is SqlField || expr is SelectQuery.Column) { return(false); } if (expr is SqlValue) { return(!optimizeValues && 1.Equals(((SqlValue)expr).Value)); } if (expr is SqlBinaryExpression) { var e = (SqlBinaryExpression)expr; if (e.Operation == "*" && e.Expr1 is SqlValue) { var value = (SqlValue)e.Expr1; if (value.Value is int && (int)value.Value == -1) { return(CheckColumn(column, e.Expr2, query, optimizeValues, optimizeColumns)); } } } var visitor = new QueryVisitor(); if (optimizeColumns && visitor.Find(expr, e => e is SelectQuery || IsAggregationFunction(e)) == null) { var n = 0; var q = query.ParentSelect ?? query; visitor.VisitAll(q, e => { if (e == column) { n++; } }); return(n > 2); } return(true); }
public void Issue95Test() { using (var db = new TestDataConnection()) { var q = db.GetTable <Issue95Entity>().Where(_ => _.EnumValue == TinyIntEnum.Value1); var ctx = q.GetMyContext(); Assert.IsNull(QueryVisitor.Find(ctx.SelectQuery.Where, _ => _.ElementType == QueryElementType.SqlExpression), db.GetSqlText(ctx.SelectQuery)); q = db.GetTable <Issue95Entity>().Where(_ => TinyIntEnum.Value1 == _.EnumValue); ctx = q.GetMyContext(); Assert.IsNull(QueryVisitor.Find(ctx.SelectQuery.Where, _ => _.ElementType == QueryElementType.SqlExpression), db.GetSqlText(ctx.SelectQuery)); var p = TinyIntEnum.Value2; q = db.GetTable <Issue95Entity>().Where(_ => _.EnumValue == p); ctx = q.GetMyContext(); Assert.IsNull(QueryVisitor.Find(ctx.SelectQuery.Where, _ => _.ElementType == QueryElementType.SqlExpression), db.GetSqlText(ctx.SelectQuery)); q = db.GetTable <Issue95Entity>().Where(_ => p == _.EnumValue); ctx = q.GetMyContext(); Assert.IsNull(QueryVisitor.Find(ctx.SelectQuery.Where, _ => _.ElementType == QueryElementType.SqlExpression), db.GetSqlText(ctx.SelectQuery)); } }
static bool CheckColumn(SelectQuery.Column column, ISqlExpression expr, SelectQuery query, bool optimizeValues, bool optimizeColumns) { if (expr is SqlField || expr is SelectQuery.Column) return false; if (expr is SqlValue) return !optimizeValues && 1.Equals(((SqlValue)expr).Value); if (expr is SqlBinaryExpression) { var e = (SqlBinaryExpression)expr; if (e.Operation == "*" && e.Expr1 is SqlValue) { var value = (SqlValue)e.Expr1; if (value.Value is int && (int)value.Value == -1) return CheckColumn(column, e.Expr2, query, optimizeValues, optimizeColumns); } } var visitor = new QueryVisitor(); if (optimizeColumns && visitor.Find(expr, e => e is SelectQuery || IsAggregationFunction(e)) == null) { var n = 0; var q = query.ParentSelect ?? query; visitor.VisitAll(q, e => { if (e == column) n++; }); return n > 2; } return true; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var resultSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap(); if (!sequence.SelectQuery.GroupBy.IsEmpty || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null || sequence.SelectQuery.Select.IsDistinct) { sequence = new SubQueryContext(sequence); } var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence); var expr = collectionSelector.Body.Unwrap(); var collectionInfo = new BuildInfo(context, expr, new SelectQuery()); var collection = builder.BuildSequence(collectionInfo); var leftJoin = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext || collectionInfo.JoinType == SelectQuery.JoinType.Left; var sql = collection.SelectQuery; var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables()); var newQuery = null != QueryVisitor.Find(sql, e => e == collectionInfo.SelectQuery); var crossApply = null != QueryVisitor.Find(sql, e => e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) || e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) || e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SelectQuery.Column)e).Parent)); if (collection is JoinBuilder.GroupJoinSubQueryContext) { var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin; groupJoin.SelectQuery.From.Tables[0].Joins[0].JoinType = SelectQuery.JoinType.Inner; groupJoin.SelectQuery.From.Tables[0].Joins[0].IsWeak = false; } if (!newQuery) { if (collection.SelectQuery.Select.HasModifier) { if (crossApply) { var foundJoin = context.SelectQuery.FindJoin(j => j.Table.Source == collection.SelectQuery); if (foundJoin != null) { foundJoin.JoinType = leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply; collection.SelectQuery.Where.ConcatSearchCondition(foundJoin.Condition); ((ISqlExpressionWalkable)collection.SelectQuery.Where).Walk(false, e => { var column = e as SelectQuery.Column; if (column != null) { if (column.Parent == collection.SelectQuery) { return(column.UnderlyingColumn); } } return(e); }); foundJoin.Condition.Conditions.Clear(); } } } context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } if (!crossApply) { if (!leftJoin) { context.Collection = new SubQueryContext(collection, sequence.SelectQuery, true); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { var join = SelectQuery.OuterApply(sql); sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } } var joinType = collectionInfo.JoinType; if (collection is TableBuilder.TableContext) { // if (collectionInfo.IsAssociationBuilt) // { // context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); // return new SelectContext(buildInfo.Parent, resultSelector, sequence, context); // } if (joinType == SelectQuery.JoinType.Auto) { var table = (TableBuilder.TableContext)collection; var isApplyJoin = collection.SelectQuery.Select.HasModifier || table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0; joinType = isApplyJoin ? (leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply) : (leftJoin ? SelectQuery.JoinType.Left : SelectQuery.JoinType.Inner); } var join = CreateJoin(joinType, sql); join.JoinedTable.CanConvertApply = false; if (!(joinType == SelectQuery.JoinType.CrossApply || joinType == SelectQuery.JoinType.OuterApply)) { join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions); sql.Where.SearchCondition.Conditions.Clear(); } var collectionParent = collection.Parent as TableBuilder.TableContext; // Association. // if (collectionParent != null && collectionInfo.IsAssociationBuilt) { var ts = (SelectQuery.TableSource)QueryVisitor.Find(sequence.SelectQuery.From, e => { if (e.ElementType == QueryElementType.TableSource) { var t = (SelectQuery.TableSource)e; return(t.Source == collectionParent.SqlTable); } return(false); }); ts.Joins.Add(join.JoinedTable); } else { //if (collectionInfo.IsAssociationBuilt) //{ // collectionInfo.AssosiationContext.ParentAssociationJoin.IsWeak = false; //} //else { sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); } } context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { if (joinType == SelectQuery.JoinType.Auto) { joinType = leftJoin ? SelectQuery.JoinType.OuterApply : SelectQuery.JoinType.CrossApply; } var join = CreateJoin(joinType, sql); if (!(joinType == SelectQuery.JoinType.CrossApply || joinType == SelectQuery.JoinType.OuterApply)) { join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions); sql.Where.SearchCondition.Conditions.Clear(); } sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var resultSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap(); if (sequence.SelectQuery.HasUnion || !sequence.SelectQuery.IsSimple) { sequence = new SubQueryContext(sequence); } var expr = collectionSelector.Body.Unwrap(); DefaultIfEmptyBuilder.DefaultIfEmptyContext defaultIfEmpty = null; if (expr is MethodCallExpression mc && AllJoinsBuilder.IsMatchingMethod(mc, true)) { defaultIfEmpty = new DefaultIfEmptyBuilder.DefaultIfEmptyContext(buildInfo.Parent, sequence, null); defaultIfEmpty.Disabled = true; sequence = new SubQueryContext(defaultIfEmpty); } var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence); context.SetAlias(collectionSelector.Parameters[0].Name); var collectionInfo = new BuildInfo(context, expr, new SelectQuery()); var collection = builder.BuildSequence(collectionInfo); if (resultSelector.Parameters.Count > 1) { collection.SetAlias(resultSelector.Parameters[1].Name); } if (defaultIfEmpty != null && (collectionInfo.JoinType == JoinType.Right || collectionInfo.JoinType == JoinType.Full)) { defaultIfEmpty.Disabled = false; } var leftJoin = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext || collectionInfo.JoinType == JoinType.Left; var sql = collection.SelectQuery; var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables()); var newQuery = null != QueryVisitor.Find(sql, e => e == collectionInfo.SelectQuery); var crossApply = null != QueryVisitor.Find(sql, e => e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) || e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) || e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SqlColumn)e).Parent)); if (collection is JoinBuilder.GroupJoinSubQueryContext queryContext) { var groupJoin = queryContext.GroupJoin; groupJoin.SelectQuery.From.Tables[0].Joins[0].JoinType = JoinType.Inner; groupJoin.SelectQuery.From.Tables[0].Joins[0].IsWeak = false; } if (!newQuery) { if (collection.SelectQuery.Select.HasModifier) { if (crossApply) { var foundJoin = context.SelectQuery.FindJoin(j => j.Table.Source == collection.SelectQuery); if (foundJoin != null) { foundJoin.JoinType = leftJoin ? JoinType.OuterApply : JoinType.CrossApply; collection.SelectQuery.Where.ConcatSearchCondition(foundJoin.Condition); ((ISqlExpressionWalkable)collection.SelectQuery.Where).Walk(new WalkOptions(), e => { if (e is SqlColumn column) { if (column.Parent == collection.SelectQuery) { return(column.UnderlyingColumn); } } return(e); }); foundJoin.Condition.Conditions.Clear(); } } } context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } if (!crossApply) { if (!leftJoin) { context.Collection = new SubQueryContext(collection, sequence.SelectQuery, true); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { var join = sql.OuterApply(); sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } } void MoveSearchConditionsToJoin(SqlFromClause.Join join) { var tableSources = new HashSet <ISqlTableSource>(); ((ISqlExpressionWalkable)sql.Where.SearchCondition).Walk(new WalkOptions(), e => { if (e is ISqlTableSource ts && !tableSources.Contains(ts)) { tableSources.Add(ts); } return(e); }); bool ContainsTable(ISqlTableSource tbl, IQueryElement qe) { return(null != QueryVisitor.Find(qe, e => e == tbl || e.ElementType == QueryElementType.SqlField && tbl == ((SqlField)e).Table || e.ElementType == QueryElementType.Column && tbl == ((SqlColumn)e).Parent)); } var conditions = sql.Where.SearchCondition.Conditions; if (conditions.Count > 0) { for (var i = conditions.Count - 1; i >= 0; i--) { var condition = conditions[i]; if (!tableSources.Any(ts => ContainsTable(ts, condition))) { join.JoinedTable.Condition.Conditions.Insert(0, condition); conditions.RemoveAt(i); } } } }
void MoveCountSubQuery(IQueryElement element) { if (element.ElementType != QueryElementType.SqlQuery) return; var query = (SelectQuery)element; for (var i = 0; i < query.Select.Columns.Count; i++) { var col = query.Select.Columns[i]; // The column is a subquery. // if (col.Expression.ElementType == QueryElementType.SqlQuery) { var subQuery = (SelectQuery)col.Expression; var isCount = false; // Check if subquery is Count subquery. // if (subQuery.Select.Columns.Count == 1) { var subCol = subQuery.Select.Columns[0]; if (subCol.Expression.ElementType == QueryElementType.SqlFunction) isCount = ((SqlFunction)subCol.Expression).Name == "Count"; } if (!isCount) continue; // Check if subquery where clause does not have ORs. // SelectQueryOptimizer.OptimizeSearchCondition(subQuery.Where.SearchCondition); var allAnd = true; for (var j = 0; allAnd && j < subQuery.Where.SearchCondition.Conditions.Count - 1; j++) { var cond = subQuery.Where.SearchCondition.Conditions[j]; if (cond.IsOr) allAnd = false; } if (!allAnd || !ConvertCountSubQuery(subQuery)) continue; // Collect tables. // var allTables = new HashSet<ISqlTableSource>(); var levelTables = new HashSet<ISqlTableSource>(); new QueryVisitor().Visit(subQuery, e => { if (e is ISqlTableSource source) allTables.Add(source); }); new QueryVisitor().Visit(subQuery, e => { if (e is ISqlTableSource source) if (subQuery.From.IsChild(source)) levelTables.Add(source); }); bool CheckTable(IQueryElement e) { switch (e.ElementType) { case QueryElementType.SqlField : return !allTables.Contains(((SqlField) e).Table); case QueryElementType.Column : return !allTables.Contains(((SqlColumn)e).Parent); } return false; } var join = subQuery.LeftJoin(); query.From.Tables[0].Joins.Add(join.JoinedTable); for (var j = 0; j < subQuery.Where.SearchCondition.Conditions.Count; j++) { var cond = subQuery.Where.SearchCondition.Conditions[j]; if (QueryVisitor.Find(cond, CheckTable) == null) continue; var replaced = new Dictionary<IQueryElement,IQueryElement>(); var nc = new QueryVisitor().Convert(cond, e => { var ne = e; switch (e.ElementType) { case QueryElementType.SqlField : if (replaced.TryGetValue(e, out ne)) return ne; if (levelTables.Contains(((SqlField)e).Table)) { subQuery.GroupBy.Expr((SqlField)e); ne = subQuery.Select.Columns[subQuery.Select.Add((SqlField)e)]; } break; case QueryElementType.Column : if (replaced.TryGetValue(e, out ne)) return ne; if (levelTables.Contains(((SqlColumn)e).Parent)) { subQuery.GroupBy.Expr((SqlColumn)e); ne = subQuery.Select.Columns[subQuery.Select.Add((SqlColumn)e)]; } break; } if (!ReferenceEquals(e, ne)) replaced.Add(e, ne); return ne; }); if (nc != null && !ReferenceEquals(nc, cond)) { join.JoinedTable.Condition.Conditions.Add(nc); subQuery.Where.SearchCondition.Conditions.RemoveAt(j); j--; } } if (!query.GroupBy.IsEmpty/* && subQuery.Select.Columns.Count > 1*/) { var oldFunc = (SqlFunction)subQuery.Select.Columns[0].Expression; subQuery.Select.Columns.RemoveAt(0); query.Select.Columns[i].Expression = new SqlFunction(oldFunc.SystemType, oldFunc.Name, subQuery.Select.Columns[0]); } else { query.Select.Columns[i].Expression = subQuery.Select.Columns[0]; } } } }
SelectQuery MoveSubQueryColumn(SelectQuery selectQuery) { var dic = new Dictionary<IQueryElement,IQueryElement>(); new QueryVisitor().Visit(selectQuery, element => { if (element.ElementType != QueryElementType.SqlQuery) return; var query = (SelectQuery)element; for (var i = 0; i < query.Select.Columns.Count; i++) { var col = query.Select.Columns[i]; if (col.Expression.ElementType == QueryElementType.SqlQuery) { var subQuery = (SelectQuery)col.Expression; var allTables = new HashSet<ISqlTableSource>(); var levelTables = new HashSet<ISqlTableSource>(); bool CheckTable(IQueryElement e) { switch (e.ElementType) { case QueryElementType.SqlField : return !allTables.Contains(((SqlField) e).Table); case QueryElementType.Column : return !allTables.Contains(((SqlColumn)e).Parent); } return false; } new QueryVisitor().Visit(subQuery, e => { if (e is ISqlTableSource source) allTables.Add(source); }); new QueryVisitor().Visit(subQuery, e => { if (e is ISqlTableSource source && subQuery.From.IsChild(source)) levelTables.Add(source); }); if (SqlProviderFlags.IsSubQueryColumnSupported && QueryVisitor.Find(subQuery, CheckTable) == null) continue; // Join should not have ParentSelect, while SubQuery has subQuery.ParentSelect = null; var join = subQuery.LeftJoin(); query.From.Tables[0].Joins.Add(join.JoinedTable); SelectQueryOptimizer.OptimizeSearchCondition(subQuery.Where.SearchCondition); var isCount = false; var isAggregated = false; if (subQuery.Select.Columns.Count == 1) { var subCol = subQuery.Select.Columns[0]; if (subCol.Expression.ElementType == QueryElementType.SqlFunction) { switch (((SqlFunction)subCol.Expression).Name) { case "Count" : isCount = true; break; } isAggregated = ((SqlFunction) subCol.Expression).IsAggregate; } } if (SqlProviderFlags.IsSubQueryColumnSupported && !isCount) continue; var allAnd = true; for (var j = 0; allAnd && j < subQuery.Where.SearchCondition.Conditions.Count - 1; j++) { var cond = subQuery.Where.SearchCondition.Conditions[j]; if (cond.IsOr) allAnd = false; } if (!allAnd) continue; var modified = false; for (var j = 0; j < subQuery.Where.SearchCondition.Conditions.Count; j++) { var cond = subQuery.Where.SearchCondition.Conditions[j]; if (QueryVisitor.Find(cond, CheckTable) == null) continue; var replaced = new Dictionary<IQueryElement,IQueryElement>(); var nc = new QueryVisitor().Convert(cond, e => { var ne = e; switch (e.ElementType) { case QueryElementType.SqlField : if (replaced.TryGetValue(e, out ne)) return ne; if (levelTables.Contains(((SqlField)e).Table)) { if (isAggregated) subQuery.GroupBy.Expr((SqlField)e); ne = subQuery.Select.Columns[subQuery.Select.Add((SqlField)e)]; } break; case QueryElementType.Column : if (replaced.TryGetValue(e, out ne)) return ne; if (levelTables.Contains(((SqlColumn)e).Parent)) { if (isAggregated) subQuery.GroupBy.Expr((SqlColumn)e); ne = subQuery.Select.Columns[subQuery.Select.Add((SqlColumn)e)]; } break; } if (!ReferenceEquals(e, ne)) replaced.Add(e, ne); return ne; }); if (nc != null && !ReferenceEquals(nc, cond)) { modified = true; join.JoinedTable.Condition.Conditions.Add(nc); subQuery.Where.SearchCondition.Conditions.RemoveAt(j); j--; } } if (modified || isAggregated) { SqlColumn newColumn; if (isCount && !query.GroupBy.IsEmpty) { var oldFunc = (SqlFunction)subQuery.Select.Columns[0].Expression; subQuery.Select.Columns.RemoveAt(0); newColumn = new SqlColumn( query, new SqlFunction(oldFunc.SystemType, oldFunc.Name, subQuery.Select.Columns[0])); } else if (isAggregated && !query.GroupBy.IsEmpty) { var oldFunc = (SqlFunction)subQuery.Select.Columns[0].Expression; subQuery.Select.Columns.RemoveAt(0); var idx = subQuery.Select.Add(oldFunc.Parameters[0]); newColumn = new SqlColumn( query, new SqlFunction(oldFunc.SystemType, oldFunc.Name, subQuery.Select.Columns[idx])); } else { newColumn = new SqlColumn(query, subQuery.Select.Columns[0]); } dic.Add(col, newColumn); } }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var wrapped = false; if (sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null) { sequence = new SubQueryContext(sequence); wrapped = true; } var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap(); SqlInfo[] sql; while (true) { var sparent = sequence.Parent; var order = new ExpressionContext(buildInfo.Parent, sequence, lambda); var body = lambda.Body.Unwrap(); sql = builder.ConvertExpressions(order, body, ConvertFlags.Key); builder.ReplaceParent(order, sparent); if (wrapped) { break; } // handle situation when order by uses complex field var isComplex = false; foreach (var sqlInfo in sql) { // possible we have to extend this list isComplex = null != QueryVisitor.Find(sqlInfo.Sql, e => e.ElementType == QueryElementType.SqlQuery); if (isComplex) { break; } } if (!isComplex) { break; } sequence = new SubQueryContext(sequence); wrapped = true; } if (!methodCall.Method.Name.StartsWith("Then") && !Configuration.Linq.DoNotClearOrderBys) { sequence.SelectQuery.OrderBy.Items.Clear(); } foreach (var expr in sql) { var e = builder.ConvertSearchCondition(sequence, expr.Sql); sequence.SelectQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending")); } return(sequence); }