C# Class System.Data.Entity.Core.Query.PlanCompiler.ProjectionPruner

The ProjectionPruner module is responsible for eliminating unnecessary column references (and other expressions) from the query. Projection pruning logically operates in two passes - the first pass is a top-down pass where information about all referenced columns and expressions is collected (pushed down from a node to its children). The second phase is a bottom-up phase, where each node (in response to the information collected above) attempts to rid itself of unwanted columns and expressions. The two phases can be combined into a single tree walk, where for each node, the processing is on the lines of: - compute and push information to children (top-down) - process children - eliminate unnecessary references from myself (bottom-up)
Inheritance: BasicOpVisitorOfNode
Mostrar archivo Open project: dotnet/ef6tools Class Usage Examples

Private Properties

Property Type Description
AddReference void
AddReference void
IsReferenced bool
IsUnreferenced bool
Process Node
Process Node
Process void
ProjectionPruner System.Collections.Generic
PruneVarMap void
PruneVarSet void
RemoveRedundantConstantKeys void
Visit Node

Public Methods

Method Description
Visit ( DistinctOp op, Node n ) : Node

DistinctOp We remove all null and constant keys that are not referenced as long as there is one key left. We add all remaining keys to the referenced list and proceed to the inputs

Visit ( ElementOp op, Node n ) : Node

ElementOp An ElementOp that is still present when Projection Prunning is invoked can only get introduced in the TransformationRules phase by transforming an apply operation into a scalar subquery. Such ElementOp serves as root of a defining expression of a VarDefinitionOp node and thus what it produces is useful.

Visit ( ExistsOp op, Node n ) : Node

ExistsOp The child must be a ProjectOp - with exactly 1 var. Mark it as referenced

Visit ( FilterOp op, Node n ) : Node

FilterOp First visit the predicate (because that may contain references to the relop input), and then visit the relop input. No additional processing is required

Visit ( GroupByIntoOp op, Node n ) : Node

First defer to default handling for groupby nodes If all group aggregate vars are prunned out turn it into a GroupBy.

Visit ( MultiStreamNestOp op, Node n ) : Node

MultiStreamNestOp Insist (for now) that all Vars are required

Visit ( PhysicalProjectOp op, Node n ) : Node

PhysicalProjectOp Insist that all Vars in this are required

Visit ( ProjectOp op, Node n ) : Node

ProjectOp We visit the projections first (the VarDefListOp child), and then the input (the RelOp child) - this reverse order is necessary, since the projections need to be visited to determine if anything from the input is really needed. The VarDefListOp child will handle the removal of unnecessary VarDefOps. On the way out, we then update our "Vars" property to reflect the Vars that have been eliminated

Visit ( SingleStreamNestOp op, Node n ) : Node

SingleStreamNestOp Insist (for now) that all Vars are required

Visit ( UnnestOp op, Node n ) : Node

UnnestOp Marks the unnestVar as referenced, and if there is a child, visits the child.

Visit ( VarDefListOp op, Node n ) : Node

VarDefListOp Walks the children (VarDefOp), and looks for those whose Vars have been referenced. Only those VarDefOps are visited - the others are ignored. At the end, a new list of children is created - with only those VarDefOps that have been referenced

Visit ( VarRefOp op, Node n ) : Node

VarRefOp Mark the corresponding Var as "referenced"

Protected Methods

Method Description
VisitApplyOp ( ApplyBaseOp op, Node n ) : Node

ApplyOps Common handling for all ApplyOps. Visit the right child first to capture any references to the left, and then visit the left child.

VisitChildren ( Node n ) : void

Visits the children and recomputes the node info

VisitChildrenReverse ( Node n ) : void

Visits the children in reverse order and recomputes the node info

VisitGroupByOp ( GroupByBaseOp op, Node n ) : Node

GroupByBase First, we visit the vardeflist for aggregates and potentially group aggregates as they may reference keys (including constant keys). Then we remove all null and constant keys that are not referenced as long as there is one key left. We add all remaining key columns to the referenced list. Then we walk through the vardeflist for the keys; and finally process the relop input Once we're done, we update the "Outputs" varset - to account for any pruned vars. The "Keys" varset will not change

