示例#1
0
        public virtual AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            node.Input     = VisitAlgebraNode(node.Input);
            node.Predicate = VisitExpression(node.Predicate);

            return(node);
        }
示例#2
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            switch (node.Input.NodeType)
            {
            case AstNodeType.SortAlgebraNode:
            case AstNodeType.ResultAlgebraNode:
            case AstNodeType.TopAlgebraNode:
                return(PushOverUnary(node));

            case AstNodeType.FilterAlgebraNode:
                return(MergeWithFilter(node));

            case AstNodeType.ComputeScalarAlgebraNode:
                return(PushOverComputeScalar(node));

            case AstNodeType.AggregateAlgebraNode:
                return(PushOverAggregate(node));

            case AstNodeType.JoinAlgebraNode:
                return(PushOverJoin(node));

            case AstNodeType.ConcatAlgebraNode:
                return(PushOverConcat(node));

            default:
                return(base.VisitFilterAlgebraNode(node));
            }
        }
示例#3
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            switch (node.Input.NodeType)
            {
                case AstNodeType.SortAlgebraNode:
                case AstNodeType.ResultAlgebraNode:
                case AstNodeType.TopAlgebraNode:
                    return PushOverUnary(node);

                case AstNodeType.FilterAlgebraNode:
                    return MergeWithFilter(node);

                case AstNodeType.ComputeScalarAlgebraNode:
                    return PushOverComputeScalar(node);

                case AstNodeType.AggregateAlgebraNode:
                    return PushOverAggregate(node);

                case AstNodeType.JoinAlgebraNode:
                    return PushOverJoin(node);

                case AstNodeType.ConcatAlgebraNode:
                    return PushOverConcat(node);

                default:
                    return base.VisitFilterAlgebraNode(node);
            }
        }
示例#4
0
        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;
        }
示例#5
0
        private static FilterAlgebraNode GetFilterFromAndParts(IList <ExpressionNode> andParts, AlgebraNode input)
        {
            FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();

            filterAlgebraNode.Input     = input;
            filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andParts);
            return(filterAlgebraNode);
        }
示例#6
0
        private AlgebraNode PushOverUnary(FilterAlgebraNode node)
        {
            UnaryAlgebraNode inputNode = (UnaryAlgebraNode)node.Input;

            node.Input      = inputNode.Input;
            inputNode.Input = VisitAlgebraNode(node);
            return(inputNode);
        }
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            node.OutputList = RemovedUnneededRowBufferColumns(node.OutputList);

            AddNeededRowBufferEntryReferences(node.Predicate);

            return(base.VisitFilterAlgebraNode(node));
        }
示例#8
0
        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));
        }
示例#9
0
		public override AstElement Clone(Dictionary<AstElement, AstElement> alreadyClonedElements)
		{
			FilterAlgebraNode result = new FilterAlgebraNode();
			result.StatisticsIterator = StatisticsIterator;
			result.OutputList = ArrayHelpers.Clone(OutputList);
			result.Input = (AlgebraNode)Input.Clone(alreadyClonedElements);
			result.Predicate = (ExpressionNode)_predicate.Clone(alreadyClonedElements);
			return result;
		}
示例#10
0
        private AlgebraNode MergeWithFilter(FilterAlgebraNode node)
        {
            // The input is also a filter, so we can merge this predicate with
            // the input filter.

            FilterAlgebraNode inputNode = (FilterAlgebraNode)node.Input;

            inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, node.Predicate);
            return(VisitAlgebraNode(inputNode));
        }
示例#11
0
        public override AstElement Clone(Dictionary <AstElement, AstElement> alreadyClonedElements)
        {
            FilterAlgebraNode result = new FilterAlgebraNode();

            result.StatisticsIterator = StatisticsIterator;
            result.OutputList         = ArrayHelpers.Clone(OutputList);
            result.Input     = (AlgebraNode)Input.Clone(alreadyClonedElements);
            result.Predicate = (ExpressionNode)_predicate.Clone(alreadyClonedElements);
            return(result);
        }
示例#12
0
		private static AlgebraNode WrapWithFilter(AlgebraNode input, ExpressionNode predicate)
		{
			if (predicate == null)
				return input;

			FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
			filterAlgebraNode.Input = input;
			filterAlgebraNode.Predicate = predicate;
			return filterAlgebraNode;
		}
示例#13
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            _xmlWriter.WriteStartElement("filterAlgebraNode");

            WriteAstNode("input", node.Input);
            WriteAstNode("predicate", node.Predicate);

            _xmlWriter.WriteEndElement();

            return(node);
        }
示例#14
0
        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));
        }
示例#15
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            node.Input = VisitAlgebraNode(node.Input);

            SetLastAlgebraNode(node.Input);
            _probingEnabledStack.Push(false);
            node.Predicate = VisitExpression(node.Predicate);
            _probingEnabledStack.Pop();

            node.Input = GetAndResetLastNode();
            return(node);
        }
示例#16
0
        private static AlgebraNode WrapWithFilter(AlgebraNode input, ExpressionNode predicate)
        {
            if (predicate == null)
            {
                return(input);
            }

            FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();

            filterAlgebraNode.Input     = input;
            filterAlgebraNode.Predicate = predicate;
            return(filterAlgebraNode);
        }
示例#17
0
        private AlgebraNode PushOverAggregate(FilterAlgebraNode node)
        {
            // TODO: It is not that easy.
            //       For example this condition can be pushed 'GroupCol = Value' while this can't: 'GroupCol = Value OR Func(const) = const'
            //       Formally, a predicate can be pushed over an aggregate if and only if all disjuncts of the predicate's CNF do reference
            //       at least one grouping column.
            //       Since this requires cloning of the predicate and heavy rewriting this is not done (yet).
            return(base.VisitFilterAlgebraNode(node));

/*
 *                      // Predicates can be pushed over an aggregation if it does not contain any aggregate function.
 *                      AggregateAlgebraNode inputNode = (AggregateAlgebraNode)node.Input;
 *                      return PushOverValueDefininingUnary(inputNode.DefinedValues, node);
 */
        }
示例#18
0
		public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
		{
			// Check for null rejecting conditions.

			foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
			{
				RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart);

				foreach (RowBufferEntry rowBufferEntry in rowBufferEntries)
				{
					if (AstUtil.ExpressionYieldsNullOrFalseIfRowBufferEntryNull(andPart, rowBufferEntry))
						AddNullRejectedTable(rowBufferEntry);
				}
			}

			return base.VisitFilterAlgebraNode(node);
		}
示例#19
0
        private AlgebraNode PullFilterUp(UnaryAlgebraNode unaryAlgebraNode)
        {
            unaryAlgebraNode.Input = VisitAlgebraNode(unaryAlgebraNode.Input);

            FilterAlgebraNode filterAlgebraNode = unaryAlgebraNode.Input as FilterAlgebraNode;

            if (filterAlgebraNode == null)
            {
                return(unaryAlgebraNode);
            }
            else
            {
                unaryAlgebraNode.Input  = filterAlgebraNode.Input;
                filterAlgebraNode.Input = unaryAlgebraNode;
                return(filterAlgebraNode);
            }
        }
示例#20
0
        private AlgebraNode PushOverConcat(FilterAlgebraNode node)
        {
            ConcatAlgebraNode inputNode = (ConcatAlgebraNode)node.Input;

            for (int i = 0; i < inputNode.Inputs.Length; i++)
            {
                ExpressionNode predicate = (ExpressionNode)node.Predicate.Clone();
                ConcatRowBufferEntryReplacer concatRowBufferEntryReplacer = new ConcatRowBufferEntryReplacer(inputNode.DefinedValues, i);
                predicate = concatRowBufferEntryReplacer.VisitExpression(predicate);

                FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                filterAlgebraNode.Input     = inputNode.Inputs[i];
                filterAlgebraNode.Predicate = predicate;
                inputNode.Inputs[i]         = VisitAlgebraNode(filterAlgebraNode);
            }

            return(inputNode);
        }
示例#21
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            ShowPlanElement inputElement = ConvertNode(node.Input);

            PropertyListBuilder propertyListBuilder = new PropertyListBuilder();

            AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOutputList, node.OutputList);
            AddStatistics(propertyListBuilder, node.StatisticsIterator);

            propertyListBuilder.Write(Resources.ShowPlanKeyPredicate, node.Predicate.GenerateSource());

            IList <ShowPlanProperty> properties = propertyListBuilder.ToList();

            ShowPlanElement element = new ShowPlanElement(ShowPlanOperator.Filter, properties, inputElement);

            _currentElement = element;

            return(node);
        }
示例#22
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            // Check for null rejecting conditions.

            foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
            {
                RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart);

                foreach (RowBufferEntry rowBufferEntry in rowBufferEntries)
                {
                    if (AstUtil.ExpressionYieldsNullOrFalseIfRowBufferEntryNull(andPart, rowBufferEntry))
                    {
                        AddNullRejectedTable(rowBufferEntry);
                    }
                }
            }

            return(base.VisitFilterAlgebraNode(node));
        }
