| | @@ -1147,11 +1147,11 @@ |
| 1147 | 1147 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 1148 | 1148 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 1149 | 1149 | */ |
| 1150 | 1150 | #define SQLITE_VERSION "3.23.0" |
| 1151 | 1151 | #define SQLITE_VERSION_NUMBER 3023000 |
| 1152 | | -#define SQLITE_SOURCE_ID "2018-03-22 17:13:44 eb4f452e354065d610ff57a6a9312ad119b6b0cc467f9dff105f0718bc27ef01" |
| 1152 | +#define SQLITE_SOURCE_ID "2018-03-28 15:56:55 eb29b3369e76ec1df25a5484d8ec5fb924e23d5c70aaa4d794b2b17ee187alt1" |
| 1153 | 1153 | |
| 1154 | 1154 | /* |
| 1155 | 1155 | ** CAPI3REF: Run-Time Library Version Numbers |
| 1156 | 1156 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 1157 | 1157 | ** |
| | @@ -2086,10 +2086,16 @@ |
| 2086 | 2086 | ** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. |
| 2087 | 2087 | ** ^This file control takes the file descriptor out of batch write mode |
| 2088 | 2088 | ** so that all subsequent write operations are independent. |
| 2089 | 2089 | ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without |
| 2090 | 2090 | ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. |
| 2091 | +** |
| 2092 | +** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]] |
| 2093 | +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain |
| 2094 | +** a file lock using the xLock or xShmLock methods of the VFS to wait |
| 2095 | +** for up to M milliseconds before failing, where M is the single |
| 2096 | +** unsigned integer parameter. |
| 2091 | 2097 | ** </ul> |
| 2092 | 2098 | */ |
| 2093 | 2099 | #define SQLITE_FCNTL_LOCKSTATE 1 |
| 2094 | 2100 | #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 |
| 2095 | 2101 | #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 |
| | @@ -2120,10 +2126,11 @@ |
| 2120 | 2126 | #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 |
| 2121 | 2127 | #define SQLITE_FCNTL_PDB 30 |
| 2122 | 2128 | #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 |
| 2123 | 2129 | #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 |
| 2124 | 2130 | #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 |
| 2131 | +#define SQLITE_FCNTL_LOCK_TIMEOUT 34 |
| 2125 | 2132 | |
| 2126 | 2133 | /* deprecated names */ |
| 2127 | 2134 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 2128 | 2135 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 2129 | 2136 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| | @@ -9833,11 +9840,11 @@ |
| 9833 | 9840 | |
| 9834 | 9841 | /* |
| 9835 | 9842 | ** CAPI3REF: Deserialize a database |
| 9836 | 9843 | ** |
| 9837 | 9844 | ** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the |
| 9838 | | -** [database connection] D to disconnection from database S and then |
| 9845 | +** [database connection] D to disconnect from database S and then |
| 9839 | 9846 | ** reopen S as an in-memory database based on the serialization contained |
| 9840 | 9847 | ** in P. The serialized database P is N bytes in size. M is the size of |
| 9841 | 9848 | ** the buffer P, which might be larger than N. If M is larger than N, and |
| 9842 | 9849 | ** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is |
| 9843 | 9850 | ** permitted to add content to the in-memory database as long as the total |
| | @@ -10974,23 +10981,22 @@ |
| 10974 | 10981 | SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); |
| 10975 | 10982 | |
| 10976 | 10983 | /* |
| 10977 | 10984 | ** CAPI3REF: Apply A Changeset To A Database |
| 10978 | 10985 | ** |
| 10979 | | -** Apply a changeset to a database. This function attempts to update the |
| 10980 | | -** "main" database attached to handle db with the changes found in the |
| 10981 | | -** changeset passed via the second and third arguments. |
| 10986 | +** Apply a changeset or patchset to a database. These functions attempt to |
| 10987 | +** update the "main" database attached to handle db with the changes found in |
| 10988 | +** the changeset passed via the second and third arguments. |
| 10982 | 10989 | ** |
| 10983 | | -** The fourth argument (xFilter) passed to this function is the "filter |
| 10990 | +** The fourth argument (xFilter) passed to these functions is the "filter |
| 10984 | 10991 | ** callback". If it is not NULL, then for each table affected by at least one |
| 10985 | 10992 | ** change in the changeset, the filter callback is invoked with |
| 10986 | 10993 | ** the table name as the second argument, and a copy of the context pointer |
| 10987 | | -** passed as the sixth argument to this function as the first. If the "filter |
| 10988 | | -** callback" returns zero, then no attempt is made to apply any changes to |
| 10989 | | -** the table. Otherwise, if the return value is non-zero or the xFilter |
| 10990 | | -** argument to this function is NULL, all changes related to the table are |
| 10991 | | -** attempted. |
| 10994 | +** passed as the sixth argument as the first. If the "filter callback" |
| 10995 | +** returns zero, then no attempt is made to apply any changes to the table. |
| 10996 | +** Otherwise, if the return value is non-zero or the xFilter argument to |
| 10997 | +** is NULL, all changes related to the table are attempted. |
| 10992 | 10998 | ** |
| 10993 | 10999 | ** For each table that is not excluded by the filter callback, this function |
| 10994 | 11000 | ** tests that the target database contains a compatible table. A table is |
| 10995 | 11001 | ** considered compatible if all of the following are true: |
| 10996 | 11002 | ** |
| | @@ -11031,11 +11037,11 @@ |
| 11031 | 11037 | ** the documentation for the three |
| 11032 | 11038 | ** [SQLITE_CHANGESET_OMIT|available return values] for details. |
| 11033 | 11039 | ** |
| 11034 | 11040 | ** <dl> |
| 11035 | 11041 | ** <dt>DELETE Changes<dd> |
| 11036 | | -** For each DELETE change, this function checks if the target database |
| 11042 | +** For each DELETE change, the function checks if the target database |
| 11037 | 11043 | ** contains a row with the same primary key value (or values) as the |
| 11038 | 11044 | ** original row values stored in the changeset. If it does, and the values |
| 11039 | 11045 | ** stored in all non-primary key columns also match the values stored in |
| 11040 | 11046 | ** the changeset the row is deleted from the target database. |
| 11041 | 11047 | ** |
| | @@ -11076,11 +11082,11 @@ |
| 11076 | 11082 | ** This includes the case where the INSERT operation is re-attempted because |
| 11077 | 11083 | ** an earlier call to the conflict handler function returned |
| 11078 | 11084 | ** [SQLITE_CHANGESET_REPLACE]. |
| 11079 | 11085 | ** |
| 11080 | 11086 | ** <dt>UPDATE Changes<dd> |
| 11081 | | -** For each UPDATE change, this function checks if the target database |
| 11087 | +** For each UPDATE change, the function checks if the target database |
| 11082 | 11088 | ** contains a row with the same primary key value (or values) as the |
| 11083 | 11089 | ** original row values stored in the changeset. If it does, and the values |
| 11084 | 11090 | ** stored in all modified non-primary key columns also match the values |
| 11085 | 11091 | ** stored in the changeset the row is updated within the target database. |
| 11086 | 11092 | ** |
| | @@ -11107,15 +11113,25 @@ |
| 11107 | 11113 | ** It is safe to execute SQL statements, including those that write to the |
| 11108 | 11114 | ** table that the callback related to, from within the xConflict callback. |
| 11109 | 11115 | ** This can be used to further customize the applications conflict |
| 11110 | 11116 | ** resolution strategy. |
| 11111 | 11117 | ** |
| 11112 | | -** All changes made by this function are enclosed in a savepoint transaction. |
| 11118 | +** All changes made by these functions are enclosed in a savepoint transaction. |
| 11113 | 11119 | ** If any other error (aside from a constraint failure when attempting to |
| 11114 | 11120 | ** write to the target database) occurs, then the savepoint transaction is |
| 11115 | 11121 | ** rolled back, restoring the target database to its original state, and an |
| 11116 | 11122 | ** SQLite error code returned. |
| 11123 | +** |
| 11124 | +** If the output parameters (ppRebase) and (pnRebase) are non-NULL and |
| 11125 | +** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() |
| 11126 | +** may set (*ppRebase) to point to a "rebase" that may be used with the |
| 11127 | +** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) |
| 11128 | +** is set to the size of the buffer in bytes. It is the responsibility of the |
| 11129 | +** caller to eventually free any such buffer using sqlite3_free(). The buffer |
| 11130 | +** is only allocated and populated if one or more conflicts were encountered |
| 11131 | +** while applying the patchset. See comments surrounding the sqlite3_rebaser |
| 11132 | +** APIs for further details. |
| 11117 | 11133 | */ |
| 11118 | 11134 | SQLITE_API int sqlite3changeset_apply( |
| 11119 | 11135 | sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 11120 | 11136 | int nChangeset, /* Size of changeset in bytes */ |
| 11121 | 11137 | void *pChangeset, /* Changeset blob */ |
| | @@ -11127,10 +11143,26 @@ |
| 11127 | 11143 | void *pCtx, /* Copy of sixth arg to _apply() */ |
| 11128 | 11144 | int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 11129 | 11145 | sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 11130 | 11146 | ), |
| 11131 | 11147 | void *pCtx /* First argument passed to xConflict */ |
| 11148 | +); |
| 11149 | +SQLITE_API int sqlite3changeset_apply_v2( |
| 11150 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 11151 | + int nChangeset, /* Size of changeset in bytes */ |
| 11152 | + void *pChangeset, /* Changeset blob */ |
| 11153 | + int(*xFilter)( |
| 11154 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 11155 | + const char *zTab /* Table name */ |
| 11156 | + ), |
| 11157 | + int(*xConflict)( |
| 11158 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 11159 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 11160 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 11161 | + ), |
| 11162 | + void *pCtx, /* First argument passed to xConflict */ |
| 11163 | + void **ppRebase, int *pnRebase |
| 11132 | 11164 | ); |
| 11133 | 11165 | |
| 11134 | 11166 | /* |
| 11135 | 11167 | ** CAPI3REF: Constants Passed To The Conflict Handler |
| 11136 | 11168 | ** |
| | @@ -11225,10 +11257,165 @@ |
| 11225 | 11257 | */ |
| 11226 | 11258 | #define SQLITE_CHANGESET_OMIT 0 |
| 11227 | 11259 | #define SQLITE_CHANGESET_REPLACE 1 |
| 11228 | 11260 | #define SQLITE_CHANGESET_ABORT 2 |
| 11229 | 11261 | |
| 11262 | +/* |
| 11263 | +** CAPI3REF: Rebasing changesets |
| 11264 | +** EXPERIMENTAL |
| 11265 | +** |
| 11266 | +** Suppose there is a site hosting a database in state S0. And that |
| 11267 | +** modifications are made that move that database to state S1 and a |
| 11268 | +** changeset recorded (the "local" changeset). Then, a changeset based |
| 11269 | +** on S0 is received from another site (the "remote" changeset) and |
| 11270 | +** applied to the database. The database is then in state |
| 11271 | +** (S1+"remote"), where the exact state depends on any conflict |
| 11272 | +** resolution decisions (OMIT or REPLACE) made while applying "remote". |
| 11273 | +** Rebasing a changeset is to update it to take those conflict |
| 11274 | +** resolution decisions into account, so that the same conflicts |
| 11275 | +** do not have to be resolved elsewhere in the network. |
| 11276 | +** |
| 11277 | +** For example, if both the local and remote changesets contain an |
| 11278 | +** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": |
| 11279 | +** |
| 11280 | +** local: INSERT INTO t1 VALUES(1, 'v1'); |
| 11281 | +** remote: INSERT INTO t1 VALUES(1, 'v2'); |
| 11282 | +** |
| 11283 | +** and the conflict resolution is REPLACE, then the INSERT change is |
| 11284 | +** removed from the local changeset (it was overridden). Or, if the |
| 11285 | +** conflict resolution was "OMIT", then the local changeset is modified |
| 11286 | +** to instead contain: |
| 11287 | +** |
| 11288 | +** UPDATE t1 SET b = 'v2' WHERE a=1; |
| 11289 | +** |
| 11290 | +** Changes within the local changeset are rebased as follows: |
| 11291 | +** |
| 11292 | +** <dl> |
| 11293 | +** <dt>Local INSERT<dd> |
| 11294 | +** This may only conflict with a remote INSERT. If the conflict |
| 11295 | +** resolution was OMIT, then add an UPDATE change to the rebased |
| 11296 | +** changeset. Or, if the conflict resolution was REPLACE, add |
| 11297 | +** nothing to the rebased changeset. |
| 11298 | +** |
| 11299 | +** <dt>Local DELETE<dd> |
| 11300 | +** This may conflict with a remote UPDATE or DELETE. In both cases the |
| 11301 | +** only possible resolution is OMIT. If the remote operation was a |
| 11302 | +** DELETE, then add no change to the rebased changeset. If the remote |
| 11303 | +** operation was an UPDATE, then the old.* fields of change are updated |
| 11304 | +** to reflect the new.* values in the UPDATE. |
| 11305 | +** |
| 11306 | +** <dt>Local UPDATE<dd> |
| 11307 | +** This may conflict with a remote UPDATE or DELETE. If it conflicts |
| 11308 | +** with a DELETE, and the conflict resolution was OMIT, then the update |
| 11309 | +** is changed into an INSERT. Any undefined values in the new.* record |
| 11310 | +** from the update change are filled in using the old.* values from |
| 11311 | +** the conflicting DELETE. Or, if the conflict resolution was REPLACE, |
| 11312 | +** the UPDATE change is simply omitted from the rebased changeset. |
| 11313 | +** |
| 11314 | +** If conflict is with a remote UPDATE and the resolution is OMIT, then |
| 11315 | +** the old.* values are rebased using the new.* values in the remote |
| 11316 | +** change. Or, if the resolution is REPLACE, then the change is copied |
| 11317 | +** into the rebased changeset with updates to columns also updated by |
| 11318 | +** the conflicting remote UPDATE removed. If this means no columns would |
| 11319 | +** be updated, the change is omitted. |
| 11320 | +** </dl> |
| 11321 | +** |
| 11322 | +** A local change may be rebased against multiple remote changes |
| 11323 | +** simultaneously. If a single key is modified by multiple remote |
| 11324 | +** changesets, they are combined as follows before the local changeset |
| 11325 | +** is rebased: |
| 11326 | +** |
| 11327 | +** <ul> |
| 11328 | +** <li> If there has been one or more REPLACE resolutions on a |
| 11329 | +** key, it is rebased according to a REPLACE. |
| 11330 | +** |
| 11331 | +** <li> If there have been no REPLACE resolutions on a key, then |
| 11332 | +** the local changeset is rebased according to the most recent |
| 11333 | +** of the OMIT resolutions. |
| 11334 | +** </ul> |
| 11335 | +** |
| 11336 | +** Note that conflict resolutions from multiple remote changesets are |
| 11337 | +** combined on a per-field basis, not per-row. This means that in the |
| 11338 | +** case of multiple remote UPDATE operations, some fields of a single |
| 11339 | +** local change may be rebased for REPLACE while others are rebased for |
| 11340 | +** OMIT. |
| 11341 | +** |
| 11342 | +** In order to rebase a local changeset, the remote changeset must first |
| 11343 | +** be applied to the local database using sqlite3changeset_apply_v2() and |
| 11344 | +** the buffer of rebase information captured. Then: |
| 11345 | +** |
| 11346 | +** <ol> |
| 11347 | +** <li> An sqlite3_rebaser object is created by calling |
| 11348 | +** sqlite3rebaser_create(). |
| 11349 | +** <li> The new object is configured with the rebase buffer obtained from |
| 11350 | +** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). |
| 11351 | +** If the local changeset is to be rebased against multiple remote |
| 11352 | +** changesets, then sqlite3rebaser_configure() should be called |
| 11353 | +** multiple times, in the same order that the multiple |
| 11354 | +** sqlite3changeset_apply_v2() calls were made. |
| 11355 | +** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase(). |
| 11356 | +** <li> The sqlite3_rebaser object is deleted by calling |
| 11357 | +** sqlite3rebaser_delete(). |
| 11358 | +** </ol> |
| 11359 | +*/ |
| 11360 | +typedef struct sqlite3_rebaser sqlite3_rebaser; |
| 11361 | + |
| 11362 | +/* |
| 11363 | +** CAPI3REF: Create a changeset rebaser object. |
| 11364 | +** EXPERIMENTAL |
| 11365 | +** |
| 11366 | +** Allocate a new changeset rebaser object. If successful, set (*ppNew) to |
| 11367 | +** point to the new object and return SQLITE_OK. Otherwise, if an error |
| 11368 | +** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) |
| 11369 | +** to NULL. |
| 11370 | +*/ |
| 11371 | +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); |
| 11372 | + |
| 11373 | +/* |
| 11374 | +** CAPI3REF: Configure a changeset rebaser object. |
| 11375 | +** EXPERIMENTAL |
| 11376 | +** |
| 11377 | +** Configure the changeset rebaser object to rebase changesets according |
| 11378 | +** to the conflict resolutions described by buffer pRebase (size nRebase |
| 11379 | +** bytes), which must have been obtained from a previous call to |
| 11380 | +** sqlite3changeset_apply_v2(). |
| 11381 | +*/ |
| 11382 | +SQLITE_API int sqlite3rebaser_configure( |
| 11383 | + sqlite3_rebaser*, |
| 11384 | + int nRebase, const void *pRebase |
| 11385 | +); |
| 11386 | + |
| 11387 | +/* |
| 11388 | +** CAPI3REF: Rebase a changeset |
| 11389 | +** EXPERIMENTAL |
| 11390 | +** |
| 11391 | +** Argument pIn must point to a buffer containing a changeset nIn bytes |
| 11392 | +** in size. This function allocates and populates a buffer with a copy |
| 11393 | +** of the changeset rebased rebased according to the configuration of the |
| 11394 | +** rebaser object passed as the first argument. If successful, (*ppOut) |
| 11395 | +** is set to point to the new buffer containing the rebased changset and |
| 11396 | +** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the |
| 11397 | +** responsibility of the caller to eventually free the new buffer using |
| 11398 | +** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) |
| 11399 | +** are set to zero and an SQLite error code returned. |
| 11400 | +*/ |
| 11401 | +SQLITE_API int sqlite3rebaser_rebase( |
| 11402 | + sqlite3_rebaser*, |
| 11403 | + int nIn, const void *pIn, |
| 11404 | + int *pnOut, void **ppOut |
| 11405 | +); |
| 11406 | + |
| 11407 | +/* |
| 11408 | +** CAPI3REF: Delete a changeset rebaser object. |
| 11409 | +** EXPERIMENTAL |
| 11410 | +** |
| 11411 | +** Delete the changeset rebaser object and all associated resources. There |
| 11412 | +** should be one call to this function for each successful invocation |
| 11413 | +** of sqlite3rebaser_create(). |
| 11414 | +*/ |
| 11415 | +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); |
| 11416 | + |
| 11230 | 11417 | /* |
| 11231 | 11418 | ** CAPI3REF: Streaming Versions of API functions. |
| 11232 | 11419 | ** |
| 11233 | 11420 | ** The six streaming API xxx_strm() functions serve similar purposes to the |
| 11234 | 11421 | ** corresponding non-streaming API functions: |
| | @@ -11328,10 +11515,26 @@ |
| 11328 | 11515 | void *pCtx, /* Copy of sixth arg to _apply() */ |
| 11329 | 11516 | int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 11330 | 11517 | sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 11331 | 11518 | ), |
| 11332 | 11519 | void *pCtx /* First argument passed to xConflict */ |
| 11520 | +); |
| 11521 | +SQLITE_API int sqlite3changeset_apply_v2_strm( |
| 11522 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 11523 | + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ |
| 11524 | + void *pIn, /* First arg for xInput */ |
| 11525 | + int(*xFilter)( |
| 11526 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 11527 | + const char *zTab /* Table name */ |
| 11528 | + ), |
| 11529 | + int(*xConflict)( |
| 11530 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 11531 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 11532 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 11533 | + ), |
| 11534 | + void *pCtx, /* First argument passed to xConflict */ |
| 11535 | + void **ppRebase, int *pnRebase |
| 11333 | 11536 | ); |
| 11334 | 11537 | SQLITE_API int sqlite3changeset_concat_strm( |
| 11335 | 11538 | int (*xInputA)(void *pIn, void *pData, int *pnData), |
| 11336 | 11539 | void *pInA, |
| 11337 | 11540 | int (*xInputB)(void *pIn, void *pData, int *pnData), |
| | @@ -11365,10 +11568,17 @@ |
| 11365 | 11568 | void *pIn |
| 11366 | 11569 | ); |
| 11367 | 11570 | SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, |
| 11368 | 11571 | int (*xOutput)(void *pOut, const void *pData, int nData), |
| 11369 | 11572 | void *pOut |
| 11573 | +); |
| 11574 | +SQLITE_API int sqlite3rebaser_rebase_strm( |
| 11575 | + sqlite3_rebaser *pRebaser, |
| 11576 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 11577 | + void *pIn, |
| 11578 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 11579 | + void *pOut |
| 11370 | 11580 | ); |
| 11371 | 11581 | |
| 11372 | 11582 | |
| 11373 | 11583 | /* |
| 11374 | 11584 | ** Make sure we can call this stuff from C++. |
| | @@ -13245,13 +13455,14 @@ |
| 13245 | 13455 | ** handle is passed a pointer to sqlite.busyHandler. The busy-handler |
| 13246 | 13456 | ** callback is currently invoked only from within pager.c. |
| 13247 | 13457 | */ |
| 13248 | 13458 | typedef struct BusyHandler BusyHandler; |
| 13249 | 13459 | struct BusyHandler { |
| 13250 | | - int (*xFunc)(void *,int); /* The busy callback */ |
| 13251 | | - void *pArg; /* First arg to busy callback */ |
| 13252 | | - int nBusy; /* Incremented with each busy call */ |
| 13460 | + int (*xBusyHandler)(void *,int); /* The busy callback */ |
| 13461 | + void *pBusyArg; /* First arg to busy callback */ |
| 13462 | + int nBusy; /* Incremented with each busy call */ |
| 13463 | + u8 bExtraFileArg; /* Include sqlite3_file as callback arg */ |
| 13253 | 13464 | }; |
| 13254 | 13465 | |
| 13255 | 13466 | /* |
| 13256 | 13467 | ** Name of the master database table. The master database table |
| 13257 | 13468 | ** is a special table that holds the names and attributes of all |
| | @@ -14456,11 +14667,11 @@ |
| 14456 | 14667 | ); |
| 14457 | 14668 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); |
| 14458 | 14669 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 14459 | 14670 | |
| 14460 | 14671 | /* Functions used to configure a Pager object. */ |
| 14461 | | -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 14672 | +SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); |
| 14462 | 14673 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| 14463 | 14674 | #ifdef SQLITE_HAS_CODEC |
| 14464 | 14675 | SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); |
| 14465 | 14676 | #endif |
| 14466 | 14677 | SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); |
| | @@ -14542,10 +14753,15 @@ |
| 14542 | 14753 | SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); |
| 14543 | 14754 | SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); |
| 14544 | 14755 | SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); |
| 14545 | 14756 | SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); |
| 14546 | 14757 | SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); |
| 14758 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 14759 | +SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager); |
| 14760 | +#else |
| 14761 | +# define sqlite3PagerResetLockTimeout(X) |
| 14762 | +#endif |
| 14547 | 14763 | |
| 14548 | 14764 | /* Functions used to truncate the database file. */ |
| 14549 | 14765 | SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); |
| 14550 | 14766 | |
| 14551 | 14767 | SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16); |
| | @@ -18099,11 +18315,11 @@ |
| 18099 | 18315 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| 18100 | 18316 | SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); |
| 18101 | 18317 | SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); |
| 18102 | 18318 | SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); |
| 18103 | 18319 | SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); |
| 18104 | | -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); |
| 18320 | +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); |
| 18105 | 18321 | SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); |
| 18106 | 18322 | SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); |
| 18107 | 18323 | SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); |
| 18108 | 18324 | SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*); |
| 18109 | 18325 | SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*); |
| | @@ -21070,11 +21286,13 @@ |
| 21070 | 21286 | ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() |
| 21071 | 21287 | ** routine has no return value since the return value would be meaningless. |
| 21072 | 21288 | */ |
| 21073 | 21289 | SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ |
| 21074 | 21290 | #ifdef SQLITE_TEST |
| 21075 | | - if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ |
| 21291 | + if( op!=SQLITE_FCNTL_COMMIT_PHASETWO |
| 21292 | + && op!=SQLITE_FCNTL_LOCK_TIMEOUT |
| 21293 | + ){ |
| 21076 | 21294 | /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite |
| 21077 | 21295 | ** is using a regular VFS, it is called after the corresponding |
| 21078 | 21296 | ** transaction has been committed. Injecting a fault at this point |
| 21079 | 21297 | ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM |
| 21080 | 21298 | ** but the transaction is committed anyway. |
| | @@ -31026,10 +31244,13 @@ |
| 31026 | 31244 | int openFlags; /* The flags specified at open() */ |
| 31027 | 31245 | #endif |
| 31028 | 31246 | #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) |
| 31029 | 31247 | unsigned fsFlags; /* cached details from statfs() */ |
| 31030 | 31248 | #endif |
| 31249 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 31250 | + unsigned iBusyTimeout; /* Wait this many millisec on locks */ |
| 31251 | +#endif |
| 31031 | 31252 | #if OS_VXWORKS |
| 31032 | 31253 | struct vxworksFileId *pId; /* Unique file ID */ |
| 31033 | 31254 | #endif |
| 31034 | 31255 | #ifdef SQLITE_DEBUG |
| 31035 | 31256 | /* The next group of variables are used to track whether or not the |
| | @@ -32459,10 +32680,47 @@ |
| 32459 | 32680 | OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); |
| 32460 | 32681 | |
| 32461 | 32682 | *pResOut = reserved; |
| 32462 | 32683 | return rc; |
| 32463 | 32684 | } |
| 32685 | + |
| 32686 | +/* |
| 32687 | +** Set a posix-advisory-lock. |
| 32688 | +** |
| 32689 | +** There are two versions of this routine. If compiled with |
| 32690 | +** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter |
| 32691 | +** which is a pointer to a unixFile. If the unixFile->iBusyTimeout |
| 32692 | +** value is set, then it is the number of milliseconds to wait before |
| 32693 | +** failing the lock. The iBusyTimeout value is always reset back to |
| 32694 | +** zero on each call. |
| 32695 | +** |
| 32696 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking |
| 32697 | +** attempt to set the lock. |
| 32698 | +*/ |
| 32699 | +#ifndef SQLITE_ENABLE_SETLK_TIMEOUT |
| 32700 | +# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x) |
| 32701 | +#else |
| 32702 | +static int osSetPosixAdvisoryLock( |
| 32703 | + int h, /* The file descriptor on which to take the lock */ |
| 32704 | + struct flock *pLock, /* The description of the lock */ |
| 32705 | + unixFile *pFile /* Structure holding timeout value */ |
| 32706 | +){ |
| 32707 | + int rc = osFcntl(h,F_SETLK,pLock); |
| 32708 | + while( rc<0 && pFile->iBusyTimeout>0 ){ |
| 32709 | + /* On systems that support some kind of blocking file lock with a timeout, |
| 32710 | + ** make appropriate changes here to invoke that blocking file lock. On |
| 32711 | + ** generic posix, however, there is no such API. So we simply try the |
| 32712 | + ** lock once every millisecond until either the timeout expires, or until |
| 32713 | + ** the lock is obtained. */ |
| 32714 | + usleep(1000); |
| 32715 | + rc = osFcntl(h,F_SETLK,pLock); |
| 32716 | + pFile->iBusyTimeout--; |
| 32717 | + } |
| 32718 | + return rc; |
| 32719 | +} |
| 32720 | +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 32721 | + |
| 32464 | 32722 | |
| 32465 | 32723 | /* |
| 32466 | 32724 | ** Attempt to set a system-lock on the file pFile. The lock is |
| 32467 | 32725 | ** described by pLock. |
| 32468 | 32726 | ** |
| | @@ -32492,19 +32750,19 @@ |
| 32492 | 32750 | assert( pInode->nLock==0 ); |
| 32493 | 32751 | lock.l_whence = SEEK_SET; |
| 32494 | 32752 | lock.l_start = SHARED_FIRST; |
| 32495 | 32753 | lock.l_len = SHARED_SIZE; |
| 32496 | 32754 | lock.l_type = F_WRLCK; |
| 32497 | | - rc = osFcntl(pFile->h, F_SETLK, &lock); |
| 32755 | + rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); |
| 32498 | 32756 | if( rc<0 ) return rc; |
| 32499 | 32757 | pInode->bProcessLock = 1; |
| 32500 | 32758 | pInode->nLock++; |
| 32501 | 32759 | }else{ |
| 32502 | 32760 | rc = 0; |
| 32503 | 32761 | } |
| 32504 | 32762 | }else{ |
| 32505 | | - rc = osFcntl(pFile->h, F_SETLK, pLock); |
| 32763 | + rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); |
| 32506 | 32764 | } |
| 32507 | 32765 | return rc; |
| 32508 | 32766 | } |
| 32509 | 32767 | |
| 32510 | 32768 | /* |
| | @@ -34860,10 +35118,16 @@ |
| 34860 | 35118 | } |
| 34861 | 35119 | case SQLITE_FCNTL_HAS_MOVED: { |
| 34862 | 35120 | *(int*)pArg = fileHasMoved(pFile); |
| 34863 | 35121 | return SQLITE_OK; |
| 34864 | 35122 | } |
| 35123 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 35124 | + case SQLITE_FCNTL_LOCK_TIMEOUT: { |
| 35125 | + pFile->iBusyTimeout = *(int*)pArg; |
| 35126 | + return SQLITE_OK; |
| 35127 | + } |
| 35128 | +#endif |
| 34865 | 35129 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 34866 | 35130 | case SQLITE_FCNTL_MMAP_SIZE: { |
| 34867 | 35131 | i64 newLimit = *(i64*)pArg; |
| 34868 | 35132 | int rc = SQLITE_OK; |
| 34869 | 35133 | if( newLimit>sqlite3GlobalConfig.mxMmap ){ |
| | @@ -35179,11 +35443,11 @@ |
| 35179 | 35443 | /* Initialize the locking parameters */ |
| 35180 | 35444 | f.l_type = lockType; |
| 35181 | 35445 | f.l_whence = SEEK_SET; |
| 35182 | 35446 | f.l_start = ofst; |
| 35183 | 35447 | f.l_len = n; |
| 35184 | | - rc = osFcntl(pShmNode->h, F_SETLK, &f); |
| 35448 | + rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile); |
| 35185 | 35449 | rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; |
| 35186 | 35450 | } |
| 35187 | 35451 | |
| 35188 | 35452 | /* Update the global lock state and do debug tracing */ |
| 35189 | 35453 | #ifdef SQLITE_DEBUG |
| | @@ -45039,11 +45303,11 @@ |
| 45039 | 45303 | ** May you find forgiveness for yourself and forgive others. |
| 45040 | 45304 | ** May you share freely, never taking more than you give. |
| 45041 | 45305 | ** |
| 45042 | 45306 | ****************************************************************************** |
| 45043 | 45307 | ** |
| 45044 | | -** This file implements in-memory VFS. A database is held as a contiguous |
| 45308 | +** This file implements an in-memory VFS. A database is held as a contiguous |
| 45045 | 45309 | ** block of memory. |
| 45046 | 45310 | ** |
| 45047 | 45311 | ** This file also implements interface sqlite3_serialize() and |
| 45048 | 45312 | ** sqlite3_deserialize(). |
| 45049 | 45313 | */ |
| | @@ -52527,11 +52791,11 @@ |
| 52527 | 52791 | ** |
| 52528 | 52792 | ** If the busy-handler callback returns non-zero, the lock is |
| 52529 | 52793 | ** retried. If it returns zero, then the SQLITE_BUSY error is |
| 52530 | 52794 | ** returned to the caller of the pager API function. |
| 52531 | 52795 | */ |
| 52532 | | -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( |
| 52796 | +SQLITE_PRIVATE void sqlite3PagerSetBusyHandler( |
| 52533 | 52797 | Pager *pPager, /* Pager object */ |
| 52534 | 52798 | int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ |
| 52535 | 52799 | void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ |
| 52536 | 52800 | ){ |
| 52537 | 52801 | pPager->xBusyHandler = xBusyHandler; |
| | @@ -54516,10 +54780,11 @@ |
| 54516 | 54780 | Pager *pPager; |
| 54517 | 54781 | assert( pPg!=0 ); |
| 54518 | 54782 | assert( pPg->pgno==1 ); |
| 54519 | 54783 | assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ |
| 54520 | 54784 | pPager = pPg->pPager; |
| 54785 | + sqlite3PagerResetLockTimeout(pPager); |
| 54521 | 54786 | sqlite3PcacheRelease(pPg); |
| 54522 | 54787 | pagerUnlockIfUnused(pPager); |
| 54523 | 54788 | } |
| 54524 | 54789 | |
| 54525 | 54790 | /* |
| | @@ -55793,10 +56058,22 @@ |
| 55793 | 56058 | */ |
| 55794 | 56059 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ |
| 55795 | 56060 | return pPager->fd; |
| 55796 | 56061 | } |
| 55797 | 56062 | |
| 56063 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 56064 | +/* |
| 56065 | +** Reset the lock timeout for pager. |
| 56066 | +*/ |
| 56067 | +SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){ |
| 56068 | + if( isOpen(pPager->fd) ){ |
| 56069 | + int x = 0; |
| 56070 | + sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x); |
| 56071 | + } |
| 56072 | +} |
| 56073 | +#endif |
| 56074 | + |
| 55798 | 56075 | /* |
| 55799 | 56076 | ** Return the file handle for the journal file (if it exists). |
| 55800 | 56077 | ** This will be either the rollback journal or the WAL file. |
| 55801 | 56078 | */ |
| 55802 | 56079 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ |
| | @@ -56253,10 +56530,11 @@ |
| 56253 | 56530 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 56254 | 56531 | pPager->pBusyHandlerArg, |
| 56255 | 56532 | pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 56256 | 56533 | pnLog, pnCkpt |
| 56257 | 56534 | ); |
| 56535 | + sqlite3PagerResetLockTimeout(pPager); |
| 56258 | 56536 | } |
| 56259 | 56537 | return rc; |
| 56260 | 56538 | } |
| 56261 | 56539 | |
| 56262 | 56540 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ |
| | @@ -63529,11 +63807,12 @@ |
| 63529 | 63807 | */ |
| 63530 | 63808 | static int btreeInvokeBusyHandler(void *pArg){ |
| 63531 | 63809 | BtShared *pBt = (BtShared*)pArg; |
| 63532 | 63810 | assert( pBt->db ); |
| 63533 | 63811 | assert( sqlite3_mutex_held(pBt->db->mutex) ); |
| 63534 | | - return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); |
| 63812 | + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler, |
| 63813 | + sqlite3PagerFile(pBt->pPager)); |
| 63535 | 63814 | } |
| 63536 | 63815 | |
| 63537 | 63816 | /* |
| 63538 | 63817 | ** Open a database file. |
| 63539 | 63818 | ** |
| | @@ -63707,11 +63986,11 @@ |
| 63707 | 63986 | if( rc!=SQLITE_OK ){ |
| 63708 | 63987 | goto btree_open_out; |
| 63709 | 63988 | } |
| 63710 | 63989 | pBt->openFlags = (u8)flags; |
| 63711 | 63990 | pBt->db = db; |
| 63712 | | - sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); |
| 63991 | + sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); |
| 63713 | 63992 | p->pBt = pBt; |
| 63714 | 63993 | |
| 63715 | 63994 | pBt->pCursor = 0; |
| 63716 | 63995 | pBt->pPage1 = 0; |
| 63717 | 63996 | if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; |
| | @@ -64670,10 +64949,11 @@ |
| 64670 | 64949 | if( rc!=SQLITE_OK ){ |
| 64671 | 64950 | unlockBtreeIfUnused(pBt); |
| 64672 | 64951 | } |
| 64673 | 64952 | }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && |
| 64674 | 64953 | btreeInvokeBusyHandler(pBt) ); |
| 64954 | + sqlite3PagerResetLockTimeout(pBt->pPager); |
| 64675 | 64955 | |
| 64676 | 64956 | if( rc==SQLITE_OK ){ |
| 64677 | 64957 | if( p->inTrans==TRANS_NONE ){ |
| 64678 | 64958 | pBt->nTransaction++; |
| 64679 | 64959 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| | @@ -98715,20 +98995,35 @@ |
| 98715 | 98995 | ** This is the Expr node callback for sqlite3ExprImpliesNotNullRow(). |
| 98716 | 98996 | ** If the expression node requires that the table at pWalker->iCur |
| 98717 | 98997 | ** have a non-NULL column, then set pWalker->eCode to 1 and abort. |
| 98718 | 98998 | */ |
| 98719 | 98999 | static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ |
| 99000 | + /* This routine is only called for WHERE clause expressions and so it |
| 99001 | + ** cannot have any TK_AGG_COLUMN entries because those are only found |
| 99002 | + ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause, |
| 99003 | + ** but that is an illegal construct and the query will be rejected at |
| 99004 | + ** a later stage of processing, so the TK_AGG_FUNCTION case does not |
| 99005 | + ** need to be considered here. */ |
| 99006 | + assert( pExpr->op!=TK_AGG_COLUMN ); |
| 99007 | + testcase( pExpr->op==TK_AGG_FUNCTION ); |
| 99008 | + |
| 98720 | 99009 | if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; |
| 98721 | 99010 | switch( pExpr->op ){ |
| 98722 | 99011 | case TK_ISNULL: |
| 98723 | 99012 | case TK_IS: |
| 98724 | 99013 | case TK_OR: |
| 99014 | + case TK_CASE: |
| 99015 | + case TK_IN: |
| 98725 | 99016 | case TK_FUNCTION: |
| 98726 | | - case TK_AGG_FUNCTION: |
| 99017 | + testcase( pExpr->op==TK_ISNULL ); |
| 99018 | + testcase( pExpr->op==TK_IS ); |
| 99019 | + testcase( pExpr->op==TK_OR ); |
| 99020 | + testcase( pExpr->op==TK_CASE ); |
| 99021 | + testcase( pExpr->op==TK_IN ); |
| 99022 | + testcase( pExpr->op==TK_FUNCTION ); |
| 98727 | 99023 | return WRC_Prune; |
| 98728 | 99024 | case TK_COLUMN: |
| 98729 | | - case TK_AGG_COLUMN: |
| 98730 | 99025 | if( pWalker->u.iCur==pExpr->iTable ){ |
| 98731 | 99026 | pWalker->eCode = 1; |
| 98732 | 99027 | return WRC_Abort; |
| 98733 | 99028 | } |
| 98734 | 99029 | return WRC_Prune; |
| | @@ -98740,10 +99035,17 @@ |
| 98740 | 99035 | /* |
| 98741 | 99036 | ** Return true (non-zero) if expression p can only be true if at least |
| 98742 | 99037 | ** one column of table iTab is non-null. In other words, return true |
| 98743 | 99038 | ** if expression p will always be NULL or false if every column of iTab |
| 98744 | 99039 | ** is NULL. |
| 99040 | +** |
| 99041 | +** False negatives are acceptable. In other words, it is ok to return |
| 99042 | +** zero even if expression p will never be true of every column of iTab |
| 99043 | +** is NULL. A false negative is merely a missed optimization opportunity. |
| 99044 | +** |
| 99045 | +** False positives are not allowed, however. A false positive may result |
| 99046 | +** in an incorrect answer. |
| 98745 | 99047 | ** |
| 98746 | 99048 | ** Terms of p that are marked with EP_FromJoin (and hence that come from |
| 98747 | 99049 | ** the ON or USING clauses of LEFT JOINS) are excluded from the analysis. |
| 98748 | 99050 | ** |
| 98749 | 99051 | ** This routine is used to check if a LEFT JOIN can be converted into |
| | @@ -101005,11 +101307,11 @@ |
| 101005 | 101307 | } |
| 101006 | 101308 | if( pTab->tnum==0 ){ |
| 101007 | 101309 | /* Do not gather statistics on views or virtual tables */ |
| 101008 | 101310 | return; |
| 101009 | 101311 | } |
| 101010 | | - if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){ |
| 101312 | + if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ |
| 101011 | 101313 | /* Do not gather statistics on system tables */ |
| 101012 | 101314 | return; |
| 101013 | 101315 | } |
| 101014 | 101316 | assert( sqlite3BtreeHoldsAllMutexes(db) ); |
| 101015 | 101317 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| | @@ -104066,11 +104368,11 @@ |
| 104066 | 104368 | if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){ |
| 104067 | 104369 | sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", |
| 104068 | 104370 | pCol->zName); |
| 104069 | 104371 | }else{ |
| 104070 | 104372 | /* A copy of pExpr is used instead of the original, as pExpr contains |
| 104071 | | - ** tokens that point to volatile memory. |
| 104373 | + ** tokens that point to volatile memory. |
| 104072 | 104374 | */ |
| 104073 | 104375 | Expr x; |
| 104074 | 104376 | sqlite3ExprDelete(db, pCol->pDflt); |
| 104075 | 104377 | memset(&x, 0, sizeof(x)); |
| 104076 | 104378 | x.op = TK_SPAN; |
| | @@ -104988,11 +105290,11 @@ |
| 104988 | 105290 | Table *pSelTab; /* A fake table from which we get the result set */ |
| 104989 | 105291 | Select *pSel; /* Copy of the SELECT that implements the view */ |
| 104990 | 105292 | int nErr = 0; /* Number of errors encountered */ |
| 104991 | 105293 | int n; /* Temporarily holds the number of cursors assigned */ |
| 104992 | 105294 | sqlite3 *db = pParse->db; /* Database connection for malloc errors */ |
| 104993 | | -#ifndef SQLITE_OMIT_VIRTUALTABLE |
| 105295 | +#ifndef SQLITE_OMIT_VIRTUALTABLE |
| 104994 | 105296 | int rc; |
| 104995 | 105297 | #endif |
| 104996 | 105298 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 104997 | 105299 | sqlite3_xauth xAuth; /* Saved xAuth pointer */ |
| 104998 | 105300 | #endif |
| | @@ -123778,12 +124080,13 @@ |
| 123778 | 124080 | ** (2) The inner query is the recursive part of a common table expression. |
| 123779 | 124081 | ** |
| 123780 | 124082 | ** (3) The inner query has a LIMIT clause (since the changes to the WHERE |
| 123781 | 124083 | ** close would change the meaning of the LIMIT). |
| 123782 | 124084 | ** |
| 123783 | | -** (4) (** This restriction was removed on 2018-03-21. It used to read: |
| 123784 | | -** The inner query is the right operand of a LEFT JOIN. **) |
| 124085 | +** (4) The inner query is the right operand of a LEFT JOIN and the |
| 124086 | +** expression to be pushed down does not come from the ON clause |
| 124087 | +** on that LEFT JOIN. |
| 123785 | 124088 | ** |
| 123786 | 124089 | ** (5) The WHERE clause expression originates in the ON or USING clause |
| 123787 | 124090 | ** of a LEFT JOIN where iCursor is not the right-hand table of that |
| 123788 | 124091 | ** left join. An example: |
| 123789 | 124092 | ** |
| | @@ -123801,11 +124104,12 @@ |
| 123801 | 124104 | */ |
| 123802 | 124105 | static int pushDownWhereTerms( |
| 123803 | 124106 | Parse *pParse, /* Parse context (for malloc() and error reporting) */ |
| 123804 | 124107 | Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ |
| 123805 | 124108 | Expr *pWhere, /* The WHERE clause of the outer query */ |
| 123806 | | - int iCursor /* Cursor number of the subquery */ |
| 124109 | + int iCursor, /* Cursor number of the subquery */ |
| 124110 | + int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ |
| 123807 | 124111 | ){ |
| 123808 | 124112 | Expr *pNew; |
| 123809 | 124113 | int nChng = 0; |
| 123810 | 124114 | if( pWhere==0 ) return 0; |
| 123811 | 124115 | if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */ |
| | @@ -123825,13 +124129,20 @@ |
| 123825 | 124129 | |
| 123826 | 124130 | if( pSubq->pLimit!=0 ){ |
| 123827 | 124131 | return 0; /* restriction (3) */ |
| 123828 | 124132 | } |
| 123829 | 124133 | while( pWhere->op==TK_AND ){ |
| 123830 | | - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); |
| 124134 | + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, |
| 124135 | + iCursor, isLeftJoin); |
| 123831 | 124136 | pWhere = pWhere->pLeft; |
| 123832 | 124137 | } |
| 124138 | + if( isLeftJoin |
| 124139 | + && (ExprHasProperty(pWhere,EP_FromJoin)==0 |
| 124140 | + || pWhere->iRightJoinTable!=iCursor) |
| 124141 | + ){ |
| 124142 | + return 0; /* restriction (4) */ |
| 124143 | + } |
| 123833 | 124144 | if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){ |
| 123834 | 124145 | return 0; /* restriction (5) */ |
| 123835 | 124146 | } |
| 123836 | 124147 | if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ |
| 123837 | 124148 | nChng++; |
| | @@ -125295,11 +125606,12 @@ |
| 125295 | 125606 | |
| 125296 | 125607 | /* Make copies of constant WHERE-clause terms in the outer query down |
| 125297 | 125608 | ** inside the subquery. This can help the subquery to run more efficiently. |
| 125298 | 125609 | */ |
| 125299 | 125610 | if( OptimizationEnabled(db, SQLITE_PushDown) |
| 125300 | | - && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) |
| 125611 | + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor, |
| 125612 | + (pItem->fg.jointype & JT_OUTER)!=0) |
| 125301 | 125613 | ){ |
| 125302 | 125614 | #if SELECTTRACE_ENABLED |
| 125303 | 125615 | if( sqlite3SelectTrace & 0x100 ){ |
| 125304 | 125616 | SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); |
| 125305 | 125617 | sqlite3TreeViewSelect(0, p, 0); |
| | @@ -146146,43 +146458,62 @@ |
| 146146 | 146458 | /* |
| 146147 | 146459 | ** This routine implements a busy callback that sleeps and tries |
| 146148 | 146460 | ** again until a timeout value is reached. The timeout value is |
| 146149 | 146461 | ** an integer number of milliseconds passed in as the first |
| 146150 | 146462 | ** argument. |
| 146463 | +** |
| 146464 | +** Return non-zero to retry the lock. Return zero to stop trying |
| 146465 | +** and cause SQLite to return SQLITE_BUSY. |
| 146151 | 146466 | */ |
| 146152 | 146467 | static int sqliteDefaultBusyCallback( |
| 146153 | | - void *ptr, /* Database connection */ |
| 146154 | | - int count /* Number of times table has been busy */ |
| 146468 | + void *ptr, /* Database connection */ |
| 146469 | + int count, /* Number of times table has been busy */ |
| 146470 | + sqlite3_file *pFile /* The file on which the lock occurred */ |
| 146155 | 146471 | ){ |
| 146156 | 146472 | #if SQLITE_OS_WIN || HAVE_USLEEP |
| 146473 | + /* This case is for systems that have support for sleeping for fractions of |
| 146474 | + ** a second. Examples: All windows systems, unix systems with usleep() */ |
| 146157 | 146475 | static const u8 delays[] = |
| 146158 | 146476 | { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; |
| 146159 | 146477 | static const u8 totals[] = |
| 146160 | 146478 | { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; |
| 146161 | 146479 | # define NDELAY ArraySize(delays) |
| 146162 | 146480 | sqlite3 *db = (sqlite3 *)ptr; |
| 146163 | | - int timeout = db->busyTimeout; |
| 146481 | + int tmout = db->busyTimeout; |
| 146164 | 146482 | int delay, prior; |
| 146165 | 146483 | |
| 146484 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 146485 | + if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){ |
| 146486 | + if( count ){ |
| 146487 | + tmout = 0; |
| 146488 | + sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout); |
| 146489 | + return 0; |
| 146490 | + }else{ |
| 146491 | + return 1; |
| 146492 | + } |
| 146493 | + } |
| 146494 | +#endif |
| 146166 | 146495 | assert( count>=0 ); |
| 146167 | 146496 | if( count < NDELAY ){ |
| 146168 | 146497 | delay = delays[count]; |
| 146169 | 146498 | prior = totals[count]; |
| 146170 | 146499 | }else{ |
| 146171 | 146500 | delay = delays[NDELAY-1]; |
| 146172 | 146501 | prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); |
| 146173 | 146502 | } |
| 146174 | | - if( prior + delay > timeout ){ |
| 146175 | | - delay = timeout - prior; |
| 146503 | + if( prior + delay > tmout ){ |
| 146504 | + delay = tmout - prior; |
| 146176 | 146505 | if( delay<=0 ) return 0; |
| 146177 | 146506 | } |
| 146178 | 146507 | sqlite3OsSleep(db->pVfs, delay*1000); |
| 146179 | 146508 | return 1; |
| 146180 | 146509 | #else |
| 146510 | + /* This case for unix systems that lack usleep() support. Sleeping |
| 146511 | + ** must be done in increments of whole seconds */ |
| 146181 | 146512 | sqlite3 *db = (sqlite3 *)ptr; |
| 146182 | | - int timeout = ((sqlite3 *)ptr)->busyTimeout; |
| 146183 | | - if( (count+1)*1000 > timeout ){ |
| 146513 | + int tmout = ((sqlite3 *)ptr)->busyTimeout; |
| 146514 | + if( (count+1)*1000 > tmout ){ |
| 146184 | 146515 | return 0; |
| 146185 | 146516 | } |
| 146186 | 146517 | sqlite3OsSleep(db->pVfs, 1000000); |
| 146187 | 146518 | return 1; |
| 146188 | 146519 | #endif |
| | @@ -146189,18 +146520,29 @@ |
| 146189 | 146520 | } |
| 146190 | 146521 | |
| 146191 | 146522 | /* |
| 146192 | 146523 | ** Invoke the given busy handler. |
| 146193 | 146524 | ** |
| 146194 | | -** This routine is called when an operation failed with a lock. |
| 146525 | +** This routine is called when an operation failed to acquire a |
| 146526 | +** lock on VFS file pFile. |
| 146527 | +** |
| 146195 | 146528 | ** If this routine returns non-zero, the lock is retried. If it |
| 146196 | 146529 | ** returns 0, the operation aborts with an SQLITE_BUSY error. |
| 146197 | 146530 | */ |
| 146198 | | -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ |
| 146531 | +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ |
| 146199 | 146532 | int rc; |
| 146200 | | - if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; |
| 146201 | | - rc = p->xFunc(p->pArg, p->nBusy); |
| 146533 | + if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; |
| 146534 | + if( p->bExtraFileArg ){ |
| 146535 | + /* Add an extra parameter with the pFile pointer to the end of the |
| 146536 | + ** callback argument list */ |
| 146537 | + int (*xTra)(void*,int,sqlite3_file*); |
| 146538 | + xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler; |
| 146539 | + rc = xTra(p->pBusyArg, p->nBusy, pFile); |
| 146540 | + }else{ |
| 146541 | + /* Legacy style busy handler callback */ |
| 146542 | + rc = p->xBusyHandler(p->pBusyArg, p->nBusy); |
| 146543 | + } |
| 146202 | 146544 | if( rc==0 ){ |
| 146203 | 146545 | p->nBusy = -1; |
| 146204 | 146546 | }else{ |
| 146205 | 146547 | p->nBusy++; |
| 146206 | 146548 | } |
| | @@ -146218,13 +146560,14 @@ |
| 146218 | 146560 | ){ |
| 146219 | 146561 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 146220 | 146562 | if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 146221 | 146563 | #endif |
| 146222 | 146564 | sqlite3_mutex_enter(db->mutex); |
| 146223 | | - db->busyHandler.xFunc = xBusy; |
| 146224 | | - db->busyHandler.pArg = pArg; |
| 146565 | + db->busyHandler.xBusyHandler = xBusy; |
| 146566 | + db->busyHandler.pBusyArg = pArg; |
| 146225 | 146567 | db->busyHandler.nBusy = 0; |
| 146568 | + db->busyHandler.bExtraFileArg = 0; |
| 146226 | 146569 | db->busyTimeout = 0; |
| 146227 | 146570 | sqlite3_mutex_leave(db->mutex); |
| 146228 | 146571 | return SQLITE_OK; |
| 146229 | 146572 | } |
| 146230 | 146573 | |
| | @@ -146268,12 +146611,14 @@ |
| 146268 | 146611 | SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ |
| 146269 | 146612 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 146270 | 146613 | if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 146271 | 146614 | #endif |
| 146272 | 146615 | if( ms>0 ){ |
| 146273 | | - sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); |
| 146616 | + sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, |
| 146617 | + (void*)db); |
| 146274 | 146618 | db->busyTimeout = ms; |
| 146619 | + db->busyHandler.bExtraFileArg = 1; |
| 146275 | 146620 | }else{ |
| 146276 | 146621 | sqlite3_busy_handler(db, 0, 0); |
| 146277 | 146622 | } |
| 146278 | 146623 | return SQLITE_OK; |
| 146279 | 146624 | } |
| | @@ -180266,12 +180611,12 @@ |
| 180266 | 180611 | ** of a patchset change is associated with the correspondingly positioned |
| 180267 | 180612 | ** table column, counting from left to right within the CREATE TABLE |
| 180268 | 180613 | ** statement. |
| 180269 | 180614 | ** |
| 180270 | 180615 | ** For a DELETE change, all fields within the record except those associated |
| 180271 | | -** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields |
| 180272 | | -** contain the values identifying the row to delete. |
| 180616 | +** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the |
| 180617 | +** values identifying the row to delete. |
| 180273 | 180618 | ** |
| 180274 | 180619 | ** For an UPDATE change, all fields except those associated with PRIMARY KEY |
| 180275 | 180620 | ** columns and columns that are modified by the UPDATE are set to "undefined". |
| 180276 | 180621 | ** PRIMARY KEY fields contain the values identifying the table row to update, |
| 180277 | 180622 | ** and fields associated with modified columns contain the new column values. |
| | @@ -180550,11 +180895,11 @@ |
| 180550 | 180895 | ** the type byte). |
| 180551 | 180896 | */ |
| 180552 | 180897 | static int sessionSerialLen(u8 *a){ |
| 180553 | 180898 | int e = *a; |
| 180554 | 180899 | int n; |
| 180555 | | - if( e==0 ) return 1; |
| 180900 | + if( e==0 || e==0xFF ) return 1; |
| 180556 | 180901 | if( e==SQLITE_NULL ) return 1; |
| 180557 | 180902 | if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; |
| 180558 | 180903 | return sessionVarintGet(&a[1], &n) + 1 + n; |
| 180559 | 180904 | } |
| 180560 | 180905 | |
| | @@ -180630,11 +180975,11 @@ |
| 180630 | 180975 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 180631 | 180976 | if( pTab->abPK[iCol] ){ |
| 180632 | 180977 | int n1 = sessionSerialLen(a1); |
| 180633 | 180978 | int n2 = sessionSerialLen(a2); |
| 180634 | 180979 | |
| 180635 | | - if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ |
| 180980 | + if( n1!=n2 || memcmp(a1, a2, n1) ){ |
| 180636 | 180981 | return 0; |
| 180637 | 180982 | } |
| 180638 | 180983 | a1 += n1; |
| 180639 | 180984 | a2 += n2; |
| 180640 | 180985 | }else{ |
| | @@ -180873,11 +181218,11 @@ |
| 180873 | 181218 | if( eType==SQLITE_TEXT ){ |
| 180874 | 181219 | z = sqlite3_value_text(pVal); |
| 180875 | 181220 | }else{ |
| 180876 | 181221 | z = sqlite3_value_blob(pVal); |
| 180877 | 181222 | } |
| 180878 | | - if( memcmp(a, z, n) ) return 0; |
| 181223 | + if( n>0 && memcmp(a, z, n) ) return 0; |
| 180879 | 181224 | a += n; |
| 180880 | 181225 | } |
| 180881 | 181226 | } |
| 180882 | 181227 | } |
| 180883 | 181228 | |
| | @@ -182217,10 +182562,11 @@ |
| 182217 | 182562 | if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){ |
| 182218 | 182563 | zSql = sqlite3_mprintf( |
| 182219 | 182564 | "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND " |
| 182220 | 182565 | "idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb |
| 182221 | 182566 | ); |
| 182567 | + if( zSql==0 ) rc = SQLITE_NOMEM; |
| 182222 | 182568 | }else{ |
| 182223 | 182569 | int i; |
| 182224 | 182570 | const char *zSep = ""; |
| 182225 | 182571 | SessionBuffer buf = {0, 0, 0}; |
| 182226 | 182572 | |
| | @@ -182952,11 +183298,12 @@ |
| 182952 | 183298 | ** changes in the changeset. |
| 182953 | 183299 | */ |
| 182954 | 183300 | static int sessionChangesetNext( |
| 182955 | 183301 | sqlite3_changeset_iter *p, /* Changeset iterator */ |
| 182956 | 183302 | u8 **paRec, /* If non-NULL, store record pointer here */ |
| 182957 | | - int *pnRec /* If non-NULL, store size of record here */ |
| 183303 | + int *pnRec, /* If non-NULL, store size of record here */ |
| 183304 | + int *pbNew /* If non-NULL, true if new table */ |
| 182958 | 183305 | ){ |
| 182959 | 183306 | int i; |
| 182960 | 183307 | u8 op; |
| 182961 | 183308 | |
| 182962 | 183309 | assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); |
| | @@ -182987,10 +183334,11 @@ |
| 182987 | 183334 | sessionDiscardData(&p->in); |
| 182988 | 183335 | p->in.iCurrent = p->in.iNext; |
| 182989 | 183336 | |
| 182990 | 183337 | op = p->in.aData[p->in.iNext++]; |
| 182991 | 183338 | while( op=='T' || op=='P' ){ |
| 183339 | + if( pbNew ) *pbNew = 1; |
| 182992 | 183340 | p->bPatchset = (op=='P'); |
| 182993 | 183341 | if( sessionChangesetReadTblhdr(p) ) return p->rc; |
| 182994 | 183342 | if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; |
| 182995 | 183343 | p->in.iCurrent = p->in.iNext; |
| 182996 | 183344 | if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; |
| | @@ -183065,11 +183413,11 @@ |
| 183065 | 183413 | ** |
| 183066 | 183414 | ** This function may not be called on iterators passed to a conflict handler |
| 183067 | 183415 | ** callback by changeset_apply(). |
| 183068 | 183416 | */ |
| 183069 | 183417 | SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ |
| 183070 | | - return sessionChangesetNext(p, 0, 0); |
| 183418 | + return sessionChangesetNext(p, 0, 0, 0); |
| 183071 | 183419 | } |
| 183072 | 183420 | |
| 183073 | 183421 | /* |
| 183074 | 183422 | ** The following function extracts information on the current change |
| 183075 | 183423 | ** from a changeset iterator. It may only be called after changeset_next() |
| | @@ -183444,10 +183792,12 @@ |
| 183444 | 183792 | const char **azCol; /* Array of column names */ |
| 183445 | 183793 | u8 *abPK; /* Boolean array - true if column is in PK */ |
| 183446 | 183794 | int bStat1; /* True if table is sqlite_stat1 */ |
| 183447 | 183795 | int bDeferConstraints; /* True to defer constraints */ |
| 183448 | 183796 | SessionBuffer constraints; /* Deferred constraints are stored here */ |
| 183797 | + SessionBuffer rebase; /* Rebase information (if any) here */ |
| 183798 | + int bRebaseStarted; /* If table header is already in rebase */ |
| 183449 | 183799 | }; |
| 183450 | 183800 | |
| 183451 | 183801 | /* |
| 183452 | 183802 | ** Formulate a statement to DELETE a row from database db. Assuming a table |
| 183453 | 183803 | ** structure like this: |
| | @@ -183710,11 +184060,10 @@ |
| 183710 | 184060 | "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " |
| 183711 | 184061 | "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " |
| 183712 | 184062 | "AND (?4 OR stat IS ?3)" |
| 183713 | 184063 | ); |
| 183714 | 184064 | } |
| 183715 | | - assert( rc==SQLITE_OK ); |
| 183716 | 184065 | return rc; |
| 183717 | 184066 | } |
| 183718 | 184067 | |
| 183719 | 184068 | /* |
| 183720 | 184069 | ** A wrapper around sqlite3_bind_value() that detects an extra problem. |
| | @@ -183824,10 +184173,58 @@ |
| 183824 | 184173 | if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect); |
| 183825 | 184174 | } |
| 183826 | 184175 | |
| 183827 | 184176 | return rc; |
| 183828 | 184177 | } |
| 184178 | + |
| 184179 | +/* |
| 184180 | +** This function is called from within sqlite3changset_apply_v2() when |
| 184181 | +** a conflict is encountered and resolved using conflict resolution |
| 184182 | +** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE).. |
| 184183 | +** It adds a conflict resolution record to the buffer in |
| 184184 | +** SessionApplyCtx.rebase, which will eventually be returned to the caller |
| 184185 | +** of apply_v2() as the "rebase" buffer. |
| 184186 | +** |
| 184187 | +** Return SQLITE_OK if successful, or an SQLite error code otherwise. |
| 184188 | +*/ |
| 184189 | +static int sessionRebaseAdd( |
| 184190 | + SessionApplyCtx *p, /* Apply context */ |
| 184191 | + int eType, /* Conflict resolution (OMIT or REPLACE) */ |
| 184192 | + sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ |
| 184193 | +){ |
| 184194 | + int rc = SQLITE_OK; |
| 184195 | + int i; |
| 184196 | + int eOp = pIter->op; |
| 184197 | + if( p->bRebaseStarted==0 ){ |
| 184198 | + /* Append a table-header to the rebase buffer */ |
| 184199 | + const char *zTab = pIter->zTab; |
| 184200 | + sessionAppendByte(&p->rebase, 'T', &rc); |
| 184201 | + sessionAppendVarint(&p->rebase, p->nCol, &rc); |
| 184202 | + sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); |
| 184203 | + sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); |
| 184204 | + p->bRebaseStarted = 1; |
| 184205 | + } |
| 184206 | + |
| 184207 | + assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); |
| 184208 | + assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); |
| 184209 | + |
| 184210 | + sessionAppendByte(&p->rebase, |
| 184211 | + (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc |
| 184212 | + ); |
| 184213 | + sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); |
| 184214 | + for(i=0; i<p->nCol; i++){ |
| 184215 | + sqlite3_value *pVal = 0; |
| 184216 | + if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ |
| 184217 | + sqlite3changeset_old(pIter, i, &pVal); |
| 184218 | + }else{ |
| 184219 | + sqlite3changeset_new(pIter, i, &pVal); |
| 184220 | + } |
| 184221 | + sessionAppendValue(&p->rebase, pVal, &rc); |
| 184222 | + } |
| 184223 | + |
| 184224 | + return rc; |
| 184225 | +} |
| 183829 | 184226 | |
| 183830 | 184227 | /* |
| 183831 | 184228 | ** Invoke the conflict handler for the change that the changeset iterator |
| 183832 | 184229 | ** currently points to. |
| 183833 | 184230 | ** |
| | @@ -183900,11 +184297,11 @@ |
| 183900 | 184297 | /* Instead of invoking the conflict handler, append the change blob |
| 183901 | 184298 | ** to the SessionApplyCtx.constraints buffer. */ |
| 183902 | 184299 | u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; |
| 183903 | 184300 | int nBlob = pIter->in.iNext - pIter->in.iCurrent; |
| 183904 | 184301 | sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); |
| 183905 | | - res = SQLITE_CHANGESET_OMIT; |
| 184302 | + return SQLITE_OK; |
| 183906 | 184303 | }else{ |
| 183907 | 184304 | /* No other row with the new.* primary key. */ |
| 183908 | 184305 | res = xConflict(pCtx, eType+1, pIter); |
| 183909 | 184306 | if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; |
| 183910 | 184307 | } |
| | @@ -183926,10 +184323,13 @@ |
| 183926 | 184323 | |
| 183927 | 184324 | default: |
| 183928 | 184325 | rc = SQLITE_MISUSE; |
| 183929 | 184326 | break; |
| 183930 | 184327 | } |
| 184328 | + if( rc==SQLITE_OK ){ |
| 184329 | + rc = sessionRebaseAdd(p, res, pIter); |
| 184330 | + } |
| 183931 | 184331 | } |
| 183932 | 184332 | |
| 183933 | 184333 | return rc; |
| 183934 | 184334 | } |
| 183935 | 184335 | |
| | @@ -184101,46 +184501,46 @@ |
| 184101 | 184501 | int bReplace = 0; |
| 184102 | 184502 | int bRetry = 0; |
| 184103 | 184503 | int rc; |
| 184104 | 184504 | |
| 184105 | 184505 | rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); |
| 184106 | | - assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); |
| 184107 | | - |
| 184108 | | - /* If the bRetry flag is set, the change has not been applied due to an |
| 184109 | | - ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and |
| 184110 | | - ** a row with the correct PK is present in the db, but one or more other |
| 184111 | | - ** fields do not contain the expected values) and the conflict handler |
| 184112 | | - ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, |
| 184113 | | - ** but pass NULL as the final argument so that sessionApplyOneOp() ignores |
| 184114 | | - ** the SQLITE_CHANGESET_DATA problem. */ |
| 184115 | | - if( bRetry ){ |
| 184116 | | - assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); |
| 184117 | | - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); |
| 184118 | | - } |
| 184119 | | - |
| 184120 | | - /* If the bReplace flag is set, the change is an INSERT that has not |
| 184121 | | - ** been performed because the database already contains a row with the |
| 184122 | | - ** specified primary key and the conflict handler returned |
| 184123 | | - ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row |
| 184124 | | - ** before reattempting the INSERT. */ |
| 184125 | | - else if( bReplace ){ |
| 184126 | | - assert( pIter->op==SQLITE_INSERT ); |
| 184127 | | - rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); |
| 184128 | | - if( rc==SQLITE_OK ){ |
| 184129 | | - rc = sessionBindRow(pIter, |
| 184130 | | - sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); |
| 184131 | | - sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); |
| 184132 | | - } |
| 184133 | | - if( rc==SQLITE_OK ){ |
| 184134 | | - sqlite3_step(pApply->pDelete); |
| 184135 | | - rc = sqlite3_reset(pApply->pDelete); |
| 184136 | | - } |
| 184137 | | - if( rc==SQLITE_OK ){ |
| 184138 | | - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); |
| 184139 | | - } |
| 184140 | | - if( rc==SQLITE_OK ){ |
| 184141 | | - rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); |
| 184506 | + if( rc==SQLITE_OK ){ |
| 184507 | + /* If the bRetry flag is set, the change has not been applied due to an |
| 184508 | + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and |
| 184509 | + ** a row with the correct PK is present in the db, but one or more other |
| 184510 | + ** fields do not contain the expected values) and the conflict handler |
| 184511 | + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, |
| 184512 | + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores |
| 184513 | + ** the SQLITE_CHANGESET_DATA problem. */ |
| 184514 | + if( bRetry ){ |
| 184515 | + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); |
| 184516 | + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); |
| 184517 | + } |
| 184518 | + |
| 184519 | + /* If the bReplace flag is set, the change is an INSERT that has not |
| 184520 | + ** been performed because the database already contains a row with the |
| 184521 | + ** specified primary key and the conflict handler returned |
| 184522 | + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row |
| 184523 | + ** before reattempting the INSERT. */ |
| 184524 | + else if( bReplace ){ |
| 184525 | + assert( pIter->op==SQLITE_INSERT ); |
| 184526 | + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); |
| 184527 | + if( rc==SQLITE_OK ){ |
| 184528 | + rc = sessionBindRow(pIter, |
| 184529 | + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); |
| 184530 | + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); |
| 184531 | + } |
| 184532 | + if( rc==SQLITE_OK ){ |
| 184533 | + sqlite3_step(pApply->pDelete); |
| 184534 | + rc = sqlite3_reset(pApply->pDelete); |
| 184535 | + } |
| 184536 | + if( rc==SQLITE_OK ){ |
| 184537 | + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); |
| 184538 | + } |
| 184539 | + if( rc==SQLITE_OK ){ |
| 184540 | + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); |
| 184541 | + } |
| 184142 | 184542 | } |
| 184143 | 184543 | } |
| 184144 | 184544 | |
| 184145 | 184545 | return rc; |
| 184146 | 184546 | } |
| | @@ -184212,11 +184612,12 @@ |
| 184212 | 184612 | int(*xConflict)( |
| 184213 | 184613 | void *pCtx, /* Copy of fifth arg to _apply() */ |
| 184214 | 184614 | int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 184215 | 184615 | sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 184216 | 184616 | ), |
| 184217 | | - void *pCtx /* First argument passed to xConflict */ |
| 184617 | + void *pCtx, /* First argument passed to xConflict */ |
| 184618 | + void **ppRebase, int *pnRebase /* OUT: Rebase information */ |
| 184218 | 184619 | ){ |
| 184219 | 184620 | int schemaMismatch = 0; |
| 184220 | 184621 | int rc; /* Return code */ |
| 184221 | 184622 | const char *zTab = 0; /* Name of current table */ |
| 184222 | 184623 | int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ |
| | @@ -184250,13 +184651,22 @@ |
| 184250 | 184651 | sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ |
| 184251 | 184652 | sqlite3_finalize(sApply.pDelete); |
| 184252 | 184653 | sqlite3_finalize(sApply.pUpdate); |
| 184253 | 184654 | sqlite3_finalize(sApply.pInsert); |
| 184254 | 184655 | sqlite3_finalize(sApply.pSelect); |
| 184255 | | - memset(&sApply, 0, sizeof(sApply)); |
| 184256 | 184656 | sApply.db = db; |
| 184657 | + sApply.pDelete = 0; |
| 184658 | + sApply.pUpdate = 0; |
| 184659 | + sApply.pInsert = 0; |
| 184660 | + sApply.pSelect = 0; |
| 184661 | + sApply.nCol = 0; |
| 184662 | + sApply.azCol = 0; |
| 184663 | + sApply.abPK = 0; |
| 184664 | + sApply.bStat1 = 0; |
| 184257 | 184665 | sApply.bDeferConstraints = 1; |
| 184666 | + sApply.bRebaseStarted = 0; |
| 184667 | + memset(&sApply.constraints, 0, sizeof(SessionBuffer)); |
| 184258 | 184668 | |
| 184259 | 184669 | /* If an xFilter() callback was specified, invoke it now. If the |
| 184260 | 184670 | ** xFilter callback returns zero, skip this table. If it returns |
| 184261 | 184671 | ** non-zero, proceed. */ |
| 184262 | 184672 | schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); |
| | @@ -184362,19 +184772,55 @@ |
| 184362 | 184772 | }else{ |
| 184363 | 184773 | sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); |
| 184364 | 184774 | sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); |
| 184365 | 184775 | } |
| 184366 | 184776 | |
| 184777 | + if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ |
| 184778 | + *ppRebase = (void*)sApply.rebase.aBuf; |
| 184779 | + *pnRebase = sApply.rebase.nBuf; |
| 184780 | + sApply.rebase.aBuf = 0; |
| 184781 | + } |
| 184367 | 184782 | sqlite3_finalize(sApply.pInsert); |
| 184368 | 184783 | sqlite3_finalize(sApply.pDelete); |
| 184369 | 184784 | sqlite3_finalize(sApply.pUpdate); |
| 184370 | 184785 | sqlite3_finalize(sApply.pSelect); |
| 184371 | 184786 | sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ |
| 184372 | 184787 | sqlite3_free((char*)sApply.constraints.aBuf); |
| 184788 | + sqlite3_free((char*)sApply.rebase.aBuf); |
| 184373 | 184789 | sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 184374 | 184790 | return rc; |
| 184375 | 184791 | } |
| 184792 | + |
| 184793 | +/* |
| 184794 | +** Apply the changeset passed via pChangeset/nChangeset to the main |
| 184795 | +** database attached to handle "db". |
| 184796 | +*/ |
| 184797 | +SQLITE_API int sqlite3changeset_apply_v2( |
| 184798 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 184799 | + int nChangeset, /* Size of changeset in bytes */ |
| 184800 | + void *pChangeset, /* Changeset blob */ |
| 184801 | + int(*xFilter)( |
| 184802 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 184803 | + const char *zTab /* Table name */ |
| 184804 | + ), |
| 184805 | + int(*xConflict)( |
| 184806 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 184807 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 184808 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 184809 | + ), |
| 184810 | + void *pCtx, /* First argument passed to xConflict */ |
| 184811 | + void **ppRebase, int *pnRebase |
| 184812 | +){ |
| 184813 | + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ |
| 184814 | + int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); |
| 184815 | + if( rc==SQLITE_OK ){ |
| 184816 | + rc = sessionChangesetApply( |
| 184817 | + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase |
| 184818 | + ); |
| 184819 | + } |
| 184820 | + return rc; |
| 184821 | +} |
| 184376 | 184822 | |
| 184377 | 184823 | /* |
| 184378 | 184824 | ** Apply the changeset passed via pChangeset/nChangeset to the main database |
| 184379 | 184825 | ** attached to handle "db". Invoke the supplied conflict handler callback |
| 184380 | 184826 | ** to resolve any conflicts encountered while applying the change. |
| | @@ -184392,23 +184838,45 @@ |
| 184392 | 184838 | int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 184393 | 184839 | sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 184394 | 184840 | ), |
| 184395 | 184841 | void *pCtx /* First argument passed to xConflict */ |
| 184396 | 184842 | ){ |
| 184397 | | - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ |
| 184398 | | - int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); |
| 184399 | | - if( rc==SQLITE_OK ){ |
| 184400 | | - rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); |
| 184401 | | - } |
| 184402 | | - return rc; |
| 184843 | + return sqlite3changeset_apply_v2( |
| 184844 | + db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0 |
| 184845 | + ); |
| 184403 | 184846 | } |
| 184404 | 184847 | |
| 184405 | 184848 | /* |
| 184406 | 184849 | ** Apply the changeset passed via xInput/pIn to the main database |
| 184407 | 184850 | ** attached to handle "db". Invoke the supplied conflict handler callback |
| 184408 | 184851 | ** to resolve any conflicts encountered while applying the change. |
| 184409 | 184852 | */ |
| 184853 | +SQLITE_API int sqlite3changeset_apply_v2_strm( |
| 184854 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 184855 | + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ |
| 184856 | + void *pIn, /* First arg for xInput */ |
| 184857 | + int(*xFilter)( |
| 184858 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 184859 | + const char *zTab /* Table name */ |
| 184860 | + ), |
| 184861 | + int(*xConflict)( |
| 184862 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 184863 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 184864 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 184865 | + ), |
| 184866 | + void *pCtx, /* First argument passed to xConflict */ |
| 184867 | + void **ppRebase, int *pnRebase |
| 184868 | +){ |
| 184869 | + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ |
| 184870 | + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); |
| 184871 | + if( rc==SQLITE_OK ){ |
| 184872 | + rc = sessionChangesetApply( |
| 184873 | + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase |
| 184874 | + ); |
| 184875 | + } |
| 184876 | + return rc; |
| 184877 | +} |
| 184410 | 184878 | SQLITE_API int sqlite3changeset_apply_strm( |
| 184411 | 184879 | sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 184412 | 184880 | int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ |
| 184413 | 184881 | void *pIn, /* First arg for xInput */ |
| 184414 | 184882 | int(*xFilter)( |
| | @@ -184420,16 +184888,13 @@ |
| 184420 | 184888 | int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 184421 | 184889 | sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 184422 | 184890 | ), |
| 184423 | 184891 | void *pCtx /* First argument passed to xConflict */ |
| 184424 | 184892 | ){ |
| 184425 | | - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ |
| 184426 | | - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); |
| 184427 | | - if( rc==SQLITE_OK ){ |
| 184428 | | - rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); |
| 184429 | | - } |
| 184430 | | - return rc; |
| 184893 | + return sqlite3changeset_apply_v2_strm( |
| 184894 | + db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0 |
| 184895 | + ); |
| 184431 | 184896 | } |
| 184432 | 184897 | |
| 184433 | 184898 | /* |
| 184434 | 184899 | ** sqlite3_changegroup handle. |
| 184435 | 184900 | */ |
| | @@ -184444,31 +184909,90 @@ |
| 184444 | 184909 | ** part of an sqlite3changeset_concat() operation. A new change object is |
| 184445 | 184910 | ** allocated and a pointer to it stored in *ppNew. |
| 184446 | 184911 | */ |
| 184447 | 184912 | static int sessionChangeMerge( |
| 184448 | 184913 | SessionTable *pTab, /* Table structure */ |
| 184914 | + int bRebase, /* True for a rebase hash-table */ |
| 184449 | 184915 | int bPatchset, /* True for patchsets */ |
| 184450 | 184916 | SessionChange *pExist, /* Existing change */ |
| 184451 | 184917 | int op2, /* Second change operation */ |
| 184452 | 184918 | int bIndirect, /* True if second change is indirect */ |
| 184453 | 184919 | u8 *aRec, /* Second change record */ |
| 184454 | 184920 | int nRec, /* Number of bytes in aRec */ |
| 184455 | 184921 | SessionChange **ppNew /* OUT: Merged change */ |
| 184456 | 184922 | ){ |
| 184457 | 184923 | SessionChange *pNew = 0; |
| 184924 | + int rc = SQLITE_OK; |
| 184458 | 184925 | |
| 184459 | 184926 | if( !pExist ){ |
| 184460 | 184927 | pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); |
| 184461 | 184928 | if( !pNew ){ |
| 184462 | 184929 | return SQLITE_NOMEM; |
| 184463 | 184930 | } |
| 184464 | 184931 | memset(pNew, 0, sizeof(SessionChange)); |
| 184465 | 184932 | pNew->op = op2; |
| 184466 | 184933 | pNew->bIndirect = bIndirect; |
| 184467 | | - pNew->nRecord = nRec; |
| 184468 | 184934 | pNew->aRecord = (u8*)&pNew[1]; |
| 184469 | | - memcpy(pNew->aRecord, aRec, nRec); |
| 184935 | + if( bIndirect==0 || bRebase==0 ){ |
| 184936 | + pNew->nRecord = nRec; |
| 184937 | + memcpy(pNew->aRecord, aRec, nRec); |
| 184938 | + }else{ |
| 184939 | + int i; |
| 184940 | + u8 *pIn = aRec; |
| 184941 | + u8 *pOut = pNew->aRecord; |
| 184942 | + for(i=0; i<pTab->nCol; i++){ |
| 184943 | + int nIn = sessionSerialLen(pIn); |
| 184944 | + if( *pIn==0 ){ |
| 184945 | + *pOut++ = 0; |
| 184946 | + }else if( pTab->abPK[i]==0 ){ |
| 184947 | + *pOut++ = 0xFF; |
| 184948 | + }else{ |
| 184949 | + memcpy(pOut, pIn, nIn); |
| 184950 | + pOut += nIn; |
| 184951 | + } |
| 184952 | + pIn += nIn; |
| 184953 | + } |
| 184954 | + pNew->nRecord = pOut - pNew->aRecord; |
| 184955 | + } |
| 184956 | + }else if( bRebase ){ |
| 184957 | + if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){ |
| 184958 | + *ppNew = pExist; |
| 184959 | + }else{ |
| 184960 | + int nByte = nRec + pExist->nRecord + sizeof(SessionChange); |
| 184961 | + pNew = (SessionChange*)sqlite3_malloc(nByte); |
| 184962 | + if( pNew==0 ){ |
| 184963 | + rc = SQLITE_NOMEM; |
| 184964 | + }else{ |
| 184965 | + int i; |
| 184966 | + u8 *a1 = pExist->aRecord; |
| 184967 | + u8 *a2 = aRec; |
| 184968 | + u8 *pOut; |
| 184969 | + |
| 184970 | + memset(pNew, 0, nByte); |
| 184971 | + pNew->bIndirect = bIndirect || pExist->bIndirect; |
| 184972 | + pNew->op = op2; |
| 184973 | + pOut = pNew->aRecord = (u8*)&pNew[1]; |
| 184974 | + |
| 184975 | + for(i=0; i<pTab->nCol; i++){ |
| 184976 | + int n1 = sessionSerialLen(a1); |
| 184977 | + int n2 = sessionSerialLen(a2); |
| 184978 | + if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){ |
| 184979 | + *pOut++ = 0xFF; |
| 184980 | + }else if( *a2==0 ){ |
| 184981 | + memcpy(pOut, a1, n1); |
| 184982 | + pOut += n1; |
| 184983 | + }else{ |
| 184984 | + memcpy(pOut, a2, n2); |
| 184985 | + pOut += n2; |
| 184986 | + } |
| 184987 | + a1 += n1; |
| 184988 | + a2 += n2; |
| 184989 | + } |
| 184990 | + pNew->nRecord = pOut - pNew->aRecord; |
| 184991 | + } |
| 184992 | + sqlite3_free(pExist); |
| 184993 | + } |
| 184470 | 184994 | }else{ |
| 184471 | 184995 | int op1 = pExist->op; |
| 184472 | 184996 | |
| 184473 | 184997 | /* |
| 184474 | 184998 | ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. |
| | @@ -184558,28 +185082,28 @@ |
| 184558 | 185082 | sqlite3_free(pExist); |
| 184559 | 185083 | } |
| 184560 | 185084 | } |
| 184561 | 185085 | |
| 184562 | 185086 | *ppNew = pNew; |
| 184563 | | - return SQLITE_OK; |
| 185087 | + return rc; |
| 184564 | 185088 | } |
| 184565 | 185089 | |
| 184566 | 185090 | /* |
| 184567 | 185091 | ** Add all changes in the changeset traversed by the iterator passed as |
| 184568 | 185092 | ** the first argument to the changegroup hash tables. |
| 184569 | 185093 | */ |
| 184570 | 185094 | static int sessionChangesetToHash( |
| 184571 | 185095 | sqlite3_changeset_iter *pIter, /* Iterator to read from */ |
| 184572 | | - sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ |
| 185096 | + sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ |
| 185097 | + int bRebase /* True if hash table is for rebasing */ |
| 184573 | 185098 | ){ |
| 184574 | 185099 | u8 *aRec; |
| 184575 | 185100 | int nRec; |
| 184576 | 185101 | int rc = SQLITE_OK; |
| 184577 | 185102 | SessionTable *pTab = 0; |
| 184578 | 185103 | |
| 184579 | | - |
| 184580 | | - while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ |
| 185104 | + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ |
| 184581 | 185105 | const char *zNew; |
| 184582 | 185106 | int nCol; |
| 184583 | 185107 | int op; |
| 184584 | 185108 | int iHash; |
| 184585 | 185109 | int bIndirect; |
| | @@ -184655,11 +185179,11 @@ |
| 184655 | 185179 | pTab->nEntry--; |
| 184656 | 185180 | break; |
| 184657 | 185181 | } |
| 184658 | 185182 | } |
| 184659 | 185183 | |
| 184660 | | - rc = sessionChangeMerge(pTab, |
| 185184 | + rc = sessionChangeMerge(pTab, bRebase, |
| 184661 | 185185 | pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange |
| 184662 | 185186 | ); |
| 184663 | 185187 | if( rc ) break; |
| 184664 | 185188 | if( pChange ){ |
| 184665 | 185189 | pChange->pNext = pTab->apChange[iHash]; |
| | @@ -184763,11 +185287,11 @@ |
| 184763 | 185287 | sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ |
| 184764 | 185288 | int rc; /* Return code */ |
| 184765 | 185289 | |
| 184766 | 185290 | rc = sqlite3changeset_start(&pIter, nData, pData); |
| 184767 | 185291 | if( rc==SQLITE_OK ){ |
| 184768 | | - rc = sessionChangesetToHash(pIter, pGrp); |
| 185292 | + rc = sessionChangesetToHash(pIter, pGrp, 0); |
| 184769 | 185293 | } |
| 184770 | 185294 | sqlite3changeset_finalize(pIter); |
| 184771 | 185295 | return rc; |
| 184772 | 185296 | } |
| 184773 | 185297 | |
| | @@ -184794,11 +185318,11 @@ |
| 184794 | 185318 | sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ |
| 184795 | 185319 | int rc; /* Return code */ |
| 184796 | 185320 | |
| 184797 | 185321 | rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); |
| 184798 | 185322 | if( rc==SQLITE_OK ){ |
| 184799 | | - rc = sessionChangesetToHash(pIter, pGrp); |
| 185323 | + rc = sessionChangesetToHash(pIter, pGrp, 0); |
| 184800 | 185324 | } |
| 184801 | 185325 | sqlite3changeset_finalize(pIter); |
| 184802 | 185326 | return rc; |
| 184803 | 185327 | } |
| 184804 | 185328 | |
| | @@ -184878,10 +185402,353 @@ |
| 184878 | 185402 | } |
| 184879 | 185403 | sqlite3changegroup_delete(pGrp); |
| 184880 | 185404 | |
| 184881 | 185405 | return rc; |
| 184882 | 185406 | } |
| 185407 | + |
| 185408 | +/* |
| 185409 | +** Changeset rebaser handle. |
| 185410 | +*/ |
| 185411 | +struct sqlite3_rebaser { |
| 185412 | + sqlite3_changegroup grp; /* Hash table */ |
| 185413 | +}; |
| 185414 | + |
| 185415 | +/* |
| 185416 | +** Buffers a1 and a2 must both contain a sessions module record nCol |
| 185417 | +** fields in size. This function appends an nCol sessions module |
| 185418 | +** record to buffer pBuf that is a copy of a1, except that for |
| 185419 | +** each field that is undefined in a1[], swap in the field from a2[]. |
| 185420 | +*/ |
| 185421 | +static void sessionAppendRecordMerge( |
| 185422 | + SessionBuffer *pBuf, /* Buffer to append to */ |
| 185423 | + int nCol, /* Number of columns in each record */ |
| 185424 | + u8 *a1, int n1, /* Record 1 */ |
| 185425 | + u8 *a2, int n2, /* Record 2 */ |
| 185426 | + int *pRc /* IN/OUT: error code */ |
| 185427 | +){ |
| 185428 | + sessionBufferGrow(pBuf, n1+n2, pRc); |
| 185429 | + if( *pRc==SQLITE_OK ){ |
| 185430 | + int i; |
| 185431 | + u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; |
| 185432 | + for(i=0; i<nCol; i++){ |
| 185433 | + int nn1 = sessionSerialLen(a1); |
| 185434 | + int nn2 = sessionSerialLen(a2); |
| 185435 | + if( *a1==0 || *a1==0xFF ){ |
| 185436 | + memcpy(pOut, a2, nn2); |
| 185437 | + pOut += nn2; |
| 185438 | + }else{ |
| 185439 | + memcpy(pOut, a1, nn1); |
| 185440 | + pOut += nn1; |
| 185441 | + } |
| 185442 | + a1 += nn1; |
| 185443 | + a2 += nn2; |
| 185444 | + } |
| 185445 | + |
| 185446 | + pBuf->nBuf = pOut-pBuf->aBuf; |
| 185447 | + assert( pBuf->nBuf<=pBuf->nAlloc ); |
| 185448 | + } |
| 185449 | +} |
| 185450 | + |
| 185451 | +/* |
| 185452 | +** This function is called when rebasing a local UPDATE change against one |
| 185453 | +** or more remote UPDATE changes. The aRec/nRec buffer contains the current |
| 185454 | +** old.* and new.* records for the change. The rebase buffer (a single |
| 185455 | +** record) is in aChange/nChange. The rebased change is appended to buffer |
| 185456 | +** pBuf. |
| 185457 | +** |
| 185458 | +** Rebasing the UPDATE involves: |
| 185459 | +** |
| 185460 | +** * Removing any changes to fields for which the corresponding field |
| 185461 | +** in the rebase buffer is set to "replaced" (type 0xFF). If this |
| 185462 | +** means the UPDATE change updates no fields, nothing is appended |
| 185463 | +** to the output buffer. |
| 185464 | +** |
| 185465 | +** * For each field modified by the local change for which the |
| 185466 | +** corresponding field in the rebase buffer is not "undefined" (0x00) |
| 185467 | +** or "replaced" (0xFF), the old.* value is replaced by the value |
| 185468 | +** in the rebase buffer. |
| 185469 | +*/ |
| 185470 | +static void sessionAppendPartialUpdate( |
| 185471 | + SessionBuffer *pBuf, /* Append record here */ |
| 185472 | + sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */ |
| 185473 | + u8 *aRec, int nRec, /* Local change */ |
| 185474 | + u8 *aChange, int nChange, /* Record to rebase against */ |
| 185475 | + int *pRc /* IN/OUT: Return Code */ |
| 185476 | +){ |
| 185477 | + sessionBufferGrow(pBuf, 2+nRec+nChange, pRc); |
| 185478 | + if( *pRc==SQLITE_OK ){ |
| 185479 | + int bData = 0; |
| 185480 | + u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; |
| 185481 | + int i; |
| 185482 | + u8 *a1 = aRec; |
| 185483 | + u8 *a2 = aChange; |
| 185484 | + |
| 185485 | + *pOut++ = SQLITE_UPDATE; |
| 185486 | + *pOut++ = pIter->bIndirect; |
| 185487 | + for(i=0; i<pIter->nCol; i++){ |
| 185488 | + int n1 = sessionSerialLen(a1); |
| 185489 | + int n2 = sessionSerialLen(a2); |
| 185490 | + if( pIter->abPK[i] || a2[0]==0 ){ |
| 185491 | + if( !pIter->abPK[i] ) bData = 1; |
| 185492 | + memcpy(pOut, a1, n1); |
| 185493 | + pOut += n1; |
| 185494 | + }else if( a2[0]!=0xFF ){ |
| 185495 | + bData = 1; |
| 185496 | + memcpy(pOut, a2, n2); |
| 185497 | + pOut += n2; |
| 185498 | + }else{ |
| 185499 | + *pOut++ = '\0'; |
| 185500 | + } |
| 185501 | + a1 += n1; |
| 185502 | + a2 += n2; |
| 185503 | + } |
| 185504 | + if( bData ){ |
| 185505 | + a2 = aChange; |
| 185506 | + for(i=0; i<pIter->nCol; i++){ |
| 185507 | + int n1 = sessionSerialLen(a1); |
| 185508 | + int n2 = sessionSerialLen(a2); |
| 185509 | + if( pIter->abPK[i] || a2[0]!=0xFF ){ |
| 185510 | + memcpy(pOut, a1, n1); |
| 185511 | + pOut += n1; |
| 185512 | + }else{ |
| 185513 | + *pOut++ = '\0'; |
| 185514 | + } |
| 185515 | + a1 += n1; |
| 185516 | + a2 += n2; |
| 185517 | + } |
| 185518 | + pBuf->nBuf = (pOut - pBuf->aBuf); |
| 185519 | + } |
| 185520 | + } |
| 185521 | +} |
| 185522 | + |
| 185523 | +/* |
| 185524 | +** pIter is configured to iterate through a changeset. This function rebases |
| 185525 | +** that changeset according to the current configuration of the rebaser |
| 185526 | +** object passed as the first argument. If no error occurs and argument xOutput |
| 185527 | +** is not NULL, then the changeset is returned to the caller by invoking |
| 185528 | +** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL, |
| 185529 | +** then (*ppOut) is set to point to a buffer containing the rebased changeset |
| 185530 | +** before this function returns. In this case (*pnOut) is set to the size of |
| 185531 | +** the buffer in bytes. It is the responsibility of the caller to eventually |
| 185532 | +** free the (*ppOut) buffer using sqlite3_free(). |
| 185533 | +** |
| 185534 | +** If an error occurs, an SQLite error code is returned. If ppOut and |
| 185535 | +** pnOut are not NULL, then the two output parameters are set to 0 before |
| 185536 | +** returning. |
| 185537 | +*/ |
| 185538 | +static int sessionRebase( |
| 185539 | + sqlite3_rebaser *p, /* Rebaser hash table */ |
| 185540 | + sqlite3_changeset_iter *pIter, /* Input data */ |
| 185541 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 185542 | + void *pOut, /* Context for xOutput callback */ |
| 185543 | + int *pnOut, /* OUT: Number of bytes in output changeset */ |
| 185544 | + void **ppOut /* OUT: Inverse of pChangeset */ |
| 185545 | +){ |
| 185546 | + int rc = SQLITE_OK; |
| 185547 | + u8 *aRec = 0; |
| 185548 | + int nRec = 0; |
| 185549 | + int bNew = 0; |
| 185550 | + SessionTable *pTab = 0; |
| 185551 | + SessionBuffer sOut = {0,0,0}; |
| 185552 | + |
| 185553 | + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ |
| 185554 | + SessionChange *pChange = 0; |
| 185555 | + int bDone = 0; |
| 185556 | + |
| 185557 | + if( bNew ){ |
| 185558 | + const char *zTab = pIter->zTab; |
| 185559 | + for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ |
| 185560 | + if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; |
| 185561 | + } |
| 185562 | + bNew = 0; |
| 185563 | + |
| 185564 | + /* A patchset may not be rebased */ |
| 185565 | + if( pIter->bPatchset ){ |
| 185566 | + rc = SQLITE_ERROR; |
| 185567 | + } |
| 185568 | + |
| 185569 | + /* Append a table header to the output for this new table */ |
| 185570 | + sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc); |
| 185571 | + sessionAppendVarint(&sOut, pIter->nCol, &rc); |
| 185572 | + sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc); |
| 185573 | + sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc); |
| 185574 | + } |
| 185575 | + |
| 185576 | + if( pTab && rc==SQLITE_OK ){ |
| 185577 | + int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange); |
| 185578 | + |
| 185579 | + for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ |
| 185580 | + if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){ |
| 185581 | + break; |
| 185582 | + } |
| 185583 | + } |
| 185584 | + } |
| 185585 | + |
| 185586 | + if( pChange ){ |
| 185587 | + assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT ); |
| 185588 | + switch( pIter->op ){ |
| 185589 | + case SQLITE_INSERT: |
| 185590 | + if( pChange->op==SQLITE_INSERT ){ |
| 185591 | + bDone = 1; |
| 185592 | + if( pChange->bIndirect==0 ){ |
| 185593 | + sessionAppendByte(&sOut, SQLITE_UPDATE, &rc); |
| 185594 | + sessionAppendByte(&sOut, pIter->bIndirect, &rc); |
| 185595 | + sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc); |
| 185596 | + sessionAppendBlob(&sOut, aRec, nRec, &rc); |
| 185597 | + } |
| 185598 | + } |
| 185599 | + break; |
| 185600 | + |
| 185601 | + case SQLITE_UPDATE: |
| 185602 | + bDone = 1; |
| 185603 | + if( pChange->op==SQLITE_DELETE ){ |
| 185604 | + if( pChange->bIndirect==0 ){ |
| 185605 | + u8 *pCsr = aRec; |
| 185606 | + sessionSkipRecord(&pCsr, pIter->nCol); |
| 185607 | + sessionAppendByte(&sOut, SQLITE_INSERT, &rc); |
| 185608 | + sessionAppendByte(&sOut, pIter->bIndirect, &rc); |
| 185609 | + sessionAppendRecordMerge(&sOut, pIter->nCol, |
| 185610 | + pCsr, nRec-(pCsr-aRec), |
| 185611 | + pChange->aRecord, pChange->nRecord, &rc |
| 185612 | + ); |
| 185613 | + } |
| 185614 | + }else{ |
| 185615 | + sessionAppendPartialUpdate(&sOut, pIter, |
| 185616 | + aRec, nRec, pChange->aRecord, pChange->nRecord, &rc |
| 185617 | + ); |
| 185618 | + } |
| 185619 | + break; |
| 185620 | + |
| 185621 | + default: |
| 185622 | + assert( pIter->op==SQLITE_DELETE ); |
| 185623 | + bDone = 1; |
| 185624 | + if( pChange->op==SQLITE_INSERT ){ |
| 185625 | + sessionAppendByte(&sOut, SQLITE_DELETE, &rc); |
| 185626 | + sessionAppendByte(&sOut, pIter->bIndirect, &rc); |
| 185627 | + sessionAppendRecordMerge(&sOut, pIter->nCol, |
| 185628 | + pChange->aRecord, pChange->nRecord, aRec, nRec, &rc |
| 185629 | + ); |
| 185630 | + } |
| 185631 | + break; |
| 185632 | + } |
| 185633 | + } |
| 185634 | + |
| 185635 | + if( bDone==0 ){ |
| 185636 | + sessionAppendByte(&sOut, pIter->op, &rc); |
| 185637 | + sessionAppendByte(&sOut, pIter->bIndirect, &rc); |
| 185638 | + sessionAppendBlob(&sOut, aRec, nRec, &rc); |
| 185639 | + } |
| 185640 | + if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ |
| 185641 | + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); |
| 185642 | + sOut.nBuf = 0; |
| 185643 | + } |
| 185644 | + if( rc ) break; |
| 185645 | + } |
| 185646 | + |
| 185647 | + if( rc!=SQLITE_OK ){ |
| 185648 | + sqlite3_free(sOut.aBuf); |
| 185649 | + memset(&sOut, 0, sizeof(sOut)); |
| 185650 | + } |
| 185651 | + |
| 185652 | + if( rc==SQLITE_OK ){ |
| 185653 | + if( xOutput ){ |
| 185654 | + if( sOut.nBuf>0 ){ |
| 185655 | + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); |
| 185656 | + } |
| 185657 | + }else{ |
| 185658 | + *ppOut = (void*)sOut.aBuf; |
| 185659 | + *pnOut = sOut.nBuf; |
| 185660 | + sOut.aBuf = 0; |
| 185661 | + } |
| 185662 | + } |
| 185663 | + sqlite3_free(sOut.aBuf); |
| 185664 | + return rc; |
| 185665 | +} |
| 185666 | + |
| 185667 | +/* |
| 185668 | +** Create a new rebaser object. |
| 185669 | +*/ |
| 185670 | +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ |
| 185671 | + int rc = SQLITE_OK; |
| 185672 | + sqlite3_rebaser *pNew; |
| 185673 | + |
| 185674 | + pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); |
| 185675 | + if( pNew==0 ){ |
| 185676 | + rc = SQLITE_NOMEM; |
| 185677 | + }else{ |
| 185678 | + memset(pNew, 0, sizeof(sqlite3_rebaser)); |
| 185679 | + } |
| 185680 | + *ppNew = pNew; |
| 185681 | + return rc; |
| 185682 | +} |
| 185683 | + |
| 185684 | +/* |
| 185685 | +** Call this one or more times to configure a rebaser. |
| 185686 | +*/ |
| 185687 | +SQLITE_API int sqlite3rebaser_configure( |
| 185688 | + sqlite3_rebaser *p, |
| 185689 | + int nRebase, const void *pRebase |
| 185690 | +){ |
| 185691 | + sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */ |
| 185692 | + int rc; /* Return code */ |
| 185693 | + rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase); |
| 185694 | + if( rc==SQLITE_OK ){ |
| 185695 | + rc = sessionChangesetToHash(pIter, &p->grp, 1); |
| 185696 | + } |
| 185697 | + sqlite3changeset_finalize(pIter); |
| 185698 | + return rc; |
| 185699 | +} |
| 185700 | + |
| 185701 | +/* |
| 185702 | +** Rebase a changeset according to current rebaser configuration |
| 185703 | +*/ |
| 185704 | +SQLITE_API int sqlite3rebaser_rebase( |
| 185705 | + sqlite3_rebaser *p, |
| 185706 | + int nIn, const void *pIn, |
| 185707 | + int *pnOut, void **ppOut |
| 185708 | +){ |
| 185709 | + sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ |
| 185710 | + int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); |
| 185711 | + |
| 185712 | + if( rc==SQLITE_OK ){ |
| 185713 | + rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); |
| 185714 | + sqlite3changeset_finalize(pIter); |
| 185715 | + } |
| 185716 | + |
| 185717 | + return rc; |
| 185718 | +} |
| 185719 | + |
| 185720 | +/* |
| 185721 | +** Rebase a changeset according to current rebaser configuration |
| 185722 | +*/ |
| 185723 | +SQLITE_API int sqlite3rebaser_rebase_strm( |
| 185724 | + sqlite3_rebaser *p, |
| 185725 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 185726 | + void *pIn, |
| 185727 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 185728 | + void *pOut |
| 185729 | +){ |
| 185730 | + sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ |
| 185731 | + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); |
| 185732 | + |
| 185733 | + if( rc==SQLITE_OK ){ |
| 185734 | + rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); |
| 185735 | + sqlite3changeset_finalize(pIter); |
| 185736 | + } |
| 185737 | + |
| 185738 | + return rc; |
| 185739 | +} |
| 185740 | + |
| 185741 | +/* |
| 185742 | +** Destroy a rebaser object |
| 185743 | +*/ |
| 185744 | +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){ |
| 185745 | + if( p ){ |
| 185746 | + sessionDeleteTable(p->grp.pList); |
| 185747 | + sqlite3_free(p); |
| 185748 | + } |
| 185749 | +} |
| 184883 | 185750 | |
| 184884 | 185751 | #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 184885 | 185752 | |
| 184886 | 185753 | /************** End of sqlite3session.c **************************************/ |
| 184887 | 185754 | /************** Begin file json1.c *******************************************/ |
| | @@ -204697,11 +205564,11 @@ |
| 204697 | 205564 | int nArg, /* Number of args */ |
| 204698 | 205565 | sqlite3_value **apUnused /* Function arguments */ |
| 204699 | 205566 | ){ |
| 204700 | 205567 | assert( nArg==0 ); |
| 204701 | 205568 | UNUSED_PARAM2(nArg, apUnused); |
| 204702 | | - sqlite3_result_text(pCtx, "fts5: 2018-03-22 17:13:44 eb4f452e354065d610ff57a6a9312ad119b6b0cc467f9dff105f0718bc27ef01", -1, SQLITE_TRANSIENT); |
| 205569 | + sqlite3_result_text(pCtx, "fts5: 2018-03-26 16:37:53 6c40c5574f4ae9795a142d01a8f84afd1b72678ea5f6bfca14a8646c4e862605", -1, SQLITE_TRANSIENT); |
| 204703 | 205570 | } |
| 204704 | 205571 | |
| 204705 | 205572 | static int fts5Init(sqlite3 *db){ |
| 204706 | 205573 | static const sqlite3_module fts5Mod = { |
| 204707 | 205574 | /* iVersion */ 2, |
| | @@ -208967,12 +209834,12 @@ |
| 208967 | 209834 | } |
| 208968 | 209835 | #endif /* SQLITE_CORE */ |
| 208969 | 209836 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ |
| 208970 | 209837 | |
| 208971 | 209838 | /************** End of stmt.c ************************************************/ |
| 208972 | | -#if __LINE__!=208972 |
| 209839 | +#if __LINE__!=209839 |
| 208973 | 209840 | #undef SQLITE_SOURCE_ID |
| 208974 | | -#define SQLITE_SOURCE_ID "2018-03-22 17:13:44 eb4f452e354065d610ff57a6a9312ad119b6b0cc467f9dff105f0718bc27alt2" |
| 209841 | +#define SQLITE_SOURCE_ID "2018-03-28 15:56:55 eb29b3369e76ec1df25a5484d8ec5fb924e23d5c70aaa4d794b2b17ee187alt2" |
| 208975 | 209842 | #endif |
| 208976 | 209843 | /* Return the source-id for this library */ |
| 208977 | 209844 | SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
| 208978 | 209845 | /************************** End of sqlite3.c ******************************/ |
| 208979 | 209846 | |