我在sqlite3
中使用C
,我想添加对REGEXP
运算符的支持。默认情况下,用户定义的函数regexp()
不存在,调用REGEXP
通常会导致错误(根据SQLite页面)。
如何添加regexp
功能以支持REGEXP
?据推测,我将通过sqlite3_create_function
调用执行此操作,但我不知道应用程序定义的regexp()
将是什么样的。
我可以使用regex.h
中sqlite3_create_function
的函数以及如何使用函数吗?我传递给SQLite的任何函数都必须使用sqlite3_context *,int,sqlite3_value **类型的三个参数。但是,SQLite文档似乎没有解释这些参数的含义。
是否有C
regexp()
功能的示例代码?
我无法使用Google或SQLite页面找到很多内容。
答案 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(®ex, reg, REG_EXTENDED | REG_NOSUB);
if ( ret != 0 ) {
sqlite3_result_error(context, "error compiling regular expression", -1);
return;
}
ret = regexec(®ex, text , 0, NULL, 0);
regfree(®ex);
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, ®s) < 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 。
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
文件和
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(®ex, regtext, REG_EXTENDED | REG_NOSUB | REG_ICASE);
if (ret != 0) {
sqlite3_result_error(context, "error compiling regular expression", -1);
return;
}
ret = regexec(®ex, text, 0, NULL, 0);
/* if (ret == 0) {
printf("Found a match. Press any key to continue");
getc(stdin);
}*/
regfree(®ex);
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位于同一文件夹中