VisitJoinOp ( JoinBaseOp op, Node n ) : Node

JoinOps Common handling for all join ops. For all joins (other than crossjoin), we must first visit the predicate (to capture any references from it), and then visit the relop inputs. The relop inputs can be visited in any order because there can be no correlations between them For crossjoins, we simply use the default processing - visit all children ; there can be no correlations between the nodes anyway

VisitNestOp ( NestBaseOp op, Node n ) : Node

NestOps Common handling for all NestOps.

VisitSetOp ( SetOp op, Node n ) : Node

SetOps Common handling for all SetOps. We first identify the "output" vars that are referenced, and mark the corresponding "input" vars as referenced We then remove all unreferenced output Vars from the "Outputs" varset as well as from the Varmaps. Finally, we visit the children

VisitSortOp ( SortBaseOp op, Node n ) : Node

SortOp First visit the sort keys - no sort key can be eliminated. Then process the vardeflist child (if there is one) that contains computed vars, and finally process the relop input. As before, the computedvars and sortkeys need to be processed before the relop input

Private Methods

Method Description
AddReference ( IEnumerable varSet ) : void

Adds a reference to each var in a set of Vars

AddReference ( Var v ) : void

Adds a reference to this Var

IsReferenced ( Var v ) : bool

Is this Var referenced?

IsUnreferenced ( Var v ) : bool

Is this var unreferenced?

Process ( Node node ) : Node

The real driver of the pruning process. Simply invokes the visitor over the input node

Process ( PlanCompiler compilerState, Node node ) : Node

Runs through the given subtree, and eliminates all unreferenced expressions

Process ( PlanCompiler compilerState ) : void

Runs through the root node of the tree, and eliminates all unreferenced expressions

ProjectionPruner ( PlanCompiler compilerState ) : System.Collections.Generic

Trivial private constructor

PruneVarMap ( VarMap varMap ) : void

Prunes a VarMap - gets rid of unreferenced vars from the VarMap inplace Additionally, propagates var references to the inner vars

PruneVarSet ( VarVec varSet ) : void

Prunes a varset - gets rid of unreferenced vars from the Varset in place

RemoveRedundantConstantKeys ( VarVec keyVec, VarVec outputVec, Node varDefListNode ) : void

Helper method for removing redundant constant keys from GroupByOp and DistictOp. It only examines the keys defined in the given varDefListNode. It removes all constant and null keys that are not referenced elsewhere, but ensuring that at least one key is left. It should not be called with empty keyVec.

Visit ( ScanTableOp op, Node n ) : Node

Method Details

Visit() public method

DistinctOp We remove all null and constant keys that are not referenced as long as there is one key left. We add all remaining keys to the referenced list and proceed to the inputs
public Visit ( DistinctOp op, Node n ) : Node
op DistinctOp the DistinctOp
n Node Current subtree
return Node

Visit() public method

ElementOp An ElementOp that is still present when Projection Prunning is invoked can only get introduced in the TransformationRules phase by transforming an apply operation into a scalar subquery. Such ElementOp serves as root of a defining expression of a VarDefinitionOp node and thus what it produces is useful.
public Visit ( ElementOp op, Node n ) : Node
op ElementOp the ElementOp
n Node Current subtree
return Node

Visit() public method

ExistsOp The child must be a ProjectOp - with exactly 1 var. Mark it as referenced
public Visit ( ExistsOp op, Node n ) : Node
op ExistsOp the ExistsOp
n Node the input node
return Node

Visit() public method

FilterOp First visit the predicate (because that may contain references to the relop input), and then visit the relop input. No additional processing is required
public Visit ( FilterOp op, Node n ) : Node
op FilterOp the filterOp
n Node current node
return Node

Visit() public method

First defer to default handling for groupby nodes If all group aggregate vars are prunned out turn it into a GroupBy.
public Visit ( GroupByIntoOp op, Node n ) : Node
op GroupByIntoOp
n Node
return Node

Visit() public method

MultiStreamNestOp Insist (for now) that all Vars are required
public Visit ( MultiStreamNestOp op, Node n ) : Node
op MultiStreamNestOp
n Node
return Node

Visit() public method

