Пример #1
0
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 1);
            var expression = e.Arguments[0].Accept(sqlGenerator);

            return(new SqlBuilder("int4(interval('day', ingresdate(date_trunc('day', ", expression, ") - date_trunc('year', ", expression, "))) + 1)"));
        }
 public SqlFragment Generate(DbFunctionExpression e, SqlGenerator caller)
 {
     callingGenerator = caller;
     if (bitwiseFunctions.ContainsKey(e.Function.Name))
     {
         return(BitwiseFunction(e));
     }
     else if (dateFunctions.ContainsKey(e.Function.Name))
     {
         return(GenericFunction(dateFunctions, e));
     }
     else if (stringFunctions.ContainsKey(e.Function.Name))
     {
         return(GenericFunction(stringFunctions, e));
     }
     else if (mathFunctions.ContainsKey(e.Function.Name))
     {
         return(GenericFunction(mathFunctions, e));
     }
     else if (geoFunctions.ContainsKey(e.Function.Name))
     {
         return(GenericFunction(geoFunctions, e));
     }
     else
     {
         return(UserDefinedFunction(e));
     }
 }
Пример #3
0
 /// <summary>
 /// Implements the visitor pattern for <see cref="T:System.Data.Common.CommandTrees.DbFunctionExpression"/>.
 /// </summary>
 /// <param name="expression">The <see cref="T:System.Data.Common.CommandTrees.DbFunctionExpression"/> that is visited.</param>
 public override void Visit(DbFunctionExpression expression)
 {
     foreach (DbExpression ex in expression.Arguments)
     {
         ex.Accept(this);
     }
 }
Пример #4
0
 private void VisitFunction_IsNotNull(DbFunctionExpression e)
 {
     Debug.Assert(e.ParamList.Count == 1);
     SqlBuilder.Append("(");
     e.ParamList[0].Accept(this);
     SqlBuilder.Append(" IS NOT NULL)");
 }
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 1, 2);
            SqlBuilder result = new SqlBuilder();

            if (e.Arguments.Count > 1)
            {
                if (ParenthesiseArguments)
                {
                    result.Append("(");
                }
                result.Append(e.Arguments[0].Accept(sqlGenerator));
                if (ParenthesiseArguments)
                {
                    result.Append(")");
                }
            }
            result.Append(" ", Operator, " ");

            if (ParenthesiseArguments)
            {
                result.Append("(");
            }
            result.Append(e.Arguments[e.Arguments.Count - 1].Accept(sqlGenerator));
            if (ParenthesiseArguments)
            {
                result.Append(")");
            }
            return(result);
        }
Пример #6
0
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 2);

            ISqlFragment result;

            string value;

            if (TryGetConstantString(e.Arguments[1], out value))
            {
                result = GetLikePredicate(sqlGenerator, e.Arguments[0], value, insertPercentStart: false, insertPercentEnd: true);
            }
            else
            {
                // We use RIGHT when the search param is not a constant string.
                result = new SqlBuilder(
                    "right(",
                    e.Arguments[0].Accept(sqlGenerator),
                    ", length(",
                    e.Arguments[1].Accept(sqlGenerator),
                    ")) = ",
                    e.Arguments[0].Accept(sqlGenerator)
                    );
            }

            return(WrapPredicate(result));
        }
        private SqlFragment GenericFunction(Dictionary <string, string> funcs,
                                            DbFunctionExpression e)
        {
            SqlFragment[] frags = new SqlFragment[e.Arguments.Count];

            for (int i = 0; i < e.Arguments.Count; i++)
            {
                frags[i] = e.Arguments[i].Accept(callingGenerator);
            }

            string sql;

            switch (e.Function.Name)
            {
            case "Round":
                // Special handling for Round as it has more than one signature.
                sql = HandleFunctionRound(e);
                break;

            default:
                sql = String.Format(funcs[e.Function.Name], frags);
                break;
            }

            return(new LiteralFragment(sql));
        }
