Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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;
		}