int sqlite3session_changeset( sqlite3_session * pSession,/ *会话对象* / int * pnChangeset,/ * OUT:* ppChangeset * /处的缓冲区大小 void ** ppChangeset / * OUT:包含更改集的缓冲区* / );
获取一个变更集,该变更集包含对附加到作为第一个参数传递的会话对象的表的更改。如果成功,则在返回SQLITE_OK之前,将* ppChangeset设置为指向包含更改集的缓冲区,并将* pnChangeset设置为更改集的大小(以字节为单位)。如果发生错误,请将* ppChangeset和* pnChangeset都设置为零,并返回SQLite错误代码。
一个变更集包含零个或多个INSERT,UPDATE和/或DELETE变更,每个变更代表对附加表的一行的变更。INSERT更改包含新数据库行的每个字段的值。DELETE包含已删除数据库行的每个字段的原始值。UPDATE更改包含更新的数据库行的每个字段的原始值,以及每个更新的非主键列的更新值。UPDATE更改不可能表示修改主键列的值的更改。如果进行了这样的更改,则它将在更改集中表示为DELETE,后跟INSERT。
对于在其一个或多个PRIMARY KEY列中存储了NULL值的行,不会记录更改。如果插入或删除了这样的行,则此函数返回的变更集中将不存在相应的变更。如果更新了在PRIMARY KEY列中存储的具有一个或多个NULL值的现有行,以使所有PRIMARY KEY列均为非NULL,则更改集中仅显示INSERT。同样,如果更新具有非NULL PRIMARY KEY值的现有行,以便将其一个或多个PRIMARY KEY列设置为NULL,则结果更改集将仅包含DELETE更改。
可以使用使用sqlite3changeset_start() API创建的迭代器遍历变更集的内容。可以使用sqlite3changeset_apply() API将变更集应用于具有兼容架构的数据库。
在此函数生成的变更集中,与单个表相关的所有变更都被分组在一起。换句话说,当遍历变更集或将变更集应用于数据库时,在移至下一个表之前,将处理与单个表相关的所有更改。表以将它们附加(或自动附加)到sqlite3_session对象的相同顺序进行排序。与单个表相关的更改的存储顺序是不确定的。
成功调用此函数之后,调用者有责任最终使用sqlite3_free()释放* ppChangeset指向的缓冲区 。
将表附加到会话对象后,会话对象将记录插入表中的所有新行的主键值。它还记录任何已删除或更新的行的原始主键和其他列值。对于每个唯一的主键值,数据仅记录一次-在会话的生命周期中第一次插入,更新或删除具有该主键的行。
上一段有一个例外:插入,更新或删除行时,如果其一个或多个主键列包含NULL值,则不会记录更改。
因此,会话对象会累积两种类型的记录-仅由主键值组成的记录(在用户插入新记录时创建),以及由主键值和其他表列的原始值组成的记录(由用户创建)删除或更新记录)。
调用此函数时,将使用累积的记录和数据库文件的当前内容创建请求的变更集。具体来说:
这意味着,除其他事项外,如果在会话对象处于活动状态时先插入一行,然后再将其删除,则更改集中将不会出现插入或删除操作。或者,如果删除了一行,然后又在会话对象处于活动状态时插入了具有相同主键值的行,则生成的变更集将包含UPDATE变更,而不是DELETE和INSERT。
禁用会话对象时(请参见sqlite3session_enable() API),当插入,更新或删除行时,它不会累积记录。如果在会话期间多次写入单个行,这可能会产生一些违反直觉的效果。例如,如果在启用会话对象时插入一行,然后在禁用同一会话对象时删除该行,则即使删除是在禁用会话的情况下进行的,更改集也不会出现INSERT记录。或者,如果在禁用会话的同时更新了一行的一个字段,而在启用会话的同时更新了同一行的另一个字段,则结果更改集将包含一个更新两个字段的UPDATE更改。