Пример #8
0
        /// <summary>
        ///     Visitor pattern method for <see cref="DbFunctionExpression" />.
        /// </summary>
        /// <param name="expression"> The DbFunctionExpression that is being visited. </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="expression" />
        ///     is null
        /// </exception>
        public override void Visit(DbFunctionExpression expression)
        {
            // #433613: PreSharp warning 56506: Parameter 'expression' to this public method must be validated: A null-dereference can occur here.
            Check.NotNull(expression, "expression");

            VisitExpressionList(expression.Arguments);
        }
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 2, 3);
            var expression = e.Arguments[0].Accept(sqlGenerator);
            var pattern    = e.Arguments[1].Accept(sqlGenerator);

            if (e.Arguments.Count == 3)
            {
                var ignoreCase = e.Arguments[2] as DbConstantExpression;
                Debug.Assert(ignoreCase != null && ignoreCase.Value is bool, string.Format("{0}: Parameter ignoreCase should be a boolean", e.Function.Name));
                if (ignoreCase != null && ignoreCase.Value is bool)
                {
                    if ((bool)ignoreCase.Value)
                    {
                        return(WrapPredicate(new SqlBuilder(
                                                 "lowercase(", expression, ") like lowercase(", pattern, ") escape '", EFIngresProviderManifest.LikeEscapeCharString, "'"
                                                 )));
                    }
                }
            }

            return(WrapPredicate(new SqlBuilder(
                                     expression, " like ", pattern, " escape '", EFIngresProviderManifest.LikeEscapeCharString, "'"
                                     )));
        }
Пример #10
0
 public override void Visit(DbFunctionExpression e)
 {
     Begin(e);
     Dump(e.Function);
     Dump(e.Arguments, "Arguments", "Argument");
     End(e);
 }
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            var result = new SqlBuilder(Name);

            HandleFunctionArgumentsDefault(sqlGenerator, e, result);
            return(result);
        }
Пример #12
0
 private void VisitFunction_Sum(DbFunctionExpression e)
 {
     Debug.Assert(e.ParamList.Count == 1);
     SqlBuilder.Append("SUM(");
     e.ParamList[0].Accept(this);
     SqlBuilder.Append(")");
 }
Пример #13
0
 public override void Visit(DbFunctionExpression e)
 {
     Check.NotNull <DbFunctionExpression>(e, nameof(e));
     this.Begin((DbExpression)e);
     this.Dump(e.Function);
     this.Dump((IEnumerable <DbExpression>)e.Arguments, "Arguments", "Argument");
     this.End((DbExpression)e);
 }
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 2);
            var expression = e.Arguments[0].Accept(sqlGenerator);
            var interval   = CreateInterval(new SqlBuilder("int4(", e.Arguments[1].Accept(sqlGenerator), ")"));

            return(new SqlBuilder("( ", expression, " + ", interval, " )"));
        }
Пример #15
0
            public override TreeNode Visit(DbFunctionExpression e)
            {
                Check.NotNull(e, "e");

                var funcInfo = VisitFunction(e.Function, e.Arguments);

                return(funcInfo);
            }
Пример #16
0
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 2);
            var left  = e.Arguments[0].Accept(sqlGenerator);
            var right = e.Arguments[1].Accept(sqlGenerator);

            return(WrapPredicate(new SqlBuilder(left, " ", Operator, " ", right)));
        }
Пример #17
0
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 2);
            var startExpression = e.Arguments[0].Accept(sqlGenerator);
            var endExpression   = e.Arguments[1].Accept(sqlGenerator);

            return(new SqlBuilder("int4(interval('", Unit, "', ingresdate(", endExpression, " - ", startExpression, ")))"));
        }
Пример #18
0
 public override void Visit(DbFunctionExpression expression)
 {
     Write(expression);
     _depth++;
     WriteLine("Function: " + expression.Function.FullName);
     Write("Arguments", expression.Arguments);
     _depth--;
 }
Пример #19
0
 private void VisitFunction_NotLike(DbFunctionExpression e)
 {
     Debug.Assert(e.ParamList.Count == 2);
     SqlBuilder.Append('(');
     e.ParamList[0].Accept(this);
     SqlBuilder.Append(" NOT LIKE ");
     e.ParamList[1].Accept(this);
     SqlBuilder.Append(')');
 }
Пример #20
0
 private void VisitFunction_Contains(DbFunctionExpression e)
 {
     Debug.Assert(e.ParamList.Count == 2);
     SqlBuilder.Append("(CHARINDEX(");
     e.ParamList[1].Accept(this);
     SqlBuilder.Append(", ");
     e.ParamList[0].Accept(this);
     SqlBuilder.Append(") > 0)");
 }
