Пример #1
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            _xmlWriter.WriteStartElement("caseExpression");
            WriteTypeAttribute(expression.ExpressionType);

            if (expression.InputExpression != null)
            {
                WriteAstNode("inputExpression", expression.InputExpression);
            }

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                _xmlWriter.WriteStartElement("whenThenPair");
                _xmlWriter.WriteAttributeString("index", XmlConvert.ToString(i));

                WriteAstNode("whenExpression", expression.WhenExpressions[i]);
                WriteAstNode("thenExpression", expression.ThenExpressions[i]);

                _xmlWriter.WriteEndElement();
            }

            if (expression.ElseExpression != null)
            {
                WriteAstNode("elseExpression", expression.ElseExpression);
            }

            _xmlWriter.WriteEndElement();

            return(expression);
        }
Пример #2
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            if (expression.InputExpression == null)
            {
                _writer.Write("CASE");
            }
            else
            {
                _writer.Write("CASE ");
                Visit(expression.InputExpression);
            }

            for (int i = 0; i < expression.WhenExpressions.Length && i < expression.ThenExpressions.Length; i++)
            {
                _writer.Write(" WHEN ");
                Visit(expression.WhenExpressions[i]);
                _writer.Write(" THEN ");
                Visit(expression.ThenExpressions[i]);
            }

            if (expression.ElseExpression != null)
            {
                _writer.Write(" ELSE ");
                Visit(expression.ElseExpression);
            }

            _writer.Write(" END");

            return(expression);
        }
Пример #3
0
        public override AstElement Clone(Dictionary <AstElement, AstElement> alreadyClonedElements)
        {
            CaseExpression result = new CaseExpression();

            if (_inputExpression != null)
            {
                result.InputExpression = (ExpressionNode)_inputExpression.Clone(alreadyClonedElements);
            }

            if (_elseExpression != null)
            {
                result.ElseExpression = (ExpressionNode)_elseExpression.Clone(alreadyClonedElements);
            }

            result.WhenExpressions = new ExpressionNode[_whenExpressions.Length];
            for (int i = 0; i < _whenExpressions.Length; i++)
            {
                result.WhenExpressions[i] = (ExpressionNode)_whenExpressions[i].Clone(alreadyClonedElements);
            }

            result.ThenExpressions = new ExpressionNode[_thenExpressions.Length];
            for (int i = 0; i < _thenExpressions.Length; i++)
            {
                result.ThenExpressions[i] = (ExpressionNode)_thenExpressions[i].Clone(alreadyClonedElements);
            }

            result.ResultType = _resultType;

            return(result);
        }
Пример #4
0
        public override ExpressionNode VisitNullIfExpression(NullIfExpression expression)
        {
            // First visit all expressions
            base.VisitNullIfExpression(expression);

            // Since a NULLIF expression can be expressed using a CASE expression we convert
            // them to simplify the evaluation and optimization engine.
            //
            // NULLIF(expression1, expression1) is equivalent to this CASE expression:
            //
            // CASE
            //   WHEN expression1 = expression2 THEN NULL
            //	 ELSE expression1
            // END

            CaseExpression caseExpression = new CaseExpression();

            caseExpression.WhenExpressions    = new ExpressionNode[1];
            caseExpression.ThenExpressions    = new ExpressionNode[1];
            caseExpression.WhenExpressions[0] = new BinaryExpression(BinaryOperator.Equal, expression.LeftExpression, expression.RightExpression);
            caseExpression.ThenExpressions[0] = LiteralExpression.FromNull();
            caseExpression.ElseExpression     = expression.LeftExpression;

            return(VisitExpression(caseExpression));
        }
Пример #5
0
        public override ExpressionNode VisitCoalesceExpression(CoalesceExpression expression)
        {
            // First visit all expressions
            base.VisitCoalesceExpression(expression);

            // Since a COALESCE expression can be expressed using a CASE expression we convert
            // them to simplify the evaluation and optimization engine.
            //
            // COALESCE(expression1,...,expressionN) is equivalent to this CASE expression:
            //
            // CASE
            //   WHEN (expression1 IS NOT NULL) THEN expression1
            //   ...
            //   WHEN (expressionN IS NOT NULL) THEN expressionN
            // END

            CaseExpression caseExpression = new CaseExpression();

            caseExpression.WhenExpressions = new ExpressionNode[expression.Expressions.Length];
            caseExpression.ThenExpressions = new ExpressionNode[expression.Expressions.Length];

            for (int i = 0; i < expression.Expressions.Length; i++)
            {
                ExpressionNode whenPart = expression.Expressions[i];
                ExpressionNode thenPart = (ExpressionNode)whenPart.Clone();
                caseExpression.WhenExpressions[i] = new IsNullExpression(true, whenPart);
                caseExpression.ThenExpressions[i] = thenPart;
            }

            return(VisitExpression(caseExpression));
        }
