为sqlite3全文引擎(fts5)编写了自定义排名功能。尝试使用“ .load /var/www/rankprice.so”加载该扩展时,该扩展会编译,但会引发“分段错误(核心已转储)sqlite3”错误。不确定我的扩展代码的正确性。
我已经用文档中的代码替换了原来的排名功能。扩展加载代码也从文档中复制而来。
这是3个功能: static void rankprice(//实际扩展功能, fts5_api * fts5_api_from_db(sqlite3 * db)//获取指向fts5_api指针的指针 int sqlite3_extension_init //加载扩展名
文档尚未在https://www.sqlite.org/fts5.html#extending_fts5上更新。在功能
中fts5_api *fts5_api_from_db(sqlite3 *db){
fts5_api *pRet = 0;
sqlite3_stmt *pStmt = 0;
if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0) ){
sqlite3_bind_pointer(pStmt, (void*)&pRet, "fts5_api_ptr", NULL);
sqlite3_step(pStmt);
}
sqlite3_finalize(pStmt);
return pRet;
}
sqlite3_bind_pointer
应该有5个参数,第二个参数应该是一个int,但是我不确定它的正确值。
这是完整的代码:
#include <stdio.h>
#include <assert.h>
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
/*
** Actual extension function, copied from https://www.sqlite.org/fts5.html
*/
static void rankprice(
const Fts5ExtensionApi *pApi,
Fts5Context *pFts,
sqlite3_context *pCtx,
int nVal,
sqlite3_value **apVal
){
int rc;
int nToken;
rc = pApi->xColumnSize(pFts, -1, &nToken);
if( rc==SQLITE_OK ){
sqlite3_result_int(pCtx, nToken);
}else{
sqlite3_result_error_code(pCtx, rc);
}
}
/*
** Return a pointer to the fts5_api pointer for database connection db.
** If an error occurs, return NULL and leave an error in the database
** handle (accessible using sqlite3_errcode()/errmsg()).
*/
fts5_api *fts5_api_from_db(sqlite3 *db){
fts5_api *pRet = 0;
sqlite3_stmt *pStmt = 0;
if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0) ){
sqlite3_bind_pointer(pStmt, 1,(void*)&pRet, "fts5_api_ptr", NULL);
sqlite3_step(pStmt);
}
sqlite3_finalize(pStmt);
return pRet;
}
/* Creates a SQL extension function. Tells sqlite which function to load as extension*/
int sqlite3_extension_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
fts5_api *fpApi;
fpApi = fts5_api_from_db(db);
SQLITE_EXTENSION_INIT2(pApi);
struct Builtin {
const char *zFunc; /* Function name (nul-terminated) */
void *pUserData; /* User-data pointer */
fts5_extension_function xFunc; /* Callback function */
void (*xDestroy)(void*); /* Destructor function */
} aBuiltin [] = {
{ "rankingMe", 0, rankprice, 0 },
};
int rc = SQLITE_OK;
rc = fpApi->xCreateFunction(fpApi,
aBuiltin[0].zFunc,
aBuiltin[0].pUserData,
aBuiltin[0].xFunc,
aBuiltin[0].xDestroy
);
return rc;
}
使用
gcc -shared -fPIC -g /var/www/rankprice.c -o /var/www/rankprice.so
确切的错误消息:
SQLite version 3.28.0 2019-04-16 19:49:53
Connected to a transient in-memory database.
sqlite> .load /var/www/rankprice.so
[2] 52632 segmentation fault (core dumped) sqlite3
链接:
https://www.sqlite.org/fts5.html
https://github.com/sqlite/sqlite/blob/ff119f04b42a7ad3a16c306446af7e301d34026a/ext/fts5/fts5_aux.c