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
- Parsers.cs
- FontSizeConverter.cs
- ThreadPoolTaskScheduler.cs
- Group.cs
- TransportSecurityBindingElement.cs
- UseAttributeSetsAction.cs
- AnnotationResourceChangedEventArgs.cs
- versioninfo.cs
- StdValidatorsAndConverters.cs
- StoreContentChangedEventArgs.cs
- SystemGatewayIPAddressInformation.cs
- ConfigurationStrings.cs
- CriticalFinalizerObject.cs
- SamlAdvice.cs
- TransformedBitmap.cs
- HttpProfileGroupBase.cs
- TransactionContext.cs
- BindingListCollectionView.cs
- NameTable.cs
- XmlBoundElement.cs
- DbXmlEnabledProviderManifest.cs
- ProviderCollection.cs
- GridViewRowPresenterBase.cs
- RijndaelManagedTransform.cs
- Rect3DConverter.cs
- dbdatarecord.cs
- DataGridPageChangedEventArgs.cs
- TextFormatterImp.cs
- CatalogPartChrome.cs
- WebBrowserHelper.cs
- ForeignKeyConstraint.cs
- ConstructorArgumentAttribute.cs
- XmlJsonWriter.cs
- XmlDataSourceView.cs
- BuilderPropertyEntry.cs
- ContextProperty.cs
- DocumentEventArgs.cs
- RoamingStoreFileUtility.cs
- UpdateExpressionVisitor.cs
- ClientSettingsProvider.cs
- SynchronizationLockException.cs
- EdmToObjectNamespaceMap.cs
- GridViewRowEventArgs.cs
- ListControlConvertEventArgs.cs
- FileDialog.cs
- TypographyProperties.cs
- HttpPostedFile.cs
- followingsibling.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- XmlNode.cs
- TraceHandler.cs
- GeneralTransform.cs
- AccessibleObject.cs
- CodePropertyReferenceExpression.cs
- UrlAuthorizationModule.cs
- ProjectionPlanCompiler.cs
- SchemaContext.cs
- ReachSerializableProperties.cs
- DocumentOrderQuery.cs
- WindowsFormsHost.cs
- DateTimeValueSerializer.cs
- NamedServiceModelExtensionCollectionElement.cs
- MulticastOption.cs
- GifBitmapEncoder.cs
- SQLDecimal.cs
- MimeBasePart.cs
- XmlSchemaRedefine.cs
- DataGridColumn.cs
- ManualResetEvent.cs
- SQLInt16Storage.cs
- DocumentViewerConstants.cs
- RequestSecurityTokenResponse.cs
- ParameterElement.cs
- PersonalizationEntry.cs
- MsmqDiagnostics.cs
- AlphabeticalEnumConverter.cs
- IIS7UserPrincipal.cs
- TypeConverterMarkupExtension.cs
- HijriCalendar.cs
- HorizontalAlignConverter.cs
- EDesignUtil.cs
- XsdValidatingReader.cs
- EntityDataSourceSelectedEventArgs.cs
- ScaleTransform3D.cs
- CodeCommentStatement.cs
- CopyEncoder.cs
- SecurityCriticalDataForSet.cs
- ConnectionManager.cs
- RunWorkerCompletedEventArgs.cs
- ZoomingMessageFilter.cs
- VariantWrapper.cs
- CustomValidator.cs
- ExtensibleClassFactory.cs
- SafeFileMapViewHandle.cs
- DataControlPagerLinkButton.cs
- DropDownList.cs
- FastEncoderWindow.cs
- WaitHandle.cs
- XmlSchemaSimpleTypeUnion.cs
- XmlIgnoreAttribute.cs