Пример #6
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            // NOTE: It is assumed that simple case expressions are already transformed into
            //       searched case expressions, i.e.
            //       CASE
            //          WHEN Pred1 THEN Expr1 ...
            //          WHEN PredN THEN ExprN
            //          [ELSE ElseExpr]
            //       END

            List <ExpressionNode> processedWhenExpressions = new List <ExpressionNode>();

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                SetWhenPassthru(processedWhenExpressions);
                expression.WhenExpressions[i] = VisitExpression(expression.WhenExpressions[i]);
                processedWhenExpressions.Add(expression.WhenExpressions[i]);

                SetThenPassthru(processedWhenExpressions);
                expression.ThenExpressions[i] = VisitExpression(expression.ThenExpressions[i]);
            }

            if (expression.ElseExpression != null)
            {
                SetWhenPassthru(processedWhenExpressions);
                expression.ElseExpression = VisitExpression(expression.ElseExpression);
            }

            _currentPassthruPredicate = null;

            return(expression);
        }
Пример #7
0
        private static bool VisitCaseExpression(CaseExpression node1, CaseExpression node2)
        {
            if (node2 == null)
            {
                return(false);
            }

            if (node1.InputExpression != null)
            {
                if (!Visit(node1.InputExpression, node2.InputExpression))
                {
                    return(false);
                }
            }

            if (node1.WhenExpressions.Length != node2.WhenExpressions.Length ||
                node1.ThenExpressions.Length != node2.ThenExpressions.Length)
            {
                return(false);
            }

            for (int i = 0; i < node1.WhenExpressions.Length; i++)
            {
                if (!Visit(node1.WhenExpressions[i], node2.WhenExpressions[i]))
                {
                    return(false);
                }
            }

            for (int i = 0; i < node1.ThenExpressions.Length; i++)
            {
                if (!Visit(node1.ThenExpressions[i], node2.ThenExpressions[i]))
                {
                    return(false);
                }
            }

            if (node1.ElseExpression != null)
            {
                if (!Visit(node1.ElseExpression, node2.ElseExpression))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #8
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            // NOTE: Must be searched CASE. The normalizer should have replaced it.

            Label finishLabel = _ilEmitContext.ILGenerator.DefineLabel();

            Label[] caseLabels = new Label[expression.WhenExpressions.Length + 1];
            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                caseLabels[i] = _ilEmitContext.ILGenerator.DefineLabel();
            }

            Label elseLabel = _ilEmitContext.ILGenerator.DefineLabel();

            caseLabels[expression.WhenExpressions.Length] = elseLabel;

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                _ilEmitContext.ILGenerator.MarkLabel(caseLabels[i]);

                int whenLocalIndex = DeclareLocal();
                Visit(expression.WhenExpressions[i]);
                _ilEmitContext.ILGenerator.Emit(OpCodes.Stloc, whenLocalIndex);
                _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, whenLocalIndex);
                _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, caseLabels[i + 1]);
                _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, whenLocalIndex);
                _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(bool));
                _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, caseLabels[i + 1]);

                Visit(expression.ThenExpressions[i]);
                _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finishLabel);
            }

            _ilEmitContext.ILGenerator.MarkLabel(elseLabel);
            if (expression.ElseExpression != null)
            {
                Visit(expression.ElseExpression);
            }
            else
            {
                _ilEmitContext.ILGenerator.Emit(OpCodes.Ldnull);
            }

            _ilEmitContext.ILGenerator.MarkLabel(finishLabel);

            return(expression);
        }
Пример #9
0
		public override AstElement Clone(Dictionary<AstElement, AstElement> alreadyClonedElements)
		{
			CaseExpression result = new CaseExpression();
			
			if (_inputExpression != null)
				result.InputExpression = (ExpressionNode)_inputExpression.Clone(alreadyClonedElements);

			if (_elseExpression != null)
				result.ElseExpression = (ExpressionNode)_elseExpression.Clone(alreadyClonedElements);

			result.WhenExpressions = new ExpressionNode[_whenExpressions.Length];
			for (int i = 0; i < _whenExpressions.Length; i++)
				result.WhenExpressions[i] = (ExpressionNode)_whenExpressions[i].Clone(alreadyClonedElements);

			result.ThenExpressions = new ExpressionNode[_thenExpressions.Length];
			for (int i = 0; i < _thenExpressions.Length; i++)
				result.ThenExpressions[i] = (ExpressionNode)_thenExpressions[i].Clone(alreadyClonedElements);

			result.ResultType = _resultType;

			return result;
		}
