Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / 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
- StreamResourceInfo.cs
- _ConnectionGroup.cs
- AssemblyInfo.cs
- FormCollection.cs
- PageTrueTypeFont.cs
- BinaryNode.cs
- TokenizerHelper.cs
- LocalClientSecuritySettings.cs
- RemotingException.cs
- WeakReferenceEnumerator.cs
- TagNameToTypeMapper.cs
- ClientCultureInfo.cs
- HtmlEmptyTagControlBuilder.cs
- StateMachineSubscriptionManager.cs
- DataSourceXmlClassAttribute.cs
- TabControl.cs
- Vector3D.cs
- ApplicationFileCodeDomTreeGenerator.cs
- ExceptionWrapper.cs
- ComponentManagerBroker.cs
- FileInfo.cs
- XmlChoiceIdentifierAttribute.cs
- ChineseLunisolarCalendar.cs
- ErrorRuntimeConfig.cs
- EntityDataSourceEntityTypeFilterItem.cs
- AsnEncodedData.cs
- PolyBezierSegment.cs
- WaitForChangedResult.cs
- StreamWithDictionary.cs
- _AcceptOverlappedAsyncResult.cs
- XmlSchemaObjectCollection.cs
- WizardStepBase.cs
- MultiView.cs
- InvalidFilterCriteriaException.cs
- ExtractorMetadata.cs
- ImmutableObjectAttribute.cs
- ControlAdapter.cs
- BinaryCommonClasses.cs
- Thumb.cs
- MdbDataFileEditor.cs
- WindowsFormsEditorServiceHelper.cs
- ElementHost.cs
- HttpListenerRequest.cs
- BinHexEncoding.cs
- SspiNegotiationTokenProvider.cs
- GridViewPageEventArgs.cs
- RectangleGeometry.cs
- FunctionImportMapping.cs
- MatrixUtil.cs
- RequestCachingSection.cs
- HttpDebugHandler.cs
- StringArrayEditor.cs
- ConnectionStringsExpressionEditor.cs
- SiteMapNodeCollection.cs
- OdbcConnectionString.cs
- BitVector32.cs
- ToolStripSystemRenderer.cs
- MetaData.cs
- PolicyAssertionCollection.cs
- OrCondition.cs
- XmlDataDocument.cs
- SmiContext.cs
- FrameworkPropertyMetadata.cs
- XPathDocumentIterator.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- RbTree.cs
- CorrelationTokenInvalidatedHandler.cs
- XhtmlBasicCalendarAdapter.cs
- HwndStylusInputProvider.cs
- QueryConverter.cs
- XmlSchemaRedefine.cs
- PropertiesTab.cs
- ItemContainerGenerator.cs
- NativeMethodsCLR.cs
- TextElement.cs
- ZipIORawDataFileBlock.cs
- HierarchicalDataBoundControl.cs
- nulltextcontainer.cs
- OleDbInfoMessageEvent.cs
- SiteMapNodeCollection.cs
- TargetParameterCountException.cs
- AnimationLayer.cs
- Substitution.cs
- LocatorPartList.cs
- MetadataSource.cs
- Compress.cs
- ResXResourceWriter.cs
- GetCertificateRequest.cs
- TextEffect.cs
- SafeNativeMethodsCLR.cs
- XmlBinaryReader.cs
- MostlySingletonList.cs
- ContentTextAutomationPeer.cs
- TextServicesCompartmentContext.cs
- ExpressionBuilderContext.cs
- VectorConverter.cs
- CanonicalXml.cs
- MetadataArtifactLoaderResource.cs
- RtfToXamlLexer.cs
- BrowserCapabilitiesFactory.cs