Пример #1
0
        private ITableSource OptimizeSubQuery(ITableSource source, bool optimizeWhere, bool allColumns,
                                              bool isApplySupported, bool optimizeValues, bool optimizeColumns, IJoinedTable joinedTable = null)
        {
            source.Joins.ForEach(
                node =>
            {
                var jt    = node.Value;
                var table = OptimizeSubQuery(
                    jt.Table,
                    jt.JoinType == EJoinType.Inner || jt.JoinType == EJoinType.CrossApply ||
                    jt.JoinType == EJoinType.Left,
                    false,
                    isApplySupported,
                    jt.JoinType == EJoinType.Inner || jt.JoinType == EJoinType.CrossApply ||
                    jt.JoinType == EJoinType.Left,
                    optimizeColumns,
                    jt
                    );

                if (table != jt.Table)
                {
                    var sql = jt.Table.Source as ISelectQuery;

                    if (sql != null && sql.OrderBy.Items.Count > 0)
                    {
                        foreach (var item in sql.OrderBy.Items)
                        {
                            _selectQuery.OrderBy.Expr(item.Expression, item.IsDescending);
                        }
                    }

                    jt.Table = table;
                }
            });

            return(source.Source is ISelectQuery
                ? RemoveSubQuery(source, optimizeWhere, allColumns&& !isApplySupported, optimizeValues, optimizeColumns,
                                 joinedTable)
                : source);
        }
Пример #2
0
        private ITableSource RemoveSubQuery(ITableSource childSource, bool concatWhere, bool allColumns,
                                            bool optimizeValues, bool optimizeColumns, IJoinedTable parentJoin)
        {
            var query = (ISelectQuery)childSource.Source;

            var isQueryOK = query.From.Tables.Count == 1;

            isQueryOK = isQueryOK && (concatWhere || query.Where.IsEmpty && query.Having.IsEmpty);
            isQueryOK = isQueryOK && !query.HasUnion && query.GroupBy.IsEmpty && !query.Select.HasModifier;
            //isQueryOK = isQueryOK && (_flags.IsDistinctOrderBySupported || query.Select.IsDistinct );

            if (!isQueryOK)
            {
                return(childSource);
            }

            var isColumnsOK = (allColumns && !query.Select.Columns.Any(c => IsAggregationFunction(c.Expression))) ||
                              !query.Select.Columns.Any(
                c => CheckColumn(c, c.Expression, query, optimizeValues, optimizeColumns));

            if (!isColumnsOK)
            {
                return(childSource);
            }

            var top = _selectQuery;

            while (top.ParentSelect != null)
            {
                top = top.ParentSelect;
            }

            var columns = new HashSet <IColumn>(query.Select.Columns);

            top.Walk(
                false,
                expr =>
            {
                var col = expr as IColumn;
                if (col == null || !columns.Contains(col))
                {
                    return(expr);
                }

                return(col.Expression);
            });

            QueryVisitor.FindOnce <IInList>(top).ForEach(
                node =>
            {
                if (node.Value.Expr1 == query)
                {
                    node.Value.Expr1 = query.From.Tables.First.Value;
                }
            });

            childSource.Joins.ForEach(node => query.From.Tables.First.Value.Joins.AddLast(node.Value));

            if (query.From.Tables.First.Value.Alias == null)
            {
                query.From.Tables.First.Value.Alias = childSource.Alias;
            }

            if (!query.Where.IsEmpty)
            {
                if (parentJoin != null && parentJoin.JoinType == EJoinType.Left)
                {
                    ConcatSearchCondition(parentJoin.Condition, query.Where.Search);
                }
                else
                {
                    ConcatSearchCondition(_selectQuery.Where.Search, query.Where.Search);
                }
            }
            if (!query.Having.IsEmpty)
            {
                ConcatSearchCondition(_selectQuery.Having.Search, query.Having.Search);
            }

            QueryVisitor.FindOnce <ISelectQuery>(top).ForEach(
                node =>
            {
                if (node.Value.ParentSelect == query)
                {
                    node.Value.ParentSelect = query.ParentSelect ?? _selectQuery;
                }
            });

            return(query.From.Tables.First.Value);
        }
Пример #3
0
        private void OptimizeApply(ITableSource tableSource, IJoinedTable joinTable, bool isApplySupported,
                                   bool optimizeColumns)
        {
            var joinSource = joinTable.Table;

            joinSource.Joins.ForEach(
                joinNode =>
            {
                var join = joinNode.Value;
                if (join.JoinType == EJoinType.CrossApply || join.JoinType == EJoinType.OuterApply)
                {
                    OptimizeApply(joinSource, join, isApplySupported, optimizeColumns);
                }
            });

            if (isApplySupported && !joinTable.CanConvertApply)
            {
                return;
            }

            if (joinSource.Source.ElementType == EQueryElementType.SqlQuery)
            {
                var sql   = (ISelectQuery)joinSource.Source;
                var isAgg = sql.Select.Columns.Any(c => IsAggregationFunction(c.Expression));

                if (isApplySupported && (isAgg || sql.Select.TakeValue != null || sql.Select.SkipValue != null))
                {
                    return;
                }

                sql.Where.Search.Conditions.Clear();

                if (!ContainsTable(tableSource.Source, sql))
                {
                    joinTable.JoinType = joinTable.JoinType == EJoinType.CrossApply
                        ? EJoinType.Inner
                        : EJoinType.Left;
                    joinTable.Condition.Conditions.AddRange(sql.Where.Search.Conditions);
                }
                else
                {
                    sql.Where.Search.Conditions.AddRange(sql.Where.Search.Conditions);

                    var table = OptimizeSubQuery(
                        joinTable.Table,
                        joinTable.JoinType == EJoinType.Inner || joinTable.JoinType == EJoinType.CrossApply,
                        joinTable.JoinType == EJoinType.CrossApply,
                        isApplySupported,
                        joinTable.JoinType == EJoinType.Inner || joinTable.JoinType == EJoinType.CrossApply,
                        optimizeColumns);

                    if (table != joinTable.Table)
                    {
                        var q = joinTable.Table.Source as ISelectQuery;

                        if (q != null && q.OrderBy.Items.Count > 0)
                        {
                            foreach (var item in q.OrderBy.Items)
                            {
                                _selectQuery.OrderBy.Expr(item.Expression, item.IsDescending);
                            }
                        }

                        joinTable.Table = table;

                        OptimizeApply(tableSource, joinTable, isApplySupported, optimizeColumns);
                    }
                }
            }
            else
            {
                if (!ContainsTable(tableSource.Source, joinSource.Source))
                {
                    joinTable.JoinType = joinTable.JoinType == EJoinType.CrossApply
                        ? EJoinType.Inner
                        : EJoinType.Left;
                }
            }
        }