SqlReorderer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / SqlReorderer.cs / 2 / SqlReorderer.cs

                            using System; 
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
 
namespace System.Data.Linq.SqlClient {
    using System.Data.Linq.Mapping; 
    using System.Data.Linq.Provider; 
    using System.Diagnostics.CodeAnalysis;
 
    // moves order-by clauses from sub-queries to outer-most or top selects
    // removes ordering in correlated sub-queries
    internal class SqlReorderer {
        TypeSystemProvider typeProvider; 
        SqlFactory sql;
 
        internal SqlReorderer(TypeSystemProvider typeProvider, SqlFactory sqlFactory) { 
            this.typeProvider = typeProvider;
            this.sql = sqlFactory; 
        }

        internal SqlNode Reorder(SqlNode node) {
            return new Visitor(this.typeProvider, this.sql).Visit(node); 
        }
 
        class Visitor : SqlVisitor { 
            TypeSystemProvider typeProvider;
            bool topSelect = true; 
            bool addPrimaryKeys;
            List orders;
            List rowNumberOrders;
            SqlSelect currentSelect; 
            SqlFactory sql;
            SqlAggregateChecker aggregateChecker; 
 
            internal Visitor(TypeSystemProvider typeProvider, SqlFactory sqlFactory) {
                this.orders = new List(); 
                this.typeProvider = typeProvider;
                this.sql = sqlFactory;
                this.aggregateChecker = new SqlAggregateChecker();
            } 

            internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { 
                List save = this.orders; 
                this.orders = new List();
                base.VisitSubSelect(ss); 
                this.orders = save;
                return ss;
            }
 
            private void PrependOrderExpressions(IEnumerable exprs) {
                if (exprs != null) { 
                    this.Orders.InsertRange(0, exprs); 
                }
            } 

            private List Orders {
                get {
                    if (this.orders == null) { 
                        this.orders = new List();
                    } 
                    return this.orders; 
                }
            } 


            internal override SqlSource VisitJoin(SqlJoin join) {
                this.Visit(join.Left); 
                List leftOrders = this.orders;
                this.orders = null; 
                this.Visit(join.Right); 
                this.PrependOrderExpressions(leftOrders);
                return join; 
            }

            internal override SqlNode VisitUnion(SqlUnion su) {
                // ordering does not carry through a union 
                this.orders = null;
                su.Left = this.Visit(su.Left); 
                this.orders = null; 
                su.Right = this.Visit(su.Right);
                this.orders = null; 
                return su;
            }

            internal override SqlAlias VisitAlias(SqlAlias a) { 
                if (IsTableAlias(a) && this.addPrimaryKeys) {
                    SqlTable tab = (SqlTable)a.Node; 
                    List list = new List(); 

                    foreach (MetaDataMember mm in tab.RowType.IdentityMembers) { 
                        string name = mm.MappedName;
                        SqlColumn col = tab.Find(name);
                        if (col == null) {
                            col = new SqlColumn(mm.MemberAccessor.Type, typeProvider.From(mm.MemberAccessor.Type), name, mm, null, tab.SourceExpression); 
                            col.Alias = a;
                            tab.Columns.Add(col); 
                        } 
                        list.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    } 

                    this.PrependOrderExpressions(list);

                    return a; 
                }
                else { 
                    return base.VisitAlias(a); 
                }
            } 

            internal override SqlSelect VisitSelect(SqlSelect select) {
                bool saveTop = this.topSelect;
                bool savePK = this.addPrimaryKeys; 

                SqlSelect saveSelect = this.currentSelect; 
                this.currentSelect = select; 

                if (select.OrderingType == SqlOrderingType.Always) { 
                    this.addPrimaryKeys = true;
                }

                this.topSelect = false; 

                // can't forward ordering information through a group-by 
                if (select.GroupBy.Count > 0) { 
                    this.Visit(select.From);
                    this.orders = null; 
                }
                else {
                    this.Visit(select.From);
                } 

                if (select.OrderBy.Count > 0) { 
                    this.PrependOrderExpressions(select.OrderBy); 
                }
 
                List save = this.orders;
                this.orders = null;
                this.rowNumberOrders = save; // lest orders be null when we need info
 
                /* do all the lower level stuff */
                select.Where = this.VisitExpression(select.Where); 
                for (int i = 0, n = select.GroupBy.Count; i < n; i++) { 
                    select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]);
                } 
                select.Having = this.VisitExpression(select.Having);
                for (int i = 0, n = select.OrderBy.Count; i < n; i++) {
                    select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression);
                } 
                select.Top = this.VisitExpression(select.Top);
                select.Selection = this.VisitExpression(select.Selection); 
                select.Row = (SqlRow)this.Visit(select.Row); 

