#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) 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* ); int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); int sqlite3_preupdate_count(sqlite3 *); int sqlite3_preupdate_depth(sqlite3 *); int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); int sqlite3_preupdate_blobwrite(sqlite3 *); #endif
这些接口只有在 SQLite 使用 SQLITE_ENABLE_PREUPDATE_HOOK 编译时选项编译时才可用。
该 sqlite3_preupdate_hook() 接口注册一个回调函数,该函数在对数据库表执行每个 INSERT、UPDATE 和 DELETE 操作之前被调用。在单个 数据库连接 上,一次最多只能注册一个更新前钩子;对 sqlite3_preupdate_hook() 的每次调用都会覆盖之前的设置。通过使用 NULL 指针作为第二个参数调用 sqlite3_preupdate_hook() 来禁用更新前钩子。传递给 sqlite3_preupdate_hook() 的第三个参数会作为回调函数的第一个参数传递。
更新前钩子只针对对真实数据库表的更改触发;更新前钩子不会针对对 虚拟表 或对 sqlite_sequence 或 sqlite_stat1 等系统表进行的更改而调用。
更新前回调的第二个参数是指向注册更新前钩子的 数据库连接 的指针。更新前回调的第三个参数是常量 SQLITE_INSERT、SQLITE_DELETE 或 SQLITE_UPDATE 之一,用于标识即将发生的更新操作类型。更新前回调的第四个参数是数据库连接中正在修改的数据库的名称。对于主数据库,它将是“main”,对于 TEMP 表,它将是“temp”,对于附加数据库,它将是在 ATTACH 语句中 AS 关键字后面的名称。更新前回调的第五个参数是正在修改的表的名称。
对于对 rowid 表 的 UPDATE 或 DELETE 操作,传递给更新前回调的第六个参数是正在修改或删除的行的初始 rowid。对于对 rowid 表的 INSERT 操作,或对 WITHOUT ROWID 表的任何操作,第六个参数的值是不确定的。对于对 rowid 表的 INSERT 或 UPDATE 操作,第七个参数是正在插入或更新的行的最终 rowid 值。对于对 WITHOUT ROWID 表的操作,或对于对 rowid 表的 DELETE 操作,传递给回调函数的第七个参数的值是不确定的。
sqlite3_preupdate_hook(D,C,P) 函数返回来自同一 数据库连接 D 上之前调用的 P 参数,或对于 D 上的第一次调用返回 NULL。
该 sqlite3_preupdate_old()、sqlite3_preupdate_new()、sqlite3_preupdate_count() 和 sqlite3_preupdate_depth() 接口提供有关更新前事件的附加信息。这些例程只能在更新前回调中调用。在更新前回调之外调用这些例程,或使用与传递给更新前回调的例程不同的 数据库连接 指针会导致不确定的行为,并且可能会产生不良行为。
该 sqlite3_preupdate_count(D) 接口返回正在插入、更新或删除的行的列数。
该 sqlite3_preupdate_old(D,N,P) 接口将指向包含表行在更新之前的第 N 列的值的 受保护的 sqlite3_value 的指针写入 P 中。N 参数必须在 0 和列数减 1 之间,否则行为将是不确定的。这只能在 SQLITE_UPDATE 和 SQLITE_DELETE 更新前回调中使用;如果在 SQLITE_INSERT 回调中使用,则行为将是不确定的。当更新前回调返回时,P 指向的 sqlite3_value 将被销毁。
该 sqlite3_preupdate_new(D,N,P) 接口将指向包含表行在更新之后的第 N 列的值的 受保护的 sqlite3_value 的指针写入 P 中。N 参数必须在 0 和列数减 1 之间,否则行为将是不确定的。这只能在 SQLITE_INSERT 和 SQLITE_UPDATE 更新前回调中使用;如果在 SQLITE_DELETE 回调中使用,则行为将是不确定的。当更新前回调返回时,P 指向的 sqlite3_value 将被销毁。
该 sqlite3_preupdate_depth(D) 接口如果更新前回调是由于直接插入、更新或删除操作而被调用,则返回 0;如果更新前回调是由于顶级触发器调用而被调用,则返回 1;如果更新前回调是由于由顶级触发器调用的触发器调用而被调用,则返回 2,依此类推。
当使用 sqlite3_blob_write() API 更新 blob 列时,更新前钩子将使用 SQLITE_DELETE 调用。这是因为在这种情况下,新值不可用。在这种情况下,当使用 sqlite3_blob_write() API 进行的回调使用 op==SQLITE_DELETE 进行时,sqlite3_preupdate_blobwrite() 将返回正在写入的列的索引。在其他情况下,如果由于其他原因(包括常规 DELETE)调用更新前钩子,sqlite3_preupdate_blobwrite() 将返回 -1。