PhysicalProjectOp Insist that all Vars in this are required
public Visit ( PhysicalProjectOp op, Node n ) : Node
op PhysicalProjectOp
n Node
return Node

Visit() public method

ProjectOp We visit the projections first (the VarDefListOp child), and then the input (the RelOp child) - this reverse order is necessary, since the projections need to be visited to determine if anything from the input is really needed. The VarDefListOp child will handle the removal of unnecessary VarDefOps. On the way out, we then update our "Vars" property to reflect the Vars that have been eliminated
public Visit ( ProjectOp op, Node n ) : Node
op ProjectOp the ProjectOp
n Node the current node
return Node

Visit() public method

SingleStreamNestOp Insist (for now) that all Vars are required
public Visit ( SingleStreamNestOp op, Node n ) : Node
op SingleStreamNestOp
n Node
return Node

Visit() public method

UnnestOp Marks the unnestVar as referenced, and if there is a child, visits the child.
public Visit ( UnnestOp op, Node n ) : Node
op UnnestOp the unnestOp
n Node current subtree
return Node

Visit() public method

VarDefListOp Walks the children (VarDefOp), and looks for those whose Vars have been referenced. Only those VarDefOps are visited - the others are ignored. At the end, a new list of children is created - with only those VarDefOps that have been referenced
public Visit ( VarDefListOp op, Node n ) : Node
op VarDefListOp the varDefListOp
n Node corresponding node
return Node

Visit() public method

VarRefOp Mark the corresponding Var as "referenced"
public Visit ( VarRefOp op, Node n ) : Node
op VarRefOp the VarRefOp
n Node current node
return Node

VisitApplyOp() protected method

ApplyOps Common handling for all ApplyOps. Visit the right child first to capture any references to the left, and then visit the left child.
protected VisitApplyOp ( ApplyBaseOp op, Node n ) : Node
op ApplyBaseOp
n Node the apply op
return Node

VisitChildren() protected method

Visits the children and recomputes the node info
protected VisitChildren ( Node n ) : void
n Node The current node
return void

VisitChildrenReverse() protected method

Visits the children in reverse order and recomputes the node info
protected VisitChildrenReverse ( Node n ) : void
n Node The current node
return void

VisitGroupByOp() protected method

GroupByBase First, we visit the vardeflist for aggregates and potentially group aggregates as they may reference keys (including constant keys). Then we remove all null and constant keys that are not referenced as long as there is one key left. We add all remaining key columns to the referenced list. Then we walk through the vardeflist for the keys; and finally process the relop input Once we're done, we update the "Outputs" varset - to account for any pruned vars. The "Keys" varset will not change
protected VisitGroupByOp ( GroupByBaseOp op, Node n ) : Node
op GroupByBaseOp the groupbyOp
n Node current subtree
return Node

VisitJoinOp() protected method

JoinOps Common handling for all join ops. For all joins (other than crossjoin), we must first visit the predicate (to capture any references from it), and then visit the relop inputs. The relop inputs can be visited in any order because there can be no correlations between them For crossjoins, we simply use the default processing - visit all children ; there can be no correlations between the nodes anyway
protected VisitJoinOp ( JoinBaseOp op, Node n ) : Node
op JoinBaseOp
n Node Node for the join subtree
return Node

VisitNestOp() protected method

NestOps Common handling for all NestOps.
protected VisitNestOp ( NestBaseOp op, Node n ) : Node
op NestBaseOp
n Node
return Node

VisitSetOp() protected method

SetOps Common handling for all SetOps. We first identify the "output" vars that are referenced, and mark the corresponding "input" vars as referenced We then remove all unreferenced output Vars from the "Outputs" varset as well as from the Varmaps. Finally, we visit the children
protected VisitSetOp ( SetOp op, Node n ) : Node
op SetOp
n Node current node
return Node

VisitSortOp() protected method

SortOp First visit the sort keys - no sort key can be eliminated. Then process the vardeflist child (if there is one) that contains computed vars, and finally process the relop input. As before, the computedvars and sortkeys need to be processed before the relop input
protected VisitSortOp ( SortBaseOp op, Node n ) : Node
op SortBaseOp the sortop
n Node the current subtree
return Node