praeclarum / praeclarum/sqlite-net

SQLiteAsyncConnection Support for REGEXP

Open
#1,237 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
4.5k
Forks
1.4k
PR merge metrics
No merged PRs in 30d

Description

Good morning,

I have been trying to use REGEXP with an SQLiteAsyncConnection for days now and am having zero luck with it. I'm not sure whether I am misunderstanding things or if sqlite-net doesn't support it. I only found one issue when searching the issues for "REGEXP" or "REGEX" and it doesn't really address this.

Nuget Packages Installed
sqlite-net-pcl v1.9.172
Microsoft.Data.Sqlite v8.0.6
I also had previously installed SQLitePCLRaw but that was causing errors with "raw" being defined in SQLitePCLRaw and SQLitePCLRaw .Core so I uninstalled it

Target Framework: .NET 8.0, WPF

I have been reading a lot of stack overflow posts but This Post is the one that I have chosen to try to implement in the code below.

My application only needs to read values from the database and will never insert or remove items from any table in it. The dabasefile is on disk and selected by the user.

Also, I am not new to C# but I am new to using it for SQL operations so please understand if I am lacking in some key understanding.

Any help is appreciated!

using CommunityToolkit.Mvvm.ComponentModel;
using EngineeringLabUi.Models;
using Microsoft.Data.Sqlite;
using SQLite;
using SQLitePCL;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace EngineeringLabUi.CustomTypes
{
    public partial class DictionaryDbServiceAsync : ObservableObject
    {
        [ObservableProperty] private static List<DictionaryDb> _dicDbTempList = new(800000);
        SQLiteAsyncConnection? dbConnection;
        SqliteCommand command;
        private string? sqlCommand = string.Empty;
        // query all values from the parameter table
        private string defaultSqlCmd = "SELECT * FROM PARAMETER";
        // path where we will create the database fle
        private string? dbPath = string.Empty;

        public DictionaryDbServiceAsync(string? newDbPath)
        {
            // set the dbpath to the path passed to the constructor
            dbPath = newDbPath;

            // create the DB directory if it doesn't exist
            if((string.IsNullOrEmpty(dbPath) == false) && (File.Exists(dbPath) == false))
            {
                Directory.CreateDirectory(dbPath);
            }

            // create the db file
            createDbFile();
        }

        public void createDbFile()
        {
            if(System.IO.File.Exists(dbPath) == true)
            {
                createDbConnection();
            }
            else
            {
                File.Create(dbPath).Close();
                createDbConnection();
            }
        }

        public void createDbConnection()
        {
            string strCon = string.Format("Data Source={0};", dbPath);
            dbConnection = new SQLiteAsyncConnection(databasePath: dbPath, openFlags: SQLiteOpenFlags.ReadOnly, storeDateTimeAsTicks: true);
            dbConnection?.CreateTableAsync<DictionaryDb>().Wait();

            // NOTE:  SQLite-net-pcl doesn't support regex at this time
            /* Here is where the error occurs that says dbConnection has no attribute "Handle"
             * which leads me to believe it isn't supported
             */
            SQLitePCL.raw.sqlite3_create_function(dbConnection.Handle, "REGEXP", 2, null, MatchRegex);
        }

        public async Task<List<DictionaryDb>> executeQuery(string sqlCommand)
        {
            if(sqlCommand.Equals("") == true)
            {
                // "SELECT * FROM PARAMETER"
                return await dbConnection.QueryAsync<DictionaryDb>(defaultSqlCmd);

            }
            else
            {
                // This one works 
                //var task = dbConnection.QueryAsync<DictionaryDb>("SELECT * FROM PARAMETER WHERE VARNAME LIKE ?", "%a665%");
                //task.Wait();
                //var result = task.Result;

                // testing regex - Can't get here with the above error
                var task = dbConnection.QueryAsync<DictionaryDb>($"SELECT VARNAME FROM PARAMETER WHERE VARNAME REGEXP '{sqlCommand}'");
                task.Wait();
                var result = task.Result;
                return result;
            }
        }

        // function to be registered for the REGEXP functionaliity
        private void MatchRegex(sqlite3_context ctx, object user_data, sqlite3_value[] args)
        {
            bool isMatched = System.Text.RegularExpressions.Regex.IsMatch(SQLitePCL.raw.sqlite3_value_text(args[1]).utf8_to_string(),
                                                                          SQLitePCL.raw.sqlite3_value_text(args[0]).utf8_to_string(),
                                                                          RegexOptions.IgnoreCase);
            if(isMatched)
                SQLitePCL.raw.sqlite3_result_int(ctx, 1);
            else
                SQLitePCL.raw.sqlite3_result_int(ctx, 0);
        }       
    }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with SQLiteAsyncConnection and the SQLitePCL.raw.sqlite3_create_function call shown in the report, then compare the connection API with the sqlite3 handle required for REGEXP registration. Done should establish whether REGEXP can be registered and queried through SQLiteAsyncConnection on .NET 8/WPF, with coverage for the reported query path.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, sqlite
Domain
database
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.