예제 #1
0
 private void VisitCallHelper(string functionName, ODataCallExpression node)
 {
     this.Write(functionName).Write("(");
     for (var i = 0; i < node.Arguments.Count; ++i)
     {
         this.Write(", ", @if: i > 0);
         this.Visit(node.Arguments[i]);
     }
     this.Write(")");
 }
예제 #2
0
        protected override void VisitCall(ODataCallExpression node)
        {
            // reference for different function syntax http://users.atw.hu/sqlnut/sqlnut2-chp-4-sect-4.html
            switch (node.Function)
            {
            case ODataFunction.Cast:
                this.Write("CAST(").Write(node.Arguments[0]);
                var toType = ((Type)((ODataConstantExpression)node.Arguments[1]).Value).ToODataExpressionType();
                this.Write(" AS ").Write(this.syntaxProvider.GetSqlTypeName(toType)).Write(")");
                break;

            case ODataFunction.Ceiling:
                this.VisitCallHelper(this.syntaxProvider.UseAbbreviatedCeilingFunction ? "CEIL" : "CEILING", node);
                break;

            case ODataFunction.Concat:
                this.Write("(").Write(node.Arguments[0])
                .Write(" + ")
                .Write(node.Arguments[1]).Write(")");
                break;

            case ODataFunction.Second:
            case ODataFunction.Minute:
            case ODataFunction.Hour:
            case ODataFunction.Day:
            case ODataFunction.Month:
            case ODataFunction.Year:
                this.syntaxProvider.RenderDatePartFunctionCall(node.Function, s => this.Write(s), () => this.Write(node.Arguments[0]));
                break;

            case ODataFunction.EndsWith:
                // endswith => (INDEXOF(needle, haystack) = LEN(haystack) - LEN(needle)) OR LEN(needle) = 0
                var needleLengthExpression = ODataExpression.Call(ODataFunction.Length, new[] { node.Arguments[1] });
                var endsWithExpression     = ODataExpression.BinaryOp(
                    ODataExpression.BinaryOp(
                        ODataExpression.Call(ODataFunction.IndexOf, node.Arguments),
                        ODataBinaryOp.Equal,
                        ODataExpression.BinaryOp(
                            ODataExpression.Call(ODataFunction.Length, new[] { node.Arguments[0] }),
                            ODataBinaryOp.Subtract,
                            needleLengthExpression
                            )
                        ),
                    ODataBinaryOp.Or,
                    ODataExpression.BinaryOp(
                        needleLengthExpression,
                        ODataBinaryOp.Equal,
                        ODataExpression.Constant(0)
                        )
                    );
                this.Visit(endsWithExpression);
                break;

            case ODataFunction.StartsWith:
                // startswith => INDEXOF(needle, haystack) = 0
                var startsWithExpression = ODataExpression.BinaryOp(
                    ODataExpression.Call(ODataFunction.IndexOf, node.Arguments),
                    ODataBinaryOp.Equal,
                    ODataExpression.Constant(0)
                    );
                this.Visit(startsWithExpression);
                break;

            case ODataFunction.SubstringOf:
                // substringof => INDEXOF(needle, haystack) >= 0
                var substringOfExpression = ODataExpression.BinaryOp(
                    ODataExpression.Call(ODataFunction.IndexOf, node.Arguments.Reverse()),
                    ODataBinaryOp.GreaterThanOrEqual,
                    ODataExpression.Constant(0)
                    );
                this.Visit(substringOfExpression);
                break;

            case ODataFunction.IndexOf:
                this.syntaxProvider.RenderIndexOfFunctionCall(s => this.Write(s), renderNeedleArgument: () => this.Write(node.Arguments[1]), renderHaystackArgument: () => this.Write(node.Arguments[0]));
                break;

            case ODataFunction.Floor:
                this.VisitCallHelper("FLOOR", node);
                break;

            case ODataFunction.Length:
                this.VisitCallHelper(this.syntaxProvider.StringLengthFunctionName, node);
                break;

            case ODataFunction.Replace:
                this.VisitCallHelper("REPLACE", node);
                break;

            case ODataFunction.Round:
                this.syntaxProvider.RenderRoundFunctionCall(s => this.Write(s), () => this.Write(node.Arguments[0]));
                break;

            case ODataFunction.Substring:
                this.syntaxProvider.RenderSubstringFunctionCall(s => this.Write(s), () => this.Write(node.Arguments[0]), () => this.Write(node.Arguments[1]), node.Arguments.Count > 2 ? new Action(() => this.Write(node.Arguments[2])) : null);
                break;

            case ODataFunction.ToLower:
                this.VisitCallHelper("LOWER", node);
                break;

            case ODataFunction.ToUpper:
                this.VisitCallHelper("UPPER", node);
                break;

            case ODataFunction.Trim:
                if (this.syntaxProvider.HasTwoSidedTrim)
                {
                    this.VisitCallHelper("TRIM", node);
                }
                else
                {
                    // call both LTRIM and RTRIM
                    this.VisitCallHelper("LTRIM(RTRIM", node);
                    this.Write(")");
                }
                break;

            case ODataFunction.IsOf:
                throw new NotSupportedException(node.Function.ToString());
            }
        }