Пример #1
0
        public static DbValue REVERSE(DbFunctionTools tools, DbFunctionArguments args)
        {
            string FunctionName = "REVERSE";

            args.EnsureCount(FunctionName, 1);

            DbType    arg0type;
            ByteSlice arg0 = args[0].Eval(out arg0type);

            if (Types.IsNullValue(arg0))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg0type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg0type.Name.ToUpper());
            }

            mstring x = tools.GetString(arg0);

            mstring r = mstring.Prepare();

            for (int i = x.Length - 1; i >= 0; i--)
            {
                r = r.AppendM(x.SubstringM(i, 1));
            }

            return(tools.AllocValue(r));
        }
Пример #2
0
        public static DbValue LEFT(DbFunctionTools tools, DbFunctionArguments args)
        {
            string FunctionName = "LEFT";

            args.EnsureCount(FunctionName, 2);

            DbType    arg0type;
            ByteSlice arg0 = args[0].Eval(out arg0type);

            if (Types.IsNullValue(arg0))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg0type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg0type.Name.ToUpper());
            }

            DbType    arg1type;
            ByteSlice arg1 = args[1].Eval(out arg1type);

            if (arg1type.ID != DbTypeID.INT)
            {
                args.Expected(FunctionName, 1, "count INT, got " + arg1type.Name.ToUpper());
            }

            mstring x         = tools.GetString(arg0);
            int     LeftCount = tools.GetInt(arg1);

            if (LeftCount >= x.Length)
            {
                // User requested the whole string.
                return(tools.AllocValue(arg0, arg0type));
            }
            else if (LeftCount < 0)
            {
                throw new ArgumentException(FunctionName + " count cannot be negative");
            }
            else
            {
                x = x.SubstringM(0, LeftCount);
                return(tools.AllocValue(x));
            }
        }
Пример #3
0
        public static DbValue CHARINDEX(DbFunctionTools tools, DbFunctionArguments args)
        {
            string FunctionName = "CHARINDEX";

            args.EnsureMinCount(FunctionName, 2);

            int       index = -1;
            DbType    arg0type;
            ByteSlice arg0 = args[0].Eval(out arg0type);
            DbType    arg1type;
            ByteSlice arg1 = args[1].Eval(out arg1type);

            if (Types.IsNullValue(arg0) || Types.IsNullValue(arg1))
            {
                return(tools.AllocValue(index));
            }

            if (arg0type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg0type.Name.ToUpper());
                return(null);
            }
            if (arg1type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg1type.Name.ToUpper());
                return(null);
            }

            int startIndex = 0;

            if (args.Length > 2)
            {
                DbType    arg2type;
                ByteSlice arg2 = args[2].Eval(out arg2type);
                if (arg2type.ID != DbTypeID.INT)
                {
                    args.Expected(FunctionName, 0, "input INT, got " + arg2type.Name.ToUpper());
                    return(null);
                }
                startIndex = tools.GetInt(arg2);
                if (startIndex < 0)
                {
                    startIndex = 0;
                }
            }

            mstring word     = tools.GetString(arg0);
            mstring sentence = tools.GetString(arg1);

            if (startIndex > sentence.Length - 1)
            {
                index = -1;
            }
            else if (startIndex == 0)
            {
                index = sentence.IndexOf(word);
            }
            else
            {
                mstring partsentence = sentence.SubstringM(startIndex);
                int     ix           = partsentence.IndexOf(word);
                if (ix == -1)
                {
                    index = -1;
                }
                else
                {
                    index = startIndex + ix;
                }
            }
            return(tools.AllocValue(index));
        }
Пример #4
0
        private static DbValue _PAD(string functionName, DbFunctionTools tools, DbFunctionArguments args, bool isLeft)
        {
            args.EnsureCount(functionName, 3);

            DbType    arg0type;
            ByteSlice arg0 = args[0].Eval(out arg0type);

            if (Types.IsNullValue(arg0))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg0type.ID != DbTypeID.CHARS)
            {
                args.Expected(functionName, 0, "input CHAR(n), got " + arg0type.Name.ToUpper());
            }
            DbType    arg1type;
            ByteSlice arg1 = args[1].Eval(out arg1type);

            if (Types.IsNullValue(arg1))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg1type.ID != DbTypeID.INT)
            {
                args.Expected(functionName, 0, "input INT, got " + arg1type.Name.ToUpper());
            }
            DbType    arg2type;
            ByteSlice arg2 = args[2].Eval(out arg2type);

            if (Types.IsNullValue(arg2))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg2type.ID != DbTypeID.CHARS)
            {
                args.Expected(functionName, 0, "input CHAR(n), got " + arg2type.Name.ToUpper());
            }

            mstring str      = tools.GetString(arg0);
            int     totallen = tools.GetInt(arg1);
            mstring padstr   = tools.GetString(arg2);

            if (str.Length > totallen)
            {
                str = str.SubstringM(0, totallen);
            }
            else if (str.Length < totallen)
            {
                int     delta  = totallen - str.Length;
                int     padlen = padstr.Length;
                mstring newstr = mstring.Prepare();

                for (int remain = delta; remain > 0;)
                {
                    newstr  = newstr.AppendM(padstr);
                    remain -= padlen;
                }

                //if we go over, truncate.
                if (newstr.Length > delta)
                {
                    newstr = newstr.SubstringM(0, delta);
                }

                if (isLeft)
                {
                    str = newstr.AppendM(str);
                }
                else
                {
                    str = str.AppendM(newstr);
                }
            }
            return(tools.AllocValue(str));
        }
Пример #5
0
        public static DbValue SUBSTRING(DbFunctionTools tools, DbFunctionArguments args)
        {
            string FunctionName = "SUBSTRING";

            args.EnsureCount(FunctionName, 3);

            DbType    arg0type;
            ByteSlice arg0 = args[0].Eval(out arg0type);

            if (Types.IsNullValue(arg0))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg0type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg0type.Name.ToUpper());
                return(null);
            }

            DbType    arg1type;
            ByteSlice arg1 = args[1].Eval(out arg1type);

            if (arg1type.ID != DbTypeID.INT)
            {
                args.Expected(FunctionName, 1, "count INT, got " + arg1type.Name.ToUpper());
                return(null);
            }

            DbType    arg2type;
            ByteSlice arg2 = args[2].Eval(out arg2type);

            if (arg2type.ID != DbTypeID.INT)
            {
                args.Expected(FunctionName, 1, "count INT, got " + arg2type.Name.ToUpper());
                return(null);
            }

            mstring x          = tools.GetString(arg0);
            int     startIndex = tools.GetInt(arg1);

            if (startIndex < 0)
            {
                startIndex = 0;
            }
            int len = tools.GetInt(arg2);

            if (len < 0)
            {
                throw new ArgumentException(FunctionName + " length cannot be negative");
            }

            if (startIndex + len > x.Length)
            {
                return(tools.AllocValue(mstring.Prepare()));
            }
            else
            {
                mstring sub = x.SubstringM(startIndex, len);
                return(tools.AllocValue(sub));
            }
        }
Пример #6
0
        public static DbValue INSTR(DbFunctionTools tools, DbFunctionArguments args)
        {
            string FunctionName = "INSTR";

            args.EnsureMinCount(FunctionName, 2);

            DbType    arg0type;
            ByteSlice arg0 = args[0].Eval(out arg0type);

            if (Types.IsNullValue(arg0))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg0type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg0type.Name.ToUpper());
            }

            DbType    arg1type;
            ByteSlice arg1 = args[1].Eval(out arg1type);

            if (Types.IsNullValue(arg1))
            {
                return(tools.AllocNullValue()); // Give a null, take a null.
            }
            if (arg1type.ID != DbTypeID.CHARS)
            {
                args.Expected(FunctionName, 0, "input CHAR(n), got " + arg1type.Name.ToUpper());
            }

            int startIndex = 0;

            if (args.Length > 2)
            {
                DbType    arg2type;
                ByteSlice arg2 = args[2].Eval(out arg2type);
                if (arg2type.ID != DbTypeID.INT)
                {
                    args.Expected(FunctionName, 0, "input INT, got " + arg2type.Name.ToUpper());
                }
                if (!Types.IsNullValue(arg2))
                {
                    startIndex = tools.GetInt(arg2);
                }
            }

            mstring sentence = tools.GetString(arg0);
            mstring word     = tools.GetString(arg1);
            int     index    = -1;

            if (startIndex < sentence.Length)
            {
                if (startIndex > 0)
                {
                    sentence = sentence.SubstringM(startIndex);
                }
                index = sentence.IndexOf(word);
                if (index > -1)
                {
                    index += startIndex;
                }
            }
            return(tools.AllocValue(index));
        }
Пример #7
0
        public static DbValue CAST(DbFunctionTools tools, DbFunctionArguments args)
        {
#if DEBUG
            //System.Diagnostics.Debugger.Launch();
#endif

            string FunctionName = "CAST";

            args.EnsureCount(FunctionName, 2);

            DbType    type;
            ByteSlice bs = args[0].Eval(out type);

            mstring xas = tools.GetString(args[1]);
            if (!xas.StartsWith("AS "))
            {
#if DEBUG
                throw new Exception("Expected AS <type> in CAST, not: " + xas);
#endif
                throw new Exception("Expected AS <type> in CAST");
            }
            mstring msastype = xas.SubstringM(3);
            string  sastype  = msastype.ToString();  // Alloc.
            sastype = DbType.NormalizeName(sastype); // Alloc if char(n).
            DbType astype = DbType.Prepare(sastype); // Alloc if char(n).
            if (DbTypeID.NULL == astype.ID)
            {
                throw new Exception("Unknown AS type in CAST: " + sastype);
            }

            switch (astype.ID)
            {
            case DbTypeID.INT:
                switch (type.ID)
                {
                case DbTypeID.INT:         // as INT
                    if (astype.Size > type.Size)
                    {
                        throw new Exception("CAST: source value buffer too small");
                    }
                    return(tools.AllocValue(ByteSlice.Prepare(bs, 0, astype.Size), astype));

                case DbTypeID.LONG:         // as INT
                    return(tools.AllocValue((int)tools.GetLong(bs)));

                case DbTypeID.DOUBLE:         // as INT
                    return(tools.AllocValue((int)tools.GetDouble(bs)));

                case DbTypeID.DATETIME:         // as INT
                    return(tools.AllocValue((int)tools.GetDateTime(bs).Ticks));

                case DbTypeID.CHARS:         // as INT
                {
                    int to = tools.GetString(bs).NextItemToInt32(' ');
                    return(tools.AllocValue(to));
                }

                default:
                    throw new Exception("Cannot handle CAST value of type " + type.Name + " AS " + astype.Name);
                }
                break;

            case DbTypeID.LONG:
                switch (type.ID)
                {
                case DbTypeID.INT:         // as LONG
                    return(tools.AllocValue((long)tools.GetInt(bs)));

                case DbTypeID.LONG:         // as LONG
                    if (astype.Size > type.Size)
                    {
                        throw new Exception("CAST: source value buffer too small");
                    }
                    return(tools.AllocValue(ByteSlice.Prepare(bs, 0, astype.Size), astype));

                case DbTypeID.DOUBLE:         // as LONG
                    return(tools.AllocValue((long)tools.GetDouble(bs)));

                case DbTypeID.DATETIME:         // as LONG
                    return(tools.AllocValue((long)tools.GetDateTime(bs).Ticks));

                case DbTypeID.CHARS:         // as LONG
                {
                    long to = tools.GetString(bs).NextItemToInt64(' ');
                    return(tools.AllocValue(to));
                }

                default:
                    throw new Exception("Cannot handle CAST value of type " + type.Name + " AS " + astype.Name);
                }
                break;

            case DbTypeID.DOUBLE:
                switch (type.ID)
                {
                case DbTypeID.INT:         // as DOUBLE
                    return(tools.AllocValue((double)tools.GetInt(bs)));

                case DbTypeID.LONG:         // as DOUBLE
                    return(tools.AllocValue((double)tools.GetLong(bs)));

                case DbTypeID.DOUBLE:         // as DOUBLE
                    if (astype.Size > type.Size)
                    {
                        throw new Exception("CAST: source value buffer too small");
                    }
                    return(tools.AllocValue(ByteSlice.Prepare(bs, 0, astype.Size), astype));

                case DbTypeID.DATETIME:         // as DOUBLE
                    return(tools.AllocValue((double)tools.GetDateTime(bs).Ticks));

                case DbTypeID.CHARS:         // as DOUBLE
                {
                    double to = tools.GetString(bs).NextItemToDouble(' ');
                    return(tools.AllocValue(to));
                }

                default:
                    throw new Exception("Cannot handle CAST value of type " + type.Name + " AS " + astype.Name);
                }
                break;

            case DbTypeID.DATETIME:
                switch (type.ID)
                {
                case DbTypeID.INT:         // as DATETIME
                    return(tools.AllocValue(new DateTime((long)tools.GetInt(bs))));

                case DbTypeID.LONG:         // as DATETIME
                    return(tools.AllocValue(new DateTime((long)tools.GetLong(bs))));

                case DbTypeID.DOUBLE:         // as DATETIME
                    return(tools.AllocValue(new DateTime((long)tools.GetDouble(bs))));

                case DbTypeID.DATETIME:         // as DATETIME
                    if (astype.Size > type.Size)
                    {
                        throw new Exception("CAST: source value buffer too small");
                    }
                    return(tools.AllocValue(ByteSlice.Prepare(bs, 0, astype.Size), astype));

                case DbTypeID.CHARS:         // as DATETIME
                {
                    mstring to = tools.GetString(bs);
                    return(tools.AllocValue(DateTime.Parse(to.ToString())));
                }

                default:
                    throw new Exception("Cannot handle CAST value of type " + type.Name + " AS " + astype.Name);
                }
                break;

            case DbTypeID.CHARS:
                switch (type.ID)
                {
                case DbTypeID.INT:         // as CHAR(n)
                {
                    mstring ms = mstring.Prepare(tools.GetInt(bs));
                    return(tools.AllocValue(ms, astype.Size));
                }

                case DbTypeID.LONG:         // as CHAR(n)
                {
                    mstring ms = mstring.Prepare(tools.GetLong(bs));
                    return(tools.AllocValue(ms, astype.Size));
                }

                case DbTypeID.DOUBLE:         // as CHAR(n)
                {
                    mstring ms = mstring.Prepare(tools.GetDouble(bs));
                    return(tools.AllocValue(ms, astype.Size));
                }

                case DbTypeID.DATETIME:         // as CHAR(n)
                {
                    mstring ms = mstring.Prepare(tools.GetDateTime(bs).ToString());
                    return(tools.AllocValue(ms, astype.Size));
                }

                case DbTypeID.CHARS:         // as CHAR(n)
                    if (astype.Size > type.Size)
                    {
                        //throw new Exception("CAST: source value buffer too small");
                        return(tools.AllocValue(tools.GetString(bs), astype.Size));
                    }
                    return(tools.AllocValue(ByteSlice.Prepare(bs, 0, astype.Size), astype));

                default:
                    throw new Exception("Cannot handle CAST value of type " + type.Name + " AS " + astype.Name);
                }
                break;

            default:
                throw new Exception("Cannot handle CAST value of type " + type.Name + " AS " + astype.Name);
            }
        }