/// <summary> /// If some node has no dependency, we will take it into consideration /// </summary> /// <param name="aggregationBlock"></param> /// <param name="predicateLinksAccessedTableAliases"></param> /// <returns></returns> public List <ExecutionOrder> GenerateNextOrders( AggregationBlock aggregationBlock, List <Tuple <PredicateLink, HashSet <string> > > predicateLinksAccessedTableAliases) { // Find all possible next tuples List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > > nextTuples = new List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > >(); foreach (KeyValuePair <string, HashSet <string> > pair in aggregationBlock.TableInputDependency) { if (!this.ExistingNodesAndEdges.Contains(pair.Key) && this.ExistingNodesAndEdges.IsSupersetOf(pair.Value)) { CompileNode node; aggregationBlock.TryGetNode(pair.Key, out node); nextTuples.AddRange(this.GenerateTuples(predicateLinksAccessedTableAliases, node)); } } // Generate all possible next orders List <ExecutionOrder> nextOrders = new List <ExecutionOrder>(); foreach (Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > tuple in nextTuples) { ExecutionOrder nextOrder = this.Duplicate(); nextOrder.AddTuple(tuple); nextOrders.Add(nextOrder); } return(nextOrders); }
public virtual ExecutionOrder GetLocalExecutionOrder(ExecutionOrder parentExecutionOrder) { ExecutionOrder executionOrder = new ExecutionOrder(); executionOrder.Order.Add(new Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> >( null, null, null, null, new List <ExecutionOrder>())); return(executionOrder); }
/// <summary> /// This constructor is used to transfer information to subquery /// </summary> /// <param name="executionOrder"></param> public ExecutionOrder(ExecutionOrder executionOrder) { this.Order = new List <Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> > >(); this.ExistingNodesAndEdges = new HashSet <string>(executionOrder.ExistingNodesAndEdges); this.ExistingPredicateLinks = new HashSet <string>(executionOrder.ExistingPredicateLinks); // It is important that the readyEdges should be empty. // If the parentOrder has some readyEdges and this order records, the subquery cannot remove edges from readyEdges // because it could see the information from parent's aggregationBlock this.ReadyEdges = new HashSet <string>(); this.Cost = 0.0; }
public QueryCompilationContext() { TemporaryTableCollection = new Dictionary <string, Tuple <TemporaryTableHeader, GraphViewExecutionOperator> >(); RawRecordLayout = new Dictionary <WColumnReferenceExpression, int>(new WColumnReferenceExpressionComparer()); TableReferences = new HashSet <string>(); SideEffectStates = new Dictionary <string, AggregateState>(); SideEffectFunctions = new Dictionary <string, IAggregateFunction>(); CarryOn = false; Containers = new List <Container>(); CurrentExecutionOrder = new ExecutionOrder(); LocalExecutionOrders = new List <ExecutionOrder>(); }
public override ExecutionOrder GetLocalExecutionOrder(ExecutionOrder parentExecutionOrder) { if (this.TableReference != null) { return(this.TableReference.GetLocalExecutionOrder(parentExecutionOrder)); } else { ExecutionOrder executionOrder = new ExecutionOrder(); executionOrder.Order.Add(new Tuple <CompileNode, CompileLink, List <Tuple <PredicateLink, int> >, List <Tuple <MatchEdge, int> >, List <ExecutionOrder> >( null, null, null, null, new List <ExecutionOrder>())); return(executionOrder); } }
public QueryCompilationContext(QueryCompilationContext parentContext) { CurrentExecutionOperator = parentContext.CurrentExecutionOperator; TemporaryTableCollection = parentContext.TemporaryTableCollection; RawRecordLayout = new Dictionary <WColumnReferenceExpression, int>(parentContext.RawRecordLayout, new WColumnReferenceExpressionComparer()); TableReferences = new HashSet <string>(parentContext.TableReferences); OuterContextOp = new EnumeratorOperator(); CarryOn = false; ParentContextRawRecordLayout = new Dictionary <WColumnReferenceExpression, int>( parentContext.RawRecordLayout, new WColumnReferenceExpressionComparer()); SideEffectStates = parentContext.SideEffectStates; SideEffectFunctions = parentContext.SideEffectFunctions; Containers = parentContext.Containers; CurrentExecutionOrder = new ExecutionOrder(parentContext.CurrentExecutionOrder); LocalExecutionOrders = new List <ExecutionOrder>(); }
/// <summary> /// Every time, we will generate multiple next orders from queue[index]. If some of them are finished, we put these into queue[1 - index]. /// If the size of candidate orders equals or exceeds the upper bound, we will leave a predetermined number of best partial solutions. /// </summary> /// <param name="tableReferences"></param> /// <returns></returns> internal ExecutionOrder GenerateOptimalExecutionOrder(ExecutionOrder parentExecutionOrder) { // Two queues, queue[index] keeps forthcoming orders and queue[1 - index] keeps results from queue[index] int queueIndex = 0, blockIndex = 0; int blocksCount = this.blocks.Count; List <List <ExecutionOrder> > queue = new List <List <ExecutionOrder> > { new List <ExecutionOrder>(), new List <ExecutionOrder>() }; queue[queueIndex].Add(new ExecutionOrder(parentExecutionOrder)); while (blockIndex < blocksCount) { // Firstly, we need to add the root table foreach (ExecutionOrder currentOrder in queue[queueIndex]) { currentOrder.AddRootTable(this.blocks[blockIndex], this.predicateLinksAccessedTableAliases); } int numberOfIterations = this.blocks[blockIndex].TableInputDependency.Count - 1; while (numberOfIterations-- > 0) { foreach (ExecutionOrder currentOrder in queue[queueIndex]) { List <ExecutionOrder> nextOrders = currentOrder.GenerateNextOrders(this.blocks[blockIndex], this.predicateLinksAccessedTableAliases); if (nextOrders.Count > MaxNumberOfOrders) { nextOrders.Sort(new ExecutionOrderComparer()); queue[1 - queueIndex].AddRange(nextOrders.GetRange(0, MaxNumberOfOrders)); } else { queue[1 - queueIndex].AddRange(nextOrders); } } queue[queueIndex].Clear(); if (queue[1 - queueIndex].Count > MaxNumberOfOrders) { queue[1 - queueIndex].Sort(new ExecutionOrderComparer()); queue[1 - queueIndex] = queue[1 - queueIndex].GetRange(0, MaxNumberOfOrders); } queueIndex = 1 - queueIndex; } // Finally, check whether there is any ready edge. If there is, we discard this order for (int index = queue[queueIndex].Count - 1; index >= 0; --index) { if (queue[queueIndex][index].ReadyEdges.Any()) { queue[queueIndex].RemoveAt(index); } } ++blockIndex; } queue[queueIndex].Sort(new ExecutionOrderComparer()); return(queue[queueIndex].First()); }
public ParentLink(ExecutionOrder parentExecutionOrder) { this.LinkAlias = parentExecutionOrder.Order.Last().Item1.NodeAlias + "->"; this.ParentExecutionOrder = parentExecutionOrder.Duplicate(); }