gpt4 book ai didi

c++ - SQLite 预更新 Hook 重入

转载 作者:搜寻专家 更新时间:2023-10-30 20:52:25 30 4
gpt4 key购买 nike

我正在尝试使用 SQLite 的新 C 接口(interface)预更新 Hook :

https://www.sqlite.org/c3ref/preupdate_count.html

现在回答我的问题:pre_update API 签名如下:

void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
),
void*
);

如您所见,它向回调注入(inject)一个指向注册 Hook 的数据库连接的指针。根据我的经验和 SQLite 文档,我知道更新/提交/回滚 Hook 不可重入,这意味着它们无法修改导致 Hook 调用的连接。

我想使用这个 pre_update 回调来读取和写入数据库。

现在我有 2 个问题:

1) SQLite pre_update 回调是否可重入并支持从回调范围修改和读取数据库?

2) 如果是这样,谁能解释一下为什么会这样?

我创建了一个新数据库并使用 SQLite shell 运行以下命令:

sqlite> CREATE TABLE Parent(_index INTEGER PRIMARY KEY);
sqlite> INSERT INTO "Parent" VALUES(1);
sqlite> CREATE TABLE Child(_index INTEGER PRIMARY KEY, CONSTRAINT ch_fk FOREIGN KEY(_index) REFERENCES Parent(_index) DEFERRABLE INITIALLY DEFERRED);
sqlite> INSERT INTO "Child" VALUES(1);

现在我正在尝试创建一个自动操作,它应该在事务内部工作,并在每次它的父亲更改它的 key 时更新一个 child ,这样它就不会违反约束。

注意:我知道我可以使用触发器/SQLite 外键更新机制实现此行为,但我愿意测试此 API 的稳定性。

所以代码:

int main(int argc, char *argv[]){

int rc;
char *err_msg;
sqlite3 *sqlite_connection;

rc = sqlite3_open("__database__.db",&sqlite_connection);
rc += rc = sqlite3_exec(sqlite_connection, "PRAGMA foreign_keys=ON;", 0, 0, &err_msg);/* set foreign keys mechanism on */
if(rc != SQLITE_OK){
printf("Error initializing connection : %s\n",err_msg);
exit(rc);
}

sqlite3_preupdate_hook(sqlite_connection,pre_hook,NULL);

//Watch tables content before
rc = sqlite3_exec(sqlite_connection, "SELECT * FROM PARENT;", callback, (void*)NULL, &err_msg);
rc = sqlite3_exec(sqlite_connection, "SELECT * FROM CHILD;", callback, (void*)NULL, &err_msg);

//BEGIN TRANSACTION
rc = sqlite3_exec(sqlite_connection, "BEGIN", 0, 0, &err_msg);

/* Update table to invoke callback */
rc += sqlite3_exec(sqlite_connection, "UPDATE Parent SET _index = 2 WHERE _index = 1", 0, 0, &err_msg); /* Update table to invoke callback */

//Watch tables content after
rc = sqlite3_exec(sqlite_connection, "SELECT * FROM PARENT;", callback, (void*)NULL, &err_msg);
rc = sqlite3_exec(sqlite_connection, "SELECT * FROM CHILD;", callback, (void*)NULL, &err_msg);

rc += sqlite3_exec(sqlite_connection, "COMMIT;", 0, 0, &err_msg);

if(rc != SQLITE_OK){
printf("Error updating the database : %s\n",err_msg);
rc = sqlite3_exec(sqlite_connection, "ROLLBACK", 0, 0, &err_msg);
if(rc != SQLITE_OK){
printf("Error updating the database : %s\n",err_msg);
}
}


sqlite3_close(sqlite_connection);

return rc;

}

还有 pre_hook :

void pre_hook(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2){
char query_buffer[100];
char *err_msg;
if((strcmp("Parent",zName) == 0) && (SQLITE_UPDATE == op)){
sprintf(query_buffer,"UPDATE Child SET _index = %d WHERE _index = %d",(int)iKey2,(int)iKey1);
if(sqlite3_exec(db,query_buffer , 0, 0, &err_msg) != SQLITE_OK){
printf("Error executin trigger\n");
}

}
}

然后我得到输出:

//运行前: parent :_索引:1

child :_索引:1

//运行后: parent :_索引:2

child :_索引:2更新数据库时出错:违反 FOREIGN KEY 约束

如您所见,根本没有违规!

然而,当我如下更改主要功能时:

1) 取消对 pre_hook 回调的签名。

2) 在回调之外操作子更新(在我们的例子中是在父更新之后)。

我突然得到了相同的输出,只是没有错误。

我认为这意味着 pre_update 回调不可重入,但我寻求对这个问题的专业解答。

最佳答案

来自documentation :

The update hook implementation must not do anything that will modifythe database connection that invoked the update hook. Any actions tomodify the database connection must be deferred until after thecompletion of the sqlite3_step() call that triggered the update hook.Note that sqlite3_prepare_v2() and sqlite3_step() both modify theirdatabase connections for the meaning of "modify" in this paragraph.

关于c++ - SQLite 预更新 Hook 重入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37545766/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com