好的,这可能有点晚了,但我还是想为所有使用C++包装器来使用C SQLITE API的人发布此帖,比如我正在使用的[SQLiteCpp]。本答案假设您使用SQLiteCpp。
从
这里安装Windows的正则表达式二进制文件。这将提供足够的文件,包括regex.h头文件和regex2.dll动态链接库。记得在项目中添加regex.h的路径,并将dll文件复制到包含客户端可执行文件的文件夹中。
在构建
SQLiteCpp之前,我们需要对
SELECT
查询添加正则表达式功能。打开
SQLiteCpp项目中的Database.cpp文件,并进行以下更改:
- 从Regex for windows中引用regex.h头文件
- 在所有的
#include
之后,添加如下代码(根据需要进行自定义):
```cpp
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);
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, 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);
regfree(®ex);
sqlite3_result_int(context, (ret != REG_NOMATCH));
}
}
```
现在是时候修改文件中定义的构造函数了。按照下面所示进行更改:
```cpp
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);
sqlite3_create_function(mpSQLite, "regexp", 2, SQLITE_ANY, 0, &sqlite_regexp, 0, 0);
if (SQLITE_OK != ret)
{
const SQLite::Exception exception(mpSQLite, ret);
sqlite3_close(mpSQLite);
throw exception;
}
if (aBusyTimeoutMs > 0)
{
setBusyTimeout(aBusyTimeoutMs);
}
}
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);
sqlite3_close(mpSQLite);
throw exception;
}
if (aBusyTimeoutMs > 0)
{
setBusyTimeout(aBusyTimeoutMs);
}
}
```
到此为止,你的SQLite现在具备了强大的正则表达式功能。现在构建项目即可。
编写一个客户端程序来测试功能。可以参考以下示例(从
SQLiteCpp Example借用):
```cpp
#include
#include
#include
#include
#include
#include
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n";
std::abort();
}
}
#endif
static inline std::string getExamplePath()
{
std::string filePath(__FILE__);
return filePath.substr(0, filePath.length() - std::string("Client.cpp").length());
}
class Example
{
public:
Example() :
mDb(filename_example_db3),
mQuery(mDb, "SELECT id,name FROM lookup WHERE name REGEXP :keyword")
{
}
virtual ~Example()
{
}
void namehaskeyword(const std::string searchfor)
{
std::cout << "Matching results for " << searchfor << "\n";
mQuery.bind(1,searchfor);
while (mQuery.executeStep())
{
std::cout<
mQuery.reset();
}
private:
SQLite::Database mDb;
SQLite::Statement mQuery;
};
int main()
{
std::cout << "SQlite3 version " << SQLite::VERSION << " (" << SQLite::getLibVersion() << ")" << std::endl;
std::cout << "SQliteC++ version " << SQLITECPP_VERSION << std::endl;
try
{
Example example;
char wannaquit = 'n';
std::string keyword;
while (wannaquit != 'y') {
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;
}
return EXIT_SUCCESS;
}
```
注意:这假设数据库与您的cpp文件在同一个文件夹中。
void
返回值,因此可以通过sqlite3_context
参数报告“真正”的返回值。 - mu is too shortsqlite3_result_int
来通知SQLite
结果。虽然我可能错了。 - Ken