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); }
private AlgebraNode ReturnInputIfItProducesJustOneRow(UnaryAlgebraNode node) { node.Input = VisitAlgebraNode(node.Input); if (AstUtil.WillProduceAtMostOneRow(node.Input)) { return(node.Input); } return(node); }
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); }
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); }