SQL中的SQLite并支持REGEXP

时间:2011-06-09 05:00:42

标签: c regex sqlite

我在sqlite3中使用C,我想添加对REGEXP运算符的支持。默认情况下,用户定义的函数regexp()不存在,调用REGEXP通常会导致错误(根据SQLite页面)。

  1. 如何添加regexp功能以支持REGEXP?据推测,我将通过sqlite3_create_function调用执行此操作,但我不知道应用程序定义的regexp()将是什么样的。

  2. 我可以使用regex.hsqlite3_create_function的函数以及如何使用函数吗?我传递给SQLite的任何函数都必须使用sqlite3_context *,int,sqlite3_value **类型的三个参数。但是,SQLite文档似乎没有解释这些参数的含义。

  3. 是否有C regexp()功能的示例代码?

  4. 我无法使用Google或SQLite页面找到很多内容。

3 个答案:

答案 0 :(得分:4)

你也可以试试这个:

#include <regex.h>

...

void sqlite_regexp(sqlite3_context* context, int argc, sqlite3_value** values) {
    int ret;
    regex_t regex;
    char* reg = (char*)sqlite3_value_text(values[0]);
    char* text = (char*)sqlite3_value_text(values[1]);

    if ( argc != 2 || reg == 0 || text == 0) {
        sqlite3_result_error(context, "SQL function regexp() called with invalid arguments.\n", -1);
        return;
    }

    ret = regcomp(&regex, reg, REG_EXTENDED | REG_NOSUB);
    if ( ret != 0 ) {
        sqlite3_result_error(context, "error compiling regular expression", -1);
        return;
    }

    ret = regexec(&regex, text , 0, NULL, 0);
    regfree(&regex);

    sqlite3_result_int(context, (ret != REG_NOMATCH));
}

...

sqlite3_create_function(*db, "regexp", 2, SQLITE_ANY,0, &sqlite_regexp,0,0)

答案 1 :(得分:1)

它看起来像这样:

static void user_regexp(sqlite3_context *context, int argc, sqlite3_value **argv)
{
    struct re_pattern_buffer buffer;
    const char *out;
    char *pattern;
    char *input_string;
    char *result;
    struct re_registers regs;

    if ((sqlite3_value_type(argv[0]) != SQLITE_TEXT )
         || ((sqlite3_value_type(argv[1]) != SQLITE_TEXT ))
    {
        sqlite3_result_err("Improper argument types");
        return;
    }

    re_set_syntax(RE_SYNTAX_POSIX_EGREP);
    memset(&buffer, 0, sizeof (buffer));
    if (!(pattern = strdupa(sqlite3_value_text(argv[0])))
        || !(input_string = strdupa(sqlite3_value_text(argv[1]))))
    {
        sqlite3_result_err_nomem("Could not allocate memory for strings");
        return;
    }

    if ((out = re_compile_pattern(pattern, strlen(pattern), &buffer))
    {
        sqlite3_result_err("Could not compile pattern!");
        return;
    }

    if (re_match(&buffer, input_string, strlen(input_string), 0, &regs) < 0) 
        sqlite3_result_int64(context, 0);
    else 
    {
        result = strndupa(input_string + regs.start[0], regs.end[0] - regs.start[0]);    
        sqlite3_result_text(context, result, NULL, SQLITE_TRANSIENT);
    }
}

答案 2 :(得分:0)

好的,有点太迟了,但我很想发布这个给所有使用C ++ Wrapper for C SQLITE API的人,比如我正在使用的[ SQLiteCpp ]。这个答案假定您使用 SQLiteCpp

  • [ here ]安装 Regex for windows 二进制文件。这为您提供了足够的文件,即def compute_probability_distribution(sides): dist = {x+y: 0 for x in range(1, sides+1) for y in range(1, sides+1)} for die_1 in range(1, sides+1): for die_2 in range(1, sides+1): dist[die_1+die_2] = dist[die_1+die_2] + 1 probs = dist.items() print "Prob dist: ", probs 包含文件和regex.h。请记住在项目中添加路径regex.h,并在包含客户端可执行文件的文件夹中包含dll的副本。
  • 在构建[ SQLiteCpp ]之前,我们需要进行一些更改,以便为regex2.dll查询添加正则表达式功能。为此,打开[ SQLiteCpp ]项目中的SELECT文件和

    • Regex for windows
    • 中加入Database.cpp标题
    • 在所有包含之后,添加以下内容(当然您可以自定义以满足您的需求!)下方的代码片段。

      regex.h
    • 现在是时候更改文件中定义的构造函数了。改变如下所示的那些。

      extern "C" {
      void sqlite_regexp(sqlite3_context* context, int argc, sqlite3_value** values) {
      int ret;
      regex_t regex;
      char regtext[100];
      char* reg = (char*)sqlite3_value_text(values[0]);
      sprintf(regtext, ".*%s.*", reg);
      //printf("Regtext : %s", regtext);
      char* text = (char*)sqlite3_value_text(values[1]);
      /*  printf("Text : %s\n", text);
      printf("Reg : %s\n", reg); */
      if (argc != 2 || reg == 0 || text == 0) {
          sqlite3_result_error(context, "SQL function regexp() called with invalid arguments.\n", -1);
          return;
      }
      
      ret = regcomp(&regex, regtext, REG_EXTENDED | REG_NOSUB | REG_ICASE);
      if (ret != 0) {
          sqlite3_result_error(context, "error compiling regular expression", -1);
          return;
      }
      
      ret = regexec(&regex, text, 0, NULL, 0);
      /*  if (ret == 0) {
      printf("Found a match. Press any key to continue");
      getc(stdin);
      }*/
      regfree(&regex);
      
      sqlite3_result_int(context, (ret != REG_NOMATCH));
      }
      }
      
  • 到目前为止,您对// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. Database::Database(const char* apFilename, const int aFlags /*= SQLite::OPEN_READONLY*/, const int aBusyTimeoutMs/* = 0 */, const char* apVfs/*= NULL*/) : mpSQLite(NULL), mFilename(apFilename) { const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs); //std::cout << "Reached here"; //sqlite3_create_function_v2(mpSQLite, "REGEXP", 2, SQLITE_ANY,&sqlite_regexp, NULL, NULL, NULL,NULL); sqlite3_create_function(mpSQLite, "regexp", 2, SQLITE_ANY, 0, &sqlite_regexp, 0, 0); if (SQLITE_OK != ret) { const SQLite::Exception exception(mpSQLite, ret); // must create before closing sqlite3_close(mpSQLite); // close is required even in case of error on opening throw exception; } else { } if (aBusyTimeoutMs > 0) { setBusyTimeout(aBusyTimeoutMs); } } // Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. Database::Database(const std::string& aFilename, const int aFlags /* = SQLite::OPEN_READONLY*/, const int aBusyTimeoutMs/* = 0*/, const std::string& aVfs/* = "" */) : mpSQLite(NULL), mFilename(aFilename) { const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? NULL : aVfs.c_str()); sqlite3_create_function(mpSQLite, "regexp", 2, SQLITE_ANY, 0, &sqlite_regexp, 0, 0); if (SQLITE_OK != ret) { const SQLite::Exception exception(mpSQLite, ret); // must create before closing sqlite3_close(mpSQLite); // close is required even in case of error on opening throw exception; } if (aBusyTimeoutMs > 0) { setBusyTimeout(aBusyTimeoutMs); } } 有一些严肃的regex功能。只需构建项目。

  • 编写客户端程序以测试功能。它可以是下面的东西(从 SQLiteCpp Example 借来的没有羞耻)。

    sqlite

注意:这假设数据库与cpp位于同一文件夹中