示例#23
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            node.Input = VisitAlgebraNode(node.Input);

            ConstantExpression predicateAsConstant = node.Predicate as ConstantExpression;

            if (predicateAsConstant != null)
            {
                if (predicateAsConstant.AsBoolean)
                {
                    return(node.Input);
                }
                else
                {
                    return(CreateNullScan(node.OutputList));
                }
            }

            return(NullScanIfInputIsNullScan(node));
        }
示例#24
0
        public override TableReference VisitJoinedTableReference(JoinedTableReference node)
        {
            TableReference nonCteTableRef;

            if (IsTableReferenceToCurrentCommonTableBinding(node.Left))
            {
                nonCteTableRef = node.Right;
            }
            else if (IsTableReferenceToCurrentCommonTableBinding(node.Right))
            {
                nonCteTableRef = node.Left;
            }
            else
            {
                nonCteTableRef = null;
            }

            if (nonCteTableRef != null)
            {
                Debug.Assert(node.JoinType == JoinType.Inner);
                AlgebraNode algebrizedPath = ConvertAstNode(nonCteTableRef);
                SetLastAlgebraNode(algebrizedPath);

                if (node.Condition != null)
                {
                    FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                    filterAlgebraNode.Input     = GetLastAlgebraNode();
                    filterAlgebraNode.Predicate = node.Condition;
                    SetLastAlgebraNode(filterAlgebraNode);
                }
                return(node);
            }

            JoinAlgebraNode algebraNode = new JoinAlgebraNode();

            algebraNode.Left      = ConvertAstNode(node.Left);
            algebraNode.Right     = ConvertAstNode(node.Right);
            algebraNode.Predicate = node.Condition;

            switch (node.JoinType)
            {
            case JoinType.Inner:
                algebraNode.Op = JoinAlgebraNode.JoinOperator.InnerJoin;
                break;

            case JoinType.LeftOuter:
                algebraNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin;
                break;

            case JoinType.RightOuter:
                algebraNode.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin;
                break;

            case JoinType.FullOuter:
                algebraNode.Op = JoinAlgebraNode.JoinOperator.FullOuterJoin;
                break;
            }

            SetLastAlgebraNode(algebraNode);
            return(node);
        }
示例#25
0
        public override QueryNode VisitSelectQuery(SelectQuery query)
        {
            // Calculate needed row buffers

            RowBufferCalculator rowBufferCalculator = query.RowBufferCalculator;

            // Emit FROM

            if (query.TableReferences != null)
            {
                Visit(query.TableReferences);
            }
            else
            {
                ConstantScanAlgebraNode constantScanAlgebraNode = new ConstantScanAlgebraNode();
                constantScanAlgebraNode.DefinedValues = new ComputedValueDefinition[0];
                SetLastAlgebraNode(constantScanAlgebraNode);
            }

            // Emit WHERE

            if (query.WhereClause != null)
            {
                FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                filterAlgebraNode.Input     = GetLastAlgebraNode();
                filterAlgebraNode.Predicate = query.WhereClause;
                SetLastAlgebraNode(filterAlgebraNode);
            }

            // Emit GROUP BY

            if (query.GroupByColumns != null || query.IsAggregated)
            {
                EmitComputeScalarIfNeeded(rowBufferCalculator.ComputedGroupColumns);

                List <AggregatedValueDefinition> definedValues = new List <AggregatedValueDefinition>();
                foreach (AggregateExpression aggregateDependency in query.AggregateDependencies)
                {
                    definedValues.Add(aggregateDependency.ValueDefinition);
                }

                if (query.GroupByColumns != null)
                {
                    SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
                    sortAlgebraNode.Input       = GetLastAlgebraNode();
                    sortAlgebraNode.SortEntries = rowBufferCalculator.GroupColumns;
                    sortAlgebraNode.SortOrders  = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);
                    SetLastAlgebraNode(sortAlgebraNode);
                }

                AggregateAlgebraNode algebraNode = new AggregateAlgebraNode();
                algebraNode.Input         = GetLastAlgebraNode();
                algebraNode.DefinedValues = definedValues.ToArray();
                algebraNode.Groups        = rowBufferCalculator.GroupColumns;
                SetLastAlgebraNode(algebraNode);
            }

            // Emit HAVING

            if (query.HavingClause != null)
            {
                FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                filterAlgebraNode.Input     = GetLastAlgebraNode();
                filterAlgebraNode.Predicate = query.HavingClause;
                SetLastAlgebraNode(filterAlgebraNode);
            }

            // Emit compute scalar to calculate expressions needed in SELECT and ORDER BY

            EmitComputeScalarIfNeeded(rowBufferCalculator.ComputedSelectAndOrderColumns);

            // Emit DISTINCT and ORDER BY

            if (query.IsDistinct && query.OrderByColumns != null)
            {
                List <RowBufferEntry> sortEntries   = new List <RowBufferEntry>();
                List <SortOrder>      sortOrderList = new List <SortOrder>();

                for (int i = 0; i < query.OrderByColumns.Length; i++)
                {
                    sortEntries.Add(rowBufferCalculator.OrderColumns[i]);
                    sortOrderList.Add(query.OrderByColumns[i].SortOrder);
                }

                foreach (RowBufferEntry selectColumn in rowBufferCalculator.SelectColumns)
                {
                    bool selectColumnMustBeSorted = !sortEntries.Contains(selectColumn);
                    if (selectColumnMustBeSorted)
                    {
                        sortEntries.Add(selectColumn);
                        sortOrderList.Add(SortOrder.Ascending);
                    }
                }

                SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
                sortAlgebraNode.Distinct    = true;
                sortAlgebraNode.Input       = GetLastAlgebraNode();
                sortAlgebraNode.SortEntries = sortEntries.ToArray();
                sortAlgebraNode.SortOrders  = sortOrderList.ToArray();

                SetLastAlgebraNode(sortAlgebraNode);
            }
            else
            {
                if (query.IsDistinct)
                {
                    SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
                    sortAlgebraNode.Distinct    = true;
                    sortAlgebraNode.Input       = GetLastAlgebraNode();
                    sortAlgebraNode.SortEntries = rowBufferCalculator.SelectColumns;
                    sortAlgebraNode.SortOrders  = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);
                    SetLastAlgebraNode(sortAlgebraNode);
                }

                if (query.OrderByColumns != null)
                {
                    List <SortOrder> sortOrderList = new List <SortOrder>();
                    foreach (OrderByColumn orderByColumn in query.OrderByColumns)
                    {
                        sortOrderList.Add(orderByColumn.SortOrder);
                    }

                    SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
                    sortAlgebraNode.Input       = GetLastAlgebraNode();
                    sortAlgebraNode.SortEntries = rowBufferCalculator.OrderColumns;
                    sortAlgebraNode.SortOrders  = sortOrderList.ToArray();
                    SetLastAlgebraNode(sortAlgebraNode);
                }
            }

            // Emit TOP

            if (query.TopClause != null)
            {
                TopAlgebraNode algebraNode = new TopAlgebraNode();
                algebraNode.Input = GetLastAlgebraNode();
                algebraNode.Limit = query.TopClause.Value;

                if (query.TopClause.WithTies)
                {
                    algebraNode.TieEntries = rowBufferCalculator.OrderColumns;
                }

                SetLastAlgebraNode(algebraNode);
            }

            // Emit select list

            List <string> columnNames = new List <string>();

            foreach (SelectColumn columnSource in query.SelectColumns)
            {
                if (columnSource.Alias != null)
                {
                    columnNames.Add(columnSource.Alias.Text);
                }
                else
                {
                    columnNames.Add(null);
                }
            }

            ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode();

            resultAlgebraNode.Input       = GetLastAlgebraNode();
            resultAlgebraNode.OutputList  = rowBufferCalculator.SelectColumns;
            resultAlgebraNode.ColumnNames = columnNames.ToArray();
            SetLastAlgebraNode(resultAlgebraNode);

            return(query);
        }
示例#26
0
		public virtual AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
		{
			node.Input = VisitAlgebraNode(node.Input);
			node.Predicate = VisitExpression(node.Predicate);

			return node;
		}
示例#27
0
        private AlgebraNode PushOverJoin(FilterAlgebraNode node)
        {
            JoinAlgebraNode inputNode = (JoinAlgebraNode)node.Input;

            // Get declared tables of left and right

            RowBufferEntry[] leftDefinedValues  = AstUtil.GetDefinedValueEntries(inputNode.Left);
            RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(inputNode.Right);

            // Obviously, we cannot merge the filter with the join if the join is an outer join
            // (since it would change the join's semantics).
            //
            // Another less obvious restriction is that we cannot merge a filter with the join if
            // the join has a passthru predicate. In case the passthru predicte evaluates to true
            // the filter would not be applied. However, we are allowed to push the filter the over
            // join.

            bool canMerge = inputNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin &&
                            inputNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
                            inputNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin &&
                            inputNode.PassthruPredicate == null;

            if (canMerge)
            {
                // We can merge the filter with the condition of the join.
                //
                // However, we have to make sure that the predicate does not reference the probe column.
                // Since not having a probe column is the most common case, we don't always split the
                // predicate into conjuncts.

                if (inputNode.ProbeBufferEntry == null || !ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(node.Predicate), inputNode.ProbeBufferEntry))
                {
                    // Either there is no probe column defined or the filter does not reference it. That means
                    // no splitting necessary, we can just merge the whole predicate with the join predicate.
                    inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, node.Predicate);
                    return(VisitAlgebraNode(inputNode));
                }
                else
                {
                    // Unfortunately, the filter references the probe column. Now let's check whether we can merge
                    // conjuncts of the predicate.

                    List <ExpressionNode> remainingAndParts = new List <ExpressionNode>();
                    List <ExpressionNode> mergableAndParts  = new List <ExpressionNode>();

                    foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
                    {
                        bool andPartReferencesProbeColumn = ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(andPart), inputNode.ProbeBufferEntry);

                        if (andPartReferencesProbeColumn)
                        {
                            remainingAndParts.Add(andPart);
                        }
                        else
                        {
                            mergableAndParts.Add(andPart);
                        }
                    }

                    if (mergableAndParts.Count > 0)
                    {
                        ExpressionNode combinedMergableAndParts = AstUtil.CombineConditions(LogicalOperator.And, mergableAndParts.ToArray());
                        inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, combinedMergableAndParts);
                        node.Predicate      = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);

                        if (node.Predicate == null)
                        {
                            return(VisitAlgebraNode(inputNode));
                        }
                    }
                }
            }
            else
            {
                // The condition cannot be merged. Now we try to push AND-parts over the join.

                List <ExpressionNode> leftAndParts      = new List <ExpressionNode>();
                List <ExpressionNode> rightAndParts     = new List <ExpressionNode>();
                List <ExpressionNode> remainingAndParts = new List <ExpressionNode>();

                foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
                {
                    bool andPartReferencesProbeColumn = inputNode.ProbeBufferEntry != null &&
                                                        ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(andPart), inputNode.ProbeBufferEntry);

                    if (!andPartReferencesProbeColumn && AstUtil.AllowsLeftPushOver(inputNode.Op) && AstUtil.ExpressionDoesNotReference(andPart, rightDefinedValues))
                    {
                        // The AND-part depends only on the LHS and the join is inner/left.
                        // So we are allowed to push this AND-part down.
                        leftAndParts.Add(andPart);
                    }
                    else if (!andPartReferencesProbeColumn && AstUtil.AllowsRightPushOver(inputNode.Op) && AstUtil.ExpressionDoesNotReference(andPart, leftDefinedValues))
                    {
                        // The AND-part depends only on the RHS and the join is inner/right.
                        // So we are allowed to push this AND-part down.
                        rightAndParts.Add(andPart);
                    }
                    else
                    {
                        remainingAndParts.Add(andPart);
                    }
                }

                if (leftAndParts.Count > 0)
                {
                    inputNode.Left = GetFilterFromAndParts(leftAndParts, inputNode.Left);
                }

                if (rightAndParts.Count > 0)
                {
                    inputNode.Right = GetFilterFromAndParts(rightAndParts, inputNode.Right);
                }

                node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
                if (node.Predicate == null)
                {
                    return(VisitAlgebraNode(inputNode));
                }
            }

            node.Input = VisitAlgebraNode(node.Input);
            return(node);
        }
示例#28
0
		public override TableReference VisitJoinedTableReference(JoinedTableReference node)
		{
			TableReference nonCteTableRef;
			if (IsTableReferenceToCurrentCommonTableBinding(node.Left))
				nonCteTableRef = node.Right;
			else if (IsTableReferenceToCurrentCommonTableBinding(node.Right))
				nonCteTableRef = node.Left;
			else
				nonCteTableRef = null;

			if (nonCteTableRef != null)
			{
				Debug.Assert(node.JoinType == JoinType.Inner);
				AlgebraNode algebrizedPath = ConvertAstNode(nonCteTableRef);
				SetLastAlgebraNode(algebrizedPath);

				if (node.Condition != null)
				{
					FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
					filterAlgebraNode.Input = GetLastAlgebraNode();
					filterAlgebraNode.Predicate = node.Condition;
					SetLastAlgebraNode(filterAlgebraNode);
				}
				return node;
			}

			JoinAlgebraNode algebraNode = new JoinAlgebraNode();
			algebraNode.Left = ConvertAstNode(node.Left);
			algebraNode.Right = ConvertAstNode(node.Right);
			algebraNode.Predicate = node.Condition;

			switch (node.JoinType)
			{
				case JoinType.Inner:
					algebraNode.Op = JoinAlgebraNode.JoinOperator.InnerJoin;
					break;
				case JoinType.LeftOuter:
					algebraNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin;
					break;
				case JoinType.RightOuter:
					algebraNode.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin;
					break;
				case JoinType.FullOuter:
					algebraNode.Op = JoinAlgebraNode.JoinOperator.FullOuterJoin;
					break;
			}

			SetLastAlgebraNode(algebraNode);
			return node;
		}
示例#29
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            node.Input = VisitAlgebraNode(node.Input);

            SetLastAlgebraNode(node.Input);
            _probingEnabledStack.Push(false);
            node.Predicate = VisitExpression(node.Predicate);
            _probingEnabledStack.Pop();

            node.Input = GetAndResetLastNode();
            return node;
        }
示例#30
0
 private AlgebraNode PushOverUnary(FilterAlgebraNode node)
 {
     UnaryAlgebraNode inputNode = (UnaryAlgebraNode) node.Input;
     node.Input = inputNode.Input;
     inputNode.Input = VisitAlgebraNode(node);
     return inputNode;
 }
示例#31
0
        public override ExpressionNode VisitBinaryExpression(BinaryExpression expression)
        {
            if (expression.Op != BinaryOperator.LogicalAnd &&
                expression.Op != BinaryOperator.LogicalOr)
            {
                return(base.VisitBinaryExpression(expression));
            }

            if (expression.Op == BinaryOperator.LogicalAnd)
            {
                // AND

                expression.Left  = VisitExpression(expression.Left);
                expression.Right = VisitExpression(expression.Right);

                return(expression);
            }
            else
            {
                // OR

                AlgebraNode input = GetAndResetLastNode();
                _probingEnabledStack.Push(false);

                List <ExpressionNode> scalarOrParts     = new List <ExpressionNode>();
                List <AlgebraNode>    algebrizedOrParts = new List <AlgebraNode>();
                foreach (ExpressionNode orPart in AstUtil.SplitCondition(LogicalOperator.Or, expression))
                {
                    if (!AstUtil.ContainsSubselect(orPart))
                    {
                        scalarOrParts.Add(orPart);
                    }
                    else
                    {
                        ExpressionNode    replacedOrPart    = VisitExpression(orPart);
                        FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                        filterAlgebraNode.Input     = GetAndResetLastNode();
                        filterAlgebraNode.Predicate = replacedOrPart;
                        algebrizedOrParts.Add(filterAlgebraNode);
                    }
                }

                if (scalarOrParts.Count > 0)
                {
                    FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                    filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.Or, scalarOrParts);
                    filterAlgebraNode.Input     = CreateConstantScan();
                    algebrizedOrParts.Insert(0, filterAlgebraNode);
                }

                _probingEnabledStack.Pop();

                ConcatAlgebraNode concat = new ConcatAlgebraNode();
                concat.DefinedValues = new UnitedValueDefinition[0];
                concat.Inputs        = algebrizedOrParts.ToArray();

                RowBufferEntry  probeColumn = CreateProbeColumn();
                JoinAlgebraNode leftSemiJoinBetweenInputAndConcat = new JoinAlgebraNode();
                leftSemiJoinBetweenInputAndConcat.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin;
                leftSemiJoinBetweenInputAndConcat.PassthruPredicate = CurrentPassthruPredicate;
                leftSemiJoinBetweenInputAndConcat.ProbeBufferEntry  = probeColumn;
                leftSemiJoinBetweenInputAndConcat.Left  = input;
                leftSemiJoinBetweenInputAndConcat.Right = concat;
                SetLastAlgebraNode(leftSemiJoinBetweenInputAndConcat);
                return(CreateProbeColumnRef(probeColumn));
            }
        }
示例#32
0
        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);
        }
示例#33
0
		public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
		{
			// Check if node only consists of INNER join nodes and simple table reference nodes.
			// This algorithm assumes that the table references have been lineraized so that
			//
			// - JoinedTableReference appear on the LHS only (the last one must be NamedTableReference ovbiviously)
			// - NamedTableReference appear on the RHS only
			//
			// While scanning the node's children we create a list of all JoinedTableReferences and
			// NamedTableReferences.

			InnerJoinTableExtractor innerJoinTableExtractor = new InnerJoinTableExtractor();
			innerJoinTableExtractor.Visit(node);

			if (!innerJoinTableExtractor.ConsistsOnlyOfInnerJoinsFiltersAndTables)
			{
				node.Left = VisitAlgebraNode(node.Left);
				node.Right = VisitAlgebraNode(node.Right);
				return node;                
			}
			else
			{
				TableAlgebraNode[] algebraNodes = innerJoinTableExtractor.GetTableNodes();
				Dictionary<TableRefBinding,TableAlgebraNode> tableRefToNodeDictionary = new Dictionary<TableRefBinding, TableAlgebraNode>();
				List<TableRefBinding> tableList = new List<TableRefBinding>();
				foreach (TableAlgebraNode algebraNode in algebraNodes)
				{
					tableRefToNodeDictionary.Add(algebraNode.TableRefBinding, algebraNode);
					tableList.Add(algebraNode.TableRefBinding);
				}

				// Create a mapping RowBufferEntry -> ColumnRefBinding

				Dictionary<RowBufferEntry, ColumnRefBinding> rowBufferColumnDictionary = new Dictionary<RowBufferEntry, ColumnRefBinding>();
				foreach (TableRefBinding tableRefBinding in tableList)
				{
					foreach (ColumnRefBinding columnRefBinding in tableRefBinding.ColumnRefs)
						rowBufferColumnDictionary.Add(columnRefBinding.ValueDefinition.Target, columnRefBinding);
				}

				// Create list of all possible join conditions and remaining AND-parts.

				List<JoinCondition> joinConditionList = new List<JoinCondition>();
				List<ExpressionNode> andPartList = new List<ExpressionNode>();

				ExpressionNode filter = AstUtil.CombineConditions(LogicalOperator.And, innerJoinTableExtractor.GetFilters());

				foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, filter))
				{
					JoinCondition joinCondition = ConvertToJoinCondition(rowBufferColumnDictionary, andPart);

					if (joinCondition != null)
						joinConditionList.Add(joinCondition);
					else
						andPartList.Add(andPart);
				}

				// After creating the list of all join conditions and AND-parts we have all we need to create
				// an optimimal join order between all tables of this part of the table tree.
				JoinOrder bestJoinOrder = GetBestJoinOrder(tableList.ToArray(), joinConditionList.ToArray(), andPartList.ToArray());

				// Get all tables that are introduced by this join order
                
				Dictionary<RowBufferEntry, ColumnValueDefinition> introducedColumns = GetIntroducedColumns(bestJoinOrder);

				// Combine AND-part list with all unused join conditions.

				andPartList.AddRange(bestJoinOrder.UnusedConditions);

				// Now we will re-create this part of the tree using the this join order.

				AlgebraNode lastAlgebraNode = null;
				for (int joinIndex = 0; joinIndex < bestJoinOrder.Joins.Length; joinIndex++)
				{
					Join join = bestJoinOrder.Joins[joinIndex];

					AlgebraNode tableInput;
					TableAlgebraNode tableNode = tableRefToNodeDictionary[join.TableRefBinding];

					ExpressionNode tableFilter = ExtractConditionsApplicableToTable(introducedColumns, andPartList, join.TableRefBinding);
					if (tableFilter == null)
					{
						tableInput = tableNode;
					}
					else
					{
						FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
						filterAlgebraNode.Input = tableNode;
						filterAlgebraNode.Predicate = tableFilter;
						tableInput = filterAlgebraNode;
					}

					if (lastAlgebraNode == null)
					{
						// This was the first one.
						lastAlgebraNode = tableInput;
					}
					else
					{
						// Not the first one, we can create a join with the current table reference
						// and last table reference.

						// Get all AND-parts that can be applied to the tables already joined.
						// This expression is merged to one condition.
						ExpressionNode[] applicableAndParts = GetAndPartsApplicableToJoin(introducedColumns, bestJoinOrder, joinIndex, andPartList, true);
						ExpressionNode condition = AstUtil.CombineConditions(LogicalOperator.And, applicableAndParts);

						ExpressionNode joinCondition;
						if (join.JoinCondition == null)
							joinCondition = null;
						else
							joinCondition = join.JoinCondition.ToExpression();

						ExpressionNode completeCondition = AstUtil.CombineConditions(LogicalOperator.And, condition, joinCondition);

						JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode();
						joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.InnerJoin;
						joinAlgebraNode.Left = lastAlgebraNode;
						joinAlgebraNode.Right = tableInput;
						joinAlgebraNode.Predicate = completeCondition;

						// Next time this newly created join is the last table reference.
						lastAlgebraNode = joinAlgebraNode;
					}
				}

				return lastAlgebraNode;
			}
		}
示例#34
0
		public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
		{
			node.Left = VisitAlgebraNode(node.Left);
			node.Right = VisitAlgebraNode(node.Right);
            
			// Get defined values of left and right

			RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left);
			RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right);
            
			List<ExpressionNode> andPartsWithinJoin = new List<ExpressionNode>();

			// Try to pull up AND-parts that contain outer references from a left sided filter and combine 
			// them with the join predicate.
			//
			// NOTE: This is only possible if the join is not a LEFT OUTER or FULL OUTER JOIN since this
			// operation would change the join's semantic.

			if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
			    node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin)
			{
				FilterAlgebraNode leftAsFilter = node.Left as FilterAlgebraNode;
				if (leftAsFilter != null)
				{
					List<ExpressionNode> remainingAndParts = new List<ExpressionNode>();
					foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, leftAsFilter.Predicate))
					{
						if (AndPartHasOuterReference(andPart, leftDefinedValues))
							andPartsWithinJoin.Add(andPart);
						else
							remainingAndParts.Add(andPart);
					}

					leftAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
					if (leftAsFilter.Predicate == null)
						node.Left = leftAsFilter.Input;
				}
			}

			// Try to pull up AND-parts that contain outer references from a right sided filter and combine 
			// them with the join predicate.
			//
			// NOTE: This is only possible if the join is not a RIGHT OUTER or FULL OUTER JOIN since this
			// operation would change the join's semantic.

			if (node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin &&
			    node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin)
			{
				FilterAlgebraNode rightAsFilter = node.Right as FilterAlgebraNode;
				if (rightAsFilter != null)
				{
					List<ExpressionNode> remainingAndParts = new List<ExpressionNode>();
					foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, rightAsFilter.Predicate))
					{
						if (AndPartHasOuterReference(andPart, rightDefinedValues))
							andPartsWithinJoin.Add(andPart);
						else 
							remainingAndParts.Add(andPart);
					}

					rightAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
					if (rightAsFilter.Predicate == null)
						node.Right = rightAsFilter.Input;
				}
			}

			// If we found any AND-parts that could be pulled up, merge them with the join predicate.

			if (andPartsWithinJoin.Count > 0)
				node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, node.Predicate, AstUtil.CombineConditions(LogicalOperator.And, andPartsWithinJoin));

			// Now we try to extract AND-parts that contain outer references from the join predicate itself.
			//
			// NOTE: This is only possible if the node is not an OUTER JOIN. If the node is a SEMI JOIN the
			// operation is only legal if the AND-part does not reference any columns from the side that is
			// is used as filter criteria (i.e. for LSJ this is the right side, for RSJ this is the left
			// side).

			if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
			    node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin &&
			    node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin &&
			    node.Predicate != null)
			{
				List<ExpressionNode> andPartsAboveJoin = new List<ExpressionNode>();
				List<ExpressionNode> remainingAndParts = new List<ExpressionNode>();

				foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
				{
					if (AndPartHasOuterReference(andPart, leftDefinedValues, rightDefinedValues) && 
						SemiJoinDoesNotDependOn(node.Op, andPart, leftDefinedValues, rightDefinedValues))
						andPartsAboveJoin.Add(andPart);
					else
						remainingAndParts.Add(andPart);
				}

				node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
                
				if (andPartsAboveJoin.Count > 0)
				{
					FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
					filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andPartsAboveJoin);
					filterAlgebraNode.Input = node;
					return filterAlgebraNode;
				}
			}
                                    
			return node;
		}
示例#35
0
        private AlgebraNode PushOverValueDefininingUnary(IEnumerable <ValueDefinition> definedValues, FilterAlgebraNode node)
        {
            UnaryAlgebraNode      inputNode            = (UnaryAlgebraNode)node.Input;
            List <ExpressionNode> nonDependingAndParts = new List <ExpressionNode>();
            List <ExpressionNode> dependingAndParts    = new List <ExpressionNode>();

            foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
            {
                RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart);

                bool dependsOnDefinedValue = false;
                foreach (ValueDefinition definedValue in definedValues)
                {
                    if (ArrayHelpers.Contains(rowBufferEntries, definedValue.Target))
                    {
                        dependsOnDefinedValue = true;
                        break;
                    }
                }

                if (dependsOnDefinedValue)
                {
                    dependingAndParts.Add(andPart);
                }
                else
                {
                    nonDependingAndParts.Add(andPart);
                }
            }

            if (nonDependingAndParts.Count > 0)
            {
                node.Predicate  = AstUtil.CombineConditions(LogicalOperator.And, dependingAndParts);
                inputNode.Input = GetFilterFromAndParts(nonDependingAndParts, inputNode.Input);

                if (node.Predicate == null)
                {
                    node.Input      = inputNode.Input;
                    inputNode.Input = VisitAlgebraNode(node);
                    return(inputNode);
                }
            }

            node.Input = VisitAlgebraNode(node.Input);
            return(node);
        }
