]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve sessions module documentation and comments. Fix some other code issues.
authordan <dan@noemail.net>
Sat, 27 Sep 2014 12:26:18 +0000 (12:26 +0000)
committerdan <dan@noemail.net>
Sat, 27 Sep 2014 12:26:18 +0000 (12:26 +0000)
FossilOrigin-Name: bfc8bd80f8b225cebc66478448510ce84223ae7d

ext/session/sqlite3session.c
ext/session/sqlite3session.h
manifest
manifest.uuid

index a0e0697ee3a41e89b106282cbc7bf80112ebdba9..eb1ff1e7742dd9713afe7ae5ba5cc73af5609bb1 100644 (file)
@@ -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;
 
index ad58c0d7728bd6b6df852caa7389c3d23ba36c70..0dd03067ed747ce49e8604d743ff499065d74c9b 100644 (file)
@@ -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>
+**  &nbsp;     int nChangeset,
+**  &nbsp;     void *pChangeset,
+**  </pre>
+**
+** Is replaced by:
+**
+**  <pre>
+**  &nbsp;     int (*xInput)(void *pIn, void *pData, int *pnData),
+**  &nbsp;     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>
+**  &nbsp;     int *pnChangeset,
+**  &nbsp;     void **ppChangeset,
+**  </pre>
+**
+** Is replaced by:
+**
+**  <pre>
+**  &nbsp;     int (*xOutput)(void *pOut, const void *pData, int nData),
+**  &nbsp;     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++.
 */
index 07a4e34a3b689f6cd183892efe541c2fe7c774d7..258fb598ba6f09f371d31d0385fab0a9fb97c28e 100644 (file)
--- a/manifest
+++ b/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
index c388e5763a72209d03b9cd23261fd408056eaa51..31da46d10be16c7e61a6ad16eeb9ca5a58ccccd5 100644 (file)
@@ -1 +1 @@
-4d8537eafb40e3687abc057ba26a1f7014f2c2d9
\ No newline at end of file
+bfc8bd80f8b225cebc66478448510ce84223ae7d
\ No newline at end of file