예제 #1
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            // Reorder
            //
            // A LSJ (B LOJ C)      --->    (A LOJ C) LSJ B     (LOJ has no join condition and C produces at most one row)

            if (node.Op == JoinAlgebraNode.JoinOperator.LeftSemiJoin ||
                node.Op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin)
            {
                JoinAlgebraNode rightChildJoin = node.Right as JoinAlgebraNode;

                if (rightChildJoin != null &&
                    rightChildJoin.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin &&
                    rightChildJoin.Predicate == null &&
                    AstUtil.WillProduceAtMostOneRow(rightChildJoin.Right))
                {
                    node.Right          = rightChildJoin.Left;
                    rightChildJoin.Left = node.Left;
                    node.Left           = rightChildJoin;
                    return(VisitAlgebraNode(node));
                }
            }

            node.Left  = VisitAlgebraNode(node.Left);
            node.Right = VisitAlgebraNode(node.Right);
            return(node);
        }
예제 #2
0
        private AlgebraNode ReturnInputIfItProducesJustOneRow(UnaryAlgebraNode node)
        {
            node.Input = VisitAlgebraNode(node.Input);

            if (AstUtil.WillProduceAtMostOneRow(node.Input))
            {
                return(node.Input);
            }

            return(node);
        }
예제 #3
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            ShowPlanElement leftElement  = ConvertNode(node.Left);
            ShowPlanElement rightElement = ConvertNode(node.Right);

            PropertyListBuilder propertyListBuilder = new PropertyListBuilder();

            AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOutputList, node.OutputList);
            propertyListBuilder.Write(Resources.ShowPlanKeyLogicalOperator, LogicalOperatorToString(node.Op));
            AddStatistics(propertyListBuilder, node.StatisticsIterator);

            if (node.Predicate != null)
            {
                propertyListBuilder.Write(Resources.ShowPlanKeyPredicate, node.Predicate.GenerateSource());
            }

            if (node.OuterReferences != null && node.OuterReferences.Length > 0)
            {
                AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOuterReferences, node.OuterReferences);
            }

            if (node.ProbeBufferEntry != null)
            {
                WriteRowBufferEntry(propertyListBuilder, Resources.ShowPlanKeyProbeColumn, node.ProbeBufferEntry);
            }

            if (node.PassthruPredicate != null)
            {
                propertyListBuilder.Write(Resources.ShowPlanKeyPassthru, node.PassthruPredicate.GenerateSource());
            }

            // We give a warning if a join has no predicate and no outer reference.
            // In this case the join would simply multiply the other side.
            // However, we supppress the warning if any side is known at produce at
            // most one row.
            if (node.Predicate == null &&
                (node.OuterReferences == null || node.OuterReferences.Length == 0) &&
                !AstUtil.WillProduceAtMostOneRow(node.Left) &&
                !AstUtil.WillProduceAtMostOneRow(node.Right))
            {
                propertyListBuilder.Write(Resources.ShowPlanKeyWarning, Resources.ShowPlanWarningNoJoinPredicate);
            }

            IList <ShowPlanProperty> properties = propertyListBuilder.ToList();
            ShowPlanElement          element    = new ShowPlanElement(ShowPlanOperator.NestedLoops, properties, leftElement, rightElement);

            _currentElement = element;

            return(node);
        }
예제 #4
0
        private static ResultAlgebraNode CreateAssertedSubquery(ResultAlgebraNode inputNode)
        {
            if (AstUtil.WillProduceAtMostOneRow(inputNode))
            {
                return(inputNode);
            }

            RowBufferEntry inputEntry = inputNode.OutputList[0];

            AggregatedValueDefinition countDefinedValue = new AggregatedValueDefinition();

            countDefinedValue.Aggregate  = new CountAggregateBinding("COUNT");
            countDefinedValue.Aggregator = countDefinedValue.Aggregate.CreateAggregator(typeof(int));
            countDefinedValue.Argument   = LiteralExpression.FromInt32(0);

            RowBufferEntry countDefinedValueEntry = new RowBufferEntry(countDefinedValue.Aggregator.ReturnType);

            countDefinedValue.Target = countDefinedValueEntry;

            RowBufferEntryExpression anyAggregateArgument = new RowBufferEntryExpression();

            anyAggregateArgument.RowBufferEntry = inputEntry;

            AggregatedValueDefinition anyDefinedValue = new AggregatedValueDefinition();

            anyDefinedValue.Aggregate  = new FirstAggregateBinding("ANY");
            anyDefinedValue.Aggregator = anyDefinedValue.Aggregate.CreateAggregator(inputEntry.DataType);
            anyDefinedValue.Argument   = anyAggregateArgument;

            RowBufferEntry anyDefinedValueEntry = new RowBufferEntry(inputEntry.DataType);

            anyDefinedValue.Target = anyDefinedValueEntry;

            AggregateAlgebraNode aggregateAlgebraNode = new AggregateAlgebraNode();

            aggregateAlgebraNode.Input         = inputNode.Input;
            aggregateAlgebraNode.DefinedValues = new AggregatedValueDefinition[] { countDefinedValue, anyDefinedValue };

            // CASE WHEN SubqueryCount > 1 THEN 0 ELSE NULL END

            ExpressionBuilder expressionBuilder = new ExpressionBuilder();

            expressionBuilder.Push(new RowBufferEntryExpression(countDefinedValueEntry));
            expressionBuilder.Push(LiteralExpression.FromInt32(1));
            expressionBuilder.PushBinary(BinaryOperator.Greater);
            ExpressionNode whenExpression = expressionBuilder.Pop();
            ExpressionNode thenExpression = LiteralExpression.FromInt32(0);

            CaseExpression caseExpression = new CaseExpression();

            caseExpression.WhenExpressions = new ExpressionNode[] { whenExpression };
            caseExpression.ThenExpressions = new ExpressionNode[] { thenExpression };

            expressionBuilder.Push(caseExpression);
            ExpressionNode predicate = expressionBuilder.Pop();

            AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode();

            assertAlgebraNode.Input         = aggregateAlgebraNode;
            assertAlgebraNode.Predicate     = predicate;
            assertAlgebraNode.AssertionType = AssertionType.MaxOneRow;

            ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode();

            resultAlgebraNode.Input       = assertAlgebraNode;
            resultAlgebraNode.OutputList  = new RowBufferEntry[] { anyDefinedValueEntry };
            resultAlgebraNode.ColumnNames = inputNode.ColumnNames;

            return(resultAlgebraNode);
        }