Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / SqlReorderer.cs / 1305376 / 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; using System.Linq.Expressions; // 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) { SqlTable tab = a.Node as SqlTable; SqlTableValuedFunctionCall tvf = a.Node as SqlTableValuedFunctionCall; if (this.addPrimaryKeys && (tab != null || tvf != null)) { List list = new List (); bool isTable = tab != null; MetaType rowType = isTable ? tab.RowType : tvf.RowType; foreach (MetaDataMember mm in rowType.IdentityMembers) { string name = mm.MappedName; SqlColumn col; Expression sourceExpression; List columns; if (isTable) { col = tab.Find(name); sourceExpression = tab.SourceExpression; columns = tab.Columns; } else { col = tvf.Find(name); sourceExpression = tvf.SourceExpression; columns = tvf.Columns; } if (col == null) { col = new SqlColumn(mm.MemberAccessor.Type, typeProvider.From(mm.MemberAccessor.Type), name, mm, null, sourceExpression); col.Alias = a; 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); } } 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
- RuleSettingsCollection.cs
- WebHttpBindingElement.cs
- validation.cs
- DataGridHeaderBorder.cs
- ProvidePropertyAttribute.cs
- documentsequencetextpointer.cs
- WebPartVerb.cs
- RuleElement.cs
- DecodeHelper.cs
- CustomErrorsSection.cs
- EventLogConfiguration.cs
- ScrollBar.cs
- ErrorProvider.cs
- ProcessHostServerConfig.cs
- cookie.cs
- RelatedCurrencyManager.cs
- DetailsView.cs
- KeyboardEventArgs.cs
- TickBar.cs
- PassportIdentity.cs
- MessageBox.cs
- EndpointConfigContainer.cs
- JulianCalendar.cs
- SoapProtocolReflector.cs
- ProcessThreadDesigner.cs
- TreeNodeStyle.cs
- TextMetrics.cs
- DataControlReferenceCollection.cs
- RootAction.cs
- Int64Storage.cs
- OptimizedTemplateContent.cs
- XPathAxisIterator.cs
- InfoCardTraceRecord.cs
- RequestResizeEvent.cs
- RoleProviderPrincipal.cs
- AutomationElementCollection.cs
- BinaryNode.cs
- OdbcStatementHandle.cs
- XmlDataDocument.cs
- ProfileSection.cs
- ScriptingWebServicesSectionGroup.cs
- itemelement.cs
- QilLiteral.cs
- WebPartConnectionsCancelVerb.cs
- WebBrowserContainer.cs
- AdornerDecorator.cs
- TCPListener.cs
- TokenBasedSet.cs
- DesignerRegionCollection.cs
- KeyTimeConverter.cs
- DesignerActionPropertyItem.cs
- GridEntry.cs
- ControlParser.cs
- PageTheme.cs
- GridView.cs
- PropertyEmitterBase.cs
- MetaModel.cs
- ToolboxItemAttribute.cs
- CreateParams.cs
- TypeUtil.cs
- InstanceContextMode.cs
- HwndHostAutomationPeer.cs
- CodeConditionStatement.cs
- DataDocumentXPathNavigator.cs
- CultureMapper.cs
- TopClause.cs
- WindowsListView.cs
- CatalogZoneBase.cs
- DesignerGenericWebPart.cs
- DataSourceControl.cs
- SequenceFullException.cs
- WebColorConverter.cs
- IApplicationTrustManager.cs
- EntityContainerEntitySet.cs
- ScrollBar.cs
- FormsAuthenticationTicket.cs
- ValidatorCollection.cs
- DynamicILGenerator.cs
- XmlChildNodes.cs
- FrameworkTextComposition.cs
- SQLInt32Storage.cs
- ComponentRenameEvent.cs
- GeneralTransformGroup.cs
- ExpressionBuilder.cs
- QueuePathDialog.cs
- NameSpaceExtractor.cs
- MatrixUtil.cs
- MimeMultiPart.cs
- LeftCellWrapper.cs
- JsonDeserializer.cs
- HtmlInputButton.cs
- ChannelListenerBase.cs
- XmlSchemaDatatype.cs
- TemplateNameScope.cs
- ToolStripSeparator.cs
- ProvidePropertyAttribute.cs
- RecordBuilder.cs
- LinqDataSourceDisposeEventArgs.cs
- InteropAutomationProvider.cs
- Bezier.cs