示例#36
0
        public override ExpressionNode VisitAllAnySubselect(AllAnySubselect expression)
        {
            expression.Left = VisitExpression(expression.Left);
            ResultAlgebraNode algebrizedQuery = Algebrizer.Convert(expression.Query);

            ExpressionNode leftExpression = expression.Left;
            RowBufferEntryExpression rightExpression = new RowBufferEntryExpression();
            rightExpression.RowBufferEntry = algebrizedQuery.OutputList[0];

            ExpressionBuilder expressionBuilder = new ExpressionBuilder();
            expressionBuilder.Push(leftExpression);
            expressionBuilder.Push(rightExpression);
            expressionBuilder.PushBinary(expression.Op);

            bool negated = (expression.Type == AllAnySubselect.AllAnyType.All);
            if (negated)
            {
                expressionBuilder.PushUnary(UnaryOperator.LogicalNot);
                expressionBuilder.Push(leftExpression);
                expressionBuilder.PushIsNull();
                expressionBuilder.Push(rightExpression);
                expressionBuilder.PushIsNull();
                expressionBuilder.PushNAry(LogicalOperator.Or);
            }

            ExpressionNode filterPredicate = expressionBuilder.Pop();

            FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
            filterAlgebraNode.Input = algebrizedQuery;
            filterAlgebraNode.Predicate = filterPredicate;

            AlgebraNode input = GetAndResetLastNode();

            if (!negated && !ProbingEnabled && input == null)
            {
                SetLastAlgebraNode(filterAlgebraNode);
                return LiteralExpression.FromBoolean(true);
            }
            else
            {
                if (input == null)
                    input = CreateConstantScan();

                RowBufferEntry probeColumn = CreateProbeColumn();

                JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode();
                joinAlgebraNode.PassthruPredicate = CurrentPassthruPredicate;
                joinAlgebraNode.ProbeBufferEntry = probeColumn;
                joinAlgebraNode.Left = input;
                joinAlgebraNode.Right = filterAlgebraNode;
                joinAlgebraNode.Op = negated ? JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin : JoinAlgebraNode.JoinOperator.LeftSemiJoin;

                SetLastAlgebraNode(joinAlgebraNode);
                return CreateProbeColumnRef(probeColumn);
            }
        }
示例#37
0
		public override QueryNode VisitSelectQuery(SelectQuery query)
		{
			// Calculate needed row buffers

			RowBufferCalculator rowBufferCalculator = query.RowBufferCalculator;

			// Emit FROM

			if (query.TableReferences != null)
			{
				Visit(query.TableReferences);
			}
			else
			{
				ConstantScanAlgebraNode constantScanAlgebraNode = new ConstantScanAlgebraNode();
				constantScanAlgebraNode.DefinedValues = new ComputedValueDefinition[0];
				SetLastAlgebraNode(constantScanAlgebraNode);
			}

			// Emit WHERE

			if (query.WhereClause != null)
			{
				FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
				filterAlgebraNode.Input = GetLastAlgebraNode();
				filterAlgebraNode.Predicate = query.WhereClause;
				SetLastAlgebraNode(filterAlgebraNode);
			}

			// Emit GROUP BY

			if (query.GroupByColumns != null || query.IsAggregated)
			{
				EmitComputeScalarIfNeeded(rowBufferCalculator.ComputedGroupColumns);

				List<AggregatedValueDefinition> definedValues = new List<AggregatedValueDefinition>();
				foreach (AggregateExpression aggregateDependency in query.AggregateDependencies)
					definedValues.Add(aggregateDependency.ValueDefinition);

				if (query.GroupByColumns != null)
				{
					SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
					sortAlgebraNode.Input = GetLastAlgebraNode();
					sortAlgebraNode.SortEntries = rowBufferCalculator.GroupColumns;
					sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);
					SetLastAlgebraNode(sortAlgebraNode);
				}

				AggregateAlgebraNode algebraNode = new AggregateAlgebraNode();
				algebraNode.Input = GetLastAlgebraNode();
				algebraNode.DefinedValues = definedValues.ToArray();
				algebraNode.Groups = rowBufferCalculator.GroupColumns;
				SetLastAlgebraNode(algebraNode);
			}

			// Emit HAVING

			if (query.HavingClause != null)
			{
				FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
				filterAlgebraNode.Input = GetLastAlgebraNode();
				filterAlgebraNode.Predicate = query.HavingClause;
				SetLastAlgebraNode(filterAlgebraNode);
			}

			// Emit compute scalar to calculate expressions needed in SELECT and ORDER BY

			EmitComputeScalarIfNeeded(rowBufferCalculator.ComputedSelectAndOrderColumns);

			// Emit DISTINCT and ORDER BY

			if (query.IsDistinct && query.OrderByColumns != null)
			{
				List<RowBufferEntry> sortEntries = new List<RowBufferEntry>();
				List<SortOrder> sortOrderList = new List<SortOrder>();

				for (int i = 0; i < query.OrderByColumns.Length; i++)
				{
					sortEntries.Add(rowBufferCalculator.OrderColumns[i]);
					sortOrderList.Add(query.OrderByColumns[i].SortOrder);
				}

				foreach (RowBufferEntry selectColumn in rowBufferCalculator.SelectColumns)
				{
					bool selectColumnMustBeSorted = !sortEntries.Contains(selectColumn);
					if (selectColumnMustBeSorted)
					{
						sortEntries.Add(selectColumn);
						sortOrderList.Add(SortOrder.Ascending);
					}
				}

				SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
				sortAlgebraNode.Distinct = true;
				sortAlgebraNode.Input = GetLastAlgebraNode();
				sortAlgebraNode.SortEntries = sortEntries.ToArray();
				sortAlgebraNode.SortOrders = sortOrderList.ToArray();

				SetLastAlgebraNode(sortAlgebraNode);
			}
			else
			{
				if (query.IsDistinct)
				{
					SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
					sortAlgebraNode.Distinct = true;
					sortAlgebraNode.Input = GetLastAlgebraNode();
					sortAlgebraNode.SortEntries = rowBufferCalculator.SelectColumns;
					sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);
					SetLastAlgebraNode(sortAlgebraNode);
				}

				if (query.OrderByColumns != null)
				{
					List<SortOrder> sortOrderList = new List<SortOrder>();
					foreach (OrderByColumn orderByColumn in query.OrderByColumns)
						sortOrderList.Add(orderByColumn.SortOrder);

					SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
					sortAlgebraNode.Input = GetLastAlgebraNode();
					sortAlgebraNode.SortEntries = rowBufferCalculator.OrderColumns;
					sortAlgebraNode.SortOrders = sortOrderList.ToArray();
					SetLastAlgebraNode(sortAlgebraNode);
				}
			}

			// Emit TOP

			if (query.TopClause != null)
			{
				TopAlgebraNode algebraNode = new TopAlgebraNode();
				algebraNode.Input = GetLastAlgebraNode();
				algebraNode.Limit = query.TopClause.Value;

				if (query.TopClause.WithTies)
					algebraNode.TieEntries = rowBufferCalculator.OrderColumns;

				SetLastAlgebraNode(algebraNode);
			}

			// Emit select list

			List<string> columnNames = new List<string>();
			foreach (SelectColumn columnSource in query.SelectColumns)
			{
				if (columnSource.Alias != null)
					columnNames.Add(columnSource.Alias.Text);
				else
					columnNames.Add(null);
			}

			ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode();
			resultAlgebraNode.Input = GetLastAlgebraNode();
			resultAlgebraNode.OutputList = rowBufferCalculator.SelectColumns;
			resultAlgebraNode.ColumnNames = columnNames.ToArray();
			SetLastAlgebraNode(resultAlgebraNode);

			return query;
		}
示例#38
0
        private AlgebraNode PushOverValueDefininingUnary(IEnumerable<ValueDefinition> definedValues, FilterAlgebraNode node)
        {
            UnaryAlgebraNode inputNode = (UnaryAlgebraNode)node.Input;
            List<ExpressionNode> nonDependingAndParts = new List<ExpressionNode>();
            List<ExpressionNode> dependingAndParts = new List<ExpressionNode>();

            foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
            {
                RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart);

                bool dependsOnDefinedValue = false;
                foreach (ValueDefinition definedValue in definedValues)
                {
                    if (ArrayHelpers.Contains(rowBufferEntries, definedValue.Target))
                    {
                        dependsOnDefinedValue = true;
                        break;
                    }
                }

                if (dependsOnDefinedValue)
                    dependingAndParts.Add(andPart);
                else
                    nonDependingAndParts.Add(andPart);
            }

            if (nonDependingAndParts.Count > 0)
            {
                node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, dependingAndParts);
                inputNode.Input = GetFilterFromAndParts(nonDependingAndParts, inputNode.Input);

                if (node.Predicate == null)
                {
                    node.Input = inputNode.Input;
                    inputNode.Input = VisitAlgebraNode(node);
                    return inputNode;
                }
            }

            node.Input = VisitAlgebraNode(node.Input);
            return node;
        }
示例#39
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            if (node.Predicate == null || !AstUtil.ContainsSubselect(node.Predicate))
            {
                return(base.VisitJoinAlgebraNode(node));
            }

            node.Left  = VisitAlgebraNode(node.Left);
            node.Right = VisitAlgebraNode(node.Right);

            switch (node.Op)
            {
            case JoinAlgebraNode.JoinOperator.InnerJoin:
            {
                FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                filterAlgebraNode.Predicate = node.Predicate;
                filterAlgebraNode.Input     = node;
                node.Predicate = null;

                SetLastAlgebraNode(node);
                _probingEnabledStack.Push(false);
                filterAlgebraNode.Predicate = VisitExpression(filterAlgebraNode.Predicate);
                _probingEnabledStack.Pop();
                filterAlgebraNode.Input = GetAndResetLastNode();

                return(filterAlgebraNode);
            }

            case JoinAlgebraNode.JoinOperator.LeftOuterJoin:
            {
                FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                filterAlgebraNode.Predicate = node.Predicate;
                filterAlgebraNode.Input     = node.Right;

                node.Right     = filterAlgebraNode;
                node.Predicate = null;

                SetLastAlgebraNode(filterAlgebraNode.Input);
                _probingEnabledStack.Push(false);
                filterAlgebraNode.Predicate = VisitExpression(filterAlgebraNode.Predicate);
                _probingEnabledStack.Pop();
                filterAlgebraNode.Input = GetAndResetLastNode();

                return(node);
            }

            case JoinAlgebraNode.JoinOperator.RightOuterJoin:
            {
                node.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin;
                AlgebraNode oldLeft = node.Left;
                node.Left  = node.Right;
                node.Right = oldLeft;
                goto case JoinAlgebraNode.JoinOperator.LeftOuterJoin;
            }

            case JoinAlgebraNode.JoinOperator.FullOuterJoin:
                // TODO: Support subqueries in FULL OUTER JOIN.
                throw ExceptionBuilder.InternalError("FULL OUTER JOIN containing a subselect predicate in ON clause is not supported.");

            default:
                throw ExceptionBuilder.UnhandledCaseLabel(node.Op);
            }
        }
示例#40
0
 public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
 {
     node.Input = VisitAlgebraNode(node.Input);
     node.OutputList = node.Input.OutputList;
     return node;
 }
示例#41
0
        public override ExpressionNode VisitAllAnySubselect(AllAnySubselect expression)
        {
            expression.Left = VisitExpression(expression.Left);
            ResultAlgebraNode algebrizedQuery = Algebrizer.Convert(expression.Query);

            ExpressionNode           leftExpression  = expression.Left;
            RowBufferEntryExpression rightExpression = new RowBufferEntryExpression();

            rightExpression.RowBufferEntry = algebrizedQuery.OutputList[0];

            ExpressionBuilder expressionBuilder = new ExpressionBuilder();

            expressionBuilder.Push(leftExpression);
            expressionBuilder.Push(rightExpression);
            expressionBuilder.PushBinary(expression.Op);

            bool negated = (expression.Type == AllAnySubselect.AllAnyType.All);

            if (negated)
            {
                expressionBuilder.PushUnary(UnaryOperator.LogicalNot);
                expressionBuilder.Push(leftExpression);
                expressionBuilder.PushIsNull();
                expressionBuilder.Push(rightExpression);
                expressionBuilder.PushIsNull();
                expressionBuilder.PushNAry(LogicalOperator.Or);
            }

            ExpressionNode filterPredicate = expressionBuilder.Pop();

            FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();

            filterAlgebraNode.Input     = algebrizedQuery;
            filterAlgebraNode.Predicate = filterPredicate;

            AlgebraNode input = GetAndResetLastNode();

            if (!negated && !ProbingEnabled && input == null)
            {
                SetLastAlgebraNode(filterAlgebraNode);
                return(LiteralExpression.FromBoolean(true));
            }
            else
            {
                if (input == null)
                {
                    input = CreateConstantScan();
                }

                RowBufferEntry probeColumn = CreateProbeColumn();

                JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode();
                joinAlgebraNode.PassthruPredicate = CurrentPassthruPredicate;
                joinAlgebraNode.ProbeBufferEntry  = probeColumn;
                joinAlgebraNode.Left  = input;
                joinAlgebraNode.Right = filterAlgebraNode;
                joinAlgebraNode.Op    = negated ? JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin : JoinAlgebraNode.JoinOperator.LeftSemiJoin;

                SetLastAlgebraNode(joinAlgebraNode);
                return(CreateProbeColumnRef(probeColumn));
            }
        }
示例#42
0
 private static FilterAlgebraNode GetFilterFromAndParts(IList<ExpressionNode> andParts, AlgebraNode input)
 {
     FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
     filterAlgebraNode.Input = input;
     filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andParts);
     return filterAlgebraNode;
 }
示例#43
0
 public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
 {
     Visit(node.Input);
     _filters.Add(node.Predicate);
     return(node);
 }
示例#44
0
 public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
 {
     node.Input      = VisitAlgebraNode(node.Input);
     node.OutputList = node.Input.OutputList;
     return(node);
 }
示例#45
0
		public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
		{
			_xmlWriter.WriteStartElement("filterAlgebraNode");

			WriteAstNode("input", node.Input);
			WriteAstNode("predicate", node.Predicate);

			_xmlWriter.WriteEndElement();

			return node;
		}
示例#46
0
			public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
			{
				Visit(node.Input);
				_filters.Add(node.Predicate);
				return node;
			}
示例#47
0
        public override ExpressionNode VisitBinaryExpression(BinaryExpression expression)
        {
            if (expression.Op != BinaryOperator.LogicalAnd &&
                expression.Op != BinaryOperator.LogicalOr)
                return base.VisitBinaryExpression(expression);

            if (expression.Op == BinaryOperator.LogicalAnd)
            {
                // AND

                expression.Left = VisitExpression(expression.Left);
                expression.Right = VisitExpression(expression.Right);

                return expression;
            }
            else
            {
                // OR

                AlgebraNode input = GetAndResetLastNode();
                _probingEnabledStack.Push(false);

                List<ExpressionNode> scalarOrParts = new List<ExpressionNode>();
                List<AlgebraNode> algebrizedOrParts = new List<AlgebraNode>();
                foreach (ExpressionNode orPart in AstUtil.SplitCondition(LogicalOperator.Or, expression))
                {
                    if (!AstUtil.ContainsSubselect(orPart))
                    {
                        scalarOrParts.Add(orPart);
                    }
                    else
                    {
                        ExpressionNode replacedOrPart = VisitExpression(orPart);
                        FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                        filterAlgebraNode.Input = GetAndResetLastNode();
                        filterAlgebraNode.Predicate = replacedOrPart;
                        algebrizedOrParts.Add(filterAlgebraNode);
                    }
                }

                if (scalarOrParts.Count > 0)
                {
                    FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                    filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.Or, scalarOrParts);
                    filterAlgebraNode.Input = CreateConstantScan();
                    algebrizedOrParts.Insert(0, filterAlgebraNode);
                }

                _probingEnabledStack.Pop();

                ConcatAlgebraNode concat = new ConcatAlgebraNode();
                concat.DefinedValues = new UnitedValueDefinition[0];
                concat.Inputs = algebrizedOrParts.ToArray();

                RowBufferEntry probeColumn = CreateProbeColumn();
                JoinAlgebraNode leftSemiJoinBetweenInputAndConcat = new JoinAlgebraNode();
                leftSemiJoinBetweenInputAndConcat.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin;
                leftSemiJoinBetweenInputAndConcat.PassthruPredicate = CurrentPassthruPredicate;
                leftSemiJoinBetweenInputAndConcat.ProbeBufferEntry = probeColumn;
                leftSemiJoinBetweenInputAndConcat.Left = input;
                leftSemiJoinBetweenInputAndConcat.Right = concat;
                SetLastAlgebraNode(leftSemiJoinBetweenInputAndConcat);
                return CreateProbeColumnRef(probeColumn);
            }
        }
示例#48
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            node.Left  = VisitAlgebraNode(node.Left);
            node.Right = VisitAlgebraNode(node.Right);

            // Get defined values of left and right

            RowBufferEntry[] leftDefinedValues  = AstUtil.GetDefinedValueEntries(node.Left);
            RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right);

            List <ExpressionNode> andPartsWithinJoin = new List <ExpressionNode>();

            // Try to pull up AND-parts that contain outer references from a left sided filter and combine
            // them with the join predicate.
            //
            // NOTE: This is only possible if the join is not a LEFT OUTER or FULL OUTER JOIN since this
            // operation would change the join's semantic.

            if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
                node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin)
            {
                FilterAlgebraNode leftAsFilter = node.Left as FilterAlgebraNode;
                if (leftAsFilter != null)
                {
                    List <ExpressionNode> remainingAndParts = new List <ExpressionNode>();
                    foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, leftAsFilter.Predicate))
                    {
                        if (AndPartHasOuterReference(andPart, leftDefinedValues))
                        {
                            andPartsWithinJoin.Add(andPart);
                        }
                        else
                        {
                            remainingAndParts.Add(andPart);
                        }
                    }

                    leftAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
                    if (leftAsFilter.Predicate == null)
                    {
                        node.Left = leftAsFilter.Input;
                    }
                }
            }

            // Try to pull up AND-parts that contain outer references from a right sided filter and combine
            // them with the join predicate.
            //
            // NOTE: This is only possible if the join is not a RIGHT OUTER or FULL OUTER JOIN since this
            // operation would change the join's semantic.

            if (node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin &&
                node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin)
            {
                FilterAlgebraNode rightAsFilter = node.Right as FilterAlgebraNode;
                if (rightAsFilter != null)
                {
                    List <ExpressionNode> remainingAndParts = new List <ExpressionNode>();
                    foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, rightAsFilter.Predicate))
                    {
                        if (AndPartHasOuterReference(andPart, rightDefinedValues))
                        {
                            andPartsWithinJoin.Add(andPart);
                        }
                        else
                        {
                            remainingAndParts.Add(andPart);
                        }
                    }

                    rightAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
                    if (rightAsFilter.Predicate == null)
                    {
                        node.Right = rightAsFilter.Input;
                    }
                }
            }

            // If we found any AND-parts that could be pulled up, merge them with the join predicate.

            if (andPartsWithinJoin.Count > 0)
            {
                node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, node.Predicate, AstUtil.CombineConditions(LogicalOperator.And, andPartsWithinJoin));
            }

            // Now we try to extract AND-parts that contain outer references from the join predicate itself.
            //
            // NOTE: This is only possible if the node is not an OUTER JOIN. If the node is a SEMI JOIN the
            // operation is only legal if the AND-part does not reference any columns from the side that is
            // is used as filter criteria (i.e. for LSJ this is the right side, for RSJ this is the left
            // side).

            if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
                node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin &&
                node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin &&
                node.Predicate != null)
            {
                List <ExpressionNode> andPartsAboveJoin = new List <ExpressionNode>();
                List <ExpressionNode> remainingAndParts = new List <ExpressionNode>();

                foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
                {
                    if (AndPartHasOuterReference(andPart, leftDefinedValues, rightDefinedValues) &&
                        SemiJoinDoesNotDependOn(node.Op, andPart, leftDefinedValues, rightDefinedValues))
                    {
                        andPartsAboveJoin.Add(andPart);
                    }
                    else
                    {
                        remainingAndParts.Add(andPart);
                    }
                }

                node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);

                if (andPartsAboveJoin.Count > 0)
                {
                    FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                    filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andPartsAboveJoin);
                    filterAlgebraNode.Input     = node;
                    return(filterAlgebraNode);
                }
            }

            return(node);
        }
示例#49
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            if (node.Predicate == null || !AstUtil.ContainsSubselect(node.Predicate))
                return base.VisitJoinAlgebraNode(node);

            node.Left = VisitAlgebraNode(node.Left);
            node.Right = VisitAlgebraNode(node.Right);

            switch (node.Op)
            {
                case JoinAlgebraNode.JoinOperator.InnerJoin:
                {
                    FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                    filterAlgebraNode.Predicate = node.Predicate;
                    filterAlgebraNode.Input = node;
                    node.Predicate = null;

                    SetLastAlgebraNode(node);
                    _probingEnabledStack.Push(false);
                    filterAlgebraNode.Predicate = VisitExpression(filterAlgebraNode.Predicate);
                    _probingEnabledStack.Pop();
                    filterAlgebraNode.Input = GetAndResetLastNode();

                    return filterAlgebraNode;

                }

                case JoinAlgebraNode.JoinOperator.LeftOuterJoin:
                {
                    FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                    filterAlgebraNode.Predicate = node.Predicate;
                    filterAlgebraNode.Input = node.Right;

                    node.Right = filterAlgebraNode;
                    node.Predicate = null;

                    SetLastAlgebraNode(filterAlgebraNode.Input);
                    _probingEnabledStack.Push(false);
                    filterAlgebraNode.Predicate = VisitExpression(filterAlgebraNode.Predicate);
                    _probingEnabledStack.Pop();
                    filterAlgebraNode.Input = GetAndResetLastNode();

                    return node;
                }

                case JoinAlgebraNode.JoinOperator.RightOuterJoin:
                {
                    node.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin;
                    AlgebraNode oldLeft = node.Left;
                    node.Left = node.Right;
                    node.Right = oldLeft;
                    goto case JoinAlgebraNode.JoinOperator.LeftOuterJoin;
                }

                case JoinAlgebraNode.JoinOperator.FullOuterJoin:
                    // TODO: Support subqueries in FULL OUTER JOIN.
                    throw ExceptionBuilder.InternalError("FULL OUTER JOIN containing a subselect predicate in ON clause is not supported.");

                default:
                    throw ExceptionBuilder.UnhandledCaseLabel(node.Op);
            }
        }
示例#50
0
        private AlgebraNode MergeWithFilter(FilterAlgebraNode node)
        {
            // The input is also a filter, so we can merge this predicate with
            // the input filter.

            FilterAlgebraNode inputNode = (FilterAlgebraNode) node.Input;
            inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, node.Predicate);
            return VisitAlgebraNode(inputNode);
        }
示例#51
0
		public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
		{
			node.Input = VisitAlgebraNode(node.Input);

			ConstantExpression predicateAsConstant = node.Predicate as ConstantExpression;
			if (predicateAsConstant != null)
			{
				if (predicateAsConstant.AsBoolean)
					return node.Input;
				else
					return CreateNullScan(node.OutputList);
			}

			return NullScanIfInputIsNullScan(node);
		}
示例#52
0
 private AlgebraNode PushOverAggregate(FilterAlgebraNode node)
 {
     // TODO: It is not that easy.
     //       For example this condition can be pushed 'GroupCol = Value' while this can't: 'GroupCol = Value OR Func(const) = const'
     //       Formally, a predicate can be pushed over an aggregate if and only if all disjuncts of the predicate's CNF do reference
     //       at least one grouping column.
     //       Since this requires cloning of the predicate and heavy rewriting this is not done (yet).
     return base.VisitFilterAlgebraNode(node);
     /*
     // Predicates can be pushed over an aggregation if it does not contain any aggregate function.
     AggregateAlgebraNode inputNode = (AggregateAlgebraNode)node.Input;
     return PushOverValueDefininingUnary(inputNode.DefinedValues, node);
     */
 }
示例#53
0
        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);
        }
示例#54
0
        private AlgebraNode PushOverConcat(FilterAlgebraNode node)
        {
            ConcatAlgebraNode inputNode = (ConcatAlgebraNode) node.Input;

            for (int i = 0; i < inputNode.Inputs.Length; i++)
            {
                ExpressionNode predicate = (ExpressionNode)node.Predicate.Clone();
                ConcatRowBufferEntryReplacer concatRowBufferEntryReplacer = new ConcatRowBufferEntryReplacer(inputNode.DefinedValues, i);
                predicate = concatRowBufferEntryReplacer.VisitExpression(predicate);

                FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                filterAlgebraNode.Input = inputNode.Inputs[i];
                filterAlgebraNode.Predicate = predicate;
                inputNode.Inputs[i] = VisitAlgebraNode(filterAlgebraNode);
            }

            return inputNode;
        }
示例#55
0
		public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
		{
			FilterIterator filterIterator = new FilterIterator();
			filterIterator.RowBuffer = new object[node.OutputList.Length];
			filterIterator.Input = ConvertAlgebraNode(node.Input);
			filterIterator.InputOutput = GetIteratorOutput(0, node.Input.OutputList, node.OutputList);
			BoundRowBufferEntrySet boundRowBufferEntrySet = new BoundRowBufferEntrySet(filterIterator.Input.RowBuffer, node.Input.OutputList);
			filterIterator.Predicate = CreateRuntimeExpression(node.Predicate, boundRowBufferEntrySet);
			SetLastIterator(node, filterIterator);

			return node;
		}
