Exemple #1
0
        public static ExpressionNode CombineConditions(LogicalOperator logicalOperator, IList <ExpressionNode> conditions)
        {
            if (conditions == null || conditions.Count == 0)
            {
                return(null);
            }

            ExpressionBuilder expressionBuilder = new ExpressionBuilder();

            foreach (ExpressionNode condition in conditions)
            {
                if (condition != null)
                {
                    expressionBuilder.Push(condition);
                }
            }

            if (expressionBuilder.Count == 0)
            {
                return(null);
            }

            expressionBuilder.PushNAry(logicalOperator);
            return(expressionBuilder.Pop());
        }
        private void SetWhenPassthru(ICollection <ExpressionNode> processedWhenExpressions)
        {
            if (processedWhenExpressions.Count == 0)
            {
                _currentPassthruPredicate = null;
            }
            else
            {
                foreach (ExpressionNode processedWhenExpression in processedWhenExpressions)
                {
                    ExpressionNode clonedExpr = (ExpressionNode)processedWhenExpression.Clone();
                    _expressionBuilder.Push(clonedExpr);
                }

                _expressionBuilder.PushNAry(LogicalOperator.Or);
                _currentPassthruPredicate = _expressionBuilder.Pop();
            }
        }
Exemple #3
0
		public static ExpressionNode CombineConditions(LogicalOperator logicalOperator, IList<ExpressionNode> conditions)
		{
			if (conditions == null || conditions.Count == 0)
				return null;

			ExpressionBuilder expressionBuilder = new ExpressionBuilder();
			foreach (ExpressionNode condition in conditions)
			{
				if (condition != null)
					expressionBuilder.Push(condition);
			}

			if (expressionBuilder.Count == 0)
				return null;

			expressionBuilder.PushNAry(logicalOperator);
			return expressionBuilder.Pop();
		}
Exemple #4
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);
            }
        }
Exemple #5
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;
        }
Exemple #6
0
        public override QueryNode VisitBinaryQuery(BinaryQuery query)
        {
            switch (query.Op)
            {
            case BinaryQueryOperator.Intersect:
            case BinaryQueryOperator.Except:
            {
                ResultAlgebraNode left  = ((ResultAlgebraNode)ConvertAstNode(query.Left));
                ResultAlgebraNode right = ((ResultAlgebraNode)ConvertAstNode(query.Right));

                // Create distinct sort

                SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
                sortAlgebraNode.Distinct    = true;
                sortAlgebraNode.Input       = left;
                sortAlgebraNode.SortEntries = left.OutputList;
                sortAlgebraNode.SortOrders  = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);

                // Insert left (anti) semi join to (except) intersect left and right.

                ExpressionBuilder expressionBuilder = new ExpressionBuilder();
                for (int i = 0; i < left.OutputList.Length; i++)
                {
                    RowBufferEntryExpression leftExpr = new RowBufferEntryExpression();
                    leftExpr.RowBufferEntry = left.OutputList[i];

                    RowBufferEntryExpression rightExpr = new RowBufferEntryExpression();
                    rightExpr.RowBufferEntry = right.OutputList[i];

                    expressionBuilder.Push(leftExpr);
                    expressionBuilder.Push(rightExpr);
                    expressionBuilder.PushBinary(BinaryOperator.Equal);
                    expressionBuilder.Push(leftExpr);
                    expressionBuilder.PushIsNull();
                    expressionBuilder.Push(rightExpr);
                    expressionBuilder.PushIsNull();
                    expressionBuilder.PushBinary(BinaryOperator.LogicalAnd);
                    expressionBuilder.PushBinary(BinaryOperator.LogicalOr);
                }
                expressionBuilder.PushNAry(LogicalOperator.And);
                ExpressionNode joinCondition = expressionBuilder.Pop();

                JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode();
                if (query.Op == BinaryQueryOperator.Intersect)
                {
                    joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin;
                }
                else
                {
                    joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin;
                }
                joinAlgebraNode.Left      = sortAlgebraNode;
                joinAlgebraNode.Right     = right;
                joinAlgebraNode.Predicate = joinCondition;
                SetLastAlgebraNode(joinAlgebraNode);

                ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode();
                resultAlgebraNode.Input       = GetLastAlgebraNode();
                resultAlgebraNode.OutputList  = left.OutputList;
                resultAlgebraNode.ColumnNames = left.ColumnNames;
                SetLastAlgebraNode(resultAlgebraNode);
                break;
            }

            case BinaryQueryOperator.Union:
            case BinaryQueryOperator.UnionAll:
            {
                // Build a flat list with all inputs.

                List <QueryNode> inputList = AstUtil.FlattenBinaryQuery(query);

                AlgebraNode[] inputs = new AlgebraNode[inputList.Count];
                for (int i = 0; i < inputs.Length; i++)
                {
                    inputs[i] = ConvertAstNode(inputList[i]);
                }

                int outputColumnCount = inputs[0].OutputList.Length;

                UnitedValueDefinition[] definedValues       = new UnitedValueDefinition[outputColumnCount];
                List <RowBufferEntry>   definedValueEntries = new List <RowBufferEntry>();

                for (int i = 0; i < outputColumnCount; i++)
                {
                    RowBufferEntry rowBufferEntry = new RowBufferEntry(inputs[0].OutputList[i].DataType);
                    definedValueEntries.Add(rowBufferEntry);

                    UnitedValueDefinition definedValue = new UnitedValueDefinition();
                    definedValue.Target = rowBufferEntry;

                    List <RowBufferEntry> dependencies = new List <RowBufferEntry>();
                    foreach (ResultAlgebraNode node in inputs)
                    {
                        dependencies.Add(node.OutputList[i]);
                    }
                    definedValue.DependendEntries = dependencies.ToArray();

                    definedValues[i] = definedValue;
                }

                ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
                concatAlgebraNode.Inputs        = inputs;
                concatAlgebraNode.DefinedValues = definedValues;
                SetLastAlgebraNode(concatAlgebraNode);

                if (query.Op == BinaryQueryOperator.Union)
                {
                    SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
                    sortAlgebraNode.Distinct    = true;
                    sortAlgebraNode.Input       = GetLastAlgebraNode();
                    sortAlgebraNode.SortEntries = definedValueEntries.ToArray();
                    sortAlgebraNode.SortOrders  = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);
                    SetLastAlgebraNode(sortAlgebraNode);
                }

                ResultAlgebraNode unionResultAlgebraNode = new ResultAlgebraNode();
                unionResultAlgebraNode.Input       = GetLastAlgebraNode();
                unionResultAlgebraNode.ColumnNames = ((ResultAlgebraNode)inputs[0]).ColumnNames;
                unionResultAlgebraNode.OutputList  = definedValueEntries.ToArray();
                SetLastAlgebraNode(unionResultAlgebraNode);

                break;
            }
            }

            return(query);
        }