Пример #10
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            // Replace simple CASE by searched CASE, i.e.
            //
            // replace
            //
            //       CASE InputExpr
            //          WHEN Expr1 THEN ThenExpr1 ...
            //          WHEN ExprN THEN ThenExprN
            //          [ELSE ElseExpr]
            //       END
            //
            // by
            //
            //       CASE
            //          WHEN InputExpr = Expr1 THEN ThenExpr1 ...
            //          WHEN InputExpr = ExprN THEN ThenExprN
            //          [ELSE ElseExpr]
            //       END

            if (expression.InputExpression != null)
            {
                for (int i = 0; i < expression.WhenExpressions.Length; i++)
                {
                    BinaryExpression binaryExpression = new BinaryExpression();
                    binaryExpression.Op           = BinaryOperator.Equal;
                    binaryExpression.Left         = (ExpressionNode)expression.InputExpression.Clone();
                    binaryExpression.Right        = expression.WhenExpressions[i];
                    expression.WhenExpressions[i] = binaryExpression;
                }

                expression.InputExpression = null;
            }

            return(base.VisitCaseExpression(expression));
        }
Пример #11
0
        public virtual ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            if (expression.InputExpression != null)
            {
                expression.InputExpression = VisitExpression(expression.InputExpression);
            }

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                expression.WhenExpressions[i] = VisitExpression(expression.WhenExpressions[i]);
            }

            for (int i = 0; i < expression.ThenExpressions.Length; i++)
            {
                expression.ThenExpressions[i] = VisitExpression(expression.ThenExpressions[i]);
            }

            if (expression.ElseExpression != null)
            {
                expression.ElseExpression = VisitExpression(expression.ElseExpression);
            }

            return(expression);
        }
Пример #12
0
		private static bool VisitCaseExpression(CaseExpression node1, CaseExpression node2)
		{
			if (node2 == null)
				return false;

			if (node1.InputExpression != null)
				if (!Visit(node1.InputExpression, node2.InputExpression))
					return false;

			if (node1.WhenExpressions.Length != node2.WhenExpressions.Length ||
				node1.ThenExpressions.Length != node2.ThenExpressions.Length)
				return false;

			for (int i = 0; i < node1.WhenExpressions.Length; i++)
				if (!Visit(node1.WhenExpressions[i], node2.WhenExpressions[i]))
					return false;

			for (int i = 0; i < node1.ThenExpressions.Length; i++)
				if (!Visit(node1.ThenExpressions[i], node2.ThenExpressions[i]))
					return false;

			if (node1.ElseExpression != null)
				if (!Visit(node1.ElseExpression, node2.ElseExpression))
					return false;

			return true;
		}
Пример #13
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            // NOTE: It is assumed that simple case expressions are already transformed into
            //       searched case expressions, i.e.
            //       CASE
            //          WHEN Pred1 THEN Expr1 ...
            //          WHEN PredN THEN ExprN
            //          [ELSE ElseExpr]
            //       END

            List<ExpressionNode> processedWhenExpressions = new List<ExpressionNode>();

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                SetWhenPassthru(processedWhenExpressions);
                expression.WhenExpressions[i] = VisitExpression(expression.WhenExpressions[i]);
                processedWhenExpressions.Add(expression.WhenExpressions[i]);

                SetThenPassthru(processedWhenExpressions);
                expression.ThenExpressions[i] = VisitExpression(expression.ThenExpressions[i]);
            }

            if (expression.ElseExpression != null)
            {
                SetWhenPassthru(processedWhenExpressions);
                expression.ElseExpression = VisitExpression(expression.ElseExpression);
            }

            _currentPassthruPredicate = null;

            return expression;
        }
Пример #14
0
		public override ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			if (expression.InputExpression == null)
			{
				_writer.Write("CASE");
			}
			else
			{
				_writer.Write("CASE ");
				Visit(expression.InputExpression);
			}

			for (int i = 0; i < expression.WhenExpressions.Length && i < expression.ThenExpressions.Length; i++)
			{
				_writer.Write(" WHEN ");
				Visit(expression.WhenExpressions[i]);
				_writer.Write(" THEN ");
				Visit(expression.ThenExpressions[i]);
			}

			if (expression.ElseExpression != null)
			{
				_writer.Write(" ELSE ");
				Visit(expression.ElseExpression);
			}

			_writer.Write(" END");

			return expression;
		}
Пример #15
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;
		}
Пример #16
0
		public override ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			base.VisitCaseExpression(expression);

			// NOTE: It must be a searched CASE. The normalizer should have normalized it already.
			//
			// Remove all WHEN expressions that are allays FALSE or NULL.
			// AND
			// Cut off all WHENs trailing an expression that is always true.

			List<ExpressionNode> whenExpressions = new List<ExpressionNode>();
			List<ExpressionNode> thenExpressions = new List<ExpressionNode>();

			for (int i = 0; i < expression.WhenExpressions.Length; i++)
			{
				if (AstUtil.IsNull(expression.WhenExpressions[i]))
				{
					// A WHEN expression is always null.
					continue;
				}

				ConstantExpression whenAsBooleanConstant = expression.WhenExpressions[i] as ConstantExpression;

				if (whenAsBooleanConstant != null)
				{
					if (!whenAsBooleanConstant.AsBoolean)
					{
						// A WHEN expression is always false.
						//
						// We remove this part from the case expression by not adding to 
						// whenExpressions and thenExpressions.
						continue;
					}
					else
					{
						// A WHEN expression is always true.							
						//
						// We replace the ELSE expression by the THEN expression and
						// cut off the rest.

						expression.ElseExpression = expression.ThenExpressions[i];
						break;
					}
				}

				whenExpressions.Add(expression.WhenExpressions[i]);
				thenExpressions.Add(expression.ThenExpressions[i]);
			}

			if (whenExpressions.Count == 0)
			{
				// This means the first WHEN expression was always false
				// or all WHEN expressions are either FALSE or NULL.
				//
				// We replace the case expression by the else expression
				// or by NULL.

				if (expression.ElseExpression != null)
					return expression.ElseExpression;

				return LiteralExpression.FromTypedNull(expression.ExpressionType);
			}

			expression.WhenExpressions = whenExpressions.ToArray();
			expression.ThenExpressions = thenExpressions.ToArray();

			return expression;
		}