示例#56
0
        private AlgebraNode PushOverJoin(FilterAlgebraNode node)
        {
            JoinAlgebraNode inputNode = (JoinAlgebraNode) node.Input;

            // Get declared tables of left and right

            RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(inputNode.Left);
            RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(inputNode.Right);

            // Obviously, we cannot merge the filter with the join if the join is an outer join
            // (since it would change the join's semantics).
            //
            // Another less obvious restriction is that we cannot merge a filter with the join if
            // the join has a passthru predicate. In case the passthru predicte evaluates to true
            // the filter would not be applied. However, we are allowed to push the filter the over
            // join.

            bool canMerge = inputNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin &&
                            inputNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
                            inputNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin &&
                            inputNode.PassthruPredicate == null;

            if (canMerge)
            {
                // We can merge the filter with the condition of the join.
                //
                // However, we have to make sure that the predicate does not reference the probe column.
                // Since not having a probe column is the most common case, we don't always split the
                // predicate into conjuncts.

                if (inputNode.ProbeBufferEntry == null || !ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(node.Predicate), inputNode.ProbeBufferEntry))
                {
                    // Either there is no probe column defined or the filter does not reference it. That means
                    // no splitting necessary, we can just merge the whole predicate with the join predicate.
                    inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, node.Predicate);
                    return VisitAlgebraNode(inputNode);
                }
                else
                {
                    // Unfortunately, the filter references the probe column. Now let's check whether we can merge
                    // conjuncts of the predicate.

                    List<ExpressionNode> remainingAndParts = new List<ExpressionNode>();
                    List<ExpressionNode> mergableAndParts = new List<ExpressionNode>();

                    foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
                    {
                        bool andPartReferencesProbeColumn = ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(andPart), inputNode.ProbeBufferEntry);

                        if (andPartReferencesProbeColumn)
                            remainingAndParts.Add(andPart);
                        else
                            mergableAndParts.Add(andPart);
                    }

                    if (mergableAndParts.Count > 0)
                    {
                        ExpressionNode combinedMergableAndParts = AstUtil.CombineConditions(LogicalOperator.And, mergableAndParts.ToArray());
                        inputNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, inputNode.Predicate, combinedMergableAndParts);
                        node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);

                        if (node.Predicate == null)
                            return VisitAlgebraNode(inputNode);
                    }
                }
            }
            else
            {
                // The condition cannot be merged. Now we try to push AND-parts over the join.

                List<ExpressionNode> leftAndParts = new List<ExpressionNode>();
                List<ExpressionNode> rightAndParts = new List<ExpressionNode>();
                List<ExpressionNode> remainingAndParts = new List<ExpressionNode>();

                foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate))
                {
                    bool andPartReferencesProbeColumn = inputNode.ProbeBufferEntry != null &&
                                                        ArrayHelpers.Contains(AstUtil.GetRowBufferEntryReferences(andPart), inputNode.ProbeBufferEntry);

                    if (!andPartReferencesProbeColumn && AstUtil.AllowsLeftPushOver(inputNode.Op) && AstUtil.ExpressionDoesNotReference(andPart, rightDefinedValues))
                    {
                        // The AND-part depends only on the LHS and the join is inner/left.
                        // So we are allowed to push this AND-part down.
                        leftAndParts.Add(andPart);
                    }
                    else if (!andPartReferencesProbeColumn && AstUtil.AllowsRightPushOver(inputNode.Op) && AstUtil.ExpressionDoesNotReference(andPart, leftDefinedValues))
                    {
                        // The AND-part depends only on the RHS and the join is inner/right.
                        // So we are allowed to push this AND-part down.
                        rightAndParts.Add(andPart);
                    }
                    else
                    {
                        remainingAndParts.Add(andPart);
                    }
                }

                if (leftAndParts.Count > 0)
                {
                    inputNode.Left = GetFilterFromAndParts(leftAndParts, inputNode.Left);
                }

                if (rightAndParts.Count > 0)
                {
                    inputNode.Right = GetFilterFromAndParts(rightAndParts, inputNode.Right);
                }

                node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts);
                if (node.Predicate == null)
                    return VisitAlgebraNode(inputNode);
            }

            node.Input = VisitAlgebraNode(node.Input);
            return node;
        }
示例#57
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            // Check if node only consists of INNER join nodes and simple table reference nodes.
            // This algorithm assumes that the table references have been lineraized so that
            //
            // - JoinedTableReference appear on the LHS only (the last one must be NamedTableReference ovbiviously)
            // - NamedTableReference appear on the RHS only
            //
            // While scanning the node's children we create a list of all JoinedTableReferences and
            // NamedTableReferences.

            InnerJoinTableExtractor innerJoinTableExtractor = new InnerJoinTableExtractor();

            innerJoinTableExtractor.Visit(node);

            if (!innerJoinTableExtractor.ConsistsOnlyOfInnerJoinsFiltersAndTables)
            {
                node.Left  = VisitAlgebraNode(node.Left);
                node.Right = VisitAlgebraNode(node.Right);
                return(node);
            }
            else
            {
                TableAlgebraNode[] algebraNodes = innerJoinTableExtractor.GetTableNodes();
                Dictionary <TableRefBinding, TableAlgebraNode> tableRefToNodeDictionary = new Dictionary <TableRefBinding, TableAlgebraNode>();
                List <TableRefBinding> tableList = new List <TableRefBinding>();
                foreach (TableAlgebraNode algebraNode in algebraNodes)
                {
                    tableRefToNodeDictionary.Add(algebraNode.TableRefBinding, algebraNode);
                    tableList.Add(algebraNode.TableRefBinding);
                }

                // Create a mapping RowBufferEntry -> ColumnRefBinding

                Dictionary <RowBufferEntry, ColumnRefBinding> rowBufferColumnDictionary = new Dictionary <RowBufferEntry, ColumnRefBinding>();
                foreach (TableRefBinding tableRefBinding in tableList)
                {
                    foreach (ColumnRefBinding columnRefBinding in tableRefBinding.ColumnRefs)
                    {
                        rowBufferColumnDictionary.Add(columnRefBinding.ValueDefinition.Target, columnRefBinding);
                    }
                }

                // Create list of all possible join conditions and remaining AND-parts.

                List <JoinCondition>  joinConditionList = new List <JoinCondition>();
                List <ExpressionNode> andPartList       = new List <ExpressionNode>();

                ExpressionNode filter = AstUtil.CombineConditions(LogicalOperator.And, innerJoinTableExtractor.GetFilters());

                foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, filter))
                {
                    JoinCondition joinCondition = ConvertToJoinCondition(rowBufferColumnDictionary, andPart);

                    if (joinCondition != null)
                    {
                        joinConditionList.Add(joinCondition);
                    }
                    else
                    {
                        andPartList.Add(andPart);
                    }
                }

                // After creating the list of all join conditions and AND-parts we have all we need to create
                // an optimimal join order between all tables of this part of the table tree.
                JoinOrder bestJoinOrder = GetBestJoinOrder(tableList.ToArray(), joinConditionList.ToArray(), andPartList.ToArray());

                // Get all tables that are introduced by this join order

                Dictionary <RowBufferEntry, ColumnValueDefinition> introducedColumns = GetIntroducedColumns(bestJoinOrder);

                // Combine AND-part list with all unused join conditions.

                andPartList.AddRange(bestJoinOrder.UnusedConditions);

                // Now we will re-create this part of the tree using the this join order.

                AlgebraNode lastAlgebraNode = null;
                for (int joinIndex = 0; joinIndex < bestJoinOrder.Joins.Length; joinIndex++)
                {
                    Join join = bestJoinOrder.Joins[joinIndex];

                    AlgebraNode      tableInput;
                    TableAlgebraNode tableNode = tableRefToNodeDictionary[join.TableRefBinding];

                    ExpressionNode tableFilter = ExtractConditionsApplicableToTable(introducedColumns, andPartList, join.TableRefBinding);
                    if (tableFilter == null)
                    {
                        tableInput = tableNode;
                    }
                    else
                    {
                        FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode();
                        filterAlgebraNode.Input     = tableNode;
                        filterAlgebraNode.Predicate = tableFilter;
                        tableInput = filterAlgebraNode;
                    }

                    if (lastAlgebraNode == null)
                    {
                        // This was the first one.
                        lastAlgebraNode = tableInput;
                    }
                    else
                    {
                        // Not the first one, we can create a join with the current table reference
                        // and last table reference.

                        // Get all AND-parts that can be applied to the tables already joined.
                        // This expression is merged to one condition.
                        ExpressionNode[] applicableAndParts = GetAndPartsApplicableToJoin(introducedColumns, bestJoinOrder, joinIndex, andPartList, true);
                        ExpressionNode   condition          = AstUtil.CombineConditions(LogicalOperator.And, applicableAndParts);

                        ExpressionNode joinCondition;
                        if (join.JoinCondition == null)
                        {
                            joinCondition = null;
                        }
                        else
                        {
                            joinCondition = join.JoinCondition.ToExpression();
                        }

                        ExpressionNode completeCondition = AstUtil.CombineConditions(LogicalOperator.And, condition, joinCondition);

                        JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode();
                        joinAlgebraNode.Op        = JoinAlgebraNode.JoinOperator.InnerJoin;
                        joinAlgebraNode.Left      = lastAlgebraNode;
                        joinAlgebraNode.Right     = tableInput;
                        joinAlgebraNode.Predicate = completeCondition;

                        // Next time this newly created join is the last table reference.
                        lastAlgebraNode = joinAlgebraNode;
                    }
                }

                return(lastAlgebraNode);
            }
        }
示例#58
0
        public override AlgebraNode VisitFilterAlgebraNode(FilterAlgebraNode node)
        {
            ShowPlanElement inputElement = ConvertNode(node.Input);

            PropertyListBuilder propertyListBuilder = new PropertyListBuilder();
            AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOutputList, node.OutputList);
            AddStatistics(propertyListBuilder, node.StatisticsIterator);

            propertyListBuilder.Write(Resources.ShowPlanKeyPredicate, node.Predicate.GenerateSource());

            IList<ShowPlanProperty> properties = propertyListBuilder.ToList();

            ShowPlanElement element = new ShowPlanElement(ShowPlanOperator.Filter, properties, inputElement);
            _currentElement = element;

            return node;
        }