예제 #1
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);
        }
예제 #2
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;
		}