Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / SqlReorderer.cs / 1 / 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;
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.
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
- Transform3DCollection.cs
- WindowsListView.cs
- ExceptionUtil.cs
- MeasureItemEvent.cs
- EventLogException.cs
- NavigationPropertyAccessor.cs
- MaskPropertyEditor.cs
- ActivationServices.cs
- ProfileSection.cs
- HttpContextWrapper.cs
- InfoCardRSACryptoProvider.cs
- SqlServer2KCompatibilityAnnotation.cs
- KnownBoxes.cs
- HttpException.cs
- AppDomainManager.cs
- oledbmetadatacollectionnames.cs
- JavaScriptSerializer.cs
- LockCookie.cs
- ExpressionBuilder.cs
- DateTimeConstantAttribute.cs
- Operators.cs
- Timer.cs
- ExceptionAggregator.cs
- MutableAssemblyCacheEntry.cs
- NullableIntMinMaxAggregationOperator.cs
- XmlNavigatorFilter.cs
- IIS7UserPrincipal.cs
- TrackingQueryElement.cs
- ListBindableAttribute.cs
- Encoding.cs
- StreamGeometry.cs
- EventManager.cs
- AtomicFile.cs
- TemplateParser.cs
- SqlCommand.cs
- ApplicationTrust.cs
- WindowPatternIdentifiers.cs
- MessageBox.cs
- WebUtil.cs
- FontDifferentiator.cs
- CheckBoxStandardAdapter.cs
- Parser.cs
- ShaperBuffers.cs
- TimeSpanValidator.cs
- UriTemplateTable.cs
- SortExpressionBuilder.cs
- SystemInfo.cs
- TypeConverters.cs
- XamlFigureLengthSerializer.cs
- EventLogLink.cs
- DrawingBrush.cs
- PasswordPropertyTextAttribute.cs
- TypeSystemHelpers.cs
- DBSchemaRow.cs
- ContentFileHelper.cs
- SapiRecoContext.cs
- DocumentSchemaValidator.cs
- MultiBinding.cs
- BaseCollection.cs
- objectresult_tresulttype.cs
- AppDomainProtocolHandler.cs
- EventDescriptor.cs
- EmptyReadOnlyDictionaryInternal.cs
- StyleBamlTreeBuilder.cs
- ActivityStateRecord.cs
- BinaryObjectInfo.cs
- MdbDataFileEditor.cs
- SchemaDeclBase.cs
- MouseWheelEventArgs.cs
- TimelineCollection.cs
- OdbcInfoMessageEvent.cs
- PartBasedPackageProperties.cs
- BadImageFormatException.cs
- ContentPlaceHolder.cs
- CompilationLock.cs
- ContextMenu.cs
- SourceElementsCollection.cs
- TextTreeDeleteContentUndoUnit.cs
- SchemaConstraints.cs
- QilBinary.cs
- PolyBezierSegment.cs
- ProcessMessagesAsyncResult.cs
- DrawingVisualDrawingContext.cs
- CacheEntry.cs
- ReadOnlyObservableCollection.cs
- TimelineCollection.cs
- FileVersionInfo.cs
- UpdatePanel.cs
- Hashtable.cs
- ViewStateModeByIdAttribute.cs
- RecipientInfo.cs
- VariableQuery.cs
- SQLChars.cs
- SiteMapDataSourceView.cs
- NTAccount.cs
- Latin1Encoding.cs
- RoleManagerEventArgs.cs
- PropertyGridEditorPart.cs
- FontTypeConverter.cs
- ToolStripPanelCell.cs