Пример #21
0
 private void VisitFunction_IfNull(DbFunctionExpression e)
 {
     Debug.Assert(e.ParamList.Count == 2);
     SqlBuilder.Append("ISNULL(");
     e.ParamList[0].Accept(this);
     SqlBuilder.Append(", ");
     e.ParamList[1].Accept(this);
     SqlBuilder.Append(')');
 }
Пример #22
0
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 2);
            var target = e.Arguments[0].Accept(sqlGenerator);
            var str    = e.Arguments[1].Accept(sqlGenerator);
            var locate = new SqlBuilder("locate(", str, ", ", target, ")");

            return(new SqlBuilder("case when ", locate, " <= size(", str, ") then int4(", locate, ") else int4(0) end"));
        }
Пример #23
0
        public override void Visit(DbFunctionExpression e)
        {
            Check.NotNull(e, "e");

            Begin(e);
            Dump(e.Function);
            Dump(e.Arguments, "Arguments", "Argument");
            End(e);
        }
Пример #24
0
 public static void Verify(this DbFunctionExpression expression, FunctionKey functionKey, params Column[] paramList)
 {
     Assert.AreEqual(functionKey, expression.FunctionKey);
     Assert.AreEqual(paramList.Length, expression.ParamList.Count);
     for (int i = 0; i < paramList.Length; i++)
     {
         Assert.AreEqual(paramList[i].DbExpression, expression.ParamList[i]);
     }
 }
Пример #25
0
        public override object Visit(DbFunctionExpression expression)
        {
            foreach (var arg in expression.Arguments)
            {
                this.Visit(arg);
            }

            return(null);
        }
Пример #26
0
        public override ISqlFragment HandleFunction(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            AssertArgumentCount(e, 3);

            var hour   = e.Arguments[0].Accept(sqlGenerator);
            var minute = e.Arguments[1].Accept(sqlGenerator);
            var second = e.Arguments[2].Accept(sqlGenerator);

            return(new SqlBuilder("time(", Time(hour, minute, second), ")"));
        }
Пример #27
0
        /// <summary>
        /// Dispatches the special function processing to the appropriate handler
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static ISqlFragment Handle(SqlGenerator sqlGenerator, DbFunctionExpression e)
        {
            FunctionHandler function;

            if (_canonicalFunctions.TryGetValue(e.Function.Name, out function))
            {
                return(function.HandleFunction(sqlGenerator, e));
            }
            return(_defaultCanonicalFunction.HandleFunction(sqlGenerator, e));
        }
 public override void Visit(DbFunctionExpression expression)
 {
     Check.NotNull <DbFunctionExpression>(expression, nameof(expression));
     base.Visit(expression);
     if (ViewValidator.ViewExpressionValidator.IsStoreSpaceOrCanonicalFunction(this.StoreItemCollection, expression.Function))
     {
         return;
     }
     this._errors.Add(new EdmSchemaError(Strings.Mapping_UnsupportedFunctionCall_QueryView((object)this._setMapping.Set.Name, (object)expression.Function.Identity), 2112, EdmSchemaErrorSeverity.Error, this._setMapping.EntityContainerMapping.SourceLocation, this._setMapping.StartLineNumber, this._setMapping.StartLinePosition));
 }
            /// <summary>
            /// Implements the visitor pattern for <see cref="T:System.Data.Common.CommandTrees.DbFunctionExpression"/>.
            /// </summary>
            /// <param name="expression">The <see cref="T:System.Data.Common.CommandTrees.DbFunctionExpression"/> that is visited.</param>
            public override void Visit(DbFunctionExpression expression)
            {
                if (expression == null)
                {
                    throw new ArgumentNullException("expression");
                }

                base.Visit(expression);
                this.functionsUsed.Add(expression.Function);
            }
Пример #30
0
        public override Expression Visit(DbFunctionExpression expression)
        {
            Expression[] arguments = new Expression[expression.Arguments.Count];

            for (int i = 0; i < expression.Arguments.Count; i++)
            {
                arguments[i] = this.Visit(expression.Arguments[i]);
            }

            return this.functionMapper.CreateMethodCall(expression.Function, arguments);
        }