Exemple #7
0
        private static AlgebraNode AlgebrizeRecursiveCte(CommonTableBinding commonTableBinding)
        {
            // It is a recursive query.
            //
            // Create row buffer entry that is used to guard the recursion and the primary table spool
            // that spools the results needed by nested recursion calls.

            ExpressionBuilder            expressionBuilder = new ExpressionBuilder();
            StackedTableSpoolAlgebraNode primaryTableSpool = new StackedTableSpoolAlgebraNode();

            RowBufferEntry anchorRecursionLevel;

            RowBufferEntry[] anchorOutput;
            AlgebraNode      anchorNode;

            #region Anchor member
            {
                // Emit anchor member.

                AlgebraNode algebrizedAnchor = Convert(commonTableBinding.AnchorMember);

                // Emit compute scalar that initializes the recursion level to 0.

                anchorRecursionLevel = new RowBufferEntry(typeof(int));
                ComputedValueDefinition computedValueDefinition1 = new ComputedValueDefinition();
                computedValueDefinition1.Target     = anchorRecursionLevel;
                computedValueDefinition1.Expression = LiteralExpression.FromInt32(0);

                ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                computeScalarAlgebraNode.Input         = algebrizedAnchor;
                computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { computedValueDefinition1 };

                anchorOutput = algebrizedAnchor.OutputList;
                anchorNode   = computeScalarAlgebraNode;
            }
            #endregion

            RowBufferEntry   incrementedRecursionLevel;
            RowBufferEntry[] tableSpoolOutput;
            AlgebraNode      tableSpoolNode;

            #region Table spool
            {
                // Emit table spool reference.

                RowBufferEntry recursionLevelRefEntry = new RowBufferEntry(typeof(int));
                tableSpoolOutput = new RowBufferEntry[anchorOutput.Length];
                for (int i = 0; i < tableSpoolOutput.Length; i++)
                {
                    tableSpoolOutput[i] = new RowBufferEntry(anchorOutput[i].DataType);
                }

                StackedTableSpoolRefAlgebraNode tableSpoolReference = new StackedTableSpoolRefAlgebraNode();
                tableSpoolReference.PrimarySpool  = primaryTableSpool;
                tableSpoolReference.DefinedValues = ArrayHelpers.JoinArrays(new RowBufferEntry[] { recursionLevelRefEntry }, tableSpoolOutput);

                // Emit compute scalar that increases the recursion level by one and renames
                // columns from the spool to the CTE column buffer entries.

                expressionBuilder.Push(new RowBufferEntryExpression(recursionLevelRefEntry));
                expressionBuilder.Push(LiteralExpression.FromInt32(1));
                expressionBuilder.PushBinary(BinaryOperator.Add);

                incrementedRecursionLevel = new RowBufferEntry(typeof(int));
                ComputedValueDefinition incremenedRecLevelValueDefinition = new ComputedValueDefinition();
                incremenedRecLevelValueDefinition.Target     = incrementedRecursionLevel;
                incremenedRecLevelValueDefinition.Expression = expressionBuilder.Pop();

                CteColumnMappingFinder cteColumnMappingFinder = new CteColumnMappingFinder(commonTableBinding, tableSpoolOutput);
                foreach (QueryNode recursiveMember in commonTableBinding.RecursiveMembers)
                {
                    cteColumnMappingFinder.Visit(recursiveMember);
                }

                CteColumnMapping[] cteColumnMappings = cteColumnMappingFinder.GetMappings();

                List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>();
                definedValues.Add(incremenedRecLevelValueDefinition);
                foreach (CteColumnMapping cteColumnMapping in cteColumnMappings)
                {
                    ComputedValueDefinition definedValue = new ComputedValueDefinition();
                    definedValue.Target     = cteColumnMapping.VirtualBufferEntry;
                    definedValue.Expression = new RowBufferEntryExpression(cteColumnMapping.SpoolBufferEntry);
                    definedValues.Add(definedValue);
                }

                ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                computeScalarAlgebraNode.Input         = tableSpoolReference;
                computeScalarAlgebraNode.DefinedValues = definedValues.ToArray();

                tableSpoolNode = computeScalarAlgebraNode;
            }
            #endregion

            RowBufferEntry[] recursiveOutput;
            AlgebraNode      recursiveNode;

            #region Recursive member(s)
            {
                // Emit all recursive parts. The join conditions to the recursive part are replaced by simple filters
                // in the nested Convert() call.

                ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
                concatAlgebraNode.Inputs = new AlgebraNode[commonTableBinding.RecursiveMembers.Length];
                for (int i = 0; i < commonTableBinding.RecursiveMembers.Length; i++)
                {
                    concatAlgebraNode.Inputs[i] = Convert(commonTableBinding, commonTableBinding.RecursiveMembers[i]);
                }

                concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length];
                for (int i = 0; i < anchorOutput.Length; i++)
                {
                    List <RowBufferEntry> dependencies = new List <RowBufferEntry>();
                    foreach (ResultAlgebraNode algebrizedRecursivePart in concatAlgebraNode.Inputs)
                    {
                        dependencies.Add(algebrizedRecursivePart.OutputList[i]);
                    }

                    concatAlgebraNode.DefinedValues[i]                  = new UnitedValueDefinition();
                    concatAlgebraNode.DefinedValues[i].Target           = new RowBufferEntry(anchorOutput[i].DataType);
                    concatAlgebraNode.DefinedValues[i].DependendEntries = dependencies.ToArray();
                }

                // Calculate the recursive output.

                recursiveOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length];
                for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++)
                {
                    recursiveOutput[i] = concatAlgebraNode.DefinedValues[i].Target;
                }

                // Emit cross join

                JoinAlgebraNode crossJoinNode = new JoinAlgebraNode();
                crossJoinNode.Left  = tableSpoolNode;
                crossJoinNode.Right = concatAlgebraNode;

                // Emit assert that ensures that the recursion level is <= 100.

                expressionBuilder.Push(new RowBufferEntryExpression(incrementedRecursionLevel));
                expressionBuilder.Push(LiteralExpression.FromInt32(100));
                expressionBuilder.PushBinary(BinaryOperator.Greater);

                CaseExpression caseExpression = new CaseExpression();
                caseExpression.WhenExpressions    = new ExpressionNode[1];
                caseExpression.WhenExpressions[0] = expressionBuilder.Pop();
                caseExpression.ThenExpressions    = new ExpressionNode[1];
                caseExpression.ThenExpressions[0] = LiteralExpression.FromInt32(0);

                AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode();
                assertAlgebraNode.Input         = crossJoinNode;
                assertAlgebraNode.AssertionType = AssertionType.BelowRecursionLimit;
                assertAlgebraNode.Predicate     = caseExpression;

                recursiveNode = assertAlgebraNode;
            }
            #endregion

            RowBufferEntry[] algebrizedOutput;
            AlgebraNode      algebrizedCte;

            #region Combination
            {
                // Create concat node to combine anchor and recursive part.

                ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
                concatAlgebraNode.Inputs    = new AlgebraNode[2];
                concatAlgebraNode.Inputs[0] = anchorNode;
                concatAlgebraNode.Inputs[1] = recursiveNode;

                concatAlgebraNode.DefinedValues                     = new UnitedValueDefinition[anchorOutput.Length + 1];
                concatAlgebraNode.DefinedValues[0]                  = new UnitedValueDefinition();
                concatAlgebraNode.DefinedValues[0].Target           = new RowBufferEntry(anchorRecursionLevel.DataType);
                concatAlgebraNode.DefinedValues[0].DependendEntries = new RowBufferEntry[] { anchorRecursionLevel, incrementedRecursionLevel };

                for (int i = 0; i < anchorOutput.Length; i++)
                {
                    concatAlgebraNode.DefinedValues[i + 1]                  = new UnitedValueDefinition();
                    concatAlgebraNode.DefinedValues[i + 1].Target           = new RowBufferEntry(anchorOutput[i].DataType);
                    concatAlgebraNode.DefinedValues[i + 1].DependendEntries = new RowBufferEntry[] { anchorOutput[i], recursiveOutput[i] };
                }

                algebrizedOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length];
                for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++)
                {
                    algebrizedOutput[i] = concatAlgebraNode.DefinedValues[i].Target;
                }

                // Assign the combination as the input to the primray spool

                primaryTableSpool.Input = concatAlgebraNode;

                // The primary spool represents the result of the "inlined" CTE.

                algebrizedCte = primaryTableSpool;
            }
            #endregion

            algebrizedCte.OutputList = algebrizedOutput;
            return(algebrizedCte);
        }
        public override 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));
            }
        }
        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);
        }
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            node.Left = VisitAlgebraNode(node.Left);
            node.Right = VisitAlgebraNode(node.Right);

            if (node.Predicate != null &&
                (node.OuterReferences == null || node.OuterReferences.Length == 0) &&
                (
                    node.Op == JoinAlgebraNode.JoinOperator.InnerJoin ||
                    node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin ||
                    node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin ||
                    node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin)
                )
            {
                RowBufferEntry[] leftDefinedEntries = AstUtil.GetDefinedValueEntries(node.Left);
                RowBufferEntry[] rightDefinedEntries = AstUtil.GetDefinedValueEntries(node.Right);

                EqualPredicatesExtractor equalPredicatesExtractor = new EqualPredicatesExtractor(leftDefinedEntries, rightDefinedEntries);
                ExpressionNode probeResidual = equalPredicatesExtractor.VisitExpression(node.Predicate);
                BinaryExpression[] equalPredicates = equalPredicatesExtractor.GetEqualPredicates();

                if (equalPredicates.Length > 0)
                {
                    BinaryExpression equalPredicate = equalPredicates[0];

                    ExpressionBuilder expressionBuilder = new ExpressionBuilder();
                    expressionBuilder.Push(probeResidual);

                    if (equalPredicates.Length > 1)
                    {
                        for (int i = 1; i < equalPredicates.Length; i++)
                            expressionBuilder.Push(equalPredicates[i]);
                        expressionBuilder.PushNAry(LogicalOperator.And);
                    }

                    probeResidual = expressionBuilder.Pop();
                    if (probeResidual is ConstantExpression)
                        probeResidual = null;

                    AlgebraNode leftInput = node.Left;
                    AlgebraNode rightInput = node.Right;

                    if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin)
                    {
                        node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin;
                        leftInput = node.Right;
                        rightInput = node.Left;
                        ExpressionNode oldLeft = equalPredicate.Left;
                        equalPredicate.Left = equalPredicate.Right;
                        equalPredicate.Right = oldLeft;
                    }

                    RowBufferEntry leftEntry;
                    RowBufferEntryExpression leftAsRowBufferEntryExpression = equalPredicate.Left as RowBufferEntryExpression;
                    if (leftAsRowBufferEntryExpression != null)
                    {
                        leftEntry = leftAsRowBufferEntryExpression.RowBufferEntry;
                    }
                    else
                    {
                        leftEntry = new RowBufferEntry(equalPredicate.Left.ExpressionType);
                        ComputedValueDefinition definedValue = new ComputedValueDefinition();
                        definedValue.Target = leftEntry;
                        definedValue.Expression = equalPredicate.Left;

                        ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                        computeScalarAlgebraNode.Input = leftInput;
                        computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] {definedValue};
                        leftInput = computeScalarAlgebraNode;
                    }

                    RowBufferEntry rightEntry;
                    RowBufferEntryExpression rightAsRowBufferEntryExpression = equalPredicate.Right as RowBufferEntryExpression;
                    if (rightAsRowBufferEntryExpression != null)
                    {
                        rightEntry = rightAsRowBufferEntryExpression.RowBufferEntry;
                    }
                    else
                    {
                        rightEntry = new RowBufferEntry(equalPredicate.Right.ExpressionType);
                        ComputedValueDefinition definedValue = new ComputedValueDefinition();
                        definedValue.Target = rightEntry;
                        definedValue.Expression = equalPredicate.Right;

                        ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                        computeScalarAlgebraNode.Input = rightInput;
                        computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] {definedValue};
                        rightInput = computeScalarAlgebraNode;
                    }

                    HashMatchAlgebraNode hashMatchAlgebraNode = new HashMatchAlgebraNode();
                    hashMatchAlgebraNode.Op = node.Op;
                    hashMatchAlgebraNode.Left = leftInput;
                    hashMatchAlgebraNode.Right = rightInput;
                    hashMatchAlgebraNode.BuildKeyEntry = leftEntry;
                    hashMatchAlgebraNode.ProbeEntry = rightEntry;
                    hashMatchAlgebraNode.ProbeResidual = probeResidual;
                    return hashMatchAlgebraNode;
                }
            }

            return node;
        }