Пример #17
0
        private ExpressionNode ParsePrimaryExpression()
        {
            switch (_token.Id)
            {
                case TokenId.NULL:
                    NextToken();
                    return LiteralExpression.FromNull();

                case TokenId.TRUE:
                case TokenId.FALSE:
                    return ParseBooleanLiteral();

                case TokenId.Date:
                    return ParseDateLiteral();

                case TokenId.Number:
                    return ParseNumberLiteral();

                case TokenId.String:
                    return LiteralExpression.FromString(ParseString());

                case TokenId.EXISTS:
                {
                    ExistsSubselect result = new ExistsSubselect();
                    NextToken();
                    Match(TokenId.LeftParentheses);
                    result.Query = ParseQuery();
                    Match(TokenId.RightParentheses);

                    return result;
                }

                case TokenId.ParameterMarker:
                {
                    _rangeRecorder.Begin();
                    NextToken();
                    Identifier name = ParseIdentifier();
                    SourceRange nameSourceRange = _rangeRecorder.End();

                    ParameterExpression result = new ParameterExpression();
                    result.Name = name;
                    result.NameSourceRange = nameSourceRange;
                    return result;
                }

                case TokenId.CAST:
                {
                    NextToken();
                    CastExpression castExpression = new CastExpression();
                    Match(TokenId.LeftParentheses);
                    castExpression.Expression = ParseExpression();
                    Match(TokenId.AS);
                    castExpression.TypeReference = ParseTypeReference();
                    Match(TokenId.RightParentheses);

                    return castExpression;
                }

                case TokenId.CASE:
                {
                    NextToken();

                    CaseExpression caseExpression = new CaseExpression();

                    if (_token.Id != TokenId.WHEN && _token.Id != TokenId.ELSE && _token.Id != TokenId.END)
                        caseExpression.InputExpression = ParseExpression();

                    List<ExpressionNode> whenExpressionList = new List<ExpressionNode>();
                    List<ExpressionNode> expressionList = new List<ExpressionNode>();

                    if (_token.Id != TokenId.WHEN)
                    {
                        Match(TokenId.WHEN);
                    }
                    else
                    {
                        while (_token.Id == TokenId.WHEN)
                        {
                            NextToken();

                            whenExpressionList.Add(ParseExpression());
                            Match(TokenId.THEN);
                            expressionList.Add(ParseExpression());
                        }
                    }

                    caseExpression.WhenExpressions = whenExpressionList.ToArray();
                    caseExpression.ThenExpressions = expressionList.ToArray();

                    if (_token.Id == TokenId.ELSE)
                    {
                        NextToken();
                        caseExpression.ElseExpression = ParseExpression();
                    }

                    Match(TokenId.END);

                    return caseExpression;
                }

                case TokenId.COALESCE:
                {
                    NextToken();
                    CoalesceExpression coalesceExpression = new CoalesceExpression();
                    coalesceExpression.Expressions = ParseExpressionList();
                    return coalesceExpression;
                }

                case TokenId.NULLIF:
                {
                    NextToken();
                    NullIfExpression nullIfExpression = new NullIfExpression();
                    Match(TokenId.LeftParentheses);
                    nullIfExpression.LeftExpression = ParseExpression();
                    Match(TokenId.Comma);
                    nullIfExpression.RightExpression = ParseExpression();
                    Match(TokenId.RightParentheses);
                    return nullIfExpression;
                }

                case TokenId.Identifier:
                {
                    _rangeRecorder.Begin();
                    Identifier name = ParseIdentifier();
                    SourceRange nameSourceRange = _rangeRecorder.End();

                    if (_token.Id != TokenId.LeftParentheses)
                    {
                        NameExpression result = new NameExpression();
                        result.Name = name;
                        result.NameSourceRange = nameSourceRange;
                        return result;
                    }
                    else
                    {
                        bool hasAsteriskModifier;
                        ExpressionNode[] args;

                        if (_lookahead.Id != TokenId.Multiply)
                        {
                            hasAsteriskModifier = false;
                            args = ParseExpressionList();
                        }
                        else
                        {
                            NextToken();
                            NextToken();
                            Match(TokenId.RightParentheses);

                            hasAsteriskModifier = true;
                            args = new ExpressionNode[0];
                        }

                        FunctionInvocationExpression result = new FunctionInvocationExpression();
                        result.Name = name;
                        result.NameSourceRange = nameSourceRange;
                        result.Arguments = args;
                        result.HasAsteriskModifier = hasAsteriskModifier;
                        return result;
                    }
                }

                case TokenId.LeftParentheses:
                {
                    NextToken();

                    ExpressionNode expr;

                    if (_token.Id != TokenId.SELECT)
                    {
                        expr = ParseExpression();
                    }
                    else
                    {
                        SingleRowSubselect singleRowSubselect = new SingleRowSubselect();
                        singleRowSubselect.Query = ParseQuery();
                        expr = singleRowSubselect;
                    }

                    Match(TokenId.RightParentheses);
                    return expr;
                }

                default:
                {
                    _errorReporter.SimpleExpressionExpected(_token.Range, _token.Text);
                    return LiteralExpression.FromNull();
                }
            }
        }
