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
- ToolTip.cs
- PrintPageEvent.cs
- DBParameter.cs
- EdmRelationshipRoleAttribute.cs
- clipboard.cs
- RelatedEnd.cs
- ExceptionAggregator.cs
- BitmapEffectInputData.cs
- AutoGeneratedField.cs
- OdbcParameter.cs
- TreeViewItem.cs
- CustomError.cs
- SrgsItemList.cs
- SafeNativeMethods.cs
- HwndHostAutomationPeer.cs
- CustomExpression.cs
- XmlSignatureProperties.cs
- HttpListenerContext.cs
- EntityContainer.cs
- BooleanProjectedSlot.cs
- PtsCache.cs
- Debug.cs
- SqlMethodAttribute.cs
- RangeValuePatternIdentifiers.cs
- SubMenuStyle.cs
- XmlDataFileEditor.cs
- TreeNodeConverter.cs
- SQLInt32Storage.cs
- XPathArrayIterator.cs
- HttpCachePolicyElement.cs
- DupHandleConnectionReader.cs
- Keyboard.cs
- LinkClickEvent.cs
- SelectionItemPattern.cs
- FactoryGenerator.cs
- ToolboxComponentsCreatingEventArgs.cs
- SmtpLoginAuthenticationModule.cs
- SmiEventSink_DeferedProcessing.cs
- CollectionEditor.cs
- UnsafeMethods.cs
- DataObjectEventArgs.cs
- HostVisual.cs
- ToolStripItemBehavior.cs
- MoveSizeWinEventHandler.cs
- FileCodeGroup.cs
- SafeReadContext.cs
- DbParameterHelper.cs
- objectquery_tresulttype.cs
- DecimalConverter.cs
- CommonDialog.cs
- Timer.cs
- SqlMethodTransformer.cs
- AsmxEndpointPickerExtension.cs
- VisualBrush.cs
- SqlConnectionManager.cs
- recordstate.cs
- TemplateBindingExtension.cs
- TagPrefixAttribute.cs
- XmlSerializableServices.cs
- StringReader.cs
- RenderData.cs
- NodeLabelEditEvent.cs
- AsyncOperation.cs
- FamilyTypeface.cs
- CmsUtils.cs
- ServiceModelExtensionCollectionElement.cs
- OpenCollectionAsyncResult.cs
- ConfigurationManagerInternalFactory.cs
- SecurityRuntime.cs
- DiscoveryClientDocuments.cs
- FontStretches.cs
- ObjectSecurity.cs
- MemberAccessException.cs
- WinFormsComponentEditor.cs
- XmlAttribute.cs
- DataGridColumnHeadersPresenterAutomationPeer.cs
- DataControlImageButton.cs
- DispatcherExceptionFilterEventArgs.cs
- PipeSecurity.cs
- StorageRoot.cs
- TemplateKeyConverter.cs
- HtmlInputRadioButton.cs
- AsyncCompletedEventArgs.cs
- ResourcePermissionBase.cs
- AppDomainAttributes.cs
- ListViewPagedDataSource.cs
- ChannelPoolSettings.cs
- ManagementScope.cs
- NativeMethods.cs
- RuntimeConfigurationRecord.cs
- CharUnicodeInfo.cs
- DotExpr.cs
- XmlSubtreeReader.cs
- VBIdentifierTrimConverter.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- Transactions.cs
- SQLConvert.cs
- UniqueIdentifierService.cs
- LogSwitch.cs
- ProcessInfo.cs