C中的SQLite及其支持的REGEXP
我正在C中的SQLite及其支持的REGEXP,c,regex,sqlite,C,Regex,Sqlite,我正在C中使用sqlite3,我想添加对REGEXP操作符的支持。默认情况下,用户定义的函数regexp()不存在,调用regexp通常会导致错误(根据SQLite页面) 如何添加regexp函数以支持regexp?我大概会通过sqlite3\u create\u函数调用来实现这一点,但我不知道应用程序定义的regexp()会是什么样子 我可以将regex.h中的函数与sqlite3\u create\u函数一起使用吗?如何使用?我传递给SQLite的任何函数都必须接受三个类型为sqlite3_
C
中使用sqlite3
,我想添加对REGEXP
操作符的支持。默认情况下,用户定义的函数regexp()
不存在,调用regexp
通常会导致错误(根据SQLite页面)
regexp
函数以支持regexp
?我大概会通过sqlite3\u create\u函数
调用来实现这一点,但我不知道应用程序定义的regexp()
会是什么样子regex.h
中的函数与sqlite3\u create\u函数一起使用吗?如何使用?我传递给SQLite的任何函数都必须接受三个类型为sqlite3_context*、int、sqlite3_value**的参数。然而,SQLite文档似乎没有解释这些参数的含义
C
regexp()
函数的示例代码我在谷歌或SQLite页面上找不到太多关于这方面的信息。它看起来像这样:
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);
}
}
static void user\u regexp(sqlite3\u context*context,int argc,sqlite3\u值**argv)
{
结构模式缓冲区;
const char*out;
字符*模式;
字符*输入字符串;
字符*结果;
结构寄存器regs;
如果((sqlite3值类型(argv[0])!=SQLITE文本)
||((sqlite3_值_类型(argv[1])!=SQLITE_文本))
{
sqlite3_result_err(“不正确的参数类型”);
返回;
}
re_集合_语法(re_语法_POSIX_EGREP);
memset(&buffer,0,sizeof(buffer));
if(!(pattern=strdupa(sqlite3\u value\u text(argv[0]))
||!(输入字符串=strdupa(sqlite3值文本(argv[1]))
{
sqlite3_result_err_nomem(“无法为字符串分配内存”);
返回;
}
if((out=re_compile_pattern(pattern,strlen(pattern),&buffer))
{
sqlite3_result_err(“无法编译模式!”);
返回;
}
if(重新匹配(&buffer,输入字符串,strlen(输入字符串),0,®s)<0)
sqlite3_result_int64(上下文,0);
其他的
{
结果=strndupa(输入字符串+regs.start[0],regs.end[0]-regs.start[0]);
sqlite3_结果_文本(上下文、结果、空、SQLITE_瞬态);
}
}
您也可以尝试以下方法:
#include <regex.h>
好的,对此有点晚了,但是我想把这篇文章发给所有使用C++包装的人,就像我正在使用的C SQLite API一样。这个答案假设你使用SQLITCPP.
- 从安装windows二进制文件的Regex。这将为您提供足够的文件,即
包含文件和Regex.h
。请记住在项目中添加路径Regex.h,并在包含客户端可执行文件的文件夹中保留dll的副本regex2.dll
- 在构建之前,我们需要进行一些更改,将regex功能添加到
查询中。为此,请从项目中打开SELECT
文件并数据库.cpp
- 包括windows正则表达式中的
标题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); } }
注意:这假设数据库与您的cpp在同一个文件夹中这里解释了用户函数的内容:@mu:谢谢,这是我第一次去的地方。当您在这里时-用户函数可以返回什么整数值?或者它们必须是空的吗?所有原型都有
返回,所以可能有这么多告诉我如何报道“真实”通过void
参数返回值。@mu:谢谢,我可能就快到了。看起来我必须在sqlite3\u context
方法结束时调用regex
来通知sqlite3\u result\u int
结果。虽然我可能在这里错了。我刚刚看到这个问题出现,可能对您有用:SQLite
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); } }
#include <iostream> #include <cstdio> #include <cstdlib> #include <string> #include <SQLiteCpp/SQLiteCpp.h> #include <SQLiteCpp/VariadicBind.h> // Notice no sqlite3.h huh? // Well, this is a C++ wrapper for the SQLITE CAPI afterall. #ifdef SQLITECPP_ENABLE_ASSERT_HANDLER namespace SQLite { /// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt) void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg) { // Print a message to the standard error output stream, and abort the program. std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n"; std::abort(); } } #endif /// Get example path static inline std::string getExamplePath() { std::string filePath(__FILE__); return filePath.substr(0, filePath.length() - std::string("Client.cpp").length()); } /// Example Database static const std::string filename_example_db3 = getExamplePath() + "/example.db3"; /// Image static const std::string filename_logo_png = getExamplePath() + "/logo.png"; /// Object Oriented Basic example class Example { public: //Constructor Example() : mDb(filename_example_db3), // User change the db and tables accordingly mQuery(mDb, "SELECT id,name FROM lookup WHERE name REGEXP :keyword") // Open a database file in readonly mode { } virtual ~Example() { } /// List the rows where the "weight" column is greater than the provided aParamValue void namehaskeyword(const std::string searchfor) { std::cout << "Matching results for " << searchfor << "\n"; // Bind the integer value provided to the first parameter of the SQL query mQuery.bind(1,searchfor); // same as mQuery.bind(1, aParamValue); // Loop to execute the query step by step, to get one a row of results at a time while (mQuery.executeStep()) { std::cout<<mQuery.getColumn(0) << "\t" << mQuery.getColumn(1) << "\n"; } // Reset the query to be able to use it again later mQuery.reset(); } private: SQLite::Database mDb; ///< Database connection SQLite::Statement mQuery; ///< Database prepared SQL query }; int main() { // Using SQLITE_VERSION would require #include <sqlite3.h> which we want to avoid: use SQLite::VERSION if possible. // std::cout << "SQlite3 version " << SQLITE_VERSION << std::endl; std::cout << "SQlite3 version " << SQLite::VERSION << " (" << SQLite::getLibVersion() << ")" << std::endl; std::cout << "SQliteC++ version " << SQLITECPP_VERSION << std::endl; try { // Doing a regex query. Example example; char wannaquit = 'n'; std::string keyword; // Deliberate unlimited loop. You implement something sensible here. while (wannaquit != 'y') { // Demonstrates the way to use the same query with different parameter values std::cout << "Enter the keyword to search for : "; std::getline(std::cin, keyword); example.namehaskeyword(keyword); } } catch (std::exception& e) { std::cout << "SQLite exception : " << e.what() << std::endl; return EXIT_FAILURE; // unexpected error : exit the example program } return EXIT_SUCCESS; }
- 包括windows正则表达式中的