Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DLinq / Dlinq / SqlClient / Query / SqlResolver.cs / 1305376 / SqlResolver.cs
using System; using System.Collections.Generic; using System.Data.Linq; namespace System.Data.Linq.SqlClient { // Resolves references to columns/expressions defined in other scopes internal class SqlResolver { Visitor visitor; internal SqlResolver() { this.visitor = new Visitor(); } internal SqlNode Resolve(SqlNode node) { return this.visitor.Visit(node); } private static string GetColumnName(SqlColumn c) { #if DEBUG return c.Text; #else return c.Name; #endif } class Visitor : SqlScopedVisitor { SqlBubbler bubbler; internal Visitor() { this.bubbler = new SqlBubbler(); } internal override SqlExpression VisitColumnRef(SqlColumnRef cref) { SqlColumnRef result = this.BubbleUp(cref); if (result == null) { throw Error.ColumnReferencedIsNotInScope(GetColumnName(cref.Column)); } return result; } private SqlColumnRef BubbleUp(SqlColumnRef cref) { for (Scope s = this.CurrentScope; s != null; s = s.ContainingScope) { if (s.Source != null) { SqlColumn found = this.bubbler.BubbleUp(cref.Column, s.Source); if (found != null) { if (found != cref.Column) return new SqlColumnRef(found); return cref; } } } return null; } } internal class SqlScopedVisitor : SqlVisitor { internal Scope CurrentScope; internal class Scope { SqlNode source; Scope containing; internal Scope(SqlNode source, Scope containing) { this.source = source; this.containing = containing; } internal SqlNode Source { get { return this.source; } } internal Scope ContainingScope { get { return this.containing; } } } internal SqlScopedVisitor() { this.CurrentScope = new Scope(null, null); } internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(null, this.CurrentScope); base.VisitSubSelect(ss); this.CurrentScope = save; return ss; } internal override SqlSelect VisitSelect(SqlSelect select) { select.From = (SqlSource)this.Visit(select.From); Scope save = this.CurrentScope; this.CurrentScope = new Scope(select.From, this.CurrentScope.ContainingScope); 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.Row = (SqlRow)this.Visit(select.Row); // selection must be able to see its own projection this.CurrentScope = new Scope(select, this.CurrentScope.ContainingScope); select.Selection = this.VisitExpression(select.Selection); this.CurrentScope = save; return select; } internal override SqlStatement VisitInsert(SqlInsert sin) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(sin, this.CurrentScope.ContainingScope); base.VisitInsert(sin); this.CurrentScope = save; return sin; } internal override SqlStatement VisitUpdate(SqlUpdate sup) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(sup.Select, this.CurrentScope.ContainingScope); base.VisitUpdate(sup); this.CurrentScope = save; return sup; } internal override SqlStatement VisitDelete(SqlDelete sd) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(sd, this.CurrentScope.ContainingScope); base.VisitDelete(sd); this.CurrentScope = save; return sd; } internal override SqlSource VisitJoin(SqlJoin join) { Scope save = this.CurrentScope; switch (join.JoinType) { case SqlJoinType.CrossApply: case SqlJoinType.OuterApply: { this.Visit(join.Left); Scope tmp = new Scope(join.Left, this.CurrentScope.ContainingScope); this.CurrentScope = new Scope(null, tmp); this.Visit(join.Right); Scope tmp2 = new Scope(join.Right, tmp); this.CurrentScope = new Scope(null, tmp2); this.Visit(join.Condition); break; } default: { this.Visit(join.Left); this.Visit(join.Right); this.CurrentScope = new Scope(null, new Scope(join.Right, new Scope(join.Left, this.CurrentScope.ContainingScope))); this.Visit(join.Condition); break; } } this.CurrentScope = save; return join; } } // finds location of expression definition and re-projects that value all the // way to the outermost projection internal class SqlBubbler : SqlVisitor { SqlColumn match; SqlColumn found; internal SqlBubbler() { } internal SqlColumn BubbleUp(SqlColumn col, SqlNode source) { this.match = this.GetOriginatingColumn(col); this.found = null; this.Visit(source); return this.found; } internal SqlColumn GetOriginatingColumn(SqlColumn col) { SqlColumnRef cref = col.Expression as SqlColumnRef; if (cref != null) { return this.GetOriginatingColumn(cref.Column); } return col; } internal override SqlRow VisitRow(SqlRow row) { foreach (SqlColumn c in row.Columns) { if (this.RefersToColumn(c, this.match)) { if (this.found != null) { throw Error.ColumnIsDefinedInMultiplePlaces(GetColumnName(this.match)); } this.found = c; break; } } return row; } internal override SqlTable VisitTable(SqlTable tab) { foreach (SqlColumn c in tab.Columns) { if (c == this.match) { if (this.found != null) throw Error.ColumnIsDefinedInMultiplePlaces(GetColumnName(this.match)); this.found = c; break; } } return tab; } internal override SqlSource VisitJoin(SqlJoin join) { switch (join.JoinType) { case SqlJoinType.CrossApply: case SqlJoinType.OuterApply: { this.Visit(join.Left); if (this.found == null) { this.Visit(join.Right); } break; } default: { this.Visit(join.Left); this.Visit(join.Right); break; } } return join; } internal override SqlExpression VisitTableValuedFunctionCall(SqlTableValuedFunctionCall fc) { foreach (SqlColumn c in fc.Columns) { if (c == this.match) { if (this.found != null) throw Error.ColumnIsDefinedInMultiplePlaces(GetColumnName(this.match)); this.found = c; break; } } return fc; } private void ForceLocal(SqlRow row, string name) { bool isLocal = false; // check to see if it already exists locally foreach (SqlColumn c in row.Columns) { if (this.RefersToColumn(c, this.found)) { this.found = c; isLocal = true; break; } } if (!isLocal) { // need to put this in the local projection list to bubble it up SqlColumn c = new SqlColumn(found.ClrType, found.SqlType, name, this.found.MetaMember, new SqlColumnRef(this.found), row.SourceExpression); row.Columns.Add(c); this.found = c; } } private bool IsFoundInGroup(SqlSelect select) { // does the column happen to be listed in the group-by clause? foreach (SqlExpression exp in select.GroupBy) { if (this.RefersToColumn(exp, this.found) || this.RefersToColumn(exp, this.match)) { return true; } } return false; } internal override SqlSelect VisitSelect(SqlSelect select) { // look in this projection this.Visit(select.Row); if (this.found == null) { // look in upstream projections this.Visit(select.From); // bubble it up if (this.found != null) { if (select.IsDistinct && !match.IsConstantColumn) { throw Error.ColumnIsNotAccessibleThroughDistinct(GetColumnName(this.match)); } if (select.GroupBy.Count == 0 || this.IsFoundInGroup(select)) { this.ForceLocal(select.Row, this.found.Name); } else { // found it, but its hidden behind the group-by throw Error.ColumnIsNotAccessibleThroughGroupBy(GetColumnName(this.match)); } } } return select; } } } } // 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.Data.Linq; namespace System.Data.Linq.SqlClient { // Resolves references to columns/expressions defined in other scopes internal class SqlResolver { Visitor visitor; internal SqlResolver() { this.visitor = new Visitor(); } internal SqlNode Resolve(SqlNode node) { return this.visitor.Visit(node); } private static string GetColumnName(SqlColumn c) { #if DEBUG return c.Text; #else return c.Name; #endif } class Visitor : SqlScopedVisitor { SqlBubbler bubbler; internal Visitor() { this.bubbler = new SqlBubbler(); } internal override SqlExpression VisitColumnRef(SqlColumnRef cref) { SqlColumnRef result = this.BubbleUp(cref); if (result == null) { throw Error.ColumnReferencedIsNotInScope(GetColumnName(cref.Column)); } return result; } private SqlColumnRef BubbleUp(SqlColumnRef cref) { for (Scope s = this.CurrentScope; s != null; s = s.ContainingScope) { if (s.Source != null) { SqlColumn found = this.bubbler.BubbleUp(cref.Column, s.Source); if (found != null) { if (found != cref.Column) return new SqlColumnRef(found); return cref; } } } return null; } } internal class SqlScopedVisitor : SqlVisitor { internal Scope CurrentScope; internal class Scope { SqlNode source; Scope containing; internal Scope(SqlNode source, Scope containing) { this.source = source; this.containing = containing; } internal SqlNode Source { get { return this.source; } } internal Scope ContainingScope { get { return this.containing; } } } internal SqlScopedVisitor() { this.CurrentScope = new Scope(null, null); } internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(null, this.CurrentScope); base.VisitSubSelect(ss); this.CurrentScope = save; return ss; } internal override SqlSelect VisitSelect(SqlSelect select) { select.From = (SqlSource)this.Visit(select.From); Scope save = this.CurrentScope; this.CurrentScope = new Scope(select.From, this.CurrentScope.ContainingScope); 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.Row = (SqlRow)this.Visit(select.Row); // selection must be able to see its own projection this.CurrentScope = new Scope(select, this.CurrentScope.ContainingScope); select.Selection = this.VisitExpression(select.Selection); this.CurrentScope = save; return select; } internal override SqlStatement VisitInsert(SqlInsert sin) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(sin, this.CurrentScope.ContainingScope); base.VisitInsert(sin); this.CurrentScope = save; return sin; } internal override SqlStatement VisitUpdate(SqlUpdate sup) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(sup.Select, this.CurrentScope.ContainingScope); base.VisitUpdate(sup); this.CurrentScope = save; return sup; } internal override SqlStatement VisitDelete(SqlDelete sd) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(sd, this.CurrentScope.ContainingScope); base.VisitDelete(sd); this.CurrentScope = save; return sd; } internal override SqlSource VisitJoin(SqlJoin join) { Scope save = this.CurrentScope; switch (join.JoinType) { case SqlJoinType.CrossApply: case SqlJoinType.OuterApply: { this.Visit(join.Left); Scope tmp = new Scope(join.Left, this.CurrentScope.ContainingScope); this.CurrentScope = new Scope(null, tmp); this.Visit(join.Right); Scope tmp2 = new Scope(join.Right, tmp); this.CurrentScope = new Scope(null, tmp2); this.Visit(join.Condition); break; } default: { this.Visit(join.Left); this.Visit(join.Right); this.CurrentScope = new Scope(null, new Scope(join.Right, new Scope(join.Left, this.CurrentScope.ContainingScope))); this.Visit(join.Condition); break; } } this.CurrentScope = save; return join; } } // finds location of expression definition and re-projects that value all the // way to the outermost projection internal class SqlBubbler : SqlVisitor { SqlColumn match; SqlColumn found; internal SqlBubbler() { } internal SqlColumn BubbleUp(SqlColumn col, SqlNode source) { this.match = this.GetOriginatingColumn(col); this.found = null; this.Visit(source); return this.found; } internal SqlColumn GetOriginatingColumn(SqlColumn col) { SqlColumnRef cref = col.Expression as SqlColumnRef; if (cref != null) { return this.GetOriginatingColumn(cref.Column); } return col; } internal override SqlRow VisitRow(SqlRow row) { foreach (SqlColumn c in row.Columns) { if (this.RefersToColumn(c, this.match)) { if (this.found != null) { throw Error.ColumnIsDefinedInMultiplePlaces(GetColumnName(this.match)); } this.found = c; break; } } return row; } internal override SqlTable VisitTable(SqlTable tab) { foreach (SqlColumn c in tab.Columns) { if (c == this.match) { if (this.found != null) throw Error.ColumnIsDefinedInMultiplePlaces(GetColumnName(this.match)); this.found = c; break; } } return tab; } internal override SqlSource VisitJoin(SqlJoin join) { switch (join.JoinType) { case SqlJoinType.CrossApply: case SqlJoinType.OuterApply: { this.Visit(join.Left); if (this.found == null) { this.Visit(join.Right); } break; } default: { this.Visit(join.Left); this.Visit(join.Right); break; } } return join; } internal override SqlExpression VisitTableValuedFunctionCall(SqlTableValuedFunctionCall fc) { foreach (SqlColumn c in fc.Columns) { if (c == this.match) { if (this.found != null) throw Error.ColumnIsDefinedInMultiplePlaces(GetColumnName(this.match)); this.found = c; break; } } return fc; } private void ForceLocal(SqlRow row, string name) { bool isLocal = false; // check to see if it already exists locally foreach (SqlColumn c in row.Columns) { if (this.RefersToColumn(c, this.found)) { this.found = c; isLocal = true; break; } } if (!isLocal) { // need to put this in the local projection list to bubble it up SqlColumn c = new SqlColumn(found.ClrType, found.SqlType, name, this.found.MetaMember, new SqlColumnRef(this.found), row.SourceExpression); row.Columns.Add(c); this.found = c; } } private bool IsFoundInGroup(SqlSelect select) { // does the column happen to be listed in the group-by clause? foreach (SqlExpression exp in select.GroupBy) { if (this.RefersToColumn(exp, this.found) || this.RefersToColumn(exp, this.match)) { return true; } } return false; } internal override SqlSelect VisitSelect(SqlSelect select) { // look in this projection this.Visit(select.Row); if (this.found == null) { // look in upstream projections this.Visit(select.From); // bubble it up if (this.found != null) { if (select.IsDistinct && !match.IsConstantColumn) { throw Error.ColumnIsNotAccessibleThroughDistinct(GetColumnName(this.match)); } if (select.GroupBy.Count == 0 || this.IsFoundInGroup(select)) { this.ForceLocal(select.Row, this.found.Name); } else { // found it, but its hidden behind the group-by throw Error.ColumnIsNotAccessibleThroughGroupBy(GetColumnName(this.match)); } } } return select; } } } } // 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
- ContextQuery.cs
- Ipv6Element.cs
- InputDevice.cs
- CallContext.cs
- DefaultValueConverter.cs
- ClientTargetSection.cs
- securestring.cs
- MatchingStyle.cs
- Root.cs
- AssociationSetEnd.cs
- LockRecursionException.cs
- SharedStatics.cs
- CollectionViewSource.cs
- SyntaxCheck.cs
- BrowserTree.cs
- ExpressionVisitorHelpers.cs
- DataGridViewAutoSizeColumnModeEventArgs.cs
- XmlTypeAttribute.cs
- AdRotator.cs
- ValueTable.cs
- XmlSchemaAnnotated.cs
- ViewStateModeByIdAttribute.cs
- ConnectionConsumerAttribute.cs
- ReliableReplySessionChannel.cs
- ValidationHelpers.cs
- ClientConfigurationSystem.cs
- RelatedCurrencyManager.cs
- EndGetFileNameFromUserRequest.cs
- RowsCopiedEventArgs.cs
- SqlDuplicator.cs
- SqlLiftWhereClauses.cs
- QueryTaskGroupState.cs
- DateTimeEditor.cs
- SettingsPropertyNotFoundException.cs
- WindowsListViewItemCheckBox.cs
- UIElementAutomationPeer.cs
- OpenTypeLayout.cs
- DrawingDrawingContext.cs
- TextTreeTextBlock.cs
- ClientSettingsSection.cs
- SHA1CryptoServiceProvider.cs
- TextModifierScope.cs
- HttpPostedFileBase.cs
- TypeDescriptionProvider.cs
- SvcFileManager.cs
- DocumentOrderQuery.cs
- MimeWriter.cs
- TypeDelegator.cs
- X509Certificate.cs
- HwndKeyboardInputProvider.cs
- ClientOperationFormatterProvider.cs
- NewArray.cs
- RootCodeDomSerializer.cs
- ProfileBuildProvider.cs
- ImagingCache.cs
- CssClassPropertyAttribute.cs
- FragmentQuery.cs
- RequestQueryProcessor.cs
- MsmqOutputSessionChannel.cs
- XamlDesignerSerializationManager.cs
- QueryInterceptorAttribute.cs
- SignatureToken.cs
- FileLoadException.cs
- ExpressionReplacer.cs
- HtmlTableCell.cs
- XslAst.cs
- FigureHelper.cs
- ThemeDictionaryExtension.cs
- SHA512.cs
- FileLoadException.cs
- DashStyle.cs
- EventLogPermissionAttribute.cs
- RTTypeWrapper.cs
- PropertyGrid.cs
- SplitterPanelDesigner.cs
- COM2Properties.cs
- ListControl.cs
- Propagator.JoinPropagator.JoinPredicateVisitor.cs
- GroupedContextMenuStrip.cs
- Point4D.cs
- _SslState.cs
- FixedDocumentPaginator.cs
- FormViewUpdatedEventArgs.cs
- _ProxyChain.cs
- NotifyCollectionChangedEventArgs.cs
- BrushMappingModeValidation.cs
- BamlResourceDeserializer.cs
- ConnectionStringSettings.cs
- BaseCodePageEncoding.cs
- WCFModelStrings.Designer.cs
- Char.cs
- DelegatingChannelListener.cs
- Wildcard.cs
- HtmlTableCell.cs
- IFlowDocumentViewer.cs
- BindingMemberInfo.cs
- PrivilegeNotHeldException.cs
- DataContext.cs
- SQLDouble.cs
- SafeCryptoHandles.cs