Exemple #11
0
        public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node)
        {
            node.Left  = VisitAlgebraNode(node.Left);
            node.Right = VisitAlgebraNode(node.Right);

            if (node.Predicate != null &&
                (node.OuterReferences == null || node.OuterReferences.Length == 0) &&
                (
                    node.Op == JoinAlgebraNode.JoinOperator.InnerJoin ||
                    node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin ||
                    node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin ||
                    node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin)
                )
            {
                RowBufferEntry[] leftDefinedEntries  = AstUtil.GetDefinedValueEntries(node.Left);
                RowBufferEntry[] rightDefinedEntries = AstUtil.GetDefinedValueEntries(node.Right);

                EqualPredicatesExtractor equalPredicatesExtractor = new EqualPredicatesExtractor(leftDefinedEntries, rightDefinedEntries);
                ExpressionNode           probeResidual            = equalPredicatesExtractor.VisitExpression(node.Predicate);
                BinaryExpression[]       equalPredicates          = equalPredicatesExtractor.GetEqualPredicates();

                if (equalPredicates.Length > 0)
                {
                    BinaryExpression equalPredicate = equalPredicates[0];

                    ExpressionBuilder expressionBuilder = new ExpressionBuilder();
                    expressionBuilder.Push(probeResidual);

                    if (equalPredicates.Length > 1)
                    {
                        for (int i = 1; i < equalPredicates.Length; i++)
                        {
                            expressionBuilder.Push(equalPredicates[i]);
                        }
                        expressionBuilder.PushNAry(LogicalOperator.And);
                    }

                    probeResidual = expressionBuilder.Pop();
                    if (probeResidual is ConstantExpression)
                    {
                        probeResidual = null;
                    }

                    AlgebraNode leftInput  = node.Left;
                    AlgebraNode rightInput = node.Right;

                    if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin)
                    {
                        node.Op    = JoinAlgebraNode.JoinOperator.RightOuterJoin;
                        leftInput  = node.Right;
                        rightInput = node.Left;
                        ExpressionNode oldLeft = equalPredicate.Left;
                        equalPredicate.Left  = equalPredicate.Right;
                        equalPredicate.Right = oldLeft;
                    }

                    RowBufferEntry           leftEntry;
                    RowBufferEntryExpression leftAsRowBufferEntryExpression = equalPredicate.Left as RowBufferEntryExpression;
                    if (leftAsRowBufferEntryExpression != null)
                    {
                        leftEntry = leftAsRowBufferEntryExpression.RowBufferEntry;
                    }
                    else
                    {
                        leftEntry = new RowBufferEntry(equalPredicate.Left.ExpressionType);
                        ComputedValueDefinition definedValue = new ComputedValueDefinition();
                        definedValue.Target     = leftEntry;
                        definedValue.Expression = equalPredicate.Left;

                        ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                        computeScalarAlgebraNode.Input         = leftInput;
                        computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue };
                        leftInput = computeScalarAlgebraNode;
                    }

                    RowBufferEntry           rightEntry;
                    RowBufferEntryExpression rightAsRowBufferEntryExpression = equalPredicate.Right as RowBufferEntryExpression;
                    if (rightAsRowBufferEntryExpression != null)
                    {
                        rightEntry = rightAsRowBufferEntryExpression.RowBufferEntry;
                    }
                    else
                    {
                        rightEntry = new RowBufferEntry(equalPredicate.Right.ExpressionType);
                        ComputedValueDefinition definedValue = new ComputedValueDefinition();
                        definedValue.Target     = rightEntry;
                        definedValue.Expression = equalPredicate.Right;

                        ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
                        computeScalarAlgebraNode.Input         = rightInput;
                        computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue };
                        rightInput = computeScalarAlgebraNode;
                    }

                    HashMatchAlgebraNode hashMatchAlgebraNode = new HashMatchAlgebraNode();
                    hashMatchAlgebraNode.Op            = node.Op;
                    hashMatchAlgebraNode.Left          = leftInput;
                    hashMatchAlgebraNode.Right         = rightInput;
                    hashMatchAlgebraNode.BuildKeyEntry = leftEntry;
                    hashMatchAlgebraNode.ProbeEntry    = rightEntry;
                    hashMatchAlgebraNode.ProbeResidual = probeResidual;
                    return(hashMatchAlgebraNode);
                }
            }

            return(node);
        }
