int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ const char *zTab /* Table name */ ), int(*xConflict)( void *pCtx, /* Copy of sixth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); int sqlite3changeset_apply_v2_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ const char *zTab /* Table name */ ), int(*xConflict)( void *pCtx, /* Copy of sixth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx, /* First argument passed to xConflict */ void **ppRebase, int *pnRebase, int flags ); int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3changeset_invert_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); int sqlite3changeset_start_v2_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int flags ); int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3rebaser_rebase_strm( sqlite3_rebaser *pRebaser, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *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 函數,而不是單一大型緩衝區,而 sessions 模組會呼叫此回呼函數以遞增請求輸入資料,視需要而定。在所有情況下,一對 API 函數參數,例如
int nChangeset, void *pChangeset,
被取代為
int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn,
每次由 sessions 模組呼叫 xInput 回呼時,傳遞的第一個引數是所提供 pIn context 指標的副本。第二個引數 pData 指向大小為 (*pnData) 位元的緩衝區。假設沒有發生錯誤,xInput 方法應將最多 (*pnData) 位元的資料複製到緩衝區中,並在傳回 SQLITE_OK 之前將 (*pnData) 設定為實際複製的位元數。如果輸入已完全用盡,應將 (*pnData) 設定為零以表示這一點。或者,如果發生錯誤,應傳回 SQLite 錯誤碼。在所有情況下,如果 xInput 回呼傳回錯誤,所有處理都會中止,且串流 API 函式會傳回錯誤碼的副本給呼叫者。
在 sqlite3changeset_start_strm() 的情況下,xInput 回呼可能會在反覆運算器的生命週期中的任何時間點由 sessions 模組呼叫。如果此類 xInput 回呼傳回錯誤,反覆運算器會進入錯誤狀態,隨後對反覆運算器函式的所有呼叫會立即失敗,並傳回與 xInput 傳回的錯誤碼相同的錯誤碼。
類似地,傳回變更集(或修補程式集)的串流 API 函式會透過回呼函式以區塊方式傳回,而不是透過指向單一大緩衝區的指標傳回。在這種情況下,一對參數(例如)
int *pnChangeset, void **ppChangeset,
被取代為
int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut
xOutput 回呼會呼叫零次或多次,以將資料傳回應用程式。傳遞給每個呼叫的第一個參數是應用程式提供的 pOut 指標的複本。第二個參數 pData 指向一個大小為 nData 位元的緩衝區,其中包含傳回的輸出資料區塊。如果 xOutput 回呼成功處理提供的資料,它應傳回 SQLITE_OK 以表示成功。否則,它應傳回其他 SQLite 錯誤碼。在此情況下,處理會立即中斷,串流 API 函式會傳回 xOutput 錯誤碼的複本給應用程式。
sessions 模組絕不會呼叫第三個參數設定為小於或等於零的 xOutput 回呼。除此之外,並未對傳回資料區塊的大小做出任何保證。