Пример #31
0
        public override Expression Visit(DbFunctionExpression expression)
        {
            Expression[] arguments = new Expression[expression.Arguments.Count];

            for (int i = 0; i < expression.Arguments.Count; i++)
            {
                arguments[i] = this.Visit(expression.Arguments[i]);
            }

            return(this.functionMapper.CreateMethodCall(expression.Function, arguments));
        }
Пример #32
0
 public SqlFragment Generate(DbFunctionExpression e, SqlGenerator caller)
 {
     callingGenerator = caller;
     if (bitwiseFunctions.ContainsKey(e.Function.Name))
         return BitwiseFunction(e);
     else if (dateFunctions.ContainsKey(e.Function.Name))
         return GenericFunction(dateFunctions, e);
     else if (stringFunctions.ContainsKey(e.Function.Name))
         return GenericFunction(stringFunctions, e);
     else if (mathFunctions.ContainsKey(e.Function.Name))
         return GenericFunction(mathFunctions, e);
     return null;
 }
        /// <summary>
        /// Common handler for the canonical functions ROUND and TRUNCATE
        /// </summary>
        /// <param name="e"></param>
        /// <param name="round"></param>
        /// <returns></returns>
        private static ISqlFragment HandleCanonicalFunctionRoundOrTruncate(SqlGenerator sqlgen, DbFunctionExpression e, bool round)
        {
            var result = new SqlBuilder();

            // Do not add the cast for the Round() overload having two arguments. 
            // Round(Single,Int32) maps to Round(Double,Int32)due to implicit casting. 
            // We don't need to cast in that case, since the server returned type is same 
            // as the expected  type. Cast is only required for the overload - Round(Single)
            var requiresCastToSingle = false;
            if (e.Arguments.Count == 1)
            {
                requiresCastToSingle = CastReturnTypeToSingle(e);
                if (requiresCastToSingle)
                {
                    result.Append(" CAST(");
                }
            }
            result.Append("ROUND(");

            Debug.Assert(e.Arguments.Count <= 2, "Round or truncate should have at most 2 arguments");
            result.Append(e.Arguments[0].Accept(sqlgen));
            result.Append(", ");

            if (e.Arguments.Count > 1)
            {
                result.Append(e.Arguments[1].Accept(sqlgen));
            }
            else
            {
                result.Append("0");
            }

            if (!round)
            {
                result.Append(", 1");
            }

            result.Append(")");

            if (requiresCastToSingle)
            {
                result.Append(" AS real)");
            }
            return result;
        }
 private static ISqlFragment HandleSpatialCanonicalFunction(
     SqlGenerator sqlgen, DbFunctionExpression functionExpression, PrimitiveTypeKind spatialTypeKind)
 {
     Debug.Assert(
         spatialTypeKind == PrimitiveTypeKind.Geography || spatialTypeKind == PrimitiveTypeKind.Geometry,
         "Spatial function does not refer to a valid spatial primitive type kind?");
     if (spatialTypeKind == PrimitiveTypeKind.Geography)
     {
         return HandleSpatialCanonicalFunction(
             sqlgen, functionExpression, _geographyFunctionNameToStaticMethodHandlerDictionary,
             _geographyFunctionNameToInstancePropertyNameDictionary, _geographyRenamedInstanceMethodFunctionDictionary);
     }
     else
     {
         return HandleSpatialCanonicalFunction(
             sqlgen, functionExpression, _geometryFunctionNameToStaticMethodHandlerDictionary,
             _geometryFunctionNameToInstancePropertyNameDictionary, _geometryRenamedInstanceMethodFunctionDictionary);
     }
 }
 private static ISqlFragment WriteInstanceFunctionCall(
     SqlGenerator sqlgen, string functionName, DbFunctionExpression functionExpression, bool isPropertyAccess)
 {
     return WriteInstanceFunctionCall(sqlgen, functionName, functionExpression, isPropertyAccess, null);
 }
        /// <summary>
        /// Default handling on function arguments.
        /// Appends the list of arguments to the given result
        /// If the function is niladic it does not append anything, 
        /// otherwise it appends (arg1, arg2, .., argn)
        /// </summary>
        /// <param name="e"></param>
        /// <param name="result"></param>
        private static void HandleFunctionArgumentsDefault(SqlGenerator sqlgen, DbFunctionExpression e, SqlBuilder result)
        {
            var isNiladicFunction = e.Function.NiladicFunctionAttribute;
            Debug.Assert(
                !(isNiladicFunction && (0 < e.Arguments.Count)),
                "function attributed as NiladicFunction='true' in the provider manifest cannot have arguments");
            if (isNiladicFunction && e.Arguments.Count > 0)
            {
                throw new MetadataException(Strings.SqlGen_NiladicFunctionsCannotHaveParameters);
            }

            if (!isNiladicFunction)
            {
                WriteFunctionArguments(sqlgen, e.Arguments, result);
            }
        }
 /// <summary>
 /// Handler for special canonical functions
 /// </summary>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment HandleSpecialCanonicalFunction(SqlGenerator sqlgen, DbFunctionExpression e)
 {
     return HandleSpecialFunction(_canonicalFunctionHandlers, sqlgen, e);
 }
 /// <summary>
 /// Default handling for functions with a given name.
 /// Translates them to FunctionName(arg1, arg2, ..., argn)
 /// </summary>
 /// <param name="e"></param>
 /// <param name="functionName"></param>
 /// <returns></returns>
 private static ISqlFragment HandleFunctionDefaultGivenName(SqlGenerator sqlgen, DbFunctionExpression e, string functionName)
 {
     // NOTE: The order of checks is important in case of CHARINDEX.
     if (CastReturnTypeToInt64(e))
     {
         return HandleFunctionDefaultCastReturnValue(sqlgen, e, functionName, "bigint");
     }
     else if (CastReturnTypeToInt32(sqlgen, e))
     {
         return HandleFunctionDefaultCastReturnValue(sqlgen, e, functionName, "int");
     }
     else if (CastReturnTypeToInt16(e))
     {
         return HandleFunctionDefaultCastReturnValue(sqlgen, e, functionName, "smallint");
     }
     else if (CastReturnTypeToSingle(e))
     {
         return HandleFunctionDefaultCastReturnValue(sqlgen, e, functionName, "real");
     }
     else
     {
         return HandleFunctionDefaultCastReturnValue(sqlgen, e, functionName, null);
     }
 }
        /// <summary>
        /// Determines whether the given function is a canonical function the translates
        /// to a spatial (geography/geometry) property access or method call.
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        private static bool IsSpatialCanonicalFunction(DbFunctionExpression e, out PrimitiveTypeKind spatialTypeKind)
        {
            if (e.Function.IsCanonicalFunction())
            {
                if (e.ResultType.IsSpatialType(out spatialTypeKind))
                {
                    return true;
                }

                foreach (var functionParameter in e.Function.Parameters)
                {
                    if (functionParameter.TypeUsage.IsSpatialType(out spatialTypeKind))
                    {
                        return true;
                    }
                }
            }

            spatialTypeKind = default(PrimitiveTypeKind);
            return false;
        }
 /// <summary>
 /// Determines whether the given function is a store function that
 /// requires special handling
 /// </summary>
 /// <param name="e"></param>
 /// <returns></returns>
 private static bool IsSpecialStoreFunction(DbFunctionExpression e)
 {
     return IsStoreFunction(e.Function)
            && _storeFunctionHandlers.ContainsKey(e.Function.Name);
 }
 private static ISqlFragment HandleSpatialStaticMethodFunctionAppendSrid(
     SqlGenerator sqlgen, DbFunctionExpression functionExpression, string functionName)
 {
     if (functionExpression.Arguments.Count == 2)
     {
         return HandleFunctionDefaultGivenName(sqlgen, functionExpression, functionName);
     }
     else
     {
         var sridExpression = functionExpression.ResultType.IsPrimitiveType(PrimitiveTypeKind.Geometry)
                                  ? _defaultGeometrySridExpression
                                  : _defaultGeographySridExpression;
         var result = new SqlBuilder();
         result.Append(functionName);
         WriteFunctionArguments(sqlgen, functionExpression.Arguments.Concat(new[] { sridExpression }), result);
         return result;
     }
 }
        private static ISqlFragment HandleSpatialFromTextFunction(SqlGenerator sqlgen, DbFunctionExpression functionExpression)
        {
            var functionNameWithSrid = functionExpression.ResultType.IsPrimitiveType(PrimitiveTypeKind.Geometry)
                                           ? "geometry::STGeomFromText"
                                           : "geography::STGeomFromText";
            var functionNameWithoutSrid = functionExpression.ResultType.IsPrimitiveType(PrimitiveTypeKind.Geometry)
                                              ? "geometry::Parse"
                                              : "geography::Parse";

            if (functionExpression.Arguments.Count == 2)
            {
                return HandleFunctionDefaultGivenName(sqlgen, functionExpression, functionNameWithSrid);
            }
            else
            {
                Debug.Assert(functionExpression.Arguments.Count == 1, "FromText function should have text or text + srid arguments only");
                return HandleFunctionDefaultGivenName(sqlgen, functionExpression, functionNameWithoutSrid);
            }
        }
 private static ISqlFragment HandleSpatialFromBinaryFunction(SqlGenerator sqlgen, DbFunctionExpression functionExpression)
 {
     return HandleSpatialStaticMethodFunctionAppendSrid(
         sqlgen, functionExpression,
         functionExpression.ResultType.IsPrimitiveType(PrimitiveTypeKind.Geometry)
             ? "geometry::STGeomFromWKB"
             : "geography::STGeomFromWKB");
 }
 /// <summary>
 /// Handle the canonical function Abs(). 
 /// </summary>
 /// <param name="sqlgen"></param>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment HandleCanonicalFunctionAbs(SqlGenerator sqlgen, DbFunctionExpression e)
 {
     // Convert the call to Abs(Byte) to a no-op, since Byte is an unsigned type. 
     if (e.Arguments[0].ResultType.IsPrimitiveType(PrimitiveTypeKind.Byte))
     {
         var result = new SqlBuilder();
         result.Append(e.Arguments[0].Accept(sqlgen));
         return result;
     }
     else
     {
         return HandleFunctionDefault(sqlgen, e);
     }
 }
        internal static ISqlFragment GenerateFunctionCallSql(SqlGenerator sqlgen, DbFunctionExpression functionExpression)
        {
            //
            // check if function requires special case processing, if so, delegates to it
            //
            if (IsSpecialCanonicalFunction(functionExpression))
            {
                return HandleSpecialCanonicalFunction(sqlgen, functionExpression);
            }

            if (IsSpecialStoreFunction(functionExpression))
            {
                return HandleSpecialStoreFunction(sqlgen, functionExpression);
            }

            PrimitiveTypeKind spatialTypeKind;
            if (IsSpatialCanonicalFunction(functionExpression, out spatialTypeKind))
            {
                return HandleSpatialCanonicalFunction(sqlgen, functionExpression, spatialTypeKind);
            }

            return HandleFunctionDefault(sqlgen, functionExpression);
        }
        /// <summary>
        /// TRIM(string) -> LTRIM(RTRIM(string))
        /// </summary>
        /// <param name="sqlgen"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private static ISqlFragment HandleCanonicalFunctionTrim(SqlGenerator sqlgen, DbFunctionExpression e)
        {
            var result = new SqlBuilder();

            result.Append("LTRIM(RTRIM(");

            Debug.Assert(e.Arguments.Count == 1, "Trim should have one argument");
            result.Append(e.Arguments[0].Accept(sqlgen));

            result.Append("))");

            return result;
        }
 /// <summary>
 /// Determines whether the given function is a canonical function that
 /// requires special handling
 /// </summary>
 /// <param name="e"></param>
 /// <returns></returns>
 private static bool IsSpecialCanonicalFunction(DbFunctionExpression e)
 {
     return e.Function.IsCanonicalFunction()
            && _canonicalFunctionHandlers.ContainsKey(e.Function.Name);
 }
 /// <summary>
 ///  Function rename ToUpper -> UPPER
 /// </summary>
 /// <param name="sqlgen"></param>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment HandleCanonicalFunctionToUpper(SqlGenerator sqlgen, DbFunctionExpression e)
 {
     return HandleFunctionDefaultGivenName(sqlgen, e, "UPPER");
 }
 /// <summary>
 /// Default handling for functions. 
 /// Translates them to FunctionName(arg1, arg2, ..., argn)
 /// </summary>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment HandleFunctionDefault(SqlGenerator sqlgen, DbFunctionExpression e)
 {
     return HandleFunctionDefaultGivenName(sqlgen, e, null);
 }
 /// <summary>
 /// Handler for EndsWith. Wraps the normal translation with a case statement
 /// </summary>
 /// <param name="sqlgen"></param>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment HandleCanonicalFunctionEndsWith(SqlGenerator sqlgen, DbFunctionExpression e)
 {
     return WrapPredicate(HandleCanonicalFunctionEndsWith, sqlgen, e);
 }
        /// <summary>
        /// Default handling for functions with a given name and given return value cast.
        /// Translates them to CAST(FunctionName(arg1, arg2, ..., argn) AS returnType)
        /// </summary>
        /// <param name="e"></param>
        /// <param name="functionName"></param>
        /// <param name="returnType"></param>
        /// <returns></returns>
        private static ISqlFragment HandleFunctionDefaultCastReturnValue(
            SqlGenerator sqlgen, DbFunctionExpression e, string functionName, string returnType)
        {
            return WrapWithCast(
                returnType, result =>
                                {
                                    if (functionName == null)
                                    {
                                        WriteFunctionName(result, e.Function);
                                    }
                                    else
                                    {
                                        result.Append(functionName);
                                    }

                                    HandleFunctionArgumentsDefault(sqlgen, e, result);
                                });
        }
 /// <summary>
 /// Turns a predicate into a statement returning a bit
 /// PREDICATE => CASE WHEN (PREDICATE) THEN CAST(1 AS BIT) WHEN (NOT (PREDICATE)) CAST (O AS BIT) END
 /// The predicate is produced by the given predicateTranslator.
 /// </summary>
 /// <param name="predicateTranslator"></param>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment WrapPredicate(
     Func<SqlGenerator, IList<DbExpression>, SqlBuilder, SqlBuilder> predicateTranslator, SqlGenerator sqlgen, DbFunctionExpression e)
 {
     var result = new SqlBuilder();
     result.Append("CASE WHEN (");
     predicateTranslator(sqlgen, e.Arguments, result);
     result.Append(") THEN cast(1 as bit) WHEN ( NOT (");
     predicateTranslator(sqlgen, e.Arguments, result);
     result.Append(")) THEN cast(0 as bit) END");
     return result;
 }
 /// <summary>
 /// Handler for functions that need to be translated to different store function based on version
 /// </summary>
 /// <param name="e"></param>
 /// <param name="preKatmaiName"></param>
 /// <param name="katmaiName"></param>
 /// <returns></returns>
 private static ISqlFragment HandleFunctionGivenNameBasedOnVersion(
     SqlGenerator sqlgen, DbFunctionExpression e, string preKatmaiName, string katmaiName)
 {
     if (sqlgen.IsPreKatmai)
     {
         return HandleFunctionDefaultGivenName(sqlgen, e, preKatmaiName);
     }
     return HandleFunctionDefaultGivenName(sqlgen, e, katmaiName);
 }
        /// <summary>
        /// determines if the function requires the return type be enforeced by use of a cast expression
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        internal static bool CastReturnTypeToInt32(SqlGenerator sqlgen, DbFunctionExpression e)
        {
            if (!_functionRequiresReturnTypeCastToInt32.Contains(e.Function.FullName))
            {
                return false;
            }

            return e.Arguments.Select(t => sqlgen.StoreItemCollection.StoreProviderManifest.GetStoreType(t.ResultType))
                .Any(storeType => _maxTypeNames.Contains(storeType.EdmType.Name));
        }
 /// <summary>
 /// Dispatches the special function processing to the appropriate handler
 /// </summary>
 /// <param name="handlers"></param>
 /// <param name="e"></param>
 /// <returns></returns>
 private static ISqlFragment HandleSpecialFunction(
     Dictionary<string, FunctionHandler> handlers, SqlGenerator sqlgen, DbFunctionExpression e)
 {
     Debug.Assert(
         handlers.ContainsKey(e.Function.Name),
         "Special handling should be called only for functions in the list of special functions");
     return handlers[e.Function.Name](sqlgen, e);
 }
 /// <summary>
 /// determines if the function requires the return type be enforeced by use of a cast expression
 /// </summary>
 /// <param name="e"></param>
 /// <returns></returns>
 internal static bool CastReturnTypeToInt16(DbFunctionExpression e)
 {
     return CastReturnTypeToGivenType(e, _functionRequiresReturnTypeCastToInt16, PrimitiveTypeKind.Int16);
 }
        private static ISqlFragment HandleSpatialCanonicalFunction(
            SqlGenerator sqlgen,
            DbFunctionExpression functionExpression,
            Dictionary<string, FunctionHandler> staticMethodsMap,
            Dictionary<string, string> instancePropertiesMap,
            Dictionary<string, string> renamedInstanceMethodsMap)
        {
            FunctionHandler staticFunctionHandler;
            string instancePropertyName;
            if (staticMethodsMap.TryGetValue(functionExpression.Function.Name, out staticFunctionHandler))
            {
                return staticFunctionHandler(sqlgen, functionExpression);
            }
            else if (instancePropertiesMap.TryGetValue(functionExpression.Function.Name, out instancePropertyName))
            {
                Debug.Assert(
                    functionExpression.Function.Parameters.Count > 0
                    && functionExpression.Function.Parameters[0].TypeUsage.IsSpatialType(),
                    "Instance property function does not have instance parameter?");
                return WriteInstanceFunctionCall(
                    sqlgen, instancePropertyName, functionExpression, isPropertyAccess: true, castReturnTypeTo: null);
            }
            else
            {
                // Default translation pattern is instance method; the instance method name may differ from that of the spatial canonical function
                Debug.Assert(
                    functionExpression.Function.Parameters.Count > 0
                    && functionExpression.Function.Parameters[0].TypeUsage.IsSpatialType(),
                    "Instance method function does not have instance parameter?");
                string effectiveFunctionName;
                if (!renamedInstanceMethodsMap.TryGetValue(functionExpression.Function.Name, out effectiveFunctionName))
                {
                    effectiveFunctionName = functionExpression.Function.Name;
                }

                // For AsGml() calls, the XML result must be cast to string to match the declared function result type.
                string castResultType = null;
                if (effectiveFunctionName == "AsGml")
                {
                    castResultType = "nvarchar(max)";
                }
                return WriteInstanceFunctionCall(
                    sqlgen, effectiveFunctionName, functionExpression, isPropertyAccess: false, castReturnTypeTo: castResultType);
            }
        }
 /// <summary>
 /// determines if the function requires the return type be enforeced by use of a cast expression
 /// </summary>
 /// <param name="e"></param>
 /// <returns></returns>
 internal static bool CastReturnTypeToSingle(DbFunctionExpression e)
 {
     //Do not add the cast for the Round() overload having 2 arguments. 
     //Round(Single,Int32) maps to Round(Double,Int32)due to implicit casting. 
     //We don't need to cast in that case, since we expect a Double as return type there anyways.
     return CastReturnTypeToGivenType(e, _functionRequiresReturnTypeCastToSingle, PrimitiveTypeKind.Single);
 }
        private static ISqlFragment WriteInstanceFunctionCall(
            SqlGenerator sqlgen, string functionName, DbFunctionExpression functionExpression, bool isPropertyAccess,
            string castReturnTypeTo)
        {
            Debug.Assert(
                !isPropertyAccess || functionExpression.Arguments.Count == 1,
                "Property accessor instance functions should have only the single instance argument");

            return WrapWithCast(
                castReturnTypeTo, result =>
                                      {
                                          var instanceExpression = functionExpression.Arguments[0];

                                          // Write the instance - if this is another function call, it need not be enclosed in parentheses.
                                          if (instanceExpression.ExpressionKind
                                              != DbExpressionKind.Function)
                                          {
                                              sqlgen.ParenthesizeExpressionIfNeeded(instanceExpression, result);
                                          }
                                          else
                                          {
                                              result.Append(instanceExpression.Accept(sqlgen));
                                          }
                                          result.Append(".");
                                          result.Append(functionName);

                                          if (!isPropertyAccess)
                                          {
                                              WriteFunctionArguments(sqlgen, functionExpression.Arguments.Skip(1), result);
                                          }
                                      });
        }
        /// <summary>
        /// Determines if the function requires the return type be enforced by use of a cast expression
        /// </summary>
        /// <param name="e"></param>
        /// <param name="functionsRequiringReturnTypeCast"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static bool CastReturnTypeToGivenType(
            DbFunctionExpression e, ISet<string> functionsRequiringReturnTypeCast, PrimitiveTypeKind type)
        {
            if (!functionsRequiringReturnTypeCast.Contains(e.Function.FullName))
            {
                return false;
            }

            return e.Arguments.Any(t => t.ResultType.IsPrimitiveType(type));
        }