Exemple #12
0
		public override QueryNode VisitBinaryQuery(BinaryQuery query)
		{
			switch (query.Op)
			{
				case BinaryQueryOperator.Intersect:
				case BinaryQueryOperator.Except:
				{
					ResultAlgebraNode left = ((ResultAlgebraNode)ConvertAstNode(query.Left));
					ResultAlgebraNode right = ((ResultAlgebraNode)ConvertAstNode(query.Right));

					// Create distinct sort

					SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
					sortAlgebraNode.Distinct = true;
					sortAlgebraNode.Input = left;
					sortAlgebraNode.SortEntries = left.OutputList;
					sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);

					// Insert left (anti) semi join to (except) intersect left and right.

					ExpressionBuilder expressionBuilder = new ExpressionBuilder();
					for (int i = 0; i < left.OutputList.Length; i++)
					{
						RowBufferEntryExpression leftExpr = new RowBufferEntryExpression();
						leftExpr.RowBufferEntry = left.OutputList[i];

						RowBufferEntryExpression rightExpr = new RowBufferEntryExpression();
						rightExpr.RowBufferEntry = right.OutputList[i];

						expressionBuilder.Push(leftExpr);
						expressionBuilder.Push(rightExpr);
						expressionBuilder.PushBinary(BinaryOperator.Equal);
						expressionBuilder.Push(leftExpr);
						expressionBuilder.PushIsNull();
						expressionBuilder.Push(rightExpr);
						expressionBuilder.PushIsNull();
						expressionBuilder.PushBinary(BinaryOperator.LogicalAnd);
						expressionBuilder.PushBinary(BinaryOperator.LogicalOr);
					}
					expressionBuilder.PushNAry(LogicalOperator.And);
					ExpressionNode joinCondition = expressionBuilder.Pop();

					JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode();
					if (query.Op == BinaryQueryOperator.Intersect)
						joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin;
					else
						joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin;
					joinAlgebraNode.Left = sortAlgebraNode;
					joinAlgebraNode.Right = right;
					joinAlgebraNode.Predicate = joinCondition;
					SetLastAlgebraNode(joinAlgebraNode);

					ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode();
					resultAlgebraNode.Input = GetLastAlgebraNode();
					resultAlgebraNode.OutputList = left.OutputList;
					resultAlgebraNode.ColumnNames = left.ColumnNames;
					SetLastAlgebraNode(resultAlgebraNode);
					break;
				}

				case BinaryQueryOperator.Union:
				case BinaryQueryOperator.UnionAll:
				{
					// Build a flat list with all inputs.

					List<QueryNode> inputList = AstUtil.FlattenBinaryQuery(query);

					AlgebraNode[] inputs = new AlgebraNode[inputList.Count];
					for (int i = 0; i < inputs.Length; i++)
						inputs[i] = ConvertAstNode(inputList[i]);

					int outputColumnCount = inputs[0].OutputList.Length;

					UnitedValueDefinition[] definedValues = new UnitedValueDefinition[outputColumnCount];
					List<RowBufferEntry> definedValueEntries = new List<RowBufferEntry>();

					for (int i = 0; i < outputColumnCount; i++)
					{
						RowBufferEntry rowBufferEntry = new RowBufferEntry(inputs[0].OutputList[i].DataType);
						definedValueEntries.Add(rowBufferEntry);

						UnitedValueDefinition definedValue = new UnitedValueDefinition();
						definedValue.Target = rowBufferEntry;

						List<RowBufferEntry> dependencies = new List<RowBufferEntry>();
						foreach (ResultAlgebraNode node in inputs)
							dependencies.Add(node.OutputList[i]);
						definedValue.DependendEntries = dependencies.ToArray();

						definedValues[i] = definedValue;
					}

					ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
					concatAlgebraNode.Inputs = inputs;
					concatAlgebraNode.DefinedValues = definedValues;
					SetLastAlgebraNode(concatAlgebraNode);

					if (query.Op == BinaryQueryOperator.Union)
					{
						SortAlgebraNode sortAlgebraNode = new SortAlgebraNode();
						sortAlgebraNode.Distinct = true;
						sortAlgebraNode.Input = GetLastAlgebraNode();
						sortAlgebraNode.SortEntries = definedValueEntries.ToArray();
						sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length);
						SetLastAlgebraNode(sortAlgebraNode);
					}

					ResultAlgebraNode unionResultAlgebraNode = new ResultAlgebraNode();
					unionResultAlgebraNode.Input = GetLastAlgebraNode();
					unionResultAlgebraNode.ColumnNames = ((ResultAlgebraNode)inputs[0]).ColumnNames;
					unionResultAlgebraNode.OutputList = definedValueEntries.ToArray();
					SetLastAlgebraNode(unionResultAlgebraNode);

					break;
				}
			}

			return query;
		}