Пример #18
0
		public override ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			// Replace simple CASE by searched CASE, i.e.
			//
			// replace
			//
			//       CASE InputExpr
			//          WHEN Expr1 THEN ThenExpr1 ...
			//          WHEN ExprN THEN ThenExprN
			//          [ELSE ElseExpr]
			//       END
			//
			// by
			//
			//       CASE
			//          WHEN InputExpr = Expr1 THEN ThenExpr1 ...
			//          WHEN InputExpr = ExprN THEN ThenExprN
			//          [ELSE ElseExpr]
			//       END

			if (expression.InputExpression != null)
			{
				for (int i = 0; i < expression.WhenExpressions.Length; i++)
				{
					BinaryExpression binaryExpression = new BinaryExpression();
					binaryExpression.Op = BinaryOperator.Equal;
					binaryExpression.Left = (ExpressionNode) expression.InputExpression.Clone();
					binaryExpression.Right = expression.WhenExpressions[i];
					expression.WhenExpressions[i] = binaryExpression;
				}

				expression.InputExpression = null;
			}

			return base.VisitCaseExpression(expression);
		}
Пример #19
0
		public override ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			// NOTE: Must be searched CASE. The normalizer should have replaced it.

			Label finishLabel = _ilEmitContext.ILGenerator.DefineLabel();

			Label[] caseLabels = new Label[expression.WhenExpressions.Length + 1];
			for (int i = 0; i < expression.WhenExpressions.Length; i++)
				caseLabels[i] = _ilEmitContext.ILGenerator.DefineLabel();

			Label elseLabel = _ilEmitContext.ILGenerator.DefineLabel();
			caseLabels[expression.WhenExpressions.Length] = elseLabel;

			for (int i = 0; i < expression.WhenExpressions.Length; i++)
			{
				_ilEmitContext.ILGenerator.MarkLabel(caseLabels[i]);

				int whenLocalIndex = DeclareLocal();
				Visit(expression.WhenExpressions[i]);
				_ilEmitContext.ILGenerator.Emit(OpCodes.Stloc, whenLocalIndex);
				_ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, whenLocalIndex);
				_ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, caseLabels[i + 1]);
				_ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, whenLocalIndex);
				_ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof (bool));
				_ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, caseLabels[i + 1]);

				Visit(expression.ThenExpressions[i]);
				_ilEmitContext.ILGenerator.Emit(OpCodes.Br, finishLabel);
			}

			_ilEmitContext.ILGenerator.MarkLabel(elseLabel);
			if (expression.ElseExpression != null)
				Visit(expression.ElseExpression);
			else
				_ilEmitContext.ILGenerator.Emit(OpCodes.Ldnull);

			_ilEmitContext.ILGenerator.MarkLabel(finishLabel);

			return expression;
		}
Пример #20
0
		public override ExpressionNode VisitCoalesceExpression(CoalesceExpression expression)
		{
			// First visit all expressions
			base.VisitCoalesceExpression(expression);

			// Since a COALESCE expression can be expressed using a CASE expression we convert
			// them to simplify the evaluation and optimization engine.
			//
			// COALESCE(expression1,...,expressionN) is equivalent to this CASE expression:
			//
			// CASE
			//   WHEN (expression1 IS NOT NULL) THEN expression1
			//   ...
			//   WHEN (expressionN IS NOT NULL) THEN expressionN
			// END

			CaseExpression caseExpression = new CaseExpression();
			caseExpression.WhenExpressions = new ExpressionNode[expression.Expressions.Length];
			caseExpression.ThenExpressions = new ExpressionNode[expression.Expressions.Length];
			
			for (int i = 0; i < expression.Expressions.Length; i++)
			{
				ExpressionNode whenPart = expression.Expressions[i];
				ExpressionNode thenPart = (ExpressionNode) whenPart.Clone();
				caseExpression.WhenExpressions[i] = new IsNullExpression(true, whenPart);
				caseExpression.ThenExpressions[i] = thenPart;
			}

			return VisitExpression(caseExpression);
		}
