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; Listorders; 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EventSetter.cs
- TextBoxBase.cs
- SerialReceived.cs
- WindowsProgressbar.cs
- SmtpNetworkElement.cs
- StreamInfo.cs
- ResumeStoryboard.cs
- ZipIOExtraField.cs
- COM2EnumConverter.cs
- CrossSiteScriptingValidation.cs
- TriggerAction.cs
- DragStartedEventArgs.cs
- ManipulationStartingEventArgs.cs
- ThemeDictionaryExtension.cs
- HelloMessageCD1.cs
- CollectionDataContractAttribute.cs
- BindingMemberInfo.cs
- SqlServer2KCompatibilityAnnotation.cs
- GridViewAutoFormat.cs
- AssemblyBuilder.cs
- ServiceMetadataPublishingElement.cs
- SQLInt16.cs
- Preprocessor.cs
- Point3DAnimationBase.cs
- UriWriter.cs
- DbProviderServices.cs
- MaskedTextProvider.cs
- AttachedAnnotationChangedEventArgs.cs
- XamlFigureLengthSerializer.cs
- IsolatedStoragePermission.cs
- EventOpcode.cs
- AlphabeticalEnumConverter.cs
- MSG.cs
- Propagator.JoinPropagator.JoinPredicateVisitor.cs
- HttpAsyncResult.cs
- ScaleTransform3D.cs
- HtmlShim.cs
- Bidi.cs
- DataControlHelper.cs
- GraphicsPathIterator.cs
- FixedHyperLink.cs
- ToolStripControlHost.cs
- DeriveBytes.cs
- Matrix.cs
- MethodToken.cs
- DataGridViewCellStyle.cs
- FixedSOMElement.cs
- PeoplePickerWrapper.cs
- MimeObjectFactory.cs
- Vector3D.cs
- LocalValueEnumerator.cs
- FactoryMaker.cs
- ShapingWorkspace.cs
- EntityDataSourceSelectingEventArgs.cs
- JsonSerializer.cs
- GeneralTransform2DTo3D.cs
- SiteMapProvider.cs
- HttpListener.cs
- SimpleType.cs
- CheckPair.cs
- CellParaClient.cs
- DoubleAnimationBase.cs
- X509Certificate2.cs
- ValidationPropertyAttribute.cs
- ResourceExpressionEditorSheet.cs
- HttpListener.cs
- RegisterInfo.cs
- Rect.cs
- TrustSection.cs
- CompressedStack.cs
- CodeNamespaceImportCollection.cs
- future.cs
- _NTAuthentication.cs
- ListViewContainer.cs
- TableLayoutSettings.cs
- ClosableStream.cs
- Cursors.cs
- HashLookup.cs
- PathFigureCollectionValueSerializer.cs
- PageBreakRecord.cs
- ThousandthOfEmRealPoints.cs
- SoapObjectReader.cs
- NativeCppClassAttribute.cs
- CanonicalFontFamilyReference.cs
- ButtonBase.cs
- HelpInfo.cs
- SynchronizingStream.cs
- BinaryMethodMessage.cs
- HttpProfileGroupBase.cs
- ControlCachePolicy.cs
- WsatConfiguration.cs
- WindowsButton.cs
- FileDialogPermission.cs
- AutoResetEvent.cs
- UdpReplyToBehavior.cs
- NetMsmqBindingElement.cs
- BinaryObjectWriter.cs
- NavigationExpr.cs
- _DynamicWinsockMethods.cs
- ObjectItemConventionAssemblyLoader.cs