Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / SqlFlattener.cs / 2 / SqlFlattener.cs
using System;
using System.Collections.Generic;
namespace System.Data.Linq.SqlClient {
using System.Data.Linq.Mapping;
using System.Data.Linq.Provider;
using System.Diagnostics.CodeAnalysis;
// flatten object expressions into rows
internal class SqlFlattener {
Visitor visitor;
internal SqlFlattener(SqlFactory sql, SqlColumnizer columnizer) {
this.visitor = new Visitor(sql, columnizer);
}
internal SqlNode Flatten(SqlNode node) {
node = this.visitor.Visit(node);
return node;
}
class Visitor : SqlVisitor {
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "[....]: part of our standard visitor pattern")]
SqlFactory sql;
SqlColumnizer columnizer;
bool isTopLevel;
Dictionary map = new Dictionary();
[SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Justification="Unknown reason.")]
internal Visitor(SqlFactory sql, SqlColumnizer columnizer) {
this.sql = sql;
this.columnizer = columnizer;
this.isTopLevel = true;
}
internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
SqlColumn mapped;
if (this.map.TryGetValue(cref.Column, out mapped)) {
return new SqlColumnRef(mapped);
}
return cref;
}
internal override SqlSelect VisitSelectCore(SqlSelect select) {
bool saveIsTopLevel = this.isTopLevel;
this.isTopLevel = false;
try {
return base.VisitSelectCore(select);
}
finally {
this.isTopLevel = saveIsTopLevel;
}
}
internal override SqlSelect VisitSelect(SqlSelect select) {
select = base.VisitSelect(select);
select.Selection = this.FlattenSelection(select.Row, false, select.Selection);
if (select.GroupBy.Count > 0) {
this.FlattenGroupBy(select.GroupBy);
}
if (select.OrderBy.Count > 0) {
this.FlattenOrderBy(select.OrderBy);
}
if (!this.isTopLevel) {
select.Selection = new SqlNop(select.Selection.ClrType, select.Selection.SqlType, select.SourceExpression);
}
return select;
}
internal override SqlStatement VisitInsert(SqlInsert sin) {
base.VisitInsert(sin);
sin.Expression = this.FlattenSelection(sin.Row, true, sin.Expression);
return sin;
}
private SqlExpression FlattenSelection(SqlRow row, bool isInput, SqlExpression selection) {
selection = this.columnizer.ColumnizeSelection(selection);
return new SelectionFlattener(row, this.map, isInput).VisitExpression(selection);
}
class SelectionFlattener : SqlVisitor {
SqlRow row;
Dictionary map;
bool isInput;
internal SelectionFlattener(SqlRow row, Dictionary map, bool isInput) {
this.row = row;
this.map = map;
this.isInput = isInput;
}
internal override SqlExpression VisitColumn(SqlColumn col) {
//
SqlColumn c = this.FindColumn(this.row.Columns, col);
if (c == null && col.Expression != null && !this.isInput) {
c = this.FindColumnWithExpression(this.row.Columns, col.Expression);
}
if (c == null) {
this.row.Columns.Add(col);
c = col;
}
else if (c != col) {
// preserve expr-sets when folding expressions together
if (col.Expression.NodeType == SqlNodeType.ExprSet && c.Expression.NodeType != SqlNodeType.ExprSet) {
c.Expression = col.Expression;
}
this.map[col] = c;
}
return new SqlColumnRef(c);
}
internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
SqlColumn c = this.FindColumn(this.row.Columns, cref.Column);
if (c == null) {
return MakeFlattenedColumn(cref, null);
}
else {
return new SqlColumnRef(c);
}
}
// ignore subquery in selection
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) {
return ss;
}
internal override SqlExpression VisitClientQuery(SqlClientQuery cq) {
return cq;
}
private SqlColumnRef MakeFlattenedColumn(SqlExpression expr, string name) {
SqlColumn c = (!this.isInput) ? this.FindColumnWithExpression(this.row.Columns, expr) : null;
if (c == null) {
c = new SqlColumn(expr.ClrType, expr.SqlType, name, null, expr, expr.SourceExpression);
this.row.Columns.Add(c);
}
return new SqlColumnRef(c);
}
private SqlColumn FindColumn(IEnumerable columns, SqlColumn col) {
foreach (SqlColumn c in columns) {
if (this.RefersToColumn(c, col)) {
return c;
}
}
return null;
}
private SqlColumn FindColumnWithExpression(IEnumerable columns, SqlExpression expr) {
foreach (SqlColumn c in columns) {
if (c == expr) {
return c;
}
if (SqlComparer.AreEqual(c.Expression, expr)) {
return c;
}
}
return null;
}
}
private void FlattenGroupBy(List exprs) {
List list = new List(exprs.Count);
foreach (SqlExpression gex in exprs) {
if (TypeSystem.IsSequenceType(gex.ClrType)) {
throw Error.InvalidGroupByExpressionType(gex.ClrType.Name);
}
this.FlattenGroupByExpression(list, gex);
}
exprs.Clear();
exprs.AddRange(list);
}
private void FlattenGroupByExpression(List exprs, SqlExpression expr) {
SqlNew sn = expr as SqlNew;
if (sn != null) {
foreach (SqlMemberAssign ma in sn.Members) {
this.FlattenGroupByExpression(exprs, ma.Expression);
}
foreach (SqlExpression arg in sn.Args) {
this.FlattenGroupByExpression(exprs, arg);
}
}
else if (expr.NodeType == SqlNodeType.TypeCase) {
SqlTypeCase tc = (SqlTypeCase)expr;
this.FlattenGroupByExpression(exprs, tc.Discriminator);
foreach (SqlTypeCaseWhen when in tc.Whens) {
this.FlattenGroupByExpression(exprs, when.TypeBinding);
}
}
else if (expr.NodeType == SqlNodeType.Link) {
SqlLink link = (SqlLink)expr;
if (link.Expansion != null) {
this.FlattenGroupByExpression(exprs, link.Expansion);
}
else {
foreach (SqlExpression key in link.KeyExpressions) {
this.FlattenGroupByExpression(exprs, key);
}
}
}
else if (expr.NodeType == SqlNodeType.OptionalValue) {
SqlOptionalValue sop = (SqlOptionalValue)expr;
this.FlattenGroupByExpression(exprs, sop.HasValue);
this.FlattenGroupByExpression(exprs, sop.Value);
}
else if (expr.NodeType == SqlNodeType.OuterJoinedValue) {
this.FlattenGroupByExpression(exprs, ((SqlUnary)expr).Operand);
}
else if (expr.NodeType == SqlNodeType.DiscriminatedType) {
SqlDiscriminatedType dt = (SqlDiscriminatedType)expr;
this.FlattenGroupByExpression(exprs, dt.Discriminator);
}
else {
// this expression should have been 'pushed-down' in SqlBinder, so we
// should only find column-references & expr-sets unless the expression could not
// be columnized (in which case it was a bad group-by expression.)
if (expr.NodeType != SqlNodeType.ColumnRef &&
expr.NodeType != SqlNodeType.ExprSet) {
if (!expr.SqlType.CanBeColumn) {
throw Error.InvalidGroupByExpressionType(expr.SqlType.ToQueryString());
}
throw Error.InvalidGroupByExpression();
}
exprs.Add(expr);
}
}
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
private void FlattenOrderBy(List exprs) {
foreach (SqlOrderExpression obex in exprs) {
if (!obex.Expression.SqlType.IsOrderable) {
if (obex.Expression.SqlType.CanBeColumn) {
throw Error.InvalidOrderByExpression(obex.Expression.SqlType.ToQueryString());
}
else {
throw Error.InvalidOrderByExpression(obex.Expression.ClrType.Name);
}
}
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Collections.Generic;
namespace System.Data.Linq.SqlClient {
using System.Data.Linq.Mapping;
using System.Data.Linq.Provider;
using System.Diagnostics.CodeAnalysis;
// flatten object expressions into rows
internal class SqlFlattener {
Visitor visitor;
internal SqlFlattener(SqlFactory sql, SqlColumnizer columnizer) {
this.visitor = new Visitor(sql, columnizer);
}
internal SqlNode Flatten(SqlNode node) {
node = this.visitor.Visit(node);
return node;
}
class Visitor : SqlVisitor {
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "[....]: part of our standard visitor pattern")]
SqlFactory sql;
SqlColumnizer columnizer;
bool isTopLevel;
Dictionary map = new Dictionary();
[SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily", Justification="Unknown reason.")]
internal Visitor(SqlFactory sql, SqlColumnizer columnizer) {
this.sql = sql;
this.columnizer = columnizer;
this.isTopLevel = true;
}
internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
SqlColumn mapped;
if (this.map.TryGetValue(cref.Column, out mapped)) {
return new SqlColumnRef(mapped);
}
return cref;
}
internal override SqlSelect VisitSelectCore(SqlSelect select) {
bool saveIsTopLevel = this.isTopLevel;
this.isTopLevel = false;
try {
return base.VisitSelectCore(select);
}
finally {
this.isTopLevel = saveIsTopLevel;
}
}
internal override SqlSelect VisitSelect(SqlSelect select) {
select = base.VisitSelect(select);
select.Selection = this.FlattenSelection(select.Row, false, select.Selection);
if (select.GroupBy.Count > 0) {
this.FlattenGroupBy(select.GroupBy);
}
if (select.OrderBy.Count > 0) {
this.FlattenOrderBy(select.OrderBy);
}
if (!this.isTopLevel) {
select.Selection = new SqlNop(select.Selection.ClrType, select.Selection.SqlType, select.SourceExpression);
}
return select;
}
internal override SqlStatement VisitInsert(SqlInsert sin) {
base.VisitInsert(sin);
sin.Expression = this.FlattenSelection(sin.Row, true, sin.Expression);
return sin;
}
private SqlExpression FlattenSelection(SqlRow row, bool isInput, SqlExpression selection) {
selection = this.columnizer.ColumnizeSelection(selection);
return new SelectionFlattener(row, this.map, isInput).VisitExpression(selection);
}
class SelectionFlattener : SqlVisitor {
SqlRow row;
Dictionary map;
bool isInput;
internal SelectionFlattener(SqlRow row, Dictionary map, bool isInput) {
this.row = row;
this.map = map;
this.isInput = isInput;
}
internal override SqlExpression VisitColumn(SqlColumn col) {
//
SqlColumn c = this.FindColumn(this.row.Columns, col);
if (c == null && col.Expression != null && !this.isInput) {
c = this.FindColumnWithExpression(this.row.Columns, col.Expression);
}
if (c == null) {
this.row.Columns.Add(col);
c = col;
}
else if (c != col) {
// preserve expr-sets when folding expressions together
if (col.Expression.NodeType == SqlNodeType.ExprSet && c.Expression.NodeType != SqlNodeType.ExprSet) {
c.Expression = col.Expression;
}
this.map[col] = c;
}
return new SqlColumnRef(c);
}
internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
SqlColumn c = this.FindColumn(this.row.Columns, cref.Column);
if (c == null) {
return MakeFlattenedColumn(cref, null);
}
else {
return new SqlColumnRef(c);
}
}
// ignore subquery in selection
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) {
return ss;
}
internal override SqlExpression VisitClientQuery(SqlClientQuery cq) {
return cq;
}
private SqlColumnRef MakeFlattenedColumn(SqlExpression expr, string name) {
SqlColumn c = (!this.isInput) ? this.FindColumnWithExpression(this.row.Columns, expr) : null;
if (c == null) {
c = new SqlColumn(expr.ClrType, expr.SqlType, name, null, expr, expr.SourceExpression);
this.row.Columns.Add(c);
}
return new SqlColumnRef(c);
}
private SqlColumn FindColumn(IEnumerable columns, SqlColumn col) {
foreach (SqlColumn c in columns) {
if (this.RefersToColumn(c, col)) {
return c;
}
}
return null;
}
private SqlColumn FindColumnWithExpression(IEnumerable columns, SqlExpression expr) {
foreach (SqlColumn c in columns) {
if (c == expr) {
return c;
}
if (SqlComparer.AreEqual(c.Expression, expr)) {
return c;
}
}
return null;
}
}
private void FlattenGroupBy(List exprs) {
List list = new List(exprs.Count);
foreach (SqlExpression gex in exprs) {
if (TypeSystem.IsSequenceType(gex.ClrType)) {
throw Error.InvalidGroupByExpressionType(gex.ClrType.Name);
}
this.FlattenGroupByExpression(list, gex);
}
exprs.Clear();
exprs.AddRange(list);
}
private void FlattenGroupByExpression(List exprs, SqlExpression expr) {
SqlNew sn = expr as SqlNew;
if (sn != null) {
foreach (SqlMemberAssign ma in sn.Members) {
this.FlattenGroupByExpression(exprs, ma.Expression);
}
foreach (SqlExpression arg in sn.Args) {
this.FlattenGroupByExpression(exprs, arg);
}
}
else if (expr.NodeType == SqlNodeType.TypeCase) {
SqlTypeCase tc = (SqlTypeCase)expr;
this.FlattenGroupByExpression(exprs, tc.Discriminator);
foreach (SqlTypeCaseWhen when in tc.Whens) {
this.FlattenGroupByExpression(exprs, when.TypeBinding);
}
}
else if (expr.NodeType == SqlNodeType.Link) {
SqlLink link = (SqlLink)expr;
if (link.Expansion != null) {
this.FlattenGroupByExpression(exprs, link.Expansion);
}
else {
foreach (SqlExpression key in link.KeyExpressions) {
this.FlattenGroupByExpression(exprs, key);
}
}
}
else if (expr.NodeType == SqlNodeType.OptionalValue) {
SqlOptionalValue sop = (SqlOptionalValue)expr;
this.FlattenGroupByExpression(exprs, sop.HasValue);
this.FlattenGroupByExpression(exprs, sop.Value);
}
else if (expr.NodeType == SqlNodeType.OuterJoinedValue) {
this.FlattenGroupByExpression(exprs, ((SqlUnary)expr).Operand);
}
else if (expr.NodeType == SqlNodeType.DiscriminatedType) {
SqlDiscriminatedType dt = (SqlDiscriminatedType)expr;
this.FlattenGroupByExpression(exprs, dt.Discriminator);
}
else {
// this expression should have been 'pushed-down' in SqlBinder, so we
// should only find column-references & expr-sets unless the expression could not
// be columnized (in which case it was a bad group-by expression.)
if (expr.NodeType != SqlNodeType.ColumnRef &&
expr.NodeType != SqlNodeType.ExprSet) {
if (!expr.SqlType.CanBeColumn) {
throw Error.InvalidGroupByExpressionType(expr.SqlType.ToQueryString());
}
throw Error.InvalidGroupByExpression();
}
exprs.Add(expr);
}
}
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
private void FlattenOrderBy(List exprs) {
foreach (SqlOrderExpression obex in exprs) {
if (!obex.Expression.SqlType.IsOrderable) {
if (obex.Expression.SqlType.CanBeColumn) {
throw Error.InvalidOrderByExpression(obex.Expression.SqlType.ToQueryString());
}
else {
throw Error.InvalidOrderByExpression(obex.Expression.ClrType.Name);
}
}
}
}
}
}
}
// 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
- TypeConverterMarkupExtension.cs
- ScriptingProfileServiceSection.cs
- Graph.cs
- TableItemPatternIdentifiers.cs
- OleDbCommandBuilder.cs
- ToolStripRendererSwitcher.cs
- DispatcherFrame.cs
- IdentityHolder.cs
- WebBrowserNavigatingEventHandler.cs
- ToolStripMenuItem.cs
- ITextView.cs
- SiteMapHierarchicalDataSourceView.cs
- DriveInfo.cs
- DuplicateWaitObjectException.cs
- EnlistmentTraceIdentifier.cs
- PermissionRequestEvidence.cs
- SqlWorkflowInstanceStore.cs
- RecognitionEventArgs.cs
- RoleGroupCollection.cs
- Menu.cs
- Walker.cs
- Typeface.cs
- ReliabilityContractAttribute.cs
- KeyEvent.cs
- WorkflowInstanceAbortedRecord.cs
- Collection.cs
- State.cs
- _IPv4Address.cs
- AlignmentYValidation.cs
- HtmlString.cs
- GenericQueueSurrogate.cs
- ViewPort3D.cs
- LookupNode.cs
- MappingModelBuildProvider.cs
- PropertyChangedEventArgs.cs
- TaskForm.cs
- OracleLob.cs
- COM2ComponentEditor.cs
- ThreadStaticAttribute.cs
- OutputCacheSettings.cs
- ActivityBindForm.cs
- DynamicMetaObjectBinder.cs
- SoapAttributes.cs
- DictionaryCustomTypeDescriptor.cs
- SystemWebSectionGroup.cs
- ApplicationManager.cs
- ReachIDocumentPaginatorSerializer.cs
- ColumnWidthChangingEvent.cs
- WebServiceMethodData.cs
- TextServicesPropertyRanges.cs
- Int32CollectionValueSerializer.cs
- MappingException.cs
- ConfigXmlElement.cs
- CharStorage.cs
- UrlMappingCollection.cs
- WizardPanelChangingEventArgs.cs
- EncodingDataItem.cs
- ViewStateException.cs
- LinearGradientBrush.cs
- Classification.cs
- FloatSumAggregationOperator.cs
- SelectionGlyph.cs
- MailWriter.cs
- PathData.cs
- CustomLineCap.cs
- TypeConverter.cs
- CLRBindingWorker.cs
- SlipBehavior.cs
- Vector3DCollectionValueSerializer.cs
- ScriptReferenceEventArgs.cs
- XmlILAnnotation.cs
- DataChangedEventManager.cs
- StylusEditingBehavior.cs
- ToolStripLocationCancelEventArgs.cs
- MissingFieldException.cs
- tabpagecollectioneditor.cs
- CommonGetThemePartSize.cs
- GridViewUpdatedEventArgs.cs
- WebAdminConfigurationHelper.cs
- FileIOPermission.cs
- ToolStripRenderEventArgs.cs
- COSERVERINFO.cs
- latinshape.cs
- FileCodeGroup.cs
- Socket.cs
- ColorKeyFrameCollection.cs
- MatrixValueSerializer.cs
- RowCache.cs
- ResourcesChangeInfo.cs
- IntranetCredentialPolicy.cs
- BasicSecurityProfileVersion.cs
- ArgumentOutOfRangeException.cs
- DecimalKeyFrameCollection.cs
- StatusBar.cs
- Trace.cs
- TextDecorationCollectionConverter.cs
- InstanceDataCollection.cs
- SmiEventSink_Default.cs
- IsolatedStorageFilePermission.cs
- ActivityTypeDesigner.xaml.cs