Exemple #13
0
		private static AlgebraNode AlgebrizeRecursiveCte(CommonTableBinding commonTableBinding)
		{
			// It is a recursive query.
			//
			// Create row buffer entry that is used to guard the recursion and the primary table spool
			// that spools the results needed by nested recursion calls.

			ExpressionBuilder expressionBuilder = new ExpressionBuilder();
			StackedTableSpoolAlgebraNode primaryTableSpool = new StackedTableSpoolAlgebraNode();

			RowBufferEntry anchorRecursionLevel;
			RowBufferEntry[] anchorOutput;
			AlgebraNode anchorNode;

			#region Anchor member
			{
				// Emit anchor member.

				AlgebraNode algebrizedAnchor = Convert(commonTableBinding.AnchorMember);

				// Emit compute scalar that initializes the recursion level to 0.

				anchorRecursionLevel = new RowBufferEntry(typeof(int));
				ComputedValueDefinition computedValueDefinition1 = new ComputedValueDefinition();
				computedValueDefinition1.Target = anchorRecursionLevel;
				computedValueDefinition1.Expression = LiteralExpression.FromInt32(0);

				ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
				computeScalarAlgebraNode.Input = algebrizedAnchor;
				computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { computedValueDefinition1 };

				anchorOutput = algebrizedAnchor.OutputList;
				anchorNode = computeScalarAlgebraNode;
			}
			#endregion

			RowBufferEntry incrementedRecursionLevel;
			RowBufferEntry[] tableSpoolOutput;
			AlgebraNode tableSpoolNode;

			#region Table spool
			{
				// Emit table spool reference.

				RowBufferEntry recursionLevelRefEntry = new RowBufferEntry(typeof(int));
				tableSpoolOutput = new RowBufferEntry[anchorOutput.Length];
				for (int i = 0; i < tableSpoolOutput.Length; i++)
					tableSpoolOutput[i] = new RowBufferEntry(anchorOutput[i].DataType);

				StackedTableSpoolRefAlgebraNode tableSpoolReference = new StackedTableSpoolRefAlgebraNode();
				tableSpoolReference.PrimarySpool = primaryTableSpool;
				tableSpoolReference.DefinedValues = ArrayHelpers.JoinArrays(new RowBufferEntry[] { recursionLevelRefEntry }, tableSpoolOutput);

				// Emit compute scalar that increases the recursion level by one and renames
				// columns from the spool to the CTE column buffer entries.

				expressionBuilder.Push(new RowBufferEntryExpression(recursionLevelRefEntry));
				expressionBuilder.Push(LiteralExpression.FromInt32(1));
				expressionBuilder.PushBinary(BinaryOperator.Add);

				incrementedRecursionLevel = new RowBufferEntry(typeof(int));
				ComputedValueDefinition incremenedRecLevelValueDefinition = new ComputedValueDefinition();
				incremenedRecLevelValueDefinition.Target = incrementedRecursionLevel;
				incremenedRecLevelValueDefinition.Expression = expressionBuilder.Pop();

				CteColumnMappingFinder cteColumnMappingFinder = new CteColumnMappingFinder(commonTableBinding, tableSpoolOutput);
				foreach (QueryNode recursiveMember in commonTableBinding.RecursiveMembers)
					cteColumnMappingFinder.Visit(recursiveMember);

				CteColumnMapping[] cteColumnMappings = cteColumnMappingFinder.GetMappings();

				List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>();
				definedValues.Add(incremenedRecLevelValueDefinition);
				foreach (CteColumnMapping cteColumnMapping in cteColumnMappings)
				{
					ComputedValueDefinition definedValue = new ComputedValueDefinition();
					definedValue.Target = cteColumnMapping.VirtualBufferEntry;
					definedValue.Expression = new RowBufferEntryExpression(cteColumnMapping.SpoolBufferEntry);
					definedValues.Add(definedValue);
				}

				ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
				computeScalarAlgebraNode.Input = tableSpoolReference;
				computeScalarAlgebraNode.DefinedValues = definedValues.ToArray();

				tableSpoolNode = computeScalarAlgebraNode;
			}
			#endregion

			RowBufferEntry[] recursiveOutput;
			AlgebraNode recursiveNode;

			#region Recursive member(s)
			{
				// Emit all recursive parts. The join conditions to the recursive part are replaced by simple filters
				// in the nested Convert() call.

				ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
				concatAlgebraNode.Inputs = new AlgebraNode[commonTableBinding.RecursiveMembers.Length];
				for (int i = 0; i < commonTableBinding.RecursiveMembers.Length; i++)
					concatAlgebraNode.Inputs[i] = Convert(commonTableBinding, commonTableBinding.RecursiveMembers[i]);

				concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length];
				for (int i = 0; i < anchorOutput.Length; i++)
				{
					List<RowBufferEntry> dependencies = new List<RowBufferEntry>();
					foreach (ResultAlgebraNode algebrizedRecursivePart in concatAlgebraNode.Inputs)
						dependencies.Add(algebrizedRecursivePart.OutputList[i]);

					concatAlgebraNode.DefinedValues[i] = new UnitedValueDefinition();
					concatAlgebraNode.DefinedValues[i].Target = new RowBufferEntry(anchorOutput[i].DataType);
					concatAlgebraNode.DefinedValues[i].DependendEntries = dependencies.ToArray();
				}

				// Calculate the recursive output.

				recursiveOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length];
				for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++)
					recursiveOutput[i] = concatAlgebraNode.DefinedValues[i].Target;

				// Emit cross join

				JoinAlgebraNode crossJoinNode = new JoinAlgebraNode();
				crossJoinNode.Left = tableSpoolNode;
				crossJoinNode.Right = concatAlgebraNode;

				// Emit assert that ensures that the recursion level is <= 100.

				expressionBuilder.Push(new RowBufferEntryExpression(incrementedRecursionLevel));
				expressionBuilder.Push(LiteralExpression.FromInt32(100));
				expressionBuilder.PushBinary(BinaryOperator.Greater);

				CaseExpression caseExpression = new CaseExpression();
				caseExpression.WhenExpressions = new ExpressionNode[1];
				caseExpression.WhenExpressions[0] = expressionBuilder.Pop();
				caseExpression.ThenExpressions = new ExpressionNode[1];
				caseExpression.ThenExpressions[0] = LiteralExpression.FromInt32(0);

				AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode();
				assertAlgebraNode.Input = crossJoinNode;
				assertAlgebraNode.AssertionType = AssertionType.BelowRecursionLimit;
				assertAlgebraNode.Predicate = caseExpression;

				recursiveNode = assertAlgebraNode;
			}
			#endregion

			RowBufferEntry[] algebrizedOutput;
			AlgebraNode algebrizedCte;

			#region Combination
			{
				// Create concat node to combine anchor and recursive part.

				ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode();
				concatAlgebraNode.Inputs = new AlgebraNode[2];
				concatAlgebraNode.Inputs[0] = anchorNode;
				concatAlgebraNode.Inputs[1] = recursiveNode;

				concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length + 1];
				concatAlgebraNode.DefinedValues[0] = new UnitedValueDefinition();
				concatAlgebraNode.DefinedValues[0].Target = new RowBufferEntry(anchorRecursionLevel.DataType);
				concatAlgebraNode.DefinedValues[0].DependendEntries = new RowBufferEntry[] { anchorRecursionLevel, incrementedRecursionLevel };

				for (int i = 0; i < anchorOutput.Length; i++)
				{
					concatAlgebraNode.DefinedValues[i + 1] = new UnitedValueDefinition();
					concatAlgebraNode.DefinedValues[i + 1].Target = new RowBufferEntry(anchorOutput[i].DataType);
					concatAlgebraNode.DefinedValues[i + 1].DependendEntries = new RowBufferEntry[] { anchorOutput[i], recursiveOutput[i] };
				}

				algebrizedOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length];
				for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++)
					algebrizedOutput[i] = concatAlgebraNode.DefinedValues[i].Target;

				// Assign the combination as the input to the primray spool

				primaryTableSpool.Input = concatAlgebraNode;

				// The primary spool represents the result of the "inlined" CTE.

				algebrizedCte = primaryTableSpool;
			}
			#endregion

			algebrizedCte.OutputList = algebrizedOutput;
			return algebrizedCte;
		}