public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { Visit(node.Input); AddDefinedValues(node.DefinedValues); return(node); }
private AlgebraNode PushOverJoin(ComputeScalarAlgebraNode node) { JoinAlgebraNode joinAlgebraNode = (JoinAlgebraNode)node.Input; RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Right); List <ComputedValueDefinition> remainingValueDefinitions = new List <ComputedValueDefinition>(); List <ComputedValueDefinition> leftPushedValueDefinitions = new List <ComputedValueDefinition>(); List <ComputedValueDefinition> rightPushedValueDefinitions = new List <ComputedValueDefinition>(); bool canPushToLeftSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; bool canPushToRightSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; foreach (ComputedValueDefinition valueDefinition in node.DefinedValues) { RowBufferEntry[] referencedValues = AstUtil.GetRowBufferEntryReferences(valueDefinition.Expression); bool referencesProbeColumn = ArrayHelpers.Contains(referencedValues, joinAlgebraNode.ProbeBufferEntry); if (!referencesProbeColumn && canPushToLeftSide && AstUtil.DoesNotReference(referencedValues, rightDefinedValues)) { leftPushedValueDefinitions.Add(valueDefinition); } else if (!referencesProbeColumn && canPushToRightSide && AstUtil.DoesNotReference(referencedValues, leftDefinedValues)) { rightPushedValueDefinitions.Add(valueDefinition); } else { remainingValueDefinitions.Add(valueDefinition); } } if (leftPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = leftPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Left; joinAlgebraNode.Left = VisitAlgebraNode(computeScalarAlgebraNode); } if (rightPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = rightPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Right; joinAlgebraNode.Right = VisitAlgebraNode(computeScalarAlgebraNode); } if (remainingValueDefinitions.Count == 0) { return(joinAlgebraNode); } node.DefinedValues = remainingValueDefinitions.ToArray(); return(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { base.VisitComputeScalarAlgebraNode(node); List <ComputedValueDefinition> remainingDefinedValues = new List <ComputedValueDefinition>(); foreach (ComputedValueDefinition definedValue in node.DefinedValues) { RowBufferEntryExpression rowBufferEntryExpression = definedValue.Expression as RowBufferEntryExpression; if (rowBufferEntryExpression != null) { _inliningDictionary[definedValue.Target] = rowBufferEntryExpression.RowBufferEntry; } else { remainingDefinedValues.Add(definedValue); } } if (remainingDefinedValues.Count == 0) { return(node.Input); } node.DefinedValues = remainingDefinedValues.ToArray(); return(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { Visit(node.Input); AddDefinedValues(node.DefinedValues); return node; }
private AlgebraNode MegeWithConstantScan(ComputeScalarAlgebraNode node) { ConstantScanAlgebraNode constantScanAlgebraNode = (ConstantScanAlgebraNode)node.Input; constantScanAlgebraNode.DefinedValues = ArrayHelpers.JoinArrays(constantScanAlgebraNode.DefinedValues, node.DefinedValues); return(VisitAlgebraNode(constantScanAlgebraNode)); }
public override TableReference VisitDerivedTableReference(DerivedTableReference node) { AlgebraNode algebrizedQuery = Convert(node.Query); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); for (int i = 0; i < node.DerivedTableBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = node.DerivedTableBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = algebrizedQuery.OutputList[i]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedQuery; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); SetLastAlgebraNode(computeScalarAlgebraNode); return(node); }
private static AlgebraNode PadLeftWithNullsOnRightSide(JoinAlgebraNode node, RowBufferCreationMode rowBufferCreationMode) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = node.Left; List <RowBufferEntry> outputList = new List <RowBufferEntry>(); outputList.AddRange(node.Left.OutputList); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Right.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); if (rowBufferCreationMode == RowBufferCreationMode.KeepExisting) { definedValue.Target = rowBufferEntry; } else { definedValue.Target = new RowBufferEntry(rowBufferEntry.DataType); } definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); definedValues.Add(definedValue); outputList.Add(definedValue.Target); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = outputList.ToArray(); return(computeScalarAlgebraNode); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { base.VisitJoinAlgebraNode(node); if (node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { // TODO: Check if we could represent this join condition by an hash match operator JoinAlgebraNode leftOuterJoinNode = new JoinAlgebraNode(); leftOuterJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; leftOuterJoinNode.Predicate = (ExpressionNode)node.Predicate.Clone(); leftOuterJoinNode.Left = (AlgebraNode) node.Left.Clone(); leftOuterJoinNode.Right = (AlgebraNode) node.Right.Clone(); leftOuterJoinNode.OutputList = ArrayHelpers.Clone(node.OutputList); List<RowBufferEntry> swappedOutputList = new List<RowBufferEntry>(); swappedOutputList.AddRange(node.Right.OutputList); swappedOutputList.AddRange(node.Left.OutputList); JoinAlgebraNode leftAntiSemiJoinNode = new JoinAlgebraNode(); leftAntiSemiJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin; leftAntiSemiJoinNode.Predicate = (ExpressionNode) node.Predicate.Clone(); leftAntiSemiJoinNode.Left = (AlgebraNode) node.Right.Clone(); leftAntiSemiJoinNode.Right = (AlgebraNode) node.Left.Clone(); leftAntiSemiJoinNode.OutputList = swappedOutputList.ToArray(); List<ComputedValueDefinition> computeScalareDefinedValues = new List<ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Left.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rowBufferEntry; definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); computeScalareDefinedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarNode = new ComputeScalarAlgebraNode(); computeScalarNode.Input = leftAntiSemiJoinNode; computeScalarNode.DefinedValues = computeScalareDefinedValues.ToArray(); computeScalarNode.OutputList = swappedOutputList.ToArray(); List<UnitedValueDefinition> concatDefinedValues = new List<UnitedValueDefinition>(); for (int i = 0; i < node.OutputList.Length; i++) { RowBufferEntry rowBufferEntry = node.OutputList[i]; UnitedValueDefinition concatDefinedValue = new UnitedValueDefinition(); concatDefinedValue.Target = rowBufferEntry; concatDefinedValue.DependendEntries = new RowBufferEntry[] { node.OutputList[i], node.OutputList[i] }; concatDefinedValues.Add(concatDefinedValue); } ConcatAlgebraNode concatenationNode = new ConcatAlgebraNode(); concatenationNode.Inputs = new AlgebraNode[] {leftOuterJoinNode, computeScalarNode}; concatenationNode.DefinedValues = concatDefinedValues.ToArray(); concatenationNode.OutputList = swappedOutputList.ToArray(); return concatenationNode; } return node; }
private AlgebraNode PushOverUnary(ComputeScalarAlgebraNode node) { UnaryAlgebraNode inputNode = (UnaryAlgebraNode) node.Input; node.Input = inputNode.Input; inputNode.Input = VisitAlgebraNode(node); return inputNode; }
private static AlgebraNode PadLeftWithNullsOnRightSide(JoinAlgebraNode node, RowBufferCreationMode rowBufferCreationMode) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = node.Left; List<RowBufferEntry> outputList = new List<RowBufferEntry>(); outputList.AddRange(node.Left.OutputList); List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Right.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); if (rowBufferCreationMode == RowBufferCreationMode.KeepExisting) { definedValue.Target = rowBufferEntry; } else { definedValue.Target = new RowBufferEntry(rowBufferEntry.DataType); } definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); definedValues.Add(definedValue); outputList.Add(definedValue.Target); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = outputList.ToArray(); return computeScalarAlgebraNode; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { base.VisitJoinAlgebraNode(node); if (node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { // TODO: Check if we could represent this join condition by an hash match operator JoinAlgebraNode leftOuterJoinNode = new JoinAlgebraNode(); leftOuterJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; leftOuterJoinNode.Predicate = (ExpressionNode)node.Predicate.Clone(); leftOuterJoinNode.Left = (AlgebraNode)node.Left.Clone(); leftOuterJoinNode.Right = (AlgebraNode)node.Right.Clone(); leftOuterJoinNode.OutputList = ArrayHelpers.Clone(node.OutputList); List <RowBufferEntry> swappedOutputList = new List <RowBufferEntry>(); swappedOutputList.AddRange(node.Right.OutputList); swappedOutputList.AddRange(node.Left.OutputList); JoinAlgebraNode leftAntiSemiJoinNode = new JoinAlgebraNode(); leftAntiSemiJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin; leftAntiSemiJoinNode.Predicate = (ExpressionNode)node.Predicate.Clone(); leftAntiSemiJoinNode.Left = (AlgebraNode)node.Right.Clone(); leftAntiSemiJoinNode.Right = (AlgebraNode)node.Left.Clone(); leftAntiSemiJoinNode.OutputList = swappedOutputList.ToArray(); List <ComputedValueDefinition> computeScalareDefinedValues = new List <ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Left.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rowBufferEntry; definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); computeScalareDefinedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarNode = new ComputeScalarAlgebraNode(); computeScalarNode.Input = leftAntiSemiJoinNode; computeScalarNode.DefinedValues = computeScalareDefinedValues.ToArray(); computeScalarNode.OutputList = swappedOutputList.ToArray(); List <UnitedValueDefinition> concatDefinedValues = new List <UnitedValueDefinition>(); for (int i = 0; i < node.OutputList.Length; i++) { RowBufferEntry rowBufferEntry = node.OutputList[i]; UnitedValueDefinition concatDefinedValue = new UnitedValueDefinition(); concatDefinedValue.Target = rowBufferEntry; concatDefinedValue.DependendEntries = new RowBufferEntry[] { node.OutputList[i], node.OutputList[i] }; concatDefinedValues.Add(concatDefinedValue); } ConcatAlgebraNode concatenationNode = new ConcatAlgebraNode(); concatenationNode.Inputs = new AlgebraNode[] { leftOuterJoinNode, computeScalarNode }; concatenationNode.DefinedValues = concatDefinedValues.ToArray(); concatenationNode.OutputList = swappedOutputList.ToArray(); return(concatenationNode); } return(node); }
public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); ExpressionNode originalPredicate = (ExpressionNode) node.Predicate.Clone(); SpoolExpressionExtractor spoolExpressionExtractor = new SpoolExpressionExtractor(_outerReferences); // HACK: This hack ensures that TRUE literals introduced by SpoolExpressionExtractor are removed. node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, spoolExpressionExtractor.VisitExpression(node.Predicate)); SpoolExpression[] spoolExpressions = spoolExpressionExtractor.GetSpoolExpressions(); // Now we must check that the remaining filter incl. input to the filter don't reference any other // outer reference. bool remainingFilterHasDependenciesToOuterReferences = CheckIfNodeHasDependenciesToOuterReferences(node); if (remainingFilterHasDependenciesToOuterReferences) { // OK; we cannot insert a spool operation here. Undo the expression replacement. node.Predicate = originalPredicate; } else if (spoolExpressions.Length > 0) { SpoolExpression spoolExpression = spoolExpressions[0]; AlgebraNode currentInput; if (node.Predicate is ConstantExpression) currentInput = node.Input; else currentInput = node; RowBufferEntry indexEntry; RowBufferEntryExpression indexExpressionAsRowBufferEntryExpression = spoolExpression.IndexExpression as RowBufferEntryExpression; if (indexExpressionAsRowBufferEntryExpression != null) { indexEntry = indexExpressionAsRowBufferEntryExpression.RowBufferEntry; } else { indexEntry = new RowBufferEntry(spoolExpression.IndexExpression.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = indexEntry; definedValue.Expression = spoolExpression.IndexExpression; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = currentInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue }; currentInput = computeScalarAlgebraNode; } IndexSpoolAlgebraNode indexSpoolAlgebraNode = new IndexSpoolAlgebraNode(); indexSpoolAlgebraNode.Input = currentInput; indexSpoolAlgebraNode.IndexEntry = indexEntry; indexSpoolAlgebraNode.ProbeExpression = spoolExpression.ProbeExpression; return indexSpoolAlgebraNode; } return node; }
private AlgebraNode PushOverUnary(ComputeScalarAlgebraNode node) { UnaryAlgebraNode inputNode = (UnaryAlgebraNode)node.Input; node.Input = inputNode.Input; inputNode.Input = VisitAlgebraNode(node); return(inputNode); }
private AlgebraNode PushOverJoin(ComputeScalarAlgebraNode node) { JoinAlgebraNode joinAlgebraNode = (JoinAlgebraNode) node.Input; RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Right); List<ComputedValueDefinition> remainingValueDefinitions = new List<ComputedValueDefinition>(); List<ComputedValueDefinition> leftPushedValueDefinitions = new List<ComputedValueDefinition>(); List<ComputedValueDefinition> rightPushedValueDefinitions = new List<ComputedValueDefinition>(); bool canPushToLeftSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; bool canPushToRightSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; foreach (ComputedValueDefinition valueDefinition in node.DefinedValues) { RowBufferEntry[] referencedValues = AstUtil.GetRowBufferEntryReferences(valueDefinition.Expression); bool referencesProbeColumn = ArrayHelpers.Contains(referencedValues, joinAlgebraNode.ProbeBufferEntry); if (!referencesProbeColumn && canPushToLeftSide && AstUtil.DoesNotReference(referencedValues, rightDefinedValues)) { leftPushedValueDefinitions.Add(valueDefinition); } else if (!referencesProbeColumn && canPushToRightSide && AstUtil.DoesNotReference(referencedValues, leftDefinedValues)) { rightPushedValueDefinitions.Add(valueDefinition); } else { remainingValueDefinitions.Add(valueDefinition); } } if (leftPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = leftPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Left; joinAlgebraNode.Left = VisitAlgebraNode(computeScalarAlgebraNode); } if (rightPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = rightPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Right; joinAlgebraNode.Right = VisitAlgebraNode(computeScalarAlgebraNode); } if (remainingValueDefinitions.Count == 0) return joinAlgebraNode; node.DefinedValues = remainingValueDefinitions.ToArray(); return node; }
public override AstElement Clone(Dictionary<AstElement, AstElement> alreadyClonedElements) { ComputeScalarAlgebraNode result = new ComputeScalarAlgebraNode(); result.StatisticsIterator = StatisticsIterator; result.OutputList = ArrayHelpers.Clone(OutputList); result.Input = (AlgebraNode)Input.Clone(alreadyClonedElements); result.DefinedValues = ArrayHelpers.CreateDeepCopyOfAstElementArray(_definedValues, alreadyClonedElements); return result; }
private AlgebraNode PushOverComputeScalar(FilterAlgebraNode node) { // Predicates can be pushed over a compute scalar if it does not contain any row buffer entries // that are defined by the compute scalar node. ComputeScalarAlgebraNode inputNode = (ComputeScalarAlgebraNode)node.Input; return(PushOverValueDefininingUnary(inputNode.DefinedValues, node)); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { base.VisitComputeScalarAlgebraNode(node); foreach (ComputedValueDefinition definedValue in node.DefinedValues) NameEntry(definedValue.Target, EXPRESSION_NAME_FMT_STR); return node; }
public override AstElement Clone(Dictionary <AstElement, AstElement> alreadyClonedElements) { ComputeScalarAlgebraNode result = new ComputeScalarAlgebraNode(); result.StatisticsIterator = StatisticsIterator; result.OutputList = ArrayHelpers.Clone(OutputList); result.Input = (AlgebraNode)Input.Clone(alreadyClonedElements); result.DefinedValues = ArrayHelpers.CreateDeepCopyOfAstElementArray(_definedValues, alreadyClonedElements); return(result); }
private void EmitComputeScalarIfNeeded(ComputedValueDefinition[] definedValues) { if (definedValues != null && definedValues.Length > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = GetLastAlgebraNode(); computeScalarAlgebraNode.DefinedValues = definedValues; SetLastAlgebraNode(computeScalarAlgebraNode); } }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { base.VisitComputeScalarAlgebraNode(node); foreach (ComputedValueDefinition definedValue in node.DefinedValues) { NameEntry(definedValue.Target, EXPRESSION_NAME_FMT_STR); } return(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); List<RowBufferEntry> outputList = new List<RowBufferEntry>(); outputList.AddRange(node.Input.OutputList); outputList.AddRange(GetRowBufferEntries(node.DefinedValues)); node.OutputList = outputList.ToArray(); return node; }
private AlgebraNode PushOverFilter(ComputeScalarAlgebraNode node) { FilterAlgebraNode filterAlgebraNode = (FilterAlgebraNode) node.Input; if (filterAlgebraNode.Input is TableAlgebraNode) { // We don't push a compute scalar over the input if this is already a table scan. return node; } return PushOverUnary(node); }
private AlgebraNode MergeWithComputeScalar(ComputeScalarAlgebraNode node) { ComputeScalarAlgebraNode inputNode = (ComputeScalarAlgebraNode) node.Input; node.Input = inputNode.Input; node.DefinedValues = ArrayHelpers.JoinArrays(node.DefinedValues, inputNode.DefinedValues); RowBufferEntryReplacer rowBufferEntryReplacer = new RowBufferEntryReplacer(inputNode.DefinedValues); foreach (ComputedValueDefinition definedValue in node.DefinedValues) definedValue.Expression = rowBufferEntryReplacer.VisitExpression(definedValue.Expression); return VisitAlgebraNode(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); List <RowBufferEntry> outputList = new List <RowBufferEntry>(); outputList.AddRange(node.Input.OutputList); outputList.AddRange(GetRowBufferEntries(node.DefinedValues)); node.OutputList = outputList.ToArray(); return(node); }
private AlgebraNode PushOverFilter(ComputeScalarAlgebraNode node) { FilterAlgebraNode filterAlgebraNode = (FilterAlgebraNode)node.Input; if (filterAlgebraNode.Input is TableAlgebraNode) { // We don't push a compute scalar over the input if this is already a table scan. return(node); } return(PushOverUnary(node)); }
public virtual AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); if (node.DefinedValues != null) { foreach (ComputedValueDefinition definedValue in node.DefinedValues) { definedValue.Expression = VisitExpression(definedValue.Expression); } } return(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { ShowPlanElement inputElement = ConvertNode(node.Input); PropertyListBuilder propertyListBuilder = new PropertyListBuilder(); AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOutputList, node.OutputList); AddStatistics(propertyListBuilder, node.StatisticsIterator); AddDefinedValues(propertyListBuilder, node.DefinedValues); IList<ShowPlanProperty> properties = propertyListBuilder.ToList(); ShowPlanElement element = new ShowPlanElement(ShowPlanOperator.ComputeScalar, properties, inputElement); _currentElement = element; return node; }
private AlgebraNode MergeWithComputeScalar(ComputeScalarAlgebraNode node) { ComputeScalarAlgebraNode inputNode = (ComputeScalarAlgebraNode)node.Input; node.Input = inputNode.Input; node.DefinedValues = ArrayHelpers.JoinArrays(node.DefinedValues, inputNode.DefinedValues); RowBufferEntryReplacer rowBufferEntryReplacer = new RowBufferEntryReplacer(inputNode.DefinedValues); foreach (ComputedValueDefinition definedValue in node.DefinedValues) { definedValue.Expression = rowBufferEntryReplacer.VisitExpression(definedValue.Expression); } return(VisitAlgebraNode(node)); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); SetLastAlgebraNode(node.Input); _probingEnabledStack.Push(true); foreach (ComputedValueDefinition definedValue in node.DefinedValues) { definedValue.Expression = VisitExpression(definedValue.Expression); } _probingEnabledStack.Pop(); node.Input = GetAndResetLastNode(); return(node); }
private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding) { // Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times. // Since same row buffer entries means that the underlying data will be stored in the same physical data slot this // will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that // operates on the same column will always compare data coming from the same join side (and therefor will always // evaluate to true). // // Some notes on the implementation: // // 1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough; // instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc. // 2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions // are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same // expression AST instances. That means that replacing the row buffers leads to failure. // HACK: This is a workaround for issue 2. However, // I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query. algebrizedCte = (AlgebraNode)algebrizedCte.Clone(); CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer(); cteTableDefinedValuesReinitializer.Visit(algebrizedCte); RowBufferEntry[] outputList = algebrizedCte.OutputList; int skipRecursionLevel = commonTableBinding.IsRecursive ? 1 : 0; // Rename the query columns to the CTE columns List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedCte; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); return(computeScalarAlgebraNode); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.OutputList = RemovedUnneededRowBufferColumns(node.OutputList); node.DefinedValues = RemovedUnneededDefinedValues(node.DefinedValues); if (node.DefinedValues.Length == 0) { return(VisitAlgebraNode(node.Input)); } foreach (ComputedValueDefinition definedValue in node.DefinedValues) { AddNeededRowBufferEntryReferences(definedValue.Expression); } return(base.VisitComputeScalarAlgebraNode(node)); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { ShowPlanElement inputElement = ConvertNode(node.Input); PropertyListBuilder propertyListBuilder = new PropertyListBuilder(); AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOutputList, node.OutputList); AddStatistics(propertyListBuilder, node.StatisticsIterator); AddDefinedValues(propertyListBuilder, node.DefinedValues); IList <ShowPlanProperty> properties = propertyListBuilder.ToList(); ShowPlanElement element = new ShowPlanElement(ShowPlanOperator.ComputeScalar, properties, inputElement); _currentElement = element; return(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { base.VisitComputeScalarAlgebraNode(node); List<ComputedValueDefinition> remainingDefinedValues = new List<ComputedValueDefinition>(); foreach (ComputedValueDefinition definedValue in node.DefinedValues) { RowBufferEntryExpression rowBufferEntryExpression = definedValue.Expression as RowBufferEntryExpression; if (rowBufferEntryExpression != null) _inliningDictionary[definedValue.Target] = rowBufferEntryExpression.RowBufferEntry; else remainingDefinedValues.Add(definedValue); } if (remainingDefinedValues.Count == 0) return node.Input; node.DefinedValues = remainingDefinedValues.ToArray(); return node; }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { switch (node.Input.NodeType) { // Push over top, filter, sort, max one row case AstNodeType.TopAlgebraNode: case AstNodeType.SortAlgebraNode: case AstNodeType.AssertAlgebraNode: case AstNodeType.ResultAlgebraNode: return(PushOverUnary(node)); case AstNodeType.FilterAlgebraNode: return(PushOverFilter(node)); // Merge with computation case AstNodeType.ComputeScalarAlgebraNode: return(MergeWithComputeScalar(node)); // Merge with constant scan case AstNodeType.ConstantScanAlgebraNode: return(MegeWithConstantScan(node)); // Push over join case AstNodeType.JoinAlgebraNode: return(PushOverJoin(node)); // TODO: Push over concatenation case AstNodeType.ConcatAlgebraNode: return(base.VisitComputeScalarAlgebraNode(node)); // TODO: Push over aggregation case AstNodeType.AggregateAlgebraNode: return(base.VisitComputeScalarAlgebraNode(node)); default: return(base.VisitComputeScalarAlgebraNode(node)); } }
public override AlgebraNode VisitConcatAlgebraNode(ConcatAlgebraNode node) { base.VisitConcatAlgebraNode(node); List<AlgebraNode> nonEmptyInputs = new List<AlgebraNode>(); foreach (AlgebraNode input in node.Inputs) { if (input is NullScanAlgebraNode) { // removed by not adding to list. } else { nonEmptyInputs.Add(input); } } if (nonEmptyInputs.Count == 0) return CreateNullScan(node.OutputList); if (nonEmptyInputs.Count == 1) { int inputIndex = Array.IndexOf(node.Inputs, nonEmptyInputs[0]); List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = nonEmptyInputs[0]; foreach (UnitedValueDefinition unitedValueDefinition in node.DefinedValues) { ComputedValueDefinition computedValueDefinition = new ComputedValueDefinition(); computedValueDefinition.Target = unitedValueDefinition.Target; computedValueDefinition.Expression = new RowBufferEntryExpression(unitedValueDefinition.DependendEntries[inputIndex]); definedValues.Add(computedValueDefinition); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = node.OutputList; return computeScalarAlgebraNode; } node.Inputs = nonEmptyInputs.ToArray(); // Update dependend entries for (int i = 0; i < node.DefinedValues.Length; i++) { UnitedValueDefinition definition = node.DefinedValues[i]; List<RowBufferEntry> dependendEntries = new List<RowBufferEntry>(); foreach (RowBufferEntry dependendEntry in definition.DependendEntries) { bool entryInAnyInput = false; foreach (AlgebraNode input in node.Inputs) { if (ArrayHelpers.Contains(input.OutputList, dependendEntry)) { entryInAnyInput = true; break; } } if (entryInAnyInput) dependendEntries.Add(dependendEntry); } definition.DependendEntries = dependendEntries.ToArray(); } return node; }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); return NullScanIfInputIsNullScan(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); SetLastAlgebraNode(node.Input); _probingEnabledStack.Push(true); foreach (ComputedValueDefinition definedValue in node.DefinedValues) definedValue.Expression = VisitExpression(definedValue.Expression); _probingEnabledStack.Pop(); node.Input = GetAndResetLastNode(); return node; }
private AlgebraNode MegeWithConstantScan(ComputeScalarAlgebraNode node) { ConstantScanAlgebraNode constantScanAlgebraNode = (ConstantScanAlgebraNode) node.Input; constantScanAlgebraNode.DefinedValues = ArrayHelpers.JoinArrays(constantScanAlgebraNode.DefinedValues, node.DefinedValues); return VisitAlgebraNode(constantScanAlgebraNode); }
public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); ExpressionNode originalPredicate = (ExpressionNode)node.Predicate.Clone(); SpoolExpressionExtractor spoolExpressionExtractor = new SpoolExpressionExtractor(_outerReferences); // HACK: This hack ensures that TRUE literals introduced by SpoolExpressionExtractor are removed. node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, spoolExpressionExtractor.VisitExpression(node.Predicate)); SpoolExpression[] spoolExpressions = spoolExpressionExtractor.GetSpoolExpressions(); // Now we must check that the remaining filter incl. input to the filter don't reference any other // outer reference. bool remainingFilterHasDependenciesToOuterReferences = CheckIfNodeHasDependenciesToOuterReferences(node); if (remainingFilterHasDependenciesToOuterReferences) { // OK; we cannot insert a spool operation here. Undo the expression replacement. node.Predicate = originalPredicate; } else if (spoolExpressions.Length > 0) { SpoolExpression spoolExpression = spoolExpressions[0]; AlgebraNode currentInput; if (node.Predicate is ConstantExpression) { currentInput = node.Input; } else { currentInput = node; } RowBufferEntry indexEntry; RowBufferEntryExpression indexExpressionAsRowBufferEntryExpression = spoolExpression.IndexExpression as RowBufferEntryExpression; if (indexExpressionAsRowBufferEntryExpression != null) { indexEntry = indexExpressionAsRowBufferEntryExpression.RowBufferEntry; } else { indexEntry = new RowBufferEntry(spoolExpression.IndexExpression.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = indexEntry; definedValue.Expression = spoolExpression.IndexExpression; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = currentInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue }; currentInput = computeScalarAlgebraNode; } IndexSpoolAlgebraNode indexSpoolAlgebraNode = new IndexSpoolAlgebraNode(); indexSpoolAlgebraNode.Input = currentInput; indexSpoolAlgebraNode.IndexEntry = indexEntry; indexSpoolAlgebraNode.ProbeExpression = spoolExpression.ProbeExpression; return(indexSpoolAlgebraNode); } return(node); }
private static AlgebraNode AlgebrizeRecursiveCte(CommonTableBinding commonTableBinding) { // It is a recursive query. // // Create row buffer entry that is used to guard the recursion and the primary table spool // that spools the results needed by nested recursion calls. ExpressionBuilder expressionBuilder = new ExpressionBuilder(); StackedTableSpoolAlgebraNode primaryTableSpool = new StackedTableSpoolAlgebraNode(); RowBufferEntry anchorRecursionLevel; RowBufferEntry[] anchorOutput; AlgebraNode anchorNode; #region Anchor member { // Emit anchor member. AlgebraNode algebrizedAnchor = Convert(commonTableBinding.AnchorMember); // Emit compute scalar that initializes the recursion level to 0. anchorRecursionLevel = new RowBufferEntry(typeof(int)); ComputedValueDefinition computedValueDefinition1 = new ComputedValueDefinition(); computedValueDefinition1.Target = anchorRecursionLevel; computedValueDefinition1.Expression = LiteralExpression.FromInt32(0); ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedAnchor; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { computedValueDefinition1 }; anchorOutput = algebrizedAnchor.OutputList; anchorNode = computeScalarAlgebraNode; } #endregion RowBufferEntry incrementedRecursionLevel; RowBufferEntry[] tableSpoolOutput; AlgebraNode tableSpoolNode; #region Table spool { // Emit table spool reference. RowBufferEntry recursionLevelRefEntry = new RowBufferEntry(typeof(int)); tableSpoolOutput = new RowBufferEntry[anchorOutput.Length]; for (int i = 0; i < tableSpoolOutput.Length; i++) tableSpoolOutput[i] = new RowBufferEntry(anchorOutput[i].DataType); StackedTableSpoolRefAlgebraNode tableSpoolReference = new StackedTableSpoolRefAlgebraNode(); tableSpoolReference.PrimarySpool = primaryTableSpool; tableSpoolReference.DefinedValues = ArrayHelpers.JoinArrays(new RowBufferEntry[] { recursionLevelRefEntry }, tableSpoolOutput); // Emit compute scalar that increases the recursion level by one and renames // columns from the spool to the CTE column buffer entries. expressionBuilder.Push(new RowBufferEntryExpression(recursionLevelRefEntry)); expressionBuilder.Push(LiteralExpression.FromInt32(1)); expressionBuilder.PushBinary(BinaryOperator.Add); incrementedRecursionLevel = new RowBufferEntry(typeof(int)); ComputedValueDefinition incremenedRecLevelValueDefinition = new ComputedValueDefinition(); incremenedRecLevelValueDefinition.Target = incrementedRecursionLevel; incremenedRecLevelValueDefinition.Expression = expressionBuilder.Pop(); CteColumnMappingFinder cteColumnMappingFinder = new CteColumnMappingFinder(commonTableBinding, tableSpoolOutput); foreach (QueryNode recursiveMember in commonTableBinding.RecursiveMembers) cteColumnMappingFinder.Visit(recursiveMember); CteColumnMapping[] cteColumnMappings = cteColumnMappingFinder.GetMappings(); List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); definedValues.Add(incremenedRecLevelValueDefinition); foreach (CteColumnMapping cteColumnMapping in cteColumnMappings) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = cteColumnMapping.VirtualBufferEntry; definedValue.Expression = new RowBufferEntryExpression(cteColumnMapping.SpoolBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = tableSpoolReference; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); tableSpoolNode = computeScalarAlgebraNode; } #endregion RowBufferEntry[] recursiveOutput; AlgebraNode recursiveNode; #region Recursive member(s) { // Emit all recursive parts. The join conditions to the recursive part are replaced by simple filters // in the nested Convert() call. ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[commonTableBinding.RecursiveMembers.Length]; for (int i = 0; i < commonTableBinding.RecursiveMembers.Length; i++) concatAlgebraNode.Inputs[i] = Convert(commonTableBinding, commonTableBinding.RecursiveMembers[i]); concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length]; for (int i = 0; i < anchorOutput.Length; i++) { List<RowBufferEntry> dependencies = new List<RowBufferEntry>(); foreach (ResultAlgebraNode algebrizedRecursivePart in concatAlgebraNode.Inputs) dependencies.Add(algebrizedRecursivePart.OutputList[i]); concatAlgebraNode.DefinedValues[i] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[i].Target = new RowBufferEntry(anchorOutput[i].DataType); concatAlgebraNode.DefinedValues[i].DependendEntries = dependencies.ToArray(); } // Calculate the recursive output. recursiveOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length]; for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++) recursiveOutput[i] = concatAlgebraNode.DefinedValues[i].Target; // Emit cross join JoinAlgebraNode crossJoinNode = new JoinAlgebraNode(); crossJoinNode.Left = tableSpoolNode; crossJoinNode.Right = concatAlgebraNode; // Emit assert that ensures that the recursion level is <= 100. expressionBuilder.Push(new RowBufferEntryExpression(incrementedRecursionLevel)); expressionBuilder.Push(LiteralExpression.FromInt32(100)); expressionBuilder.PushBinary(BinaryOperator.Greater); CaseExpression caseExpression = new CaseExpression(); caseExpression.WhenExpressions = new ExpressionNode[1]; caseExpression.WhenExpressions[0] = expressionBuilder.Pop(); caseExpression.ThenExpressions = new ExpressionNode[1]; caseExpression.ThenExpressions[0] = LiteralExpression.FromInt32(0); AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode(); assertAlgebraNode.Input = crossJoinNode; assertAlgebraNode.AssertionType = AssertionType.BelowRecursionLimit; assertAlgebraNode.Predicate = caseExpression; recursiveNode = assertAlgebraNode; } #endregion RowBufferEntry[] algebrizedOutput; AlgebraNode algebrizedCte; #region Combination { // Create concat node to combine anchor and recursive part. ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[2]; concatAlgebraNode.Inputs[0] = anchorNode; concatAlgebraNode.Inputs[1] = recursiveNode; concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length + 1]; concatAlgebraNode.DefinedValues[0] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[0].Target = new RowBufferEntry(anchorRecursionLevel.DataType); concatAlgebraNode.DefinedValues[0].DependendEntries = new RowBufferEntry[] { anchorRecursionLevel, incrementedRecursionLevel }; for (int i = 0; i < anchorOutput.Length; i++) { concatAlgebraNode.DefinedValues[i + 1] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[i + 1].Target = new RowBufferEntry(anchorOutput[i].DataType); concatAlgebraNode.DefinedValues[i + 1].DependendEntries = new RowBufferEntry[] { anchorOutput[i], recursiveOutput[i] }; } algebrizedOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length]; for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++) algebrizedOutput[i] = concatAlgebraNode.DefinedValues[i].Target; // Assign the combination as the input to the primray spool primaryTableSpool.Input = concatAlgebraNode; // The primary spool represents the result of the "inlined" CTE. algebrizedCte = primaryTableSpool; } #endregion algebrizedCte.OutputList = algebrizedOutput; return algebrizedCte; }
private static AlgebraNode AlgebrizeRecursiveCte(CommonTableBinding commonTableBinding) { // It is a recursive query. // // Create row buffer entry that is used to guard the recursion and the primary table spool // that spools the results needed by nested recursion calls. ExpressionBuilder expressionBuilder = new ExpressionBuilder(); StackedTableSpoolAlgebraNode primaryTableSpool = new StackedTableSpoolAlgebraNode(); RowBufferEntry anchorRecursionLevel; RowBufferEntry[] anchorOutput; AlgebraNode anchorNode; #region Anchor member { // Emit anchor member. AlgebraNode algebrizedAnchor = Convert(commonTableBinding.AnchorMember); // Emit compute scalar that initializes the recursion level to 0. anchorRecursionLevel = new RowBufferEntry(typeof(int)); ComputedValueDefinition computedValueDefinition1 = new ComputedValueDefinition(); computedValueDefinition1.Target = anchorRecursionLevel; computedValueDefinition1.Expression = LiteralExpression.FromInt32(0); ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedAnchor; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { computedValueDefinition1 }; anchorOutput = algebrizedAnchor.OutputList; anchorNode = computeScalarAlgebraNode; } #endregion RowBufferEntry incrementedRecursionLevel; RowBufferEntry[] tableSpoolOutput; AlgebraNode tableSpoolNode; #region Table spool { // Emit table spool reference. RowBufferEntry recursionLevelRefEntry = new RowBufferEntry(typeof(int)); tableSpoolOutput = new RowBufferEntry[anchorOutput.Length]; for (int i = 0; i < tableSpoolOutput.Length; i++) { tableSpoolOutput[i] = new RowBufferEntry(anchorOutput[i].DataType); } StackedTableSpoolRefAlgebraNode tableSpoolReference = new StackedTableSpoolRefAlgebraNode(); tableSpoolReference.PrimarySpool = primaryTableSpool; tableSpoolReference.DefinedValues = ArrayHelpers.JoinArrays(new RowBufferEntry[] { recursionLevelRefEntry }, tableSpoolOutput); // Emit compute scalar that increases the recursion level by one and renames // columns from the spool to the CTE column buffer entries. expressionBuilder.Push(new RowBufferEntryExpression(recursionLevelRefEntry)); expressionBuilder.Push(LiteralExpression.FromInt32(1)); expressionBuilder.PushBinary(BinaryOperator.Add); incrementedRecursionLevel = new RowBufferEntry(typeof(int)); ComputedValueDefinition incremenedRecLevelValueDefinition = new ComputedValueDefinition(); incremenedRecLevelValueDefinition.Target = incrementedRecursionLevel; incremenedRecLevelValueDefinition.Expression = expressionBuilder.Pop(); CteColumnMappingFinder cteColumnMappingFinder = new CteColumnMappingFinder(commonTableBinding, tableSpoolOutput); foreach (QueryNode recursiveMember in commonTableBinding.RecursiveMembers) { cteColumnMappingFinder.Visit(recursiveMember); } CteColumnMapping[] cteColumnMappings = cteColumnMappingFinder.GetMappings(); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); definedValues.Add(incremenedRecLevelValueDefinition); foreach (CteColumnMapping cteColumnMapping in cteColumnMappings) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = cteColumnMapping.VirtualBufferEntry; definedValue.Expression = new RowBufferEntryExpression(cteColumnMapping.SpoolBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = tableSpoolReference; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); tableSpoolNode = computeScalarAlgebraNode; } #endregion RowBufferEntry[] recursiveOutput; AlgebraNode recursiveNode; #region Recursive member(s) { // Emit all recursive parts. The join conditions to the recursive part are replaced by simple filters // in the nested Convert() call. ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[commonTableBinding.RecursiveMembers.Length]; for (int i = 0; i < commonTableBinding.RecursiveMembers.Length; i++) { concatAlgebraNode.Inputs[i] = Convert(commonTableBinding, commonTableBinding.RecursiveMembers[i]); } concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length]; for (int i = 0; i < anchorOutput.Length; i++) { List <RowBufferEntry> dependencies = new List <RowBufferEntry>(); foreach (ResultAlgebraNode algebrizedRecursivePart in concatAlgebraNode.Inputs) { dependencies.Add(algebrizedRecursivePart.OutputList[i]); } concatAlgebraNode.DefinedValues[i] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[i].Target = new RowBufferEntry(anchorOutput[i].DataType); concatAlgebraNode.DefinedValues[i].DependendEntries = dependencies.ToArray(); } // Calculate the recursive output. recursiveOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length]; for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++) { recursiveOutput[i] = concatAlgebraNode.DefinedValues[i].Target; } // Emit cross join JoinAlgebraNode crossJoinNode = new JoinAlgebraNode(); crossJoinNode.Left = tableSpoolNode; crossJoinNode.Right = concatAlgebraNode; // Emit assert that ensures that the recursion level is <= 100. expressionBuilder.Push(new RowBufferEntryExpression(incrementedRecursionLevel)); expressionBuilder.Push(LiteralExpression.FromInt32(100)); expressionBuilder.PushBinary(BinaryOperator.Greater); CaseExpression caseExpression = new CaseExpression(); caseExpression.WhenExpressions = new ExpressionNode[1]; caseExpression.WhenExpressions[0] = expressionBuilder.Pop(); caseExpression.ThenExpressions = new ExpressionNode[1]; caseExpression.ThenExpressions[0] = LiteralExpression.FromInt32(0); AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode(); assertAlgebraNode.Input = crossJoinNode; assertAlgebraNode.AssertionType = AssertionType.BelowRecursionLimit; assertAlgebraNode.Predicate = caseExpression; recursiveNode = assertAlgebraNode; } #endregion RowBufferEntry[] algebrizedOutput; AlgebraNode algebrizedCte; #region Combination { // Create concat node to combine anchor and recursive part. ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[2]; concatAlgebraNode.Inputs[0] = anchorNode; concatAlgebraNode.Inputs[1] = recursiveNode; concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length + 1]; concatAlgebraNode.DefinedValues[0] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[0].Target = new RowBufferEntry(anchorRecursionLevel.DataType); concatAlgebraNode.DefinedValues[0].DependendEntries = new RowBufferEntry[] { anchorRecursionLevel, incrementedRecursionLevel }; for (int i = 0; i < anchorOutput.Length; i++) { concatAlgebraNode.DefinedValues[i + 1] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[i + 1].Target = new RowBufferEntry(anchorOutput[i].DataType); concatAlgebraNode.DefinedValues[i + 1].DependendEntries = new RowBufferEntry[] { anchorOutput[i], recursiveOutput[i] }; } algebrizedOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length]; for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++) { algebrizedOutput[i] = concatAlgebraNode.DefinedValues[i].Target; } // Assign the combination as the input to the primray spool primaryTableSpool.Input = concatAlgebraNode; // The primary spool represents the result of the "inlined" CTE. algebrizedCte = primaryTableSpool; } #endregion algebrizedCte.OutputList = algebrizedOutput; return(algebrizedCte); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); return(NullScanIfInputIsNullScan(node)); }
private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding) { // Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times. // Since same row buffer entries means that the underlying data will be stored in the same physical data slot this // will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that // operates on the same column will always compare data coming from the same join side (and therefor will always // evaluate to true). // // Some notes on the implementation: // // 1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough; // instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc. // 2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions // are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same // expression AST instances. That means that replacing the row buffers leads to failure. // HACK: This is a workaround for issue 2. However, // I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query. algebrizedCte = (AlgebraNode) algebrizedCte.Clone(); CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer(); cteTableDefinedValuesReinitializer.Visit(algebrizedCte); RowBufferEntry[] outputList = algebrizedCte.OutputList; int skipRecursionLevel = commonTableBinding.IsRecursive ? 1 : 0; // Rename the query columns to the CTE columns List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedCte; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); return computeScalarAlgebraNode; }
public override TableReference VisitDerivedTableReference(DerivedTableReference node) { AlgebraNode algebrizedQuery = Convert(node.Query); List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); for (int i = 0; i < node.DerivedTableBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = node.DerivedTableBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = algebrizedQuery.OutputList[i]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedQuery; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); SetLastAlgebraNode(computeScalarAlgebraNode); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); if (node.Predicate != null && (node.OuterReferences == null || node.OuterReferences.Length == 0) && ( node.Op == JoinAlgebraNode.JoinOperator.InnerJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) ) { RowBufferEntry[] leftDefinedEntries = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedEntries = AstUtil.GetDefinedValueEntries(node.Right); EqualPredicatesExtractor equalPredicatesExtractor = new EqualPredicatesExtractor(leftDefinedEntries, rightDefinedEntries); ExpressionNode probeResidual = equalPredicatesExtractor.VisitExpression(node.Predicate); BinaryExpression[] equalPredicates = equalPredicatesExtractor.GetEqualPredicates(); if (equalPredicates.Length > 0) { BinaryExpression equalPredicate = equalPredicates[0]; ExpressionBuilder expressionBuilder = new ExpressionBuilder(); expressionBuilder.Push(probeResidual); if (equalPredicates.Length > 1) { for (int i = 1; i < equalPredicates.Length; i++) { expressionBuilder.Push(equalPredicates[i]); } expressionBuilder.PushNAry(LogicalOperator.And); } probeResidual = expressionBuilder.Pop(); if (probeResidual is ConstantExpression) { probeResidual = null; } AlgebraNode leftInput = node.Left; AlgebraNode rightInput = node.Right; if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; leftInput = node.Right; rightInput = node.Left; ExpressionNode oldLeft = equalPredicate.Left; equalPredicate.Left = equalPredicate.Right; equalPredicate.Right = oldLeft; } RowBufferEntry leftEntry; RowBufferEntryExpression leftAsRowBufferEntryExpression = equalPredicate.Left as RowBufferEntryExpression; if (leftAsRowBufferEntryExpression != null) { leftEntry = leftAsRowBufferEntryExpression.RowBufferEntry; } else { leftEntry = new RowBufferEntry(equalPredicate.Left.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = leftEntry; definedValue.Expression = equalPredicate.Left; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = leftInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue }; leftInput = computeScalarAlgebraNode; } RowBufferEntry rightEntry; RowBufferEntryExpression rightAsRowBufferEntryExpression = equalPredicate.Right as RowBufferEntryExpression; if (rightAsRowBufferEntryExpression != null) { rightEntry = rightAsRowBufferEntryExpression.RowBufferEntry; } else { rightEntry = new RowBufferEntry(equalPredicate.Right.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rightEntry; definedValue.Expression = equalPredicate.Right; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = rightInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue }; rightInput = computeScalarAlgebraNode; } HashMatchAlgebraNode hashMatchAlgebraNode = new HashMatchAlgebraNode(); hashMatchAlgebraNode.Op = node.Op; hashMatchAlgebraNode.Left = leftInput; hashMatchAlgebraNode.Right = rightInput; hashMatchAlgebraNode.BuildKeyEntry = leftEntry; hashMatchAlgebraNode.ProbeEntry = rightEntry; hashMatchAlgebraNode.ProbeResidual = probeResidual; return(hashMatchAlgebraNode); } } return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); if (node.Predicate != null && (node.OuterReferences == null || node.OuterReferences.Length == 0) && ( node.Op == JoinAlgebraNode.JoinOperator.InnerJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) ) { RowBufferEntry[] leftDefinedEntries = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedEntries = AstUtil.GetDefinedValueEntries(node.Right); EqualPredicatesExtractor equalPredicatesExtractor = new EqualPredicatesExtractor(leftDefinedEntries, rightDefinedEntries); ExpressionNode probeResidual = equalPredicatesExtractor.VisitExpression(node.Predicate); BinaryExpression[] equalPredicates = equalPredicatesExtractor.GetEqualPredicates(); if (equalPredicates.Length > 0) { BinaryExpression equalPredicate = equalPredicates[0]; ExpressionBuilder expressionBuilder = new ExpressionBuilder(); expressionBuilder.Push(probeResidual); if (equalPredicates.Length > 1) { for (int i = 1; i < equalPredicates.Length; i++) expressionBuilder.Push(equalPredicates[i]); expressionBuilder.PushNAry(LogicalOperator.And); } probeResidual = expressionBuilder.Pop(); if (probeResidual is ConstantExpression) probeResidual = null; AlgebraNode leftInput = node.Left; AlgebraNode rightInput = node.Right; if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; leftInput = node.Right; rightInput = node.Left; ExpressionNode oldLeft = equalPredicate.Left; equalPredicate.Left = equalPredicate.Right; equalPredicate.Right = oldLeft; } RowBufferEntry leftEntry; RowBufferEntryExpression leftAsRowBufferEntryExpression = equalPredicate.Left as RowBufferEntryExpression; if (leftAsRowBufferEntryExpression != null) { leftEntry = leftAsRowBufferEntryExpression.RowBufferEntry; } else { leftEntry = new RowBufferEntry(equalPredicate.Left.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = leftEntry; definedValue.Expression = equalPredicate.Left; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = leftInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] {definedValue}; leftInput = computeScalarAlgebraNode; } RowBufferEntry rightEntry; RowBufferEntryExpression rightAsRowBufferEntryExpression = equalPredicate.Right as RowBufferEntryExpression; if (rightAsRowBufferEntryExpression != null) { rightEntry = rightAsRowBufferEntryExpression.RowBufferEntry; } else { rightEntry = new RowBufferEntry(equalPredicate.Right.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rightEntry; definedValue.Expression = equalPredicate.Right; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = rightInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] {definedValue}; rightInput = computeScalarAlgebraNode; } HashMatchAlgebraNode hashMatchAlgebraNode = new HashMatchAlgebraNode(); hashMatchAlgebraNode.Op = node.Op; hashMatchAlgebraNode.Left = leftInput; hashMatchAlgebraNode.Right = rightInput; hashMatchAlgebraNode.BuildKeyEntry = leftEntry; hashMatchAlgebraNode.ProbeEntry = rightEntry; hashMatchAlgebraNode.ProbeResidual = probeResidual; return hashMatchAlgebraNode; } } return node; }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { return PullFilterUp(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { switch (node.Input.NodeType) { // Push over top, filter, sort, max one row case AstNodeType.TopAlgebraNode: case AstNodeType.SortAlgebraNode: case AstNodeType.AssertAlgebraNode: case AstNodeType.ResultAlgebraNode: return PushOverUnary(node); case AstNodeType.FilterAlgebraNode: return PushOverFilter(node); // Merge with computation case AstNodeType.ComputeScalarAlgebraNode: return MergeWithComputeScalar(node); // Merge with constant scan case AstNodeType.ConstantScanAlgebraNode: return MegeWithConstantScan(node); // Push over join case AstNodeType.JoinAlgebraNode: return PushOverJoin(node); // TODO: Push over concatenation case AstNodeType.ConcatAlgebraNode: return base.VisitComputeScalarAlgebraNode(node); // TODO: Push over aggregation case AstNodeType.AggregateAlgebraNode: return base.VisitComputeScalarAlgebraNode(node); default: return base.VisitComputeScalarAlgebraNode(node); } }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { return(PullFilterUp(node)); }
public override AlgebraNode VisitConcatAlgebraNode(ConcatAlgebraNode node) { base.VisitConcatAlgebraNode(node); List <AlgebraNode> nonEmptyInputs = new List <AlgebraNode>(); foreach (AlgebraNode input in node.Inputs) { if (input is NullScanAlgebraNode) { // removed by not adding to list. } else { nonEmptyInputs.Add(input); } } if (nonEmptyInputs.Count == 0) { return(CreateNullScan(node.OutputList)); } if (nonEmptyInputs.Count == 1) { int inputIndex = Array.IndexOf(node.Inputs, nonEmptyInputs[0]); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = nonEmptyInputs[0]; foreach (UnitedValueDefinition unitedValueDefinition in node.DefinedValues) { ComputedValueDefinition computedValueDefinition = new ComputedValueDefinition(); computedValueDefinition.Target = unitedValueDefinition.Target; computedValueDefinition.Expression = new RowBufferEntryExpression(unitedValueDefinition.DependendEntries[inputIndex]); definedValues.Add(computedValueDefinition); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = node.OutputList; return(computeScalarAlgebraNode); } node.Inputs = nonEmptyInputs.ToArray(); // Update dependend entries for (int i = 0; i < node.DefinedValues.Length; i++) { UnitedValueDefinition definition = node.DefinedValues[i]; List <RowBufferEntry> dependendEntries = new List <RowBufferEntry>(); foreach (RowBufferEntry dependendEntry in definition.DependendEntries) { bool entryInAnyInput = false; foreach (AlgebraNode input in node.Inputs) { if (ArrayHelpers.Contains(input.OutputList, dependendEntry)) { entryInAnyInput = true; break; } } if (entryInAnyInput) { dependendEntries.Add(dependendEntry); } } definition.DependendEntries = dependendEntries.ToArray(); } return(node); }
public override AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { ComputeScalarIterator computeScalarIterator = new ComputeScalarIterator(); computeScalarIterator.RowBuffer = new object[node.OutputList.Length]; computeScalarIterator.Input = ConvertAlgebraNode(node.Input); computeScalarIterator.InputOutput = GetIteratorOutput(0, node.Input.OutputList, node.OutputList); BoundRowBufferEntrySet boundRowBufferEntrySet = new BoundRowBufferEntrySet(computeScalarIterator.Input.RowBuffer, node.Input.OutputList); computeScalarIterator.DefinedValues = GetDefinedValues(node.OutputList, node.DefinedValues, boundRowBufferEntrySet); SetLastIterator(node, computeScalarIterator); return node; }
public virtual AlgebraNode VisitComputeScalarAlgebraNode(ComputeScalarAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); if (node.DefinedValues != null) { foreach (ComputedValueDefinition definedValue in node.DefinedValues) definedValue.Expression = VisitExpression(definedValue.Expression); } return node; }