mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Improve sessions module documentation and comments. Fix some other code issues.
FossilOrigin-Name: bfc8bd80f8b225cebc66478448510ce84223ae7d
This commit is contained in:
@ -49,10 +49,10 @@ struct SessionBuffer {
|
||||
};
|
||||
|
||||
/*
|
||||
** An object of this type is used internally as an abstraction for the
|
||||
** input data read by changeset iterators. Input data may be supplied
|
||||
** either as a single large buffer (sqlite3changeset_start()) or using
|
||||
** a stream function (sqlite3changeset_start_str()).
|
||||
** An object of this type is used internally as an abstraction for
|
||||
** input data. Input data may be supplied either as a single large buffer
|
||||
** (e.g. sqlite3changeset_start()) or using a stream function (e.g.
|
||||
** sqlite3changeset_start_str()).
|
||||
*/
|
||||
struct SessionInput {
|
||||
int iNext; /* Offset in aData[] of next change */
|
||||
@ -2173,6 +2173,10 @@ static int sessionValueSetStr(
|
||||
int nData, /* Size of buffer aData[] in bytes */
|
||||
u8 enc /* String encoding (0 for blobs) */
|
||||
){
|
||||
/* In theory this code could just pass SQLITE_TRANSIENT as the final
|
||||
** argument to sqlite3ValueSetStr() and have the copy created
|
||||
** automatically. But doing so makes it difficult to detect any OOM
|
||||
** error. Hence the code to create the copy externally. */
|
||||
u8 *aCopy = sqlite3_malloc(nData);
|
||||
if( aCopy==0 ) return SQLITE_NOMEM;
|
||||
memcpy(aCopy, aData, nData);
|
||||
@ -2299,12 +2303,16 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){
|
||||
/*
|
||||
** The input pointer currently points to the first byte of the first field
|
||||
** of a record consisting of nCol columns. This function ensures the entire
|
||||
** record is buffered.
|
||||
** record is buffered. It does not move the input pointer.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned and *pnByte is set to the size of
|
||||
** the record in bytes. Otherwise, an SQLite error code is returned. The
|
||||
** final value of *pnByte is undefined in this case.
|
||||
*/
|
||||
static int sessionChangesetBufferRecord(
|
||||
SessionInput *pIn,
|
||||
int nCol,
|
||||
int *pnByte
|
||||
SessionInput *pIn, /* Input data */
|
||||
int nCol, /* Number of columns in record */
|
||||
int *pnByte /* OUT: Size of record in bytes */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nByte = 0;
|
||||
@ -2335,6 +2343,15 @@ static int sessionChangesetBufferRecord(
|
||||
** + number of columns in table (varint)
|
||||
** + array of PK flags (1 byte per column),
|
||||
** + table name (nul terminated).
|
||||
**
|
||||
** This function decodes the table-header and populates the p->nCol,
|
||||
** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is
|
||||
** also allocated or resized according to the new value of p->nCol. The
|
||||
** input pointer is left pointing to the byte following the table header.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code
|
||||
** is returned and the final values of the various fields enumerated above
|
||||
** are undefined.
|
||||
*/
|
||||
static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
|
||||
int rc;
|
||||
@ -3775,7 +3792,7 @@ static int sessionChangeMerge(
|
||||
** Add all changes in the changeset passed via the first two arguments to
|
||||
** hash tables.
|
||||
*/
|
||||
static int sessionAddChangeset(
|
||||
static int sessionChangesetToHash(
|
||||
sqlite3_changeset_iter *pIter, /* Iterator to read from */
|
||||
SessionTable **ppTabList /* IN/OUT: List of table objects */
|
||||
){
|
||||
@ -3794,15 +3811,6 @@ static int sessionAddChangeset(
|
||||
SessionChange *pExist = 0;
|
||||
SessionChange **pp;
|
||||
|
||||
#if 0
|
||||
assert( bPatchset==0 || bPatchset==1 );
|
||||
assert( pIter->bPatchset==0 || pIter->bPatchset==1 );
|
||||
if( pIter->bPatchset!=bPatchset ){
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect);
|
||||
if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){
|
||||
/* Search the list for a matching table */
|
||||
@ -3899,9 +3907,9 @@ int sessionChangesetConcat(
|
||||
|
||||
assert( xOutput==0 || (ppOut==0 && pnOut==0) );
|
||||
|
||||
rc = sessionAddChangeset(pLeft, &pList);
|
||||
rc = sessionChangesetToHash(pLeft, &pList);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sessionAddChangeset(pRight, &pList);
|
||||
rc = sessionChangesetToHash(pRight, &pList);
|
||||
}
|
||||
bPatch = pLeft->bPatchset || pRight->bPatchset;
|
||||
|
||||
|
@ -274,30 +274,6 @@ int sqlite3session_changeset(
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** This function is similar to sqlite3session_changeset(), except that instead
|
||||
** of storing the output changeset in a buffer obtained from sqlite3_malloc()
|
||||
** it invokes the supplied xOutput() callback zero or more times to stream the
|
||||
** changeset to the application. This is useful in order to avoid large memory
|
||||
** allocations when working with very large changesets.
|
||||
**
|
||||
** The first parameter passed to each call to the xOutput callback is a copy
|
||||
** of the pOut parameter passed to this function. The following two parameters
|
||||
** are a pointer to the buffer containing the next chunk of the output changeset
|
||||
** and the size of that buffer in bytes.
|
||||
**
|
||||
** If the data is successfully processed by the xOutput callback, it should
|
||||
** return SQLITE_OK. Or, if an error occurs, some other SQLite error code. In
|
||||
** this case the sqlite3session_changeset_str() call is abandoned immediately
|
||||
** and returns a copy of the xOutput return code.
|
||||
*/
|
||||
int sqlite3session_changeset_str(
|
||||
sqlite3_session *pSession,
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Generate A Patchset From A Session Object
|
||||
**
|
||||
@ -327,15 +303,6 @@ int sqlite3session_patchset(
|
||||
void **ppPatchset /* OUT: Buffer containing changeset */
|
||||
);
|
||||
|
||||
/*
|
||||
** Streaming version of sqlite3session_patchset().
|
||||
*/
|
||||
int sqlite3session_patchset_str(
|
||||
sqlite3_session *pSession,
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Test if a changeset has recorded any changes.
|
||||
**
|
||||
@ -393,29 +360,6 @@ int sqlite3changeset_start(
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** This function is similar to sqlite3changeset_start(), except that instead
|
||||
** of reading data from a single buffer, it requests it one chunk at a time
|
||||
** from the application by invoking the supplied xInput() callback. The xInput()
|
||||
** callback may be invoked at any time during the lifetime of the iterator.
|
||||
**
|
||||
** Each time the xInput callback is invoked, the first argument passed is a
|
||||
** copy of the third parameter passed to this function. The second argument,
|
||||
** pData, points to a buffer (*pnData) bytes in size. Assuming no error occurs
|
||||
** the xInput method should copy up to (*pnData) bytes of data into the buffer
|
||||
** and set (*pnData) to the actual number of bytes copied before returning
|
||||
** SQLITE_OK. If the input is completely exhausted, (*pnData) should be set
|
||||
** to zero to indicate this. Or, if an error occurs, an SQLite error code
|
||||
** should be returned. In this case the iterator is put into an error state and
|
||||
** all subsequent calls to iterator methods return a copy of the xInput error
|
||||
** code.
|
||||
*/
|
||||
int sqlite3changeset_start_str(
|
||||
sqlite3_changeset_iter **pp,
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData),
|
||||
void *pIn
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Advance A Changeset Iterator
|
||||
**
|
||||
@ -670,16 +614,6 @@ int sqlite3changeset_invert(
|
||||
int *pnOut, void **ppOut /* OUT: Inverse of input */
|
||||
);
|
||||
|
||||
/*
|
||||
** Streaming version of sqlite3changeset_invert().
|
||||
*/
|
||||
int sqlite3changeset_invert_str(
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData),
|
||||
void *pIn,
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Concatenate Two Changeset Objects
|
||||
**
|
||||
@ -761,18 +695,6 @@ int sqlite3changeset_concat(
|
||||
void **ppOut /* OUT: Buffer containing output changeset */
|
||||
);
|
||||
|
||||
/*
|
||||
** Streaming verson of sqlite3changeset_concat().
|
||||
*/
|
||||
int sqlite3changeset_concat_str(
|
||||
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
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Apply A Changeset To A Database
|
||||
**
|
||||
@ -925,30 +847,6 @@ int sqlite3changeset_apply(
|
||||
void *pCtx /* First argument passed to xConflict */
|
||||
);
|
||||
|
||||
/*
|
||||
** This function is similar to sqlite3changeset_apply(), except that instead
|
||||
** of reading data from a single buffer, it requests it one chunk at a time
|
||||
** from the application by invoking the supplied xInput() callback.
|
||||
**
|
||||
** See the documentation for sqlite3changeset_start_str() for a description
|
||||
** of how the xInput callback should be implemented.
|
||||
*/
|
||||
int sqlite3changeset_apply_str(
|
||||
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 */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||
**
|
||||
@ -1045,6 +943,141 @@ int sqlite3changeset_apply_str(
|
||||
#define SQLITE_CHANGESET_REPLACE 1
|
||||
#define SQLITE_CHANGESET_ABORT 2
|
||||
|
||||
/*
|
||||
** CAPI3REF: Streaming Versions of API functions.
|
||||
**
|
||||
** The six streaming API xxx_str() functions serve similar purposes to the
|
||||
** corresponding non-streaming API functions:
|
||||
**
|
||||
** <table border=1 style="margin-left:8ex;margin-right:8ex">
|
||||
** <tr><th>Streaming function<th>Non-streaming equivalent</th>
|
||||
** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply]
|
||||
** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat]
|
||||
** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert]
|
||||
** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start]
|
||||
** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset]
|
||||
** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset]
|
||||
** </table>
|
||||
**
|
||||
** Non-streaming functions that accept changesets (or patchsets) as input
|
||||
** require that the entire changeset be stored in a single buffer in memory.
|
||||
** Similarly, those that return a changeset or patchset do so by returning
|
||||
** a pointer to a single large buffer allocated using sqlite3_malloc().
|
||||
** Normally this is convenient. However, if an application running in a
|
||||
** low-memory environment is required to handle very large changesets, the
|
||||
** large contiguous memory allocations required can become onerous.
|
||||
**
|
||||
** In order to avoid this problem, instead of a single large buffer, input
|
||||
** is passed to a streaming API functions by way of a callback function that
|
||||
** the sessions module invokes to incrementally request input data as it is
|
||||
** required. In all cases, a pair of API function parameters such as
|
||||
**
|
||||
** <pre>
|
||||
** int nChangeset,
|
||||
** void *pChangeset,
|
||||
** </pre>
|
||||
**
|
||||
** Is replaced by:
|
||||
**
|
||||
** <pre>
|
||||
** int (*xInput)(void *pIn, void *pData, int *pnData),
|
||||
** void *pIn,
|
||||
** </pre>
|
||||
**
|
||||
** Each time the xInput callback is invoked by the sessions module, the first
|
||||
** argument passed is a copy of the supplied pIn context pointer. The second
|
||||
** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no
|
||||
** error occurs the xInput method should copy up to (*pnData) bytes of data
|
||||
** into the buffer and set (*pnData) to the actual number of bytes copied
|
||||
** before returning SQLITE_OK. If the input is completely exhausted, (*pnData)
|
||||
** should be set to zero to indicate this. Or, if an error occurs, an SQLite
|
||||
** error code should be returned. In all cases, if an xInput callback returns
|
||||
** an error, all processing is abandoned and the streaming API function
|
||||
** returns a copy of the error code to the caller.
|
||||
**
|
||||
** In the case of sqlite3changeset_start_str(), the xInput callback may be
|
||||
** invoked by the sessions module at any point during the lifetime of the
|
||||
** iterator. If such an xInput callback returns an error, the iterator enters
|
||||
** an error state, whereby all subsequent calls to iterator functions
|
||||
** immediately fail with the same error code as returned by xInput.
|
||||
**
|
||||
** Similarly, streaming API functions that return changesets (or patchsets)
|
||||
** return them in chunks by way of a callback function instead of via a
|
||||
** pointer to a single large buffer. In this case, a pair of parameters such
|
||||
** as:
|
||||
**
|
||||
** <pre>
|
||||
** int *pnChangeset,
|
||||
** void **ppChangeset,
|
||||
** </pre>
|
||||
**
|
||||
** Is replaced by:
|
||||
**
|
||||
** <pre>
|
||||
** int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
** void *pOut
|
||||
** </pre>
|
||||
**
|
||||
** The xOutput callback is invoked zero or more times to return data to
|
||||
** the application. The first parameter passed to each call is a copy of the
|
||||
** pOut pointer supplied by the application. The second parameter, pData,
|
||||
** points to a buffer nData bytes in size containing the chunk of output
|
||||
** data being returned. If the xOutput callback successfully processes the
|
||||
** supplied data, it should return SQLITE_OK to indicate success. Otherwise,
|
||||
** it should return some other SQLite error code. In this case processing
|
||||
** is immediately abandoned and the streaming API function returns a copy
|
||||
** of the xOutput error code to the application.
|
||||
**
|
||||
** The sessions module never invokes an xOutput callback with the third
|
||||
** parameter set to a value less than or equal to zero. Other than this,
|
||||
** no guarantees are made as to the size of the chunks of data returned.
|
||||
*/
|
||||
int sqlite3changeset_apply_str(
|
||||
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_concat_str(
|
||||
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_str(
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData),
|
||||
void *pIn,
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
);
|
||||
int sqlite3changeset_start_str(
|
||||
sqlite3_changeset_iter **pp,
|
||||
int (*xInput)(void *pIn, void *pData, int *pnData),
|
||||
void *pIn
|
||||
);
|
||||
int sqlite3session_changeset_str(
|
||||
sqlite3_session *pSession,
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
);
|
||||
int sqlite3session_patchset_str(
|
||||
sqlite3_session *pSession,
|
||||
int (*xOutput)(void *pOut, const void *pData, int nData),
|
||||
void *pOut
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** Make sure we can call this stuff from C++.
|
||||
*/
|
||||
|
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\sproblem\swith\sconcatenating\spatchsets\scontaining\sDELETE\sand\sINSERT\soperations\son\sthe\ssame\srow.
|
||||
D 2014-09-26T10:52:21.193
|
||||
C Improve\ssessions\smodule\sdocumentation\sand\scomments.\sFix\ssome\sother\scode\sissues.
|
||||
D 2014-09-27T12:26:18.848
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -158,8 +158,8 @@ F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4
|
||||
F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d
|
||||
F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5
|
||||
F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6
|
||||
F ext/session/sqlite3session.c ade9fa2f7341b822dddaa865115ec964a030df94
|
||||
F ext/session/sqlite3session.h 04529352750006b32811384db64eb1b6e5c3cd80
|
||||
F ext/session/sqlite3session.c 9ce77f4752cd5d8982e7b64f665ae66754dda723
|
||||
F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a
|
||||
F ext/session/test_session.c 194083ee1f0f6f38404f662fe9b50849abd3b7ee
|
||||
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 88eb6656bdb047a104837a2e15e7fe18c0a7a159
|
||||
R 81a0c7112c65d31bc1808253eb2f372f
|
||||
P 4d8537eafb40e3687abc057ba26a1f7014f2c2d9
|
||||
R c2c5a501f3f294cbca1bcb47eb806551
|
||||
U dan
|
||||
Z a169087f5f6ea34184b5d5b4868830f7
|
||||
Z c7ab4f2784fbdfc318b000ddf7671e24
|
||||
|
@ -1 +1 @@
|
||||
4d8537eafb40e3687abc057ba26a1f7014f2c2d9
|
||||
bfc8bd80f8b225cebc66478448510ce84223ae7d
|
Reference in New Issue
Block a user