Пример #21
0
		public override ExpressionNode VisitNullIfExpression(NullIfExpression expression)
		{
			// First visit all expressions
			base.VisitNullIfExpression (expression);
			
			// Since a NULLIF expression can be expressed using a CASE expression we convert
			// them to simplify the evaluation and optimization engine.
			//
			// NULLIF(expression1, expression1) is equivalent to this CASE expression:
			//
			// CASE
			//   WHEN expression1 = expression2 THEN NULL
			//	 ELSE expression1 
			// END
			
			CaseExpression caseExpression = new CaseExpression();
			caseExpression.WhenExpressions = new ExpressionNode[1];
			caseExpression.ThenExpressions = new ExpressionNode[1];
			caseExpression.WhenExpressions[0] = new BinaryExpression(BinaryOperator.Equal, expression.LeftExpression, expression.RightExpression);
			caseExpression.ThenExpressions[0] = LiteralExpression.FromNull();
			caseExpression.ElseExpression = expression.LeftExpression;

			return VisitExpression(caseExpression);
		}
Пример #22
0
		public override ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			_xmlWriter.WriteStartElement("caseExpression");
			WriteTypeAttribute(expression.ExpressionType);

			if (expression.InputExpression != null)
				WriteAstNode("inputExpression", expression.InputExpression);

			for (int i = 0; i < expression.WhenExpressions.Length; i++)
			{
				_xmlWriter.WriteStartElement("whenThenPair");
				_xmlWriter.WriteAttributeString("index", XmlConvert.ToString(i));

				WriteAstNode("whenExpression", expression.WhenExpressions[i]);
				WriteAstNode("thenExpression", expression.ThenExpressions[i]);

				_xmlWriter.WriteEndElement();
			}

			if (expression.ElseExpression != null)
				WriteAstNode("elseExpression", expression.ElseExpression);

			_xmlWriter.WriteEndElement();

			return expression;
		}
Пример #23
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);
        }
Пример #24
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;
        }
Пример #25
0
		public virtual ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			if (expression.InputExpression != null)
				expression.InputExpression = VisitExpression(expression.InputExpression);

			for (int i = 0; i < expression.WhenExpressions.Length; i++)
				expression.WhenExpressions[i] = VisitExpression(expression.WhenExpressions[i]);

			for (int i = 0; i < expression.ThenExpressions.Length; i++)
				expression.ThenExpressions[i] = VisitExpression(expression.ThenExpressions[i]);

			if (expression.ElseExpression != null)
				expression.ElseExpression = VisitExpression(expression.ElseExpression);

			return expression;
		}
