Exemple #1
0
        public CommonTableBinding DeclareCommonTableExpression(Identifier identifier, QueryNode anchorMember)
        {
            CommonTableBinding derivedTableBinding = new CommonTableBinding(identifier.Text, anchorMember);

            _commonTables.Add(derivedTableBinding);
            return(derivedTableBinding);
        }
Exemple #2
0
		private static ResultAlgebraNode Convert(CommonTableBinding currentCommonTableBinding, QueryNode queryNode)
		{
			Algebrizer algebrizer = new Algebrizer(currentCommonTableBinding);
			AlgebraNode result = algebrizer.ConvertAstNode(queryNode);
			result = new SubqueryExpander().VisitAlgebraNode(result);
			return (ResultAlgebraNode)result;
		}
Exemple #3
0
        private static ResultAlgebraNode Convert(CommonTableBinding currentCommonTableBinding, QueryNode queryNode)
        {
            Algebrizer  algebrizer = new Algebrizer(currentCommonTableBinding);
            AlgebraNode result     = algebrizer.ConvertAstNode(queryNode);

            result = new SubqueryExpander().VisitAlgebraNode(result);
            return((ResultAlgebraNode)result);
        }
Exemple #4
0
        public override TableReference VisitNamedTableReference(NamedTableReference node)
        {
            CommonTableBinding tableBindingAsCommonTable = node.TableRefBinding.TableBinding as CommonTableBinding;

            if (tableBindingAsCommonTable == null)
            {
                // It is a regular table reference. Emit just a table node.

                List <ColumnValueDefinition> definedValues = new List <ColumnValueDefinition>();
                foreach (ColumnRefBinding columnRefBinding in node.TableRefBinding.ColumnRefs)
                {
                    definedValues.Add(columnRefBinding.ValueDefinition);
                }

                TableAlgebraNode algebraNode = new TableAlgebraNode();
                algebraNode.TableRefBinding = node.TableRefBinding;
                algebraNode.DefinedValues   = definedValues.ToArray();
                SetLastAlgebraNode(algebraNode);
            }
            else
            {
                // It is a reference to a CTE. Instead of emitting a table node we have to replace the
                // reference to the CTE by the algebrized representation of the CTE. One could speak
                // of "inlining" the CTE.

                if (tableBindingAsCommonTable == _currentCommonTableBinding)
                {
                    // This should never happen. The JoinAlgebraNode should ignore these table references.
                    Debug.Fail("The current common table binding should never be reached as a table reference.");
                }

                AlgebraNode algebrizedCte;
                if (tableBindingAsCommonTable.IsRecursive)
                {
                    algebrizedCte = AlgebrizeRecursiveCte(tableBindingAsCommonTable);
                }
                else
                {
                    algebrizedCte = Convert(tableBindingAsCommonTable.AnchorMember);
                }

                // In order to use the CTE we have to instantiate it. See commonets in InstantiateCte() for
                // details.

                AlgebraNode computeScalarAlgebraNode = InstantiateCte(algebrizedCte, tableBindingAsCommonTable, node.TableRefBinding);
                SetLastAlgebraNode(computeScalarAlgebraNode);
            }

            return(node);
        }
Exemple #5
0
        private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding)
        {
            // Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times.
            // Since same row buffer entries means that the underlying data will be stored in the same physical data slot this
            // will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that
            // operates on the same column will always compare data coming from the same join side (and therefor will always
            // evaluate to true).
            //
            // Some notes on the implementation:
            //
            //      1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough;
            //         instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc.
            //      2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions
            //         are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same
            //         expression AST instances. That means that replacing the row buffers leads to failure.

            // HACK: This is a workaround for issue 2. However,
            //       I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query.
            algebrizedCte = (AlgebraNode)algebrizedCte.Clone();

            CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer();

            cteTableDefinedValuesReinitializer.Visit(algebrizedCte);

            RowBufferEntry[] outputList = algebrizedCte.OutputList;
            int skipRecursionLevel      = commonTableBinding.IsRecursive ? 1 : 0;

            // Rename the query columns to the CTE columns
            List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>();

            for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++)
            {
                RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target;
                RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel];

                ComputedValueDefinition definedValue = new ComputedValueDefinition();
                definedValue.Target     = targetRowBufferEntry;
                definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry);
                definedValues.Add(definedValue);
            }

            ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();

            computeScalarAlgebraNode.Input         = algebrizedCte;
            computeScalarAlgebraNode.DefinedValues = definedValues.ToArray();
            return(computeScalarAlgebraNode);
        }
Exemple #6
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);
        }
Exemple #7
0
 private Algebrizer(CommonTableBinding currentCommonTableBinding)
 {
     _currentCommonTableBinding = currentCommonTableBinding;
 }
Exemple #8
0
 public CteColumnMappingFinder(CommonTableBinding commonTableBinding, RowBufferEntry[] spoolBufferEntries)
 {
     _commonTableBinding = commonTableBinding;
     _spoolBufferEntries = spoolBufferEntries;
 }
Exemple #9
0
			public CteColumnMappingFinder(CommonTableBinding commonTableBinding, RowBufferEntry[] spoolBufferEntries)
			{
				_commonTableBinding = commonTableBinding;
				_spoolBufferEntries = spoolBufferEntries;
			}
Exemple #10
0
		private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding)
		{
			// Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times.
			// Since same row buffer entries means that the underlying data will be stored in the same physical data slot this
			// will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that
			// operates on the same column will always compare data coming from the same join side (and therefor will always
			// evaluate to true).
			//
			// Some notes on the implementation:
			//
			//      1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough;
			//         instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc.
			//      2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions
			//         are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same
			//         expression AST instances. That means that replacing the row buffers leads to failure.

			// HACK: This is a workaround for issue 2. However, 
			//       I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query.
			algebrizedCte = (AlgebraNode) algebrizedCte.Clone();

			CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer();
			cteTableDefinedValuesReinitializer.Visit(algebrizedCte);

			RowBufferEntry[] outputList = algebrizedCte.OutputList;
			int skipRecursionLevel = commonTableBinding.IsRecursive ? 1 : 0;

			// Rename the query columns to the CTE columns
			List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>();
			for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++)
			{
				RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target;
				RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel];

				ComputedValueDefinition definedValue = new ComputedValueDefinition();
				definedValue.Target = targetRowBufferEntry;
				definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry);
				definedValues.Add(definedValue);
			}

			ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode();
			computeScalarAlgebraNode.Input = algebrizedCte;
			computeScalarAlgebraNode.DefinedValues = definedValues.ToArray();
			return computeScalarAlgebraNode;
		}
Exemple #11
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;
		}
Exemple #12
0
		private Algebrizer(CommonTableBinding currentCommonTableBinding)
		{
			_currentCommonTableBinding = currentCommonTableBinding;
		}