int sqlite3changeset_apply_strm( sqlite3 * db,/ *将更改应用于此句柄的“主” db * / int(* xInput)(void * pIn,void * pData,int * pnData),/ *输入函数* / void * pIn,/ * xInput的第一个arg * / 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_strm( sqlite3 * db,/ *将更改应用于此句柄的“主” db * / int(* xInput)(void * pIn,void * pData,int * pnData),/ *输入函数* / void * pIn,/ * xInput的第一个arg * / 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, 整型标志 ); int sqlite3changeset_concat_strm( int(* xInputA)(void * pIn,void * pData,int * pnData), 无效* pInA, int(* xInputB)(void * pIn,void * pData,int * pnData), 无效* pInB, int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut ); int sqlite3changeset_invert_strm( int(* xInput)(void * pIn,void * pData,int * pnData), 无效* pIn, int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut ); int sqlite3changeset_start_strm( sqlite3_changeset_iter ** pp, int(* xInput)(void * pIn,void * pData,int * pnData), 无效* pIn ); int sqlite3changeset_start_v2_strm( sqlite3_changeset_iter ** pp, int(* xInput)(void * pIn,void * pData,int * pnData), 无效* pIn, 整型标志 ); int sqlite3session_changeset_strm( sqlite3_session * pSession, int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut ); int sqlite3session_patchset_strm( sqlite3_session * pSession, int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut ); int sqlite3changegroup_add_strm(sqlite3_changegroup *, int(* xInput)(void * pIn,void * pData,int * pnData), 无效* pIn ); int sqlite3changegroup_output_strm(sqlite3_changegroup *, int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut ); int sqlite3rebaser_rebase_strm( sqlite3_rebaser * pRebaser, int(* xInput)(void * pIn,void * pData,int * pnData), 无效* pIn, int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut );
六个流API xxx_strm()函数的作用与相应的非流API函数类似:
流功能 | 非流式等效 |
---|---|
sqlite3changeset_apply_strm | sqlite3changeset_apply |
sqlite3changeset_apply_strm_v2 | sqlite3changeset_apply_v2 |
sqlite3changeset_concat_strm | sqlite3changeset_concat |
sqlite3changeset_invert_strm | sqlite3changeset_invert |
sqlite3changeset_start_strm | sqlite3changeset_start |
sqlite3session_changeset_strm | sqlite3session_changeset |
sqlite3session_patchset_strm | sqlite3session_patchset |
接受变更集(或补丁集)作为输入的非流式函数要求将整个变更集存储在内存中的单个缓冲区中。类似地,那些返回变更集或补丁集的方法是通过返回指向使用sqlite3_malloc()分配的单个大缓冲区的指针来实现的。通常这很方便。但是,如果需要在低内存环境中运行的应用程序来处理非常大的变更集,则所需的大量连续内存分配可能会变得很繁重。
为了避免此问题,不是通过单个大缓冲区,而是通过会话模块调用的回调函数将输入传递给流式API函数,以根据需要递增地请求输入数据。在所有情况下,都有一对API函数参数,例如
int nChangeset, 无效* pChangeset,
替换为:
int(* xInput)(void * pIn,void * pData,int * pnData), 无效* pIn,
每次由session模块调用xInput回调时,传递的第一个参数是所提供的pIn上下文指针的副本。第二个参数pData指向缓冲区(* pnData)字节大小。假设没有错误发生,xInput方法应该将最多(* pnData)个字节的数据复制到缓冲区中,并在返回SQLITE_OK之前将(* pnData)设置为实际复制的字节数。如果输入完全用尽,则应将(* pnData)设置为零以表明这一点。或者,如果发生错误,则应返回SQLite错误代码。在所有情况下,如果xInput回调返回错误,则将放弃所有处理,并且流API函数将错误代码的副本返回给调用方。
对于sqlite3changeset_start_strm(),会话模块可以在迭代器的生命周期内的任何时候调用xInput回调。如果此类xInput回调返回错误,则迭代器将进入错误状态,从而所有后续对迭代器函数的调用将立即失败,并返回与xInput返回的相同的错误代码。
同样,返回变更集(或补丁集)的流式API函数通过回调函数(而不是通过指向单个大缓冲区的指针)以块的形式返回它们。在这种情况下,需要一对参数,例如:
int * pnChangeset, 无效** ppChangeset,
替换为:
int(* xOutput)(无效* pOut,const void * pData,int nData), 无效* pOut
xOutput回调被调用零次或更多次,以将数据返回给应用程序。传递给每个调用的第一个参数是应用程序提供的pOut指针的副本。第二个参数pData指向大小为nData字节的缓冲区,其中包含要返回的输出数据块。如果xOutput回调成功处理了提供的数据,则应返回SQLITE_OK表示成功。否则,它应该返回其他一些SQLite错误代码。在这种情况下,将立即放弃处理,并且流API函数将xOutput错误代码的副本返回给应用程序。
会话模块永远不会调用第三个参数设置为小于或等于零的值的xOutput回调。除此之外,不能保证返回的数据块的大小。