int sqlite3changeset_apply( sqlite3 * db,/ *将更改应用于此句柄的“主” db * / int nChangeset,/ *变更集的大小(以字节为单位)* / 无效* pChangeset,/ *更改集blob * / int(* xFilter)( void * pCtx,/ *将第六个arg复制到_apply()* / const char * zTab / *表名* / ), int(* xConflict)( void * pCtx,/ *将第六个arg复制到_apply()* / int eConflict,/ * DATA,MISSING,CONFLICT,CONSTRAINT * / sqlite3_changeset_iter * p / *描述更改和冲突的句柄* / ), 无效* pCtx / *传递给xConflict的第一个参数* / ); int sqlite3changeset_apply_v2( sqlite3 * db,/ *将更改应用于此句柄的“主” db * / int nChangeset,/ *变更集的大小(以字节为单位)* / 无效* pChangeset,/ *更改集blob * / int(* xFilter)( void * pCtx,/ *将第六个arg复制到_apply()* / const char * zTab / *表名* / ), int(* xConflict)( void * pCtx,/ *将第六个arg复制到_apply()* / int eConflict,/ * DATA,MISSING,CONFLICT,CONSTRAINT * / sqlite3_changeset_iter * p / *描述更改和冲突的句柄* / ), void * pCtx,/ *传递给xConflict的第一个参数* / void ** ppRebase,int * pnRebase,/ * OUT:重新设置数据* / int标志/ * SESSION_CHANGESETAPPLY_ *标志* / );
将变更集或补丁集应用于数据库。这些函数尝试使用通过第二个和第三个参数传递的变更集中的变更来更新附加到句柄db的“主”数据库。
传递给这些函数的第四个参数(xFilter)是“过滤器回调”。如果它不是NULL,则对于受变更集至少一个更改影响的每个表,将以表名作为第二个参数调用过滤器回调,并以第六个参数作为第一个参数传递上下文指针的副本。如果“过滤器回调”返回零,则不尝试将任何更改应用于表。否则,如果返回值非零或xFilter的参数为NULL,则尝试与表相关的所有更改。
对于过滤器回调未排除的每个表,此函数将测试目标数据库是否包含兼容表。如果满足以下所有条件,则表被认为是兼容的:
如果没有兼容的表,则不是错误,但是不会应用与该表关联的任何更改。通过sqlite3_log()机制发出警告消息,错误代码为SQLITE_SCHEMA。对于变更集中的每个表,最多发出一个这样的警告。
对于具有兼容表的每个更改,都会尝试根据UPDATE,INSERT或DELETE更改来修改表内容。如果无法彻底应用更改,则可以调用作为第五个参数传递给sqlite3changeset_apply()的冲突处理程序函数。以下是对每种更改类型何时调用冲突处理程序的确切说明。
与xFilter参数不同,xConflict不能传递为NULL。未定义将有效函数指针以外的任何内容作为xConflict参数传递的结果。
每次调用冲突处理程序函数时,它都必须返回SQLITE_CHANGESET_OMIT,SQLITE_CHANGESET_ABORT或 SQLITE_CHANGESET_REPLACE中的一个。仅当传递给冲突处理程序的第二个参数是SQLITE_CHANGESET_DATA或SQLITE_CHANGESET_CONFLICT时,才可以返回SQLITE_CHANGESET_REPLACE。如果冲突处理程序返回非法值,则已进行的所有更改都将回滚,对sqlite3changeset_apply()的调用将返回SQLITE_MISUSE。sqlite3changeset_apply()会根据冲突处理程序函数的每次调用返回的值采取不同的操作。有关详细信息,请参考文档中的三个 可用返回值。
如果找到具有匹配的主键值的行,但是一个或多个非主键字段包含的值与更改集中存储的原始行值不同,则将使用SQLITE_CHANGESET_DATA作为第二个参数来调用冲突处理程序函数。如果数据库表中的列数多于变更集中记录的列数,则仅将那些非主键字段的值与当前数据库内容进行比较-忽略任何尾随的数据库表列。
如果在数据库中未找到具有匹配主键值的行,则使用 第二个参数传递的SQLITE_CHANGESET_NOTFOUND调用冲突处理程序函数。
如果尝试执行DELETE操作,但是SQLite返回SQLITE_CONSTRAINT(只有在违反外键约束的情况下才会发生),将使用 作为第二个参数传递的SQLITE_CHANGESET_CONSTRAINT调用冲突处理程序函数。这包括由于先前对冲突处理程序函数的调用返回SQLITE_CHANGESET_REPLACE而尝试执行DELETE操作的情况。
如果由于数据库已经包含具有相同主键值的行而导致插入行的尝试失败,则将第二个参数设置为SQLITE_CHANGESET_CONFLICT来调用冲突处理程序函数 。
如果由于某些其他违反约束(例如NOT NOT NULL或UNIQUE)的原因而导致插入行的尝试失败,则在将第二个参数设置为SQLITE_CHANGESET_CONSTRAINT的情况下调用冲突处理程序函数。这包括由于先前对冲突处理程序函数的调用返回SQLITE_CHANGESET_REPLACE而重新尝试INSERT操作的情况 。
如果找到具有匹配的主键值的行,但是一个或多个修改后的非主键字段包含的值与更改集中存储的原始行值不同,则使用SQLITE_CHANGESET_DATA作为第二个参数来调用冲突处理程序函数。由于UPDATE更改仅包含要修改的非主键字段的值,因此只有那些字段需要与原始值匹配,以避免SQLITE_CHANGESET_DATA冲突处理程序回调。
如果在数据库中未找到具有匹配主键值的行,则使用 第二个参数传递的SQLITE_CHANGESET_NOTFOUND调用冲突处理程序函数。
如果尝试执行UPDATE操作,但是SQLite返回SQLITE_CONSTRAINT,则使用作为第二个参数传递的SQLITE_CHANGESET_CONSTRAINT调用冲突处理程序函数 。这包括在冲突调用函数的更早调用返回SQLITE_CHANGESET_REPLACE之后尝试执行UPDATE操作的情况 。
从xConflict回调中执行SQL语句(包括那些写入与回调相关的表的语句)是安全的。这可用于进一步自定义应用程序的冲突解决策略。
这些功能所做的所有更改都包含在保存点事务中。如果发生任何其他错误(除了尝试写入目标数据库时的约束失败),那么将回滚保存点事务,将目标数据库还原到其原始状态,并返回SQLite错误代码。
如果输出参数(ppRebase)和(pnRebase)为非NULL,并且输入为变更集(而非补丁集),则sqlite3changeset_apply_v2()可以设置(* ppRebase)指向可与sqlite3_rebaser API会在返回之前缓冲。在这种情况下(* pnRebase)设置为缓冲区的大小(以字节为单位)。最终,调用者有责任使用sqlite3_free()释放任何此类缓冲区。仅当应用补丁集时遇到一个或多个冲突时,才分配和填充缓冲区。有关更多详细信息,请参见有关sqlite3_rebaser API的注释。
sqlite3changeset_apply_v2()的行为及其流等效项可以通过将支持的标志的组合作为第9个参数来进行修改 。
请注意,sqlite3changeset_apply_v2()API仍处于试验阶段 ,因此可能会发生变化。