                this.topSelect = saveTop; 
                this.addPrimaryKeys = savePK;

                this.orders = save;
 
                // all ordering is blocked for this layer and above
                if (select.OrderingType == SqlOrderingType.Blocked) { 
                    this.orders = null; 
                }
 
                // rebuild orderby expressions, provided this select doesn't contain a SqlRowNumber
                // otherwise, replace the orderby with a reference to that column
                select.OrderBy.Clear();
                var rowNumberChecker = new SqlRowNumberChecker(); 

                if (rowNumberChecker.HasRowNumber(select) && rowNumberChecker.RowNumberColumn != null) { 
                    select.Row.Columns.Remove(rowNumberChecker.RowNumberColumn); 
                    this.PushDown(rowNumberChecker.RowNumberColumn);
                    this.Orders.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(rowNumberChecker.RowNumberColumn))); 
                }
                if ((this.topSelect || select.Top != null) && select.OrderingType != SqlOrderingType.Never && this.orders != null) {
                    this.orders = new HashSet(this.orders).ToList();
                    SqlDuplicator dup = new SqlDuplicator(true); 
                    foreach (SqlOrderExpression sox in this.orders) {
                        select.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression))); 
                    } 
                }
                this.currentSelect = saveSelect; 

                return select;
            }
 
            internal override SqlRowNumber VisitRowNumber(SqlRowNumber rowNumber) {
                if (rowNumber.OrderBy.Count > 0) return rowNumber; 
 
                SqlDuplicator dup = new SqlDuplicator(true);
                List orderBy = new List(); 
                List existingOrders = new List();

                if (this.rowNumberOrders != null && this.rowNumberOrders.Count != 0) {
                    existingOrders = new List(this.rowNumberOrders); 
                }
                else if (this.orders != null) { 
                    existingOrders = new List(this.orders); 
                }
 
                foreach (SqlOrderExpression expr in existingOrders) {
                    if (!expr.Expression.IsConstantColumn) {
                        orderBy.Add(expr);
                        if (this.rowNumberOrders != null) { 
                            this.rowNumberOrders.Remove(expr);
                        } 
                        if (this.orders != null) { 
                            this.orders.Remove(expr);
                        } 
                    }
                }

                rowNumber.OrderBy.Clear(); 

                if (orderBy.Count == 0) { 
                    List columns = SqlGatherColumnsProduced.GatherColumns(this.currentSelect.From); 

                    foreach (SqlColumn col in columns) { 
                        if (col.Expression.SqlType.IsOrderable) {
                            orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                        }
                    } 

                    if (orderBy.Count == 0) { 
                        // insert simple column 
                        SqlColumn col =
                            new SqlColumn( 
                                "rowNumberOrder",
                                sql.Value(typeof(int), this.typeProvider.From(typeof(int)), 1, false, rowNumber.SourceExpression)
                            );
                        this.PushDown(col); 
                        orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    } 
                } 

                foreach (SqlOrderExpression sox in orderBy) { 
                    rowNumber.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                }

                return rowNumber; 
            }
 
            private void PushDown(SqlColumn column) { 
                SqlSelect select = new SqlSelect(new SqlNop(column.ClrType, column.SqlType, column.SourceExpression), this.currentSelect.From, this.currentSelect.SourceExpression);
                this.currentSelect.From = new SqlAlias(select); 
                select.Row.Columns.Add(column);
            }

            private static bool IsTableAlias(SqlSource src) { 
                SqlAlias a = src as SqlAlias;
                return (a != null && a.Node is SqlTable); 
            } 
        }
 
        internal class SqlGatherColumnsProduced {
            static internal List GatherColumns(SqlSource source) {
                List columns = new List();
                new Visitor(columns).Visit(source); 
                return columns;
            } 
            class Visitor : SqlVisitor { 
                List columns;
                internal Visitor(List columns) { 
                    this.columns = columns;
                }
                internal override SqlSelect VisitSelect(SqlSelect select) {
                    foreach (SqlColumn c in select.Row.Columns) { 
                        this.columns.Add(c);
                    } 
                    return select; 
                }
                internal override SqlNode VisitUnion(SqlUnion su) { 
                    return su;
                }
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
 
namespace System.Data.Linq.SqlClient {
    using System.Data.Linq.Mapping; 
    using System.Data.Linq.Provider; 
    using System.Diagnostics.CodeAnalysis;
 
    // moves order-by clauses from sub-queries to outer-most or top selects
    // removes ordering in correlated sub-queries
    internal class SqlReorderer {
        TypeSystemProvider typeProvider; 
        SqlFactory sql;
 
        internal SqlReorderer(TypeSystemProvider typeProvider, SqlFactory sqlFactory) { 
            this.typeProvider = typeProvider;
            this.sql = sqlFactory; 
        }

        internal SqlNode Reorder(SqlNode node) {
            return new Visitor(this.typeProvider, this.sql).Visit(node); 
        }
 
        class Visitor : SqlVisitor { 
            TypeSystemProvider typeProvider;
            bool topSelect = true; 
            bool addPrimaryKeys;
            List orders;
            List rowNumberOrders;
            SqlSelect currentSelect; 
            SqlFactory sql;
            SqlAggregateChecker aggregateChecker; 
 
            internal Visitor(TypeSystemProvider typeProvider, SqlFactory sqlFactory) {
                this.orders = new List(); 
                this.typeProvider = typeProvider;
                this.sql = sqlFactory;
                this.aggregateChecker = new SqlAggregateChecker();
            } 

            internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { 
                List save = this.orders; 
                this.orders = new List();
                base.VisitSubSelect(ss); 
                this.orders = save;
                return ss;
            }
 
            private void PrependOrderExpressions(IEnumerable exprs) {
                if (exprs != null) { 
                    this.Orders.InsertRange(0, exprs); 
                }
            } 

            private List Orders {
                get {
                    if (this.orders == null) { 
                        this.orders = new List();
                    } 
                    return this.orders; 
                }
            } 


            internal override SqlSource VisitJoin(SqlJoin join) {
                this.Visit(join.Left); 
                List leftOrders = this.orders;
                this.orders = null; 
                this.Visit(join.Right); 
                this.PrependOrderExpressions(leftOrders);
                return join; 
            }

            internal override SqlNode VisitUnion(SqlUnion su) {
                // ordering does not carry through a union 
                this.orders = null;
                su.Left = this.Visit(su.Left); 
                this.orders = null; 
                su.Right = this.Visit(su.Right);
                this.orders = null; 
                return su;
            }

            internal override SqlAlias VisitAlias(SqlAlias a) { 
                if (IsTableAlias(a) && this.addPrimaryKeys) {
                    SqlTable tab = (SqlTable)a.Node; 
                    List list = new List(); 

                    foreach (MetaDataMember mm in tab.RowType.IdentityMembers) { 
                        string name = mm.MappedName;
                        SqlColumn col = tab.Find(name);
                        if (col == null) {
                            col = new SqlColumn(mm.MemberAccessor.Type, typeProvider.From(mm.MemberAccessor.Type), name, mm, null, tab.SourceExpression); 
                            col.Alias = a;
                            tab.Columns.Add(col); 
                        } 
                        list.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    } 

                    this.PrependOrderExpressions(list);

                    return a; 
                }
                else { 
                    return base.VisitAlias(a); 
                }
            } 

            internal override SqlSelect VisitSelect(SqlSelect select) {
                bool saveTop = this.topSelect;
                bool savePK = this.addPrimaryKeys; 

                SqlSelect saveSelect = this.currentSelect; 
                this.currentSelect = select; 

                if (select.OrderingType == SqlOrderingType.Always) { 
                    this.addPrimaryKeys = true;
                }

                this.topSelect = false; 

                // can't forward ordering information through a group-by 
                if (select.GroupBy.Count > 0) { 
                    this.Visit(select.From);
                    this.orders = null; 
                }
                else {
                    this.Visit(select.From);
                } 

                if (select.OrderBy.Count > 0) { 
                    this.PrependOrderExpressions(select.OrderBy); 
                }
 
                List save = this.orders;
                this.orders = null;
                this.rowNumberOrders = save; // lest orders be null when we need info
 
                /* do all the lower level stuff */
                select.Where = this.VisitExpression(select.Where); 
                for (int i = 0, n = select.GroupBy.Count; i < n; i++) { 
                    select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]);
                } 
                select.Having = this.VisitExpression(select.Having);
                for (int i = 0, n = select.OrderBy.Count; i < n; i++) {
                    select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression);
                } 
                select.Top = this.VisitExpression(select.Top);
                select.Selection = this.VisitExpression(select.Selection); 
                select.Row = (SqlRow)this.Visit(select.Row); 

                this.topSelect = saveTop; 
                this.addPrimaryKeys = savePK;

                this.orders = save;
 
                // all ordering is blocked for this layer and above
                if (select.OrderingType == SqlOrderingType.Blocked) { 
                    this.orders = null; 
                }
 
                // rebuild orderby expressions, provided this select doesn't contain a SqlRowNumber
                // otherwise, replace the orderby with a reference to that column
                select.OrderBy.Clear();
                var rowNumberChecker = new SqlRowNumberChecker(); 

                if (rowNumberChecker.HasRowNumber(select) && rowNumberChecker.RowNumberColumn != null) { 
                    select.Row.Columns.Remove(rowNumberChecker.RowNumberColumn); 
                    this.PushDown(rowNumberChecker.RowNumberColumn);
                    this.Orders.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(rowNumberChecker.RowNumberColumn))); 
                }
                if ((this.topSelect || select.Top != null) && select.OrderingType != SqlOrderingType.Never && this.orders != null) {
                    this.orders = new HashSet(this.orders).ToList();
                    SqlDuplicator dup = new SqlDuplicator(true); 
                    foreach (SqlOrderExpression sox in this.orders) {
                        select.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression))); 
                    } 
                }
                this.currentSelect = saveSelect; 

                return select;
            }
 
            internal override SqlRowNumber VisitRowNumber(SqlRowNumber rowNumber) {
                if (rowNumber.OrderBy.Count > 0) return rowNumber; 
 
                SqlDuplicator dup = new SqlDuplicator(true);
                List orderBy = new List(); 
                List existingOrders = new List();

                if (this.rowNumberOrders != null && this.rowNumberOrders.Count != 0) {
                    existingOrders = new List(this.rowNumberOrders); 
                }
                else if (this.orders != null) { 
                    existingOrders = new List(this.orders); 
                }
 
                foreach (SqlOrderExpression expr in existingOrders) {
                    if (!expr.Expression.IsConstantColumn) {
                        orderBy.Add(expr);
                        if (this.rowNumberOrders != null) { 
                            this.rowNumberOrders.Remove(expr);
                        } 
                        if (this.orders != null) { 
                            this.orders.Remove(expr);
                        } 
                    }
                }

                rowNumber.OrderBy.Clear(); 

                if (orderBy.Count == 0) { 
                    List columns = SqlGatherColumnsProduced.GatherColumns(this.currentSelect.From); 

                    foreach (SqlColumn col in columns) { 
                        if (col.Expression.SqlType.IsOrderable) {
                            orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                        }
                    } 

                    if (orderBy.Count == 0) { 
                        // insert simple column 
                        SqlColumn col =
                            new SqlColumn( 
                                "rowNumberOrder",
                                sql.Value(typeof(int), this.typeProvider.From(typeof(int)), 1, false, rowNumber.SourceExpression)
                            );
                        this.PushDown(col); 
                        orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    } 
                } 

                foreach (SqlOrderExpression sox in orderBy) { 
                    rowNumber.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                }

                return rowNumber; 
            }
 
            private void PushDown(SqlColumn column) { 
                SqlSelect select = new SqlSelect(new SqlNop(column.ClrType, column.SqlType, column.SourceExpression), this.currentSelect.From, this.currentSelect.SourceExpression);
                this.currentSelect.From = new SqlAlias(select); 
                select.Row.Columns.Add(column);
            }

            private static bool IsTableAlias(SqlSource src) { 
                SqlAlias a = src as SqlAlias;
                return (a != null && a.Node is SqlTable); 
            } 
        }
 
        internal class SqlGatherColumnsProduced {
            static internal List GatherColumns(SqlSource source) {
                List columns = new List();
                new Visitor(columns).Visit(source); 
                return columns;
            } 
            class Visitor : SqlVisitor { 
                List columns;
                internal Visitor(List columns) { 
                    this.columns = columns;
                }
                internal override SqlSelect VisitSelect(SqlSelect select) {
                    foreach (SqlColumn c in select.Row.Columns) { 
                        this.columns.Add(c);
                    } 
                    return select; 
                }
                internal override SqlNode VisitUnion(SqlUnion su) { 
                    return su;
                }
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK