Example #1
0
        public static FuncDef FindFunction(Context ctx, string name, int nameLength, int args, TEXTENCODE encode, bool createFlag)
        {
            Debug.Assert(args >= -2);
            Debug.Assert(args >= -1 || !createFlag);
            Debug.Assert(encode == TEXTENCODE.UTF8 || encode == TEXTENCODE.UTF16LE || encode == TEXTENCODE.UTF16BE);
            int h = (char.ToLowerInvariant(name[0]) + nameLength) % ctx.Funcs.data.Length; // Hash value

            // First search for a match amongst the application-defined functions.
            FuncDef best      = null; // Best match found so far
            int     bestScore = 0;    // Score of best match
            FuncDef p         = FunctionSearch(ctx.Funcs, h, name, nameLength);

            while (p != null)
            {
                int score = MatchQuality(p, args, encode);
                if (score > bestScore)
                {
                    best      = p;
                    bestScore = score;
                }
                p = p.Next;
            }

            // If no match is found, search the built-in functions.
            //
            // If the SQLITE_PreferBuiltin flag is set, then search the built-in functions even if a prior app-defined function was found.  And give
            // priority to built-in functions.
            //
            // Except, if createFlag is true, that means that we are trying to install a new function.  Whatever FuncDef structure is returned it will
            // have fields overwritten with new information appropriate for the new function.  But the FuncDefs for built-in functions are read-only.
            // So we must not search for built-ins when creating a new function.
            if (createFlag && (best == null || (ctx.Flags & Context.FLAG.PreferBuiltin) != 0))
            {
                FuncDefHash hash = sqlite3GlobalFunctions;
                bestScore = 0;
                p         = FunctionSearch(hash, h, name, nameLength);
                while (p != null)
                {
                    int score = MatchQuality(p, args, encode);
                    if (score > bestScore)
                    {
                        best      = p;
                        bestScore = score;
                    }
                    p = p.Next;
                }
            }

            // If the createFlag parameter is true and the search did not reveal an exact match for the name, number of arguments and encoding, then add a
            // new entry to the hash table and return it.
            if (createFlag && bestScore < FUNC_PERFECT_MATCH && (best = new FuncDef()) != null)
            {
                best.Name       = name;
                best.Args       = (short)args;
                best.PrefEncode = encode;
                FuncDefInsert(ctx.Funcs, best);
            }

            return(best != null && (best.Step != null || best.Func != null || createFlag) ? best : null);
        }
Example #2
0
 static FuncDef FunctionSearch(FuncDefHash hash, int h, string func, int funcLength)
 {
     for (FuncDef p = hash[h]; p != null; p = p.Hash)
     {
         if (p.Name.Length == funcLength && p.Name.StartsWith(func, StringComparison.OrdinalIgnoreCase))
         {
             return(p);
         }
     }
     return(null);
 }
Example #3
0
        public static void FuncDefInsert(FuncDefHash hash, FuncDef def)
        {
            int     nameLength = def.Name.Length;
            int     h          = (char.ToLowerInvariant(def.Name[0]) + nameLength) % hash.data.Length;
            FuncDef other      = FunctionSearch(hash, h, def.Name, nameLength);

            if (other != null)
            {
                Debug.Assert(other != def && other.Next != def);
                def.Next   = other.Next;
                other.Next = def;
            }
            else
            {
                def.Next = null;
                def.Hash = hash[h];
                hash[h]  = def;
            }
        }