Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / PlanCompiler / Normalizer.cs / 1305376 / Normalizer.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Data.Common; using System.Data.Metadata.Edm; using System.Data.Query.InternalTrees; //using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class... // // The normalizer performs transformations of the tree to bring it to a 'normalized' format // In particular it does the following: // (a) Transforms collection aggregate functions into a GroupBy. // (b) Translates Exists(X) into Exists(select 1 from X) // namespace System.Data.Query.PlanCompiler { ////// The normalizer performs transformations of the tree to bring it to a 'normalized' format /// internal class Normalizer : SubqueryTrackingVisitor { #region constructors private Normalizer(PlanCompiler planCompilerState) :base(planCompilerState) { } #endregion #region public methods ////// The driver routine. /// /// plan compiler state internal static void Process(PlanCompiler planCompilerState) { Normalizer normalizer = new Normalizer(planCompilerState); normalizer.Process(); } #endregion #region private methods #region driver private void Process() { m_command.Root = VisitNode(m_command.Root); } #endregion #region visitor methods #region ScalarOps ////// Translate Exists(X) into Exists(select 1 from X) /// /// /// ///public override Node Visit(ExistsOp op, Node n) { VisitChildren(n); // Build up a dummy project node over the input n.Child0 = BuildDummyProjectForExists(n.Child0); return n; } /// /// Build Project(select 1 from child). /// /// ///private Node BuildDummyProjectForExists(Node child) { Var newVar; Node projectNode = m_command.BuildProject( child, m_command.CreateNode(m_command.CreateInternalConstantOp(m_command.IntegerType, 1)), out newVar); return projectNode; } /// /// Build up an unnest above a scalar op node /// X => unnest(X) /// /// the scalarop collection node ///the unnest node private Node BuildUnnest(Node collectionNode) { PlanCompiler.Assert(collectionNode.Op.IsScalarOp, "non-scalar usage of Unnest?"); PlanCompiler.Assert(TypeSemantics.IsCollectionType(collectionNode.Op.Type), "non-collection usage for Unnest?"); Var newVar; Node varDefNode = m_command.CreateVarDefNode(collectionNode, out newVar); UnnestOp unnestOp = m_command.CreateUnnestOp(newVar); Node unnestNode = m_command.CreateNode(unnestOp, varDefNode); return unnestNode; } ////// Converts a reference to a TVF, by the following /// Collect(PhysicalProject(Unnest(Func))) /// /// current function op /// current function subtree ///the new expression that corresponds to the TVF private Node VisitCollectionFunction(FunctionOp op, Node n) { PlanCompiler.Assert(TypeSemantics.IsCollectionType(op.Type), "non-TVF function?"); Node unnestNode = BuildUnnest(n); UnnestOp unnestOp = unnestNode.Op as UnnestOp; PhysicalProjectOp projectOp = m_command.CreatePhysicalProjectOp(unnestOp.Table.Columns[0]); Node projectNode = m_command.CreateNode(projectOp, unnestNode); CollectOp collectOp = m_command.CreateCollectOp(n.Op.Type); Node collectNode = m_command.CreateNode(collectOp, projectNode); return collectNode; } ////// Converts a collection aggregate function count(X), where X is a collection into /// two parts. Part A is a groupby subquery that looks like /// GroupBy(Unnest(X), empty, count(y)) /// where "empty" describes the fact that the groupby has no keys, and y is an /// element var of the Unnest /// /// Part 2 is a VarRef that refers to the aggregate var for count(y) described above. /// /// Logically, we would replace the entire functionOp by element(GroupBy...). However, /// since we also want to translate element() into single-row-subqueries, we do this /// here as well. /// /// The function itself is replaced by the VarRef, and the GroupBy is added to the list /// of scalar subqueries for the current relOp node on the stack /// /// /// the functionOp for the collection agg /// current subtree ///the VarRef node that should replace the function private Node VisitCollectionAggregateFunction(FunctionOp op, Node n) { TypeUsage softCastType = null; Node argNode = n.Child0; if (OpType.SoftCast == argNode.Op.OpType) { softCastType = TypeHelpers.GetEdmType(argNode.Op.Type).TypeUsage; argNode = argNode.Child0; while (OpType.SoftCast == argNode.Op.OpType) { argNode = argNode.Child0; } } Node unnestNode = BuildUnnest(argNode); UnnestOp unnestOp = unnestNode.Op as UnnestOp; Var unnestOutputVar = unnestOp.Table.Columns[0]; AggregateOp aggregateOp = m_command.CreateAggregateOp(op.Function, false); VarRefOp unnestVarRefOp = m_command.CreateVarRefOp(unnestOutputVar); Node unnestVarRefNode = m_command.CreateNode(unnestVarRefOp); if (softCastType != null) { unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode); } Node aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode); VarVec keyVars = m_command.CreateVarVec(); // empty keys Node keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp()); VarVec gbyOutputVars = m_command.CreateVarVec(); Var aggVar; Node aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar); gbyOutputVars.Set(aggVar); GroupByOp gbyOp = m_command.CreateGroupByOp(keyVars, gbyOutputVars); Node gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode); // "Move" this subquery to my parent relop Node ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode); return ret; } /// /// Pre-processing for a function. Does the default thing. In addition, if the /// function is a TVF (ie) returns a collection, convert this expression into /// Nest(select value p from unnest(f) as p) /// /// /// ///public override Node Visit(FunctionOp op, Node n) { VisitScalarOpDefault(op, n); Node newNode = null; // Is this a TVF? if (TypeSemantics.IsCollectionType(op.Type)) { newNode = VisitCollectionFunction(op, n); } // Is this a collection-aggregate function? else if (PlanCompilerUtil.IsCollectionAggregateFunction(op, n)) { newNode = VisitCollectionAggregateFunction(op, n); } else { newNode = n; } PlanCompiler.Assert(newNode != null, "failure to construct a functionOp?"); return newNode; } #endregion #region RelOps /// /// Processing for all JoinOps /// /// JoinOp /// Current subtree ///protected override Node VisitJoinOp(JoinBaseOp op, Node n) { if (base.ProcessJoinOp(op, n)) { // update the join condition // #479372: Build up a dummy project node over the input, as we always wrap the child of exists n.Child2.Child0 = BuildDummyProjectForExists(n.Child2.Child0); } return n; } #endregion #endregion #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Data.Common; using System.Data.Metadata.Edm; using System.Data.Query.InternalTrees; //using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class... // // The normalizer performs transformations of the tree to bring it to a 'normalized' format // In particular it does the following: // (a) Transforms collection aggregate functions into a GroupBy. // (b) Translates Exists(X) into Exists(select 1 from X) // namespace System.Data.Query.PlanCompiler { ////// The normalizer performs transformations of the tree to bring it to a 'normalized' format /// internal class Normalizer : SubqueryTrackingVisitor { #region constructors private Normalizer(PlanCompiler planCompilerState) :base(planCompilerState) { } #endregion #region public methods ////// The driver routine. /// /// plan compiler state internal static void Process(PlanCompiler planCompilerState) { Normalizer normalizer = new Normalizer(planCompilerState); normalizer.Process(); } #endregion #region private methods #region driver private void Process() { m_command.Root = VisitNode(m_command.Root); } #endregion #region visitor methods #region ScalarOps ////// Translate Exists(X) into Exists(select 1 from X) /// /// /// ///public override Node Visit(ExistsOp op, Node n) { VisitChildren(n); // Build up a dummy project node over the input n.Child0 = BuildDummyProjectForExists(n.Child0); return n; } /// /// Build Project(select 1 from child). /// /// ///private Node BuildDummyProjectForExists(Node child) { Var newVar; Node projectNode = m_command.BuildProject( child, m_command.CreateNode(m_command.CreateInternalConstantOp(m_command.IntegerType, 1)), out newVar); return projectNode; } /// /// Build up an unnest above a scalar op node /// X => unnest(X) /// /// the scalarop collection node ///the unnest node private Node BuildUnnest(Node collectionNode) { PlanCompiler.Assert(collectionNode.Op.IsScalarOp, "non-scalar usage of Unnest?"); PlanCompiler.Assert(TypeSemantics.IsCollectionType(collectionNode.Op.Type), "non-collection usage for Unnest?"); Var newVar; Node varDefNode = m_command.CreateVarDefNode(collectionNode, out newVar); UnnestOp unnestOp = m_command.CreateUnnestOp(newVar); Node unnestNode = m_command.CreateNode(unnestOp, varDefNode); return unnestNode; } ////// Converts a reference to a TVF, by the following /// Collect(PhysicalProject(Unnest(Func))) /// /// current function op /// current function subtree ///the new expression that corresponds to the TVF private Node VisitCollectionFunction(FunctionOp op, Node n) { PlanCompiler.Assert(TypeSemantics.IsCollectionType(op.Type), "non-TVF function?"); Node unnestNode = BuildUnnest(n); UnnestOp unnestOp = unnestNode.Op as UnnestOp; PhysicalProjectOp projectOp = m_command.CreatePhysicalProjectOp(unnestOp.Table.Columns[0]); Node projectNode = m_command.CreateNode(projectOp, unnestNode); CollectOp collectOp = m_command.CreateCollectOp(n.Op.Type); Node collectNode = m_command.CreateNode(collectOp, projectNode); return collectNode; } ////// Converts a collection aggregate function count(X), where X is a collection into /// two parts. Part A is a groupby subquery that looks like /// GroupBy(Unnest(X), empty, count(y)) /// where "empty" describes the fact that the groupby has no keys, and y is an /// element var of the Unnest /// /// Part 2 is a VarRef that refers to the aggregate var for count(y) described above. /// /// Logically, we would replace the entire functionOp by element(GroupBy...). However, /// since we also want to translate element() into single-row-subqueries, we do this /// here as well. /// /// The function itself is replaced by the VarRef, and the GroupBy is added to the list /// of scalar subqueries for the current relOp node on the stack /// /// /// the functionOp for the collection agg /// current subtree ///the VarRef node that should replace the function private Node VisitCollectionAggregateFunction(FunctionOp op, Node n) { TypeUsage softCastType = null; Node argNode = n.Child0; if (OpType.SoftCast == argNode.Op.OpType) { softCastType = TypeHelpers.GetEdmType(argNode.Op.Type).TypeUsage; argNode = argNode.Child0; while (OpType.SoftCast == argNode.Op.OpType) { argNode = argNode.Child0; } } Node unnestNode = BuildUnnest(argNode); UnnestOp unnestOp = unnestNode.Op as UnnestOp; Var unnestOutputVar = unnestOp.Table.Columns[0]; AggregateOp aggregateOp = m_command.CreateAggregateOp(op.Function, false); VarRefOp unnestVarRefOp = m_command.CreateVarRefOp(unnestOutputVar); Node unnestVarRefNode = m_command.CreateNode(unnestVarRefOp); if (softCastType != null) { unnestVarRefNode = m_command.CreateNode(m_command.CreateSoftCastOp(softCastType), unnestVarRefNode); } Node aggExprNode = m_command.CreateNode(aggregateOp, unnestVarRefNode); VarVec keyVars = m_command.CreateVarVec(); // empty keys Node keyVarDefListNode = m_command.CreateNode(m_command.CreateVarDefListOp()); VarVec gbyOutputVars = m_command.CreateVarVec(); Var aggVar; Node aggVarDefListNode = m_command.CreateVarDefListNode(aggExprNode, out aggVar); gbyOutputVars.Set(aggVar); GroupByOp gbyOp = m_command.CreateGroupByOp(keyVars, gbyOutputVars); Node gbySubqueryNode = m_command.CreateNode(gbyOp, unnestNode, keyVarDefListNode, aggVarDefListNode); // "Move" this subquery to my parent relop Node ret = AddSubqueryToParentRelOp(aggVar, gbySubqueryNode); return ret; } /// /// Pre-processing for a function. Does the default thing. In addition, if the /// function is a TVF (ie) returns a collection, convert this expression into /// Nest(select value p from unnest(f) as p) /// /// /// ///public override Node Visit(FunctionOp op, Node n) { VisitScalarOpDefault(op, n); Node newNode = null; // Is this a TVF? if (TypeSemantics.IsCollectionType(op.Type)) { newNode = VisitCollectionFunction(op, n); } // Is this a collection-aggregate function? else if (PlanCompilerUtil.IsCollectionAggregateFunction(op, n)) { newNode = VisitCollectionAggregateFunction(op, n); } else { newNode = n; } PlanCompiler.Assert(newNode != null, "failure to construct a functionOp?"); return newNode; } #endregion #region RelOps /// /// Processing for all JoinOps /// /// JoinOp /// Current subtree ///protected override Node VisitJoinOp(JoinBaseOp op, Node n) { if (base.ProcessJoinOp(op, n)) { // update the join condition // #479372: Build up a dummy project node over the input, as we always wrap the child of exists n.Child2.Child0 = BuildDummyProjectForExists(n.Child2.Child0); } return n; } #endregion #endregion #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SiteMapSection.cs
- CodeDelegateInvokeExpression.cs
- Triplet.cs
- PasswordPropertyTextAttribute.cs
- XamlParser.cs
- ZoneMembershipCondition.cs
- DataRowChangeEvent.cs
- DataGridParentRows.cs
- UserControlAutomationPeer.cs
- ServiceReference.cs
- DispatcherExceptionEventArgs.cs
- UiaCoreTypesApi.cs
- Util.cs
- FrameworkPropertyMetadata.cs
- CannotUnloadAppDomainException.cs
- DispatcherProcessingDisabled.cs
- Type.cs
- MetaType.cs
- Floater.cs
- DockProviderWrapper.cs
- IssuedTokenClientBehaviorsElement.cs
- RenderTargetBitmap.cs
- TextServicesPropertyRanges.cs
- DataGridViewCellValidatingEventArgs.cs
- TreeWalker.cs
- ReturnType.cs
- odbcmetadatafactory.cs
- Point4D.cs
- MailWebEventProvider.cs
- XmlFormatReaderGenerator.cs
- WindowsRebar.cs
- HttpCacheParams.cs
- XmlNodeReader.cs
- SqlDependencyListener.cs
- SQLInt16.cs
- SafeHandles.cs
- AddInStore.cs
- HitTestFilterBehavior.cs
- ImageFormat.cs
- TypeNameConverter.cs
- ConnectionStringSettingsCollection.cs
- DesigntimeLicenseContextSerializer.cs
- VariableModifiersHelper.cs
- FormsAuthenticationConfiguration.cs
- CompilerTypeWithParams.cs
- TriState.cs
- IsolatedStorageFilePermission.cs
- Stylesheet.cs
- Permission.cs
- ReceiveMessageContent.cs
- TypeForwardedFromAttribute.cs
- LoadedEvent.cs
- Encoding.cs
- TimeSpanConverter.cs
- SplitterPanel.cs
- QueryTaskGroupState.cs
- BookmarkList.cs
- CustomAttribute.cs
- StringToken.cs
- DbgUtil.cs
- CommittableTransaction.cs
- HelpProvider.cs
- IFlowDocumentViewer.cs
- StreamHelper.cs
- CodeDomConfigurationHandler.cs
- DataViewManager.cs
- XamlToRtfParser.cs
- XamlSerializerUtil.cs
- ComponentDispatcherThread.cs
- ExpandSegmentCollection.cs
- ViewgenGatekeeper.cs
- XomlCompilerResults.cs
- SecurityBindingElement.cs
- EntityDataSourceMemberPath.cs
- LifetimeServices.cs
- BufferedGraphics.cs
- odbcmetadatacollectionnames.cs
- BasicViewGenerator.cs
- RepeaterDesigner.cs
- PersonalizationProviderCollection.cs
- RegexWorker.cs
- Atom10FormatterFactory.cs
- StandardBindingElement.cs
- ListSortDescriptionCollection.cs
- BrowserCapabilitiesCompiler.cs
- EntityContainerEntitySetDefiningQuery.cs
- ConfigurationSettings.cs
- LogEntryDeserializer.cs
- DependencyStoreSurrogate.cs
- WebResourceAttribute.cs
- FontConverter.cs
- XmlDictionary.cs
- OverflowException.cs
- HitTestWithGeometryDrawingContextWalker.cs
- QilSortKey.cs
- OuterGlowBitmapEffect.cs
- ColorMap.cs
- DbProviderFactoriesConfigurationHandler.cs
- FileUtil.cs
- BasicExpandProvider.cs