Пример #26
0
        private ExpressionNode ParsePrimaryExpression()
        {
            switch (_token.Id)
            {
            case TokenId.NULL:
                NextToken();
                return(LiteralExpression.FromNull());

            case TokenId.TRUE:
            case TokenId.FALSE:
                return(ParseBooleanLiteral());

            case TokenId.Date:
                return(ParseDateLiteral());

            case TokenId.Number:
                return(ParseNumberLiteral());

            case TokenId.String:
                return(LiteralExpression.FromString(ParseString()));

            case TokenId.EXISTS:
            {
                ExistsSubselect result = new ExistsSubselect();
                NextToken();
                Match(TokenId.LeftParentheses);
                result.Query = ParseQuery();
                Match(TokenId.RightParentheses);

                return(result);
            }

            case TokenId.ParameterMarker:
            {
                _rangeRecorder.Begin();
                NextToken();
                Identifier  name            = ParseIdentifier();
                SourceRange nameSourceRange = _rangeRecorder.End();

                ParameterExpression result = new ParameterExpression();
                result.Name            = name;
                result.NameSourceRange = nameSourceRange;
                return(result);
            }

            case TokenId.CAST:
            {
                NextToken();
                CastExpression castExpression = new CastExpression();
                Match(TokenId.LeftParentheses);
                castExpression.Expression = ParseExpression();
                Match(TokenId.AS);
                castExpression.TypeReference = ParseTypeReference();
                Match(TokenId.RightParentheses);

                return(castExpression);
            }

            case TokenId.CASE:
            {
                NextToken();

                CaseExpression caseExpression = new CaseExpression();

                if (_token.Id != TokenId.WHEN && _token.Id != TokenId.ELSE && _token.Id != TokenId.END)
                {
                    caseExpression.InputExpression = ParseExpression();
                }

                List <ExpressionNode> whenExpressionList = new List <ExpressionNode>();
                List <ExpressionNode> expressionList     = new List <ExpressionNode>();

                if (_token.Id != TokenId.WHEN)
                {
                    Match(TokenId.WHEN);
                }
                else
                {
                    while (_token.Id == TokenId.WHEN)
                    {
                        NextToken();

                        whenExpressionList.Add(ParseExpression());
                        Match(TokenId.THEN);
                        expressionList.Add(ParseExpression());
                    }
                }

                caseExpression.WhenExpressions = whenExpressionList.ToArray();
                caseExpression.ThenExpressions = expressionList.ToArray();

                if (_token.Id == TokenId.ELSE)
                {
                    NextToken();
                    caseExpression.ElseExpression = ParseExpression();
                }

                Match(TokenId.END);

                return(caseExpression);
            }

            case TokenId.COALESCE:
            {
                NextToken();
                CoalesceExpression coalesceExpression = new CoalesceExpression();
                coalesceExpression.Expressions = ParseExpressionList();
                return(coalesceExpression);
            }

            case TokenId.NULLIF:
            {
                NextToken();
                NullIfExpression nullIfExpression = new NullIfExpression();
                Match(TokenId.LeftParentheses);
                nullIfExpression.LeftExpression = ParseExpression();
                Match(TokenId.Comma);
                nullIfExpression.RightExpression = ParseExpression();
                Match(TokenId.RightParentheses);
                return(nullIfExpression);
            }

            case TokenId.Identifier:
            {
                _rangeRecorder.Begin();
                Identifier  name            = ParseIdentifier();
                SourceRange nameSourceRange = _rangeRecorder.End();

                if (_token.Id != TokenId.LeftParentheses)
                {
                    NameExpression result = new NameExpression();
                    result.Name            = name;
                    result.NameSourceRange = nameSourceRange;
                    return(result);
                }
                else
                {
                    bool             hasAsteriskModifier;
                    ExpressionNode[] args;

                    if (_lookahead.Id != TokenId.Multiply)
                    {
                        hasAsteriskModifier = false;
                        args = ParseExpressionList();
                    }
                    else
                    {
                        NextToken();
                        NextToken();
                        Match(TokenId.RightParentheses);

                        hasAsteriskModifier = true;
                        args = new ExpressionNode[0];
                    }

                    FunctionInvocationExpression result = new FunctionInvocationExpression();
                    result.Name                = name;
                    result.NameSourceRange     = nameSourceRange;
                    result.Arguments           = args;
                    result.HasAsteriskModifier = hasAsteriskModifier;
                    return(result);
                }
            }

            case TokenId.LeftParentheses:
            {
                NextToken();

                ExpressionNode expr;

                if (_token.Id != TokenId.SELECT)
                {
                    expr = ParseExpression();
                }
                else
                {
                    SingleRowSubselect singleRowSubselect = new SingleRowSubselect();
                    singleRowSubselect.Query = ParseQuery();
                    expr = singleRowSubselect;
                }

                Match(TokenId.RightParentheses);
                return(expr);
            }

            default:
            {
                _errorReporter.SimpleExpressionExpected(_token.Range, _token.Text);
                return(LiteralExpression.FromNull());
            }
            }
        }
Пример #27
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            base.VisitCaseExpression(expression);

            // NOTE: It must be a searched CASE. The normalizer should have normalized it already.
            //
            // Remove all WHEN expressions that are allays FALSE or NULL.
            // AND
            // Cut off all WHENs trailing an expression that is always true.

            List <ExpressionNode> whenExpressions = new List <ExpressionNode>();
            List <ExpressionNode> thenExpressions = new List <ExpressionNode>();

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                if (AstUtil.IsNull(expression.WhenExpressions[i]))
                {
                    // A WHEN expression is always null.
                    continue;
                }

                ConstantExpression whenAsBooleanConstant = expression.WhenExpressions[i] as ConstantExpression;

                if (whenAsBooleanConstant != null)
                {
                    if (!whenAsBooleanConstant.AsBoolean)
                    {
                        // A WHEN expression is always false.
                        //
                        // We remove this part from the case expression by not adding to
                        // whenExpressions and thenExpressions.
                        continue;
                    }
                    else
                    {
                        // A WHEN expression is always true.
                        //
                        // We replace the ELSE expression by the THEN expression and
                        // cut off the rest.

                        expression.ElseExpression = expression.ThenExpressions[i];
                        break;
                    }
                }

                whenExpressions.Add(expression.WhenExpressions[i]);
                thenExpressions.Add(expression.ThenExpressions[i]);
            }

            if (whenExpressions.Count == 0)
            {
                // This means the first WHEN expression was always false
                // or all WHEN expressions are either FALSE or NULL.
                //
                // We replace the case expression by the else expression
                // or by NULL.

                if (expression.ElseExpression != null)
                {
                    return(expression.ElseExpression);
                }

                return(LiteralExpression.FromTypedNull(expression.ExpressionType));
            }

            expression.WhenExpressions = whenExpressions.ToArray();
            expression.ThenExpressions = thenExpressions.ToArray();

            return(expression);
        }
