A
A
Archestron2017-02-26 19:36:33
SQLite
Archestron, 2017-02-26 19:36:33

How to properly create a custom SQLite function in C#?

Gentlemen programmers, the other day I ran into a small problem. Unable to create custom function in SQLite in C# .NET so that it works as intended. The scalar function compares two strings for similarity using the LongestCommonSubsequence algorithm from the DuoVia.FuzzyStrings project . For a long time I was looking for a code example that would explain how to do this, but C-style functions were described everywhere (meaning sqlite_create_function () from the sish interface to the sqlite core).
As a result, I found only this: How to make Linq-to-Entities and Regex friends . There (closer to the beginning) only a scalar function was described, but so far this is all I need.
Everything looked clear and simple, so I did it the same way:

//Создание функции 
public class CloseToSQLiteFunction : SQLiteFunction
    {
        public static SQLiteFunctionAttribute GetAttribute()
        {
            return new SQLiteFunctionAttribute("CLOSETO", 2, FunctionType.Scalar); 
        }
        public override object Invoke(object[] args)
        {
            try
            {
                return FuzzyStrings.LongestCommonSubsequenceExtensions.LongestCommonSubsequence(args[0].ToString(), args[1].ToString()).Item2;
            }
            catch (Exception ex)
            {
                return ex;
            }
        }
    }
//***Разный код***//
//Добавление функции в базу при ее создании или подключении:
sql.DB_Conn.BindFunction(CloseToSQLiteFunction.GetAttribute(), new CloseToSQLiteFunction());

So, in the future, this function should take 2 arguments of type String and issue Double in requests of the type:
SELECT * FROM BaseTable WHERE CLOSETO('...какая-то строка...',Column1) > 0.33;
SELECT CLOSETO('...какая-то строка...',Column1) from BaseTable

But in debug mode or otherwise, it is REALLY created as a scalar function with two input parameters, BUT one of the arguments is ALWAYS DbNull, and the CLOSETO function always returns 0.0d.
Code example:
static public T Execute<T>(string SQL_Query, params object[] fmtParams)
        {
            using (var comm = new SQLiteCommand(string.Format(SQL_Query, fmtParams), DB_Conn))
                try
                {
                    return (T)Convert.ChangeType(comm.ExecuteScalar(), typeof(T));
                }
                catch (InvalidCastException)
                {
                    return default(T);
                }
        }
 
//***Разный код***//
    //...
    long myID = Execute<long>("select ID from Person where closeto('{0}',PersonName) > 0.33;", PersonName); //Всегда выдает 0!
    //...

What could be the reason for this behavior of the function?
I will introduce some explanation to the first section of the code:
//Создание функции 
public class CloseToSQLiteFunction : SQLiteFunction
    {
        public static SQLiteFunctionAttribute GetAttribute()
        {
            return new SQLiteFunctionAttribute("CLOSETO", 2, FunctionType.Scalar); 
        }
        //Режим отладки показывает, что args[0] - всегда имеет тип DbNull, несмотря на то, что функции передается две строки
        //Запрос: string.Format("select closeto(FirstName||' '||SecondName||' '||ThirdName,'{0}') as Closes from Person",PersonName);
        //PersonName - строка, содержащая исключительно символы [A-Za-zА-Яа-я0-9].
        public override object Invoke(object[] args)
        {
            try
            {
                return FuzzyStrings.LongestCommonSubsequenceExtensions.LongestCommonSubsequence(args[0].ToString(), args[1].ToString()).Item2;
            }
            catch (Exception ex)
            {
                return ex;
            }
        }
    }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Archestron, 2017-02-26
@Archestron

I know how and what SQLite is written in...
Need an answer within the question (see C#).
I respectfully ask you not to focus on side details, to answer on the topic.
In addition, the DuoVia.FuzzyStrings project is written in C#, and I need to convert its functions into custom scalar SQLite.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question