private void DateFunctions()
        {
            Register(config => config.Named("date")
                     .WhenExecute(context => Simple(context, () => SystemFunctions.CurrentDate(context.Request)))
                     .ReturnsType(PrimitiveTypes.Date()));

            Register(config => config.Named("time")
                     .WhenExecute(context => Simple(context, () => SystemFunctions.CurrentTime(context.Request)))
                     .ReturnsType(PrimitiveTypes.Time()));

            Register(config => config.Named("timestamp")
                     .WhenExecute(context => Simple(context, () => SystemFunctions.CurrentTimeStamp(context.Request)))
                     .ReturnsDateTime());

            Register(config => config.Named("system_date")
                     .WhenExecute(context => Simple(context, SystemFunctions.SystemDate))
                     .ReturnsType(PrimitiveTypes.Date()));

            Register(config => config.Named("system_time")
                     .WhenExecute(context => Simple(context, SystemFunctions.SystemTime))
                     .ReturnsType(PrimitiveTypes.Time()));

            Register(config => config
                     .Named("system_timestamp")
                     .WhenExecute(context => Simple(context, SystemFunctions.SystemTimeStamp))
                     .ReturnsDateTime());

            // ADD_DATE
            Register(config => config.Named("add_date")
                     .WithDateTimeParameter("date")
                     .WithStringParameter("datePart")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.AddDate(args[0], args[1], args[2])))
                     .ReturnsDateTime());

            // EXTRACT
            Register(config => config.Named("extract")
                     .WithDateTimeParameter("date")
                     .WithStringParameter("unit")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Extract(args[0], args[1])))
                     .ReturnsNumeric());

            // DATEFORMAT
            Register(config => config.Named("dateformat")
                     .WithDateTimeParameter("date")
                     .WithStringParameter("format")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.DateFormat(args[0], args[1])))
                     .ReturnsString());

            // NEXT_DAY
            Register(config => config
                     .Named("next_day")
                     .WithDateTimeParameter("date")
                     .WithStringParameter("dayOfWeek")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.NextDay(args[0], args[1])))
                     .ReturnsDateTime());
        }
            public static InvokeResult Execute(InvokeContext context)
            {
                var value      = context.EvaluatedArguments[0];
                var typeArg    = context.EvaluatedArguments[1];
                var typeString = typeArg.AsVarChar().Value.ToString();
                var type       = SqlType.Parse(context.Request.Context, typeString);

                return(context.Result(SystemFunctions.Cast(value, type)));
            }
        private void MathFunctions()
        {
            Register(config => config.Named("cos")
                     .WithNumericParameter("value")
                     .ReturnsNumeric()
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Cos(args[0]))));

            Register(config => config.Named("cosh")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.CosH(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("log2")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Log2(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("log")
                     .WithNumericParameter("value")
                     .WithNumericParameter("newBase")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Log(args[0], args[1]))));

            Register(config => config.Named("abs")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Abs(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("tan")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Tan(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("tanh")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.TanH(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("sin")
                     .WithNumericParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Sin(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("round")
                     .WithNumericParameter("value")
                     .WithNumericParameter("precision")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.Round(args[0], args[1])))
                     .ReturnsNumeric());

            // TODO: support function overloads
            //Register(config => config.Named("round")
            //	.WithNumericParameter("value")
            //	.WhenExecute(context => Simple(context, args => SystemFunctions.Round(args[0])))
            //	.ReturnsNumeric());
        }
        private void AddSequenceFunctions()
        {
            Register(config => config.Named("uniquekey")
                     .WithStringParameter("table")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.UniqueKey(context.Request, args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("curval")
                     .WithStringParameter("table")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.CurrentValue(context.Request, args[0])))
                     .ReturnsNumeric());
        }
        private void ConversionFunctions()
        {
            Register(config => config.Named("cast")
                     .WithDynamicParameter("value")
                     .WithStringParameter("destType")
                     .WhenExecute(Cast.Execute)
                     .ReturnsType(Cast.ReturnType));

            Register(config => config.Named("tonumber")
                     .WithDynamicParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToNumber(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("tostring")
                     .WithDynamicParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToString(args[0])))
                     .ReturnsString());

            Register(config => config.Named("tobinary")
                     .WithDynamicParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToBinary(args[0])))
                     .ReturnsType(PrimitiveTypes.Binary()));

            // Date Conversions
            Register(config => config.Named("todate")
                     .WithStringParameter("value")
                     .WhenExecute(context => Simple(context, objects => SystemFunctions.ToDate(objects[0])))
                     .ReturnsType(PrimitiveTypes.Date()));

            Register(config => config.Named("todatetime")
                     .WithStringParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToDateTime(args[0])))
                     .ReturnsType(PrimitiveTypes.DateTime()));

            Register(config => config.Named("totimestamp")
                     .WithParameter(p => p.Named("value").OfStringType())
                     .WithParameter(p => p.Named("ts").OfStringType())
                     .WhenExecute(context => {
                if (context.ArgumentCount == 1)
                {
                    return(Simple(context, args => SystemFunctions.ToTimeStamp(args[0])));
                }
                if (context.ArgumentCount == 2)
                {
                    return(Simple(context, args => SystemFunctions.ToTimeStamp(args[0], args[1])));
                }

                throw new InvalidOperationException("Invalid number of arguments for TOTIMESTAMP function");
            })
                     .ReturnsType(PrimitiveTypes.TimeStamp()));
        }
        private void AddMiscFunctions()
        {
            Register(config => config.Named("iif")
                     .WithBooleanParameter("condition")
                     .WithDynamicParameter("ifTrue")
                     .WithDynamicParameter("ifFalse")
                     .WhenExecute(context => SystemFunctions.Iif(context))
                     .ReturnsType(IifReturnType));

            Register(config => config.Named("i_frule_convert")
                     .WithDynamicParameter("rule")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.FRuleConvert(args[0])))
                     .ReturnsType(context => {
                var argType = ReturnType(context.Arguments[0], context);
                return(argType is StringType ? (SqlType)PrimitiveTypes.Numeric() : (SqlType)PrimitiveTypes.String());
            }));
        }
        private void AddConversionFunctions()
        {
            Register(config => config.Named("cast")
                     .WithDynamicParameter("value")
                     .WithStringParameter("destType")
                     .WhenExecute(Cast.Execute)
                     .ReturnsType(Cast.ReturnType));

            Register(config => config.Named("tonumber")
                     .WithDynamicParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToNumber(args[0])))
                     .ReturnsNumeric());

            Register(config => config.Named("tostring")
                     .WithDynamicParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToString(args[0])))
                     .ReturnsString());

            Register(config => config.Named("tobinary")
                     .WithDynamicParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToBinary(args[0])))
                     .ReturnsType(PrimitiveTypes.Binary()));

            // Date Conversions
            Register(config => config.Named("todate")
                     .WithStringParameter("value")
                     .WhenExecute(context => Simple(context, objects => SystemFunctions.ToDate(objects[0])))
                     .ReturnsType(PrimitiveTypes.Date()));

            Register(config => config.Named("todatetime")
                     .WithStringParameter("value")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToDateTime(args[0])))
                     .ReturnsType(PrimitiveTypes.DateTime()));

            Register(config => config.Named("totimestamp")
                     .WithParameter(p => p.Named("value").OfStringType())
                     .WhenExecute(context => Simple(context, args => SystemFunctions.ToTimeStamp(args[0])))
                     .ReturnsType(PrimitiveTypes.TimeStamp()));
        }
 private void AddSecurityFunctions()
 {
     Register(config => config.Named("user")
              .WhenExecute(context => context.Result(SystemFunctions.User(context.Request)))
              .ReturnsString());
 }
        private void MiscFunctions()
        {
            Register(config => config.Named("iif")
                     .WithBooleanParameter("condition")
                     .WithDynamicParameter("ifTrue")
                     .WithDynamicParameter("ifFalse")
                     .WhenExecute(context => Simple(context, args => {
                Field result = Field.Null();

                var condition = args[0];
                if (condition.Type is BooleanType)
                {
                    if (condition.Equals(Field.BooleanTrue))
                    {
                        result = args[1];
                    }
                    else if (condition.Equals(Field.BooleanFalse))
                    {
                        result = args[2];
                    }
                }

                return(result);
            }))
                     .ReturnsType(IifReturnType));

            Register(config => config.Named("i_frule_convert")
                     .WithDynamicParameter("rule")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.FRuleConvert(args[0])))
                     .ReturnsType(context => {
                var argType = ReturnType(context.Arguments[0].Value, context);
                return(argType is StringType ? PrimitiveTypes.Numeric() : (SqlType)PrimitiveTypes.String());
            }));

            Register(config => config.Named("i_privilege_string")
                     .WithNumericParameter("privBit")
                     .WhenExecute(context => Simple(context, args => SystemFunctions.PrivilegeString(args[0])))
                     .ReturnsString());

            // VERSION
            Register(config => config
                     .Named("version")
                     .WhenExecute(context => context.Result(Field.String(context.Request.Query.Session.Database().Version.ToString(3))))
                     .ReturnsString());

            // COALESCE
            Register(config => config.Named("coalesce")
                     .WhenExecute(context => Simple(context, args => {
                var argc = args.Length;
                for (int i = 0; i < argc; i++)
                {
                    var arg = args[i];
                    if (!Field.IsNullField(arg))
                    {
                        return(arg);
                    }
                }

                return(Field.Null());
            }))
                     .ReturnsType(context => {
                var argc = context.Arguments.Length;
                for (int i = 0; i < argc; i++)
                {
                    var returnType = context.Arguments[i].Value.ReturnType(context.Request, context.VariableResolver);
                    if (!(returnType is NullType))
                    {
                        return(returnType);
                    }
                }

                return(PrimitiveTypes.Null());
            }));

            // object instantiation
            Register(config => config.Named("new_object")
                     .WithStringParameter("typeName")
                     .WithUnoundedParameter("args", Function.DynamicType)
                     .WhenExecute(context => {
                var typeName = context.EvaluatedArguments[0];
                var argc     = context.ArgumentCount;
                var args     = new Field[argc - 1];
                if (argc > 1)
                {
                    Array.Copy(context.EvaluatedArguments, 1, args, 0, args.Length);
                }

                var obj = SystemFunctions.NewObject(context.Request, typeName, args);
                return(context.Result(obj));
            }).ReturnsType(context => {
                var typeName = context.EvaluatedArguments[0].Value.ToString();
                return(context.Request.Access().ResolveUserType(typeName));
            }));
        }