Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Query / PlanCompiler / PropertyPushdownHelper.cs / 3 / PropertyPushdownHelper.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
using System.Globalization;
using System.Data.Common;
using md = System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees;
namespace System.Data.Query.PlanCompiler {
///
/// The PropertyPushdownHelper module is a submodule of the StructuredTypeEliminator
/// module. It serves as a useful optimization sidekick for NominalTypeEliminator which
/// is the real guts of eliminating structured types.
///
/// The goal of this module is to identify a list of desired properties for each node
/// (and Var) in the tree that is of a structured type. This list of desired properties
/// is identified in a top-down push fashion.
///
/// While it is desirable to get as accurate information as possible, it is unnecessary
/// for this module to be super-efficient (i.e.) it is ok for it to get a superset
/// of the appropriate information for each node, but it is absolutely not ok for it
/// to get a subset. Later phases (projection pruning) can help eliminate unnecessary
/// information, but the query cannot be made incorrect.
///
/// This module is implemented as a visitor - it leverages information about
/// types in the query - made possible by the TypeFlattener module - and walks
/// down the tree pushing properties to each child of a node. It builds two maps:
///
/// (*) a node-property map
/// (*) a var-property map
///
/// Each of these keeps trackof the properties needed from each node/var.
///
/// These maps are returned to the caller and will be used by the NominalTypeEliminator
/// module to eliminate all structured types.
///
internal class PropertyPushdownHelper : BasicOpVisitor {
#region private state
private readonly Dictionary m_nodePropertyRefMap;
private readonly Dictionary m_varPropertyRefMap;
private readonly StructuredTypeInfo m_structuredTypeInfo;
#endregion
#region constructor
private PropertyPushdownHelper(StructuredTypeInfo structuredTypeInfo) {
m_structuredTypeInfo = structuredTypeInfo;
m_varPropertyRefMap = new Dictionary();
m_nodePropertyRefMap = new Dictionary();
}
#endregion
#region Process Driver
///
/// The driver.
/// Walks the tree, and "pushes" down information about required properties
/// to every node and Var in the tree.
///
/// The query tree
/// Type info for structured types appearing in query.
/// List of desired properties from each Var
/// List of desired properties from each node
internal static void Process(Command itree, StructuredTypeInfo structuredTypeInfo, out Dictionary varPropertyRefs, out Dictionary nodePropertyRefs) {
PropertyPushdownHelper pph = new PropertyPushdownHelper(structuredTypeInfo);
pph.Process(itree.Root);
varPropertyRefs = pph.m_varPropertyRefMap;
nodePropertyRefs = pph.m_nodePropertyRefMap;
}
///
/// the driver routine. Invokes the visitor, and then returns the collected
/// info
///
/// node in the tree to begin processing at
private void Process(Node rootNode) {
// simply invoke the visitor
rootNode.Op.Accept(this, rootNode);
}
#endregion
#region private methods
#region state maintenance
///
/// Get the list of propertyrefs for a node. If none exists, create an
/// empty structure and store it in the map
///
/// Specific node
/// List of properties expected from this node
private PropertyRefList GetPropertyRefList(Node node) {
PropertyRefList propRefs;
if (!m_nodePropertyRefMap.TryGetValue(node, out propRefs)) {
propRefs = new PropertyRefList();
m_nodePropertyRefMap[node] = propRefs;
}
return propRefs;
}
///
/// Add a list of property references for this node
///
/// the node
/// list of property references
private void AddPropertyRefs(Node node, PropertyRefList propertyRefs) {
PropertyRefList refs = GetPropertyRefList(node);
refs.Append(propertyRefs);
}
///
/// Get the list of desired properties for a Var
///
/// the var
/// List of desired properties
private PropertyRefList GetPropertyRefList(Var v) {
PropertyRefList propRefs;
if (!m_varPropertyRefMap.TryGetValue(v, out propRefs)) {
propRefs = new PropertyRefList();
m_varPropertyRefMap[v] = propRefs;
}
return propRefs;
}
///
/// Add a new set of properties to a Var
///
/// the var
/// desired properties
private void AddPropertyRefs(Var v, PropertyRefList propertyRefs) {
PropertyRefList currentRefs = GetPropertyRefList(v);
currentRefs.Append(propertyRefs);
}
#endregion
#region Visitor Helpers
///
/// Gets the list of "identity" properties for an entity. Gets the
/// "entitysetid" property in addition to the "key" properties
///
///
///
private static PropertyRefList GetIdentityProperties(md.EntityType type) {
PropertyRefList desiredProperties = GetKeyProperties(type);
desiredProperties.Add(EntitySetIdPropertyRef.Instance);
return desiredProperties;
}
///
/// Gets the list of key properties for an entity
///
///
///
private static PropertyRefList GetKeyProperties(md.EntityType entityType) {
PropertyRefList desiredProperties = new PropertyRefList();
foreach (md.EdmMember p in entityType.KeyMembers) {
md.EdmProperty edmP = p as md.EdmProperty;
PlanCompiler.Assert(edmP!=null, "EntityType had non-EdmProperty key member?");
SimplePropertyRef pRef = new SimplePropertyRef(edmP);
desiredProperties.Add(pRef);
}
return desiredProperties;
}
#endregion
///
/// Default visitor for an Op.
///
/// Simply walks through all children looking for Ops of structured
/// types, and asks for all their properties.
///
///
/// Several of the ScalarOps take the default handling, to simply ask
/// for all the children's properties:
///
/// AggegateOp
/// ArithmeticOp
/// CastOp
/// ConditionalOp
/// ConstantOp
/// ElementOp
/// ExistsOp
/// FunctionOp
/// GetRefKeyOp
/// LikeOp
/// NestAggregateOp
/// NewInstanceOp
/// NewMultisetOp
/// NewRecordOp
/// RefOp
///
/// They do not exist here to eliminate noise.
///
/// Note that the NewRecordOp and the NewInstanceOp could be optimized to only
/// push down the appropriate references, but it isn't clear to Murali that the
/// complexity is worth it.
///
///
protected override void VisitDefault(Node n) {
// for each child that is a complex type, simply ask for all properties
foreach (Node chi in n.Children) {
ScalarOp chiOp = chi.Op as ScalarOp;
if (chiOp != null && TypeUtils.IsStructuredType(chiOp.Type)) {
AddPropertyRefs(chi, PropertyRefList.All);
}
}
VisitChildren(n);
}
#region ScalarOps
///
/// SoftCastOp:
/// If the input is
/// Ref - ask for all properties
/// Entity, ComplexType - ask for the same properties I've been asked for
/// Record - ask for all properties (Note: This should be more optimized in the future
/// since we can actually "remap" the properties)
///
///
///
public override void Visit(SoftCastOp op, Node n) {
PropertyRefList childProps = null;
if (md.TypeSemantics.IsReferenceType(op.Type)) {
childProps = PropertyRefList.All;
}
else if (md.TypeSemantics.IsNominalType(op.Type)) {
PropertyRefList myProps = m_nodePropertyRefMap[n];
childProps = myProps.Clone();
}
else if (md.TypeSemantics.IsRowType(op.Type)) {
//
// Note: We should do a better job here (by translating
// our PropertyRefs to the equivalent property refs on the child
//
childProps = PropertyRefList.All;
}
if (childProps != null) {
AddPropertyRefs(n.Child0, childProps);
}
VisitChildren(n);
}
///
/// CaseOp handling
///
/// Pushes its desired properties to each of the WHEN/ELSE clauses
///
///
///
public override void Visit(CaseOp op, Node n) {
// First find the properties that my parent expects from me
PropertyRefList pdProps = GetPropertyRefList(n);
// push down the same properties to my then/else clauses.
// the "when" clauses are irrelevant
for (int i = 1; i < n.Children.Count - 1; i += 2) {
PropertyRefList cdProps = pdProps.Clone();
AddPropertyRefs(n.Children[i], cdProps);
}
AddPropertyRefs(n.Children[n.Children.Count - 1], pdProps.Clone());
// Now visit the children
VisitChildren(n);
}
///
/// CollectOp handling.
///
///
///
public override void Visit(CollectOp op, Node n) {
// Simply visit the children without pushing down any references to them.
VisitChildren(n);
}
///
/// ComparisonOp handling
///
///
///
public override void Visit(ComparisonOp op, Node n) {
// Check to see if the children are structured types. Furthermore,
// if the children are of entity types, then all we really need are
// the key properties (and the entityset property)
// For record and ref types, simply keep going
md.TypeUsage childOpType = (n.Child0.Op as ScalarOp).Type;
if (!TypeUtils.IsStructuredType(childOpType)) {
VisitChildren(n);
}
else if (md.TypeSemantics.IsRowType(childOpType) || md.TypeSemantics.IsReferenceType(childOpType))
VisitDefault(n);
else {
PlanCompiler.Assert(md.TypeSemantics.IsEntityType(childOpType), "unexpected childOpType?");
PropertyRefList desiredProperties = GetIdentityProperties(TypeHelpers.GetEdmType(childOpType));
// Now push these set of properties to each child
foreach (Node chi in n.Children)
AddPropertyRefs(chi, desiredProperties);
// Visit the children
VisitChildren(n);
}
}
///
/// ElementOp handling
///
///
///
public override void Visit(ElementOp op, Node n) {
// Cannot occur at this stage of processing
throw EntityUtil.NotSupported();
}
///
/// GetEntityRefOp handling
///
/// Ask for the "identity" properties from the input entity, and push that
/// down to my child
///
///
///
public override void Visit(GetEntityRefOp op, Node n) {
ScalarOp childOp = n.Child0.Op as ScalarOp;
PlanCompiler.Assert(childOp != null, "input to GetEntityRefOp is not a ScalarOp?");
// bug 428542 - the child is of the entity type; not this op
md.EntityType entityType = TypeHelpers.GetEdmType(childOp.Type);
PropertyRefList desiredProperties = GetIdentityProperties(entityType);
AddPropertyRefs(n.Child0, desiredProperties);
VisitNode(n.Child0);
}
///
/// IsOfOp handling
///
/// Simply requests the "typeid" property from
/// the input. No other property is required
///
/// IsOf op
/// Node to visit
public override void Visit(IsOfOp op, Node n) {
// The only property I need from my child is the typeid property;
PropertyRefList childProps = new PropertyRefList();
childProps.Add(TypeIdPropertyRef.Instance);
AddPropertyRefs(n.Child0, childProps);
VisitChildren(n);
}
///
/// Common handler for RelPropertyOp and PropertyOp.
/// Simply pushes down the desired set of properties to the child
///
/// the *propertyOp
/// node tree corresponding to the Op
/// the property reference
private void VisitPropertyOp(Op op, Node n, PropertyRef propertyRef) {
PropertyRefList cdProps = new PropertyRefList();
if (!TypeUtils.IsStructuredType(op.Type)) {
cdProps.Add(propertyRef);
}
else {
// Get the list of properties my parent expects from me.
PropertyRefList pdProps = GetPropertyRefList(n);
// Ask my child (which is really my container type) for each of these
// properties
// If I've been asked for all my properties, then get the
// corresponding flat list of properties from my children.
// For now, however, simply ask for all properties in this case
// What we really need to do is to get the "flattened" list of
// properties from the input, and prepend each of these with
// our property name. We don't have that info available, so
// I'm taking the easier route.
if (pdProps.AllProperties) {
cdProps = pdProps;
}
else {
foreach (PropertyRef p in pdProps.Properties) {
cdProps.Add(p.CreateNestedPropertyRef(propertyRef));
}
}
}
// push down my expectations
AddPropertyRefs(n.Child0, cdProps);
VisitChildren(n);
}
///
/// RelPropertyOp handling.
/// Delegates to VisitPropertyOp. Marks the rel-property as required from the
/// child
///
/// the RelPropertyOp
/// node tree corresponding to the op
public override void Visit(RelPropertyOp op, Node n) {
VisitPropertyOp(op, n, new RelPropertyRef(op.PropertyInfo));
}
///
/// PropertyOp handling
///
/// Pushes down the requested properties along with the current
/// property to the child
///
///
///
public override void Visit(PropertyOp op, Node n) {
VisitPropertyOp(op, n, new SimplePropertyRef(op.PropertyInfo));
}
///
/// TreatOp handling
///
/// Simply passes down "my" desired properties, and additionally
/// asks for the TypeID property
///
///
///
public override void Visit(TreatOp op, Node n) {
// First find the properties that my parent expects from me
PropertyRefList pdProps = GetPropertyRefList(n);
// Push down each of these, and in addition, push down the typeid property
// to my child
PropertyRefList childProps = pdProps.Clone();
childProps.Add(TypeIdPropertyRef.Instance);
AddPropertyRefs(n.Child0, childProps);
VisitChildren(n);
}
///
/// VarRefOp handling
///
/// Simply passes along the current "desired" properties
/// to the corresponding Var
///
///
///
public override void Visit(VarRefOp op, Node n) {
if (TypeUtils.IsStructuredType(op.Var.Type)) {
// Get the properties that my parent expects from me.
PropertyRefList myProps = GetPropertyRefList(n);
// Add this onto the list of properties expected from the var itself
AddPropertyRefs(op.Var, myProps);
}
}
#endregion
#region AncillaryOps
///
/// VarDefOp handling
///
/// Pushes the "desired" properties to the
/// defining expression
///
///
///
public override void Visit(VarDefOp op, Node n) {
if (TypeUtils.IsStructuredType(op.Var.Type)) {
PropertyRefList myProps = GetPropertyRefList(op.Var);
// Push this down to the expression defining the var
AddPropertyRefs(n.Child0, myProps);
}
VisitChildren(n);
}
///
/// VarDefListOp handling
///
///
///
public override void Visit(VarDefListOp op, Node n) {
// Simply visit the children without pushing down any references to them.
VisitChildren(n);
}
#endregion
#region RelOps
///
/// ApplyOp handling
/// CrossApplyOp handling
/// OuterApplyOp handling
///
/// Handling for all ApplyOps: Process the right child, and then
/// the left child - since the right child may have references to the
/// left
///
/// apply op
///
protected override void VisitApplyOp(ApplyBaseOp op, Node n) {
VisitNode(n.Child1); // the right input
VisitNode(n.Child0); // the left input
}
///
/// DistinctOp handling
///
/// Require all properties out of all structured vars
///
///
///
public override void Visit(DistinctOp op, Node n) {
foreach (Var v in op.Keys)
if (TypeUtils.IsStructuredType(v.Type)) {
AddPropertyRefs(v, PropertyRefList.All);
}
VisitChildren(n);
}
///
/// FilterOp handling
///
/// Process the predicate child, and then the input child - since the
/// predicate child will probably have references to the input.
///
///
///
public override void Visit(FilterOp op, Node n) {
VisitNode(n.Child1); // visit predicate first
VisitNode(n.Child0); // then visit the relop input
}
///
/// GroupByOp handling
///
///
///
public override void Visit(GroupByOp op, Node n) {
// First "request" all properties for every key (that is a structured type)
foreach (Var v in op.Keys) {
if (TypeUtils.IsStructuredType(v.Type)) {
AddPropertyRefs(v, PropertyRefList.All);
}
}
// Now visit the aggregate definitions, the key definitions, and
// the relop input in that order
VisitNode(n.Child2);
VisitNode(n.Child1);
VisitNode(n.Child0);
}
///
/// JoinOp handling
/// CrossJoinOp handling
/// InnerJoinOp handling
/// LeftOuterJoinOp handling
/// FullOuterJoinOp handling
///
/// Handler for all JoinOps. For all joins except cross joins, process
/// the predicate first, and then the inputs - the inputs can be processed
/// in any order.
///
/// For cross joins, simply process all the (relop) inputs
///
/// join op
///
protected override void VisitJoinOp(JoinBaseOp op, Node n) {
if (n.Op.OpType == OpType.CrossJoin)
VisitChildren(n);
else {
VisitNode(n.Child2); // the predicate first
VisitNode(n.Child0); // then, the left input
VisitNode(n.Child1); // the right input
}
}
///
/// ProjectOp handling
///
///
///
public override void Visit(ProjectOp op, Node n) {
VisitNode(n.Child1); // visit projections first
VisitNode(n.Child0); // then visit the relop input
}
///
/// ScanTableOp handler
///
///
///
public override void Visit(ScanTableOp op, Node n) {
PlanCompiler.Assert(!n.HasChild0, "scanTableOp with an input?");
}
///
/// ScanViewOp
///
/// ask for all properties from the view definition
/// that have currently been requested from the view itself
///
/// current ScanViewOp
/// current node
public override void Visit(ScanViewOp op, Node n) {
PlanCompiler.Assert(op.Table.Columns.Count == 1, "ScanViewOp with multiple columns?");
Var columnVar = op.Table.Columns[0];
PropertyRefList columnProps = GetPropertyRefList(columnVar);
Var inputVar = NominalTypeEliminator.GetSingletonVar(n.Child0);
PlanCompiler.Assert(inputVar != null, "cannot determine single Var from ScanViewOp's input");
AddPropertyRefs(inputVar, columnProps.Clone());
VisitChildren(n);
}
///
/// SetOp handling
/// UnionAllOp handling
/// IntersectOp handling
/// ExceptOp handling
///
/// Visitor for a SetOp. Pushes desired properties to the corresponding
/// Vars of the input
///
/// the setop
///
protected override void VisitSetOp(SetOp op, Node n) {
foreach (VarMap varMap in op.VarMap)
foreach (KeyValuePair kv in varMap) {
if (TypeUtils.IsStructuredType(kv.Key.Type)) {
// Get the set of expected properties for the unionVar, and
// push it down to the inputvars
// For Intersect and ExceptOps, we need all properties
// from the input
// We call GetPropertyRefList() always to initialize
// the map, even though we may not use it
//
PropertyRefList myProps = GetPropertyRefList(kv.Key);
if (op.OpType == OpType.Intersect || op.OpType == OpType.Except) {
myProps = PropertyRefList.All;
// We "want" all properties even on the output of the setop
AddPropertyRefs(kv.Key, myProps);
}
else {
myProps = myProps.Clone();
}
AddPropertyRefs(kv.Value, myProps);
}
}
VisitChildren(n);
}
///
/// SortOp handling
///
/// First, "request" that for any sort key that is a structured type, we
/// need all its properties. Then process any local definitions, and
/// finally the relop input
///
///
///
protected override void VisitSortOp(SortBaseOp op, Node n) {
// foreach sort key, every single bit of the Var is needed
foreach (InternalTrees.SortKey sk in op.Keys)
if (TypeUtils.IsStructuredType(sk.Var.Type))
AddPropertyRefs(sk.Var, PropertyRefList.All);
// if the sort has any local definitions, process those first
if (n.HasChild1)
VisitNode(n.Child1);
// then process the relop input
VisitNode(n.Child0);
}
///
/// UnnestOp handling
///
///
///
public override void Visit(UnnestOp op, Node n) {
VisitChildren(n);
}
#endregion
#region PhysicalOps
///
/// PhysicalProjectOp handling
///
///
///
public override void Visit(PhysicalProjectOp op, Node n) {
// Insist that we need all properties from all the outputs
foreach (Var v in op.Outputs) {
if (TypeUtils.IsStructuredType(v.Type)) {
AddPropertyRefs(v, PropertyRefList.All);
}
}
// simply visit the children
VisitChildren(n);
}
///
/// MultiStreamNestOp handling
///
///
///
public override void Visit(MultiStreamNestOp op, Node n) {
// Cannot occur at this stage of processing
throw EntityUtil.NotSupported();
}
///
/// SingleStreamNestOp handling
///
///
///
public override void Visit(SingleStreamNestOp op, Node n) {
// Cannot occur at this stage of processing
throw EntityUtil.NotSupported();
}
#endregion
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
using System.Globalization;
using System.Data.Common;
using md = System.Data.Metadata.Edm;
using System.Data.Query.InternalTrees;
namespace System.Data.Query.PlanCompiler {
///
/// The PropertyPushdownHelper module is a submodule of the StructuredTypeEliminator
/// module. It serves as a useful optimization sidekick for NominalTypeEliminator which
/// is the real guts of eliminating structured types.
///
/// The goal of this module is to identify a list of desired properties for each node
/// (and Var) in the tree that is of a structured type. This list of desired properties
/// is identified in a top-down push fashion.
///
/// While it is desirable to get as accurate information as possible, it is unnecessary
/// for this module to be super-efficient (i.e.) it is ok for it to get a superset
/// of the appropriate information for each node, but it is absolutely not ok for it
/// to get a subset. Later phases (projection pruning) can help eliminate unnecessary
/// information, but the query cannot be made incorrect.
///
/// This module is implemented as a visitor - it leverages information about
/// types in the query - made possible by the TypeFlattener module - and walks
/// down the tree pushing properties to each child of a node. It builds two maps:
///
/// (*) a node-property map
/// (*) a var-property map
///
/// Each of these keeps trackof the properties needed from each node/var.
///
/// These maps are returned to the caller and will be used by the NominalTypeEliminator
/// module to eliminate all structured types.
///
internal class PropertyPushdownHelper : BasicOpVisitor {
#region private state
private readonly Dictionary m_nodePropertyRefMap;
private readonly Dictionary m_varPropertyRefMap;
private readonly StructuredTypeInfo m_structuredTypeInfo;
#endregion
#region constructor
private PropertyPushdownHelper(StructuredTypeInfo structuredTypeInfo) {
m_structuredTypeInfo = structuredTypeInfo;
m_varPropertyRefMap = new Dictionary();
m_nodePropertyRefMap = new Dictionary();
}
#endregion
#region Process Driver
///
/// The driver.
/// Walks the tree, and "pushes" down information about required properties
/// to every node and Var in the tree.
///
/// The query tree
/// Type info for structured types appearing in query.
/// List of desired properties from each Var
/// List of desired properties from each node
internal static void Process(Command itree, StructuredTypeInfo structuredTypeInfo, out Dictionary varPropertyRefs, out Dictionary nodePropertyRefs) {
PropertyPushdownHelper pph = new PropertyPushdownHelper(structuredTypeInfo);
pph.Process(itree.Root);
varPropertyRefs = pph.m_varPropertyRefMap;
nodePropertyRefs = pph.m_nodePropertyRefMap;
}
///
/// the driver routine. Invokes the visitor, and then returns the collected
/// info
///
/// node in the tree to begin processing at
private void Process(Node rootNode) {
// simply invoke the visitor
rootNode.Op.Accept(this, rootNode);
}
#endregion
#region private methods
#region state maintenance
///
/// Get the list of propertyrefs for a node. If none exists, create an
/// empty structure and store it in the map
///
/// Specific node
/// List of properties expected from this node
private PropertyRefList GetPropertyRefList(Node node) {
PropertyRefList propRefs;
if (!m_nodePropertyRefMap.TryGetValue(node, out propRefs)) {
propRefs = new PropertyRefList();
m_nodePropertyRefMap[node] = propRefs;
}
return propRefs;
}
///
/// Add a list of property references for this node
///
/// the node
/// list of property references
private void AddPropertyRefs(Node node, PropertyRefList propertyRefs) {
PropertyRefList refs = GetPropertyRefList(node);
refs.Append(propertyRefs);
}
///
/// Get the list of desired properties for a Var
///
/// the var
/// List of desired properties
private PropertyRefList GetPropertyRefList(Var v) {
PropertyRefList propRefs;
if (!m_varPropertyRefMap.TryGetValue(v, out propRefs)) {
propRefs = new PropertyRefList();
m_varPropertyRefMap[v] = propRefs;
}
return propRefs;
}
///
/// Add a new set of properties to a Var
///
/// the var
/// desired properties
private void AddPropertyRefs(Var v, PropertyRefList propertyRefs) {
PropertyRefList currentRefs = GetPropertyRefList(v);
currentRefs.Append(propertyRefs);
}
#endregion
#region Visitor Helpers
///
/// Gets the list of "identity" properties for an entity. Gets the
/// "entitysetid" property in addition to the "key" properties
///
///
///
private static PropertyRefList GetIdentityProperties(md.EntityType type) {
PropertyRefList desiredProperties = GetKeyProperties(type);
desiredProperties.Add(EntitySetIdPropertyRef.Instance);
return desiredProperties;
}
///
/// Gets the list of key properties for an entity
///
///
///
private static PropertyRefList GetKeyProperties(md.EntityType entityType) {
PropertyRefList desiredProperties = new PropertyRefList();
foreach (md.EdmMember p in entityType.KeyMembers) {
md.EdmProperty edmP = p as md.EdmProperty;
PlanCompiler.Assert(edmP!=null, "EntityType had non-EdmProperty key member?");
SimplePropertyRef pRef = new SimplePropertyRef(edmP);
desiredProperties.Add(pRef);
}
return desiredProperties;
}
#endregion
///
/// Default visitor for an Op.
///
/// Simply walks through all children looking for Ops of structured
/// types, and asks for all their properties.
///
///
/// Several of the ScalarOps take the default handling, to simply ask
/// for all the children's properties:
///
/// AggegateOp
/// ArithmeticOp
/// CastOp
/// ConditionalOp
/// ConstantOp
/// ElementOp
/// ExistsOp
/// FunctionOp
/// GetRefKeyOp
/// LikeOp
/// NestAggregateOp
/// NewInstanceOp
/// NewMultisetOp
/// NewRecordOp
/// RefOp
///
/// They do not exist here to eliminate noise.
///
/// Note that the NewRecordOp and the NewInstanceOp could be optimized to only
/// push down the appropriate references, but it isn't clear to Murali that the
/// complexity is worth it.
///
///
protected override void VisitDefault(Node n) {
// for each child that is a complex type, simply ask for all properties
foreach (Node chi in n.Children) {
ScalarOp chiOp = chi.Op as ScalarOp;
if (chiOp != null && TypeUtils.IsStructuredType(chiOp.Type)) {
AddPropertyRefs(chi, PropertyRefList.All);
}
}
VisitChildren(n);
}
#region ScalarOps
///
/// SoftCastOp:
/// If the input is
/// Ref - ask for all properties
/// Entity, ComplexType - ask for the same properties I've been asked for
/// Record - ask for all properties (Note: This should be more optimized in the future
/// since we can actually "remap" the properties)
///
///
///
public override void Visit(SoftCastOp op, Node n) {
PropertyRefList childProps = null;
if (md.TypeSemantics.IsReferenceType(op.Type)) {
childProps = PropertyRefList.All;
}
else if (md.TypeSemantics.IsNominalType(op.Type)) {
PropertyRefList myProps = m_nodePropertyRefMap[n];
childProps = myProps.Clone();
}
else if (md.TypeSemantics.IsRowType(op.Type)) {
//
// Note: We should do a better job here (by translating
// our PropertyRefs to the equivalent property refs on the child
//
childProps = PropertyRefList.All;
}
if (childProps != null) {
AddPropertyRefs(n.Child0, childProps);
}
VisitChildren(n);
}
///
/// CaseOp handling
///
/// Pushes its desired properties to each of the WHEN/ELSE clauses
///
///
///
public override void Visit(CaseOp op, Node n) {
// First find the properties that my parent expects from me
PropertyRefList pdProps = GetPropertyRefList(n);
// push down the same properties to my then/else clauses.
// the "when" clauses are irrelevant
for (int i = 1; i < n.Children.Count - 1; i += 2) {
PropertyRefList cdProps = pdProps.Clone();
AddPropertyRefs(n.Children[i], cdProps);
}
AddPropertyRefs(n.Children[n.Children.Count - 1], pdProps.Clone());
// Now visit the children
VisitChildren(n);
}
///
/// CollectOp handling.
///
///
///
public override void Visit(CollectOp op, Node n) {
// Simply visit the children without pushing down any references to them.
VisitChildren(n);
}
///
/// ComparisonOp handling
///
///
///
public override void Visit(ComparisonOp op, Node n) {
// Check to see if the children are structured types. Furthermore,
// if the children are of entity types, then all we really need are
// the key properties (and the entityset property)
// For record and ref types, simply keep going
md.TypeUsage childOpType = (n.Child0.Op as ScalarOp).Type;
if (!TypeUtils.IsStructuredType(childOpType)) {
VisitChildren(n);
}
else if (md.TypeSemantics.IsRowType(childOpType) || md.TypeSemantics.IsReferenceType(childOpType))
VisitDefault(n);
else {
PlanCompiler.Assert(md.TypeSemantics.IsEntityType(childOpType), "unexpected childOpType?");
PropertyRefList desiredProperties = GetIdentityProperties(TypeHelpers.GetEdmType(childOpType));
// Now push these set of properties to each child
foreach (Node chi in n.Children)
AddPropertyRefs(chi, desiredProperties);
// Visit the children
VisitChildren(n);
}
}
///
/// ElementOp handling
///
///
///
public override void Visit(ElementOp op, Node n) {
// Cannot occur at this stage of processing
throw EntityUtil.NotSupported();
}
///
/// GetEntityRefOp handling
///
/// Ask for the "identity" properties from the input entity, and push that
/// down to my child
///
///
///
public override void Visit(GetEntityRefOp op, Node n) {
ScalarOp childOp = n.Child0.Op as ScalarOp;
PlanCompiler.Assert(childOp != null, "input to GetEntityRefOp is not a ScalarOp?");
// bug 428542 - the child is of the entity type; not this op
md.EntityType entityType = TypeHelpers.GetEdmType(childOp.Type);
PropertyRefList desiredProperties = GetIdentityProperties(entityType);
AddPropertyRefs(n.Child0, desiredProperties);
VisitNode(n.Child0);
}
///
/// IsOfOp handling
///
/// Simply requests the "typeid" property from
/// the input. No other property is required
///
/// IsOf op
/// Node to visit
public override void Visit(IsOfOp op, Node n) {
// The only property I need from my child is the typeid property;
PropertyRefList childProps = new PropertyRefList();
childProps.Add(TypeIdPropertyRef.Instance);
AddPropertyRefs(n.Child0, childProps);
VisitChildren(n);
}
///
/// Common handler for RelPropertyOp and PropertyOp.
/// Simply pushes down the desired set of properties to the child
///
/// the *propertyOp
/// node tree corresponding to the Op
/// the property reference
private void VisitPropertyOp(Op op, Node n, PropertyRef propertyRef) {
PropertyRefList cdProps = new PropertyRefList();
if (!TypeUtils.IsStructuredType(op.Type)) {
cdProps.Add(propertyRef);
}
else {
// Get the list of properties my parent expects from me.
PropertyRefList pdProps = GetPropertyRefList(n);
// Ask my child (which is really my container type) for each of these
// properties
// If I've been asked for all my properties, then get the
// corresponding flat list of properties from my children.
// For now, however, simply ask for all properties in this case
// What we really need to do is to get the "flattened" list of
// properties from the input, and prepend each of these with
// our property name. We don't have that info available, so
// I'm taking the easier route.
if (pdProps.AllProperties) {
cdProps = pdProps;
}
else {
foreach (PropertyRef p in pdProps.Properties) {
cdProps.Add(p.CreateNestedPropertyRef(propertyRef));
}
}
}
// push down my expectations
AddPropertyRefs(n.Child0, cdProps);
VisitChildren(n);
}
///
/// RelPropertyOp handling.
/// Delegates to VisitPropertyOp. Marks the rel-property as required from the
/// child
///
/// the RelPropertyOp
/// node tree corresponding to the op
public override void Visit(RelPropertyOp op, Node n) {
VisitPropertyOp(op, n, new RelPropertyRef(op.PropertyInfo));
}
///
/// PropertyOp handling
///
/// Pushes down the requested properties along with the current
/// property to the child
///
///
///
public override void Visit(PropertyOp op, Node n) {
VisitPropertyOp(op, n, new SimplePropertyRef(op.PropertyInfo));
}
///
/// TreatOp handling
///
/// Simply passes down "my" desired properties, and additionally
/// asks for the TypeID property
///
///
///
public override void Visit(TreatOp op, Node n) {
// First find the properties that my parent expects from me
PropertyRefList pdProps = GetPropertyRefList(n);
// Push down each of these, and in addition, push down the typeid property
// to my child
PropertyRefList childProps = pdProps.Clone();
childProps.Add(TypeIdPropertyRef.Instance);
AddPropertyRefs(n.Child0, childProps);
VisitChildren(n);
}
///
/// VarRefOp handling
///
/// Simply passes along the current "desired" properties
/// to the corresponding Var
///
///
///
public override void Visit(VarRefOp op, Node n) {
if (TypeUtils.IsStructuredType(op.Var.Type)) {
// Get the properties that my parent expects from me.
PropertyRefList myProps = GetPropertyRefList(n);
// Add this onto the list of properties expected from the var itself
AddPropertyRefs(op.Var, myProps);
}
}
#endregion
#region AncillaryOps
///
/// VarDefOp handling
///
/// Pushes the "desired" properties to the
/// defining expression
///
///
///
public override void Visit(VarDefOp op, Node n) {
if (TypeUtils.IsStructuredType(op.Var.Type)) {
PropertyRefList myProps = GetPropertyRefList(op.Var);
// Push this down to the expression defining the var
AddPropertyRefs(n.Child0, myProps);
}
VisitChildren(n);
}
///
/// VarDefListOp handling
///
///
///
public override void Visit(VarDefListOp op, Node n) {
// Simply visit the children without pushing down any references to them.
VisitChildren(n);
}
#endregion
#region RelOps
///
/// ApplyOp handling
/// CrossApplyOp handling
/// OuterApplyOp handling
///
/// Handling for all ApplyOps: Process the right child, and then
/// the left child - since the right child may have references to the
/// left
///
/// apply op
///
protected override void VisitApplyOp(ApplyBaseOp op, Node n) {
VisitNode(n.Child1); // the right input
VisitNode(n.Child0); // the left input
}
///
/// DistinctOp handling
///
/// Require all properties out of all structured vars
///
///
///
public override void Visit(DistinctOp op, Node n) {
foreach (Var v in op.Keys)
if (TypeUtils.IsStructuredType(v.Type)) {
AddPropertyRefs(v, PropertyRefList.All);
}
VisitChildren(n);
}
///
/// FilterOp handling
///
/// Process the predicate child, and then the input child - since the
/// predicate child will probably have references to the input.
///
///
///
public override void Visit(FilterOp op, Node n) {
VisitNode(n.Child1); // visit predicate first
VisitNode(n.Child0); // then visit the relop input
}
///
/// GroupByOp handling
///
///
///
public override void Visit(GroupByOp op, Node n) {
// First "request" all properties for every key (that is a structured type)
foreach (Var v in op.Keys) {
if (TypeUtils.IsStructuredType(v.Type)) {
AddPropertyRefs(v, PropertyRefList.All);
}
}
// Now visit the aggregate definitions, the key definitions, and
// the relop input in that order
VisitNode(n.Child2);
VisitNode(n.Child1);
VisitNode(n.Child0);
}
///
/// JoinOp handling
/// CrossJoinOp handling
/// InnerJoinOp handling
/// LeftOuterJoinOp handling
/// FullOuterJoinOp handling
///
/// Handler for all JoinOps. For all joins except cross joins, process
/// the predicate first, and then the inputs - the inputs can be processed
/// in any order.
///
/// For cross joins, simply process all the (relop) inputs
///
/// join op
///
protected override void VisitJoinOp(JoinBaseOp op, Node n) {
if (n.Op.OpType == OpType.CrossJoin)
VisitChildren(n);
else {
VisitNode(n.Child2); // the predicate first
VisitNode(n.Child0); // then, the left input
VisitNode(n.Child1); // the right input
}
}
///
/// ProjectOp handling
///
///
///
public override void Visit(ProjectOp op, Node n) {
VisitNode(n.Child1); // visit projections first
VisitNode(n.Child0); // then visit the relop input
}
///
/// ScanTableOp handler
///
///
///
public override void Visit(ScanTableOp op, Node n) {
PlanCompiler.Assert(!n.HasChild0, "scanTableOp with an input?");
}
///
/// ScanViewOp
///
/// ask for all properties from the view definition
/// that have currently been requested from the view itself
///
/// current ScanViewOp
/// current node
public override void Visit(ScanViewOp op, Node n) {
PlanCompiler.Assert(op.Table.Columns.Count == 1, "ScanViewOp with multiple columns?");
Var columnVar = op.Table.Columns[0];
PropertyRefList columnProps = GetPropertyRefList(columnVar);
Var inputVar = NominalTypeEliminator.GetSingletonVar(n.Child0);
PlanCompiler.Assert(inputVar != null, "cannot determine single Var from ScanViewOp's input");
AddPropertyRefs(inputVar, columnProps.Clone());
VisitChildren(n);
}
///
/// SetOp handling
/// UnionAllOp handling
/// IntersectOp handling
/// ExceptOp handling
///
/// Visitor for a SetOp. Pushes desired properties to the corresponding
/// Vars of the input
///
/// the setop
///
protected override void VisitSetOp(SetOp op, Node n) {
foreach (VarMap varMap in op.VarMap)
foreach (KeyValuePair kv in varMap) {
if (TypeUtils.IsStructuredType(kv.Key.Type)) {
// Get the set of expected properties for the unionVar, and
// push it down to the inputvars
// For Intersect and ExceptOps, we need all properties
// from the input
// We call GetPropertyRefList() always to initialize
// the map, even though we may not use it
//
PropertyRefList myProps = GetPropertyRefList(kv.Key);
if (op.OpType == OpType.Intersect || op.OpType == OpType.Except) {
myProps = PropertyRefList.All;
// We "want" all properties even on the output of the setop
AddPropertyRefs(kv.Key, myProps);
}
else {
myProps = myProps.Clone();
}
AddPropertyRefs(kv.Value, myProps);
}
}
VisitChildren(n);
}
///
/// SortOp handling
///
/// First, "request" that for any sort key that is a structured type, we
/// need all its properties. Then process any local definitions, and
/// finally the relop input
///
///
///
protected override void VisitSortOp(SortBaseOp op, Node n) {
// foreach sort key, every single bit of the Var is needed
foreach (InternalTrees.SortKey sk in op.Keys)
if (TypeUtils.IsStructuredType(sk.Var.Type))
AddPropertyRefs(sk.Var, PropertyRefList.All);
// if the sort has any local definitions, process those first
if (n.HasChild1)
VisitNode(n.Child1);
// then process the relop input
VisitNode(n.Child0);
}
///
/// UnnestOp handling
///
///
///
public override void Visit(UnnestOp op, Node n) {
VisitChildren(n);
}
#endregion
#region PhysicalOps
///
/// PhysicalProjectOp handling
///
///
///
public override void Visit(PhysicalProjectOp op, Node n) {
// Insist that we need all properties from all the outputs
foreach (Var v in op.Outputs) {
if (TypeUtils.IsStructuredType(v.Type)) {
AddPropertyRefs(v, PropertyRefList.All);
}
}
// simply visit the children
VisitChildren(n);
}
///
/// MultiStreamNestOp handling
///
///
///
public override void Visit(MultiStreamNestOp op, Node n) {
// Cannot occur at this stage of processing
throw EntityUtil.NotSupported();
}
///
/// SingleStreamNestOp handling
///
///
///
public override void Visit(SingleStreamNestOp op, Node n) {
// Cannot occur at this stage of processing
throw EntityUtil.NotSupported();
}
#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
- XmlSchemaAttribute.cs
- HttpHandlersSection.cs
- HMACSHA384.cs
- WindowsMenu.cs
- ContextMarshalException.cs
- XPathParser.cs
- EventListener.cs
- UrlParameterWriter.cs
- HashMembershipCondition.cs
- GPPOINT.cs
- DatagridviewDisplayedBandsData.cs
- ObsoleteAttribute.cs
- webproxy.cs
- arc.cs
- ListViewTableRow.cs
- BitmapDecoder.cs
- QuotedPrintableStream.cs
- WorkflowMarkupElementEventArgs.cs
- SafeSecurityHandles.cs
- Normalization.cs
- RequestBringIntoViewEventArgs.cs
- AssemblyName.cs
- BCryptHashAlgorithm.cs
- StateValidator.cs
- FormatterServices.cs
- SqlServer2KCompatibilityAnnotation.cs
- CompiledRegexRunner.cs
- DeclaredTypeElement.cs
- DataServiceRequestException.cs
- XmlSchemaResource.cs
- CellTreeNodeVisitors.cs
- DataView.cs
- ModelItemDictionary.cs
- EdmTypeAttribute.cs
- ActivatedMessageQueue.cs
- ToolboxComponentsCreatingEventArgs.cs
- PropertyInformationCollection.cs
- RuleSettings.cs
- XmlDocumentViewSchema.cs
- RegexNode.cs
- ToolStripRendererSwitcher.cs
- HandlerBase.cs
- AuthenticationException.cs
- SqlRetyper.cs
- FtpCachePolicyElement.cs
- StateManagedCollection.cs
- BamlWriter.cs
- TabControlToolboxItem.cs
- Compiler.cs
- DefaultParameterValueAttribute.cs
- UInt32Converter.cs
- TextReader.cs
- HtmlToClrEventProxy.cs
- ZipIOLocalFileBlock.cs
- PostBackOptions.cs
- CompiledRegexRunner.cs
- StubHelpers.cs
- DataListItemCollection.cs
- OleDbRowUpdatedEvent.cs
- FillBehavior.cs
- HttpCapabilitiesSectionHandler.cs
- EntityDataSourceChangedEventArgs.cs
- ImageMapEventArgs.cs
- formatter.cs
- XmlCDATASection.cs
- DataGridViewHitTestInfo.cs
- DocumentPageHost.cs
- AlignmentXValidation.cs
- DataGridViewCellCollection.cs
- BrowserInteropHelper.cs
- DbConnectionInternal.cs
- DbInsertCommandTree.cs
- SimpleApplicationHost.cs
- StyleCollection.cs
- StateMachineHelpers.cs
- RelatedPropertyManager.cs
- EntityClassGenerator.cs
- XmlSerializerNamespaces.cs
- RbTree.cs
- EntityDataSourceWrapperCollection.cs
- SmtpNtlmAuthenticationModule.cs
- DataRecordInfo.cs
- TypeDependencyAttribute.cs
- DocumentOrderQuery.cs
- CodePageEncoding.cs
- AsyncOperationManager.cs
- Component.cs
- VoiceInfo.cs
- Schedule.cs
- CultureData.cs
- AutoGeneratedField.cs
- WebPartMenu.cs
- XmlQueryType.cs
- HttpWriter.cs
- COM2ColorConverter.cs
- FileReader.cs
- FixedPage.cs
- listitem.cs
- WebConfigurationFileMap.cs
- PenCursorManager.cs