Пример #28
0
		public override ExpressionNode VisitCaseExpression(CaseExpression expression)
		{
			// Ensure all nested expressions are fully resolved.

			base.VisitCaseExpression(expression);

			for (int i = 0; i < expression.WhenExpressions.Length; i++)
			{
				if (expression.WhenExpressions[i].ExpressionType == null || expression.ThenExpressions[i].ExpressionType == null)
					return expression;
			}

			if (expression.ElseExpression != null && expression.ElseExpression.ExpressionType == null)
				return expression;

			// Ok, all nested expressions could be fully resolved. Lets validate the CASE expression.

			// The semantic of CASE says that if no expression incl. ELSE does match the result is NULL.
			// So having an ELSE expression that returns NULL is quite redundant.

			LiteralExpression elseAsLiteral = expression.ElseExpression as LiteralExpression;
			if (elseAsLiteral != null && elseAsLiteral.IsNullValue)
				expression.ElseExpression = null;

			// All WHEN expressions must evaluate to bool.

			foreach (ExpressionNode whenExpression in expression.WhenExpressions)
			{
				if (whenExpression.ExpressionType != typeof(bool) && whenExpression.ExpressionType != typeof(DBNull))
					_errorReporter.WhenMustEvaluateToBoolIfCaseInputIsOmitted(whenExpression);
			}

			// Check that all result expression incl. else share a common type.
			//
			// To do this and to support good error reporting we first try to find
			// the best common type. Any needed conversions or type errors are
			// ignored.

			Type commonResultType = expression.ThenExpressions[0].ExpressionType;

			for (int i = 1; i < expression.ThenExpressions.Length; i++)
			{
				commonResultType = _binder.ChooseBetterTypeConversion(commonResultType, expression.ThenExpressions[i].ExpressionType);
			}

			if (expression.ElseExpression != null)
				commonResultType = _binder.ChooseBetterTypeConversion(expression.ElseExpression.ExpressionType, commonResultType);

			// Now we know that commonResultType is the best type for all result expressions.
			// Insert cast nodes for all expressions that have a different type but are
			// implicit convertible and report errors for all expressions that not convertible.

			if (expression.ElseExpression != null)
			{
				expression.ElseExpression = _binder.ConvertExpressionIfRequired(expression.ElseExpression, commonResultType);
			}

			for (int i = 0; i < expression.ThenExpressions.Length; i++)
			{
				expression.ThenExpressions[i] = _binder.ConvertExpressionIfRequired(expression.ThenExpressions[i], commonResultType);
			}

			expression.ResultType = commonResultType;

			return expression;
		}
Пример #29
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);
        }
Пример #30
0
        public override ExpressionNode VisitCaseExpression(CaseExpression expression)
        {
            // Ensure all nested expressions are fully resolved.

            base.VisitCaseExpression(expression);

            for (int i = 0; i < expression.WhenExpressions.Length; i++)
            {
                if (expression.WhenExpressions[i].ExpressionType == null || expression.ThenExpressions[i].ExpressionType == null)
                {
                    return(expression);
                }
            }

            if (expression.ElseExpression != null && expression.ElseExpression.ExpressionType == null)
            {
                return(expression);
            }

            // Ok, all nested expressions could be fully resolved. Lets validate the CASE expression.

            // The semantic of CASE says that if no expression incl. ELSE does match the result is NULL.
            // So having an ELSE expression that returns NULL is quite redundant.

            LiteralExpression elseAsLiteral = expression.ElseExpression as LiteralExpression;

            if (elseAsLiteral != null && elseAsLiteral.IsNullValue)
            {
                expression.ElseExpression = null;
            }

            // All WHEN expressions must evaluate to bool.

            foreach (ExpressionNode whenExpression in expression.WhenExpressions)
            {
                if (whenExpression.ExpressionType != typeof(bool) && whenExpression.ExpressionType != typeof(DBNull))
                {
                    _errorReporter.WhenMustEvaluateToBoolIfCaseInputIsOmitted(whenExpression);
                }
            }

            // Check that all result expression incl. else share a common type.
            //
            // To do this and to support good error reporting we first try to find
            // the best common type. Any needed conversions or type errors are
            // ignored.

            Type commonResultType = expression.ThenExpressions[0].ExpressionType;

            for (int i = 1; i < expression.ThenExpressions.Length; i++)
            {
                commonResultType = _binder.ChooseBetterTypeConversion(commonResultType, expression.ThenExpressions[i].ExpressionType);
            }

            if (expression.ElseExpression != null)
            {
                commonResultType = _binder.ChooseBetterTypeConversion(expression.ElseExpression.ExpressionType, commonResultType);
            }

            // Now we know that commonResultType is the best type for all result expressions.
            // Insert cast nodes for all expressions that have a different type but are
            // implicit convertible and report errors for all expressions that not convertible.

            if (expression.ElseExpression != null)
            {
                expression.ElseExpression = _binder.ConvertExpressionIfRequired(expression.ElseExpression, commonResultType);
            }

            for (int i = 0; i < expression.ThenExpressions.Length; i++)
            {
                expression.ThenExpressions[i] = _binder.ConvertExpressionIfRequired(expression.ThenExpressions[i], commonResultType);
            }

            expression.ResultType = commonResultType;

            return(expression);
        }