| | @@ -1,8 +1,8 @@ |
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | | -** version 3.12.0. By combining all the individual C code files into this |
| 3 | +** version 3.13.0. By combining all the individual C code files into this |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| | @@ -334,13 +334,13 @@ |
| 334 | 334 | ** |
| 335 | 335 | ** See also: [sqlite3_libversion()], |
| 336 | 336 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 337 | 337 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 338 | 338 | */ |
| 339 | | -#define SQLITE_VERSION "3.12.0" |
| 340 | | -#define SQLITE_VERSION_NUMBER 3012000 |
| 341 | | -#define SQLITE_SOURCE_ID "2016-03-29 10:14:15 e9bb4cf40f4971974a74468ef922bdee481c988b" |
| 339 | +#define SQLITE_VERSION "3.13.0" |
| 340 | +#define SQLITE_VERSION_NUMBER 3013000 |
| 341 | +#define SQLITE_SOURCE_ID "2016-04-07 21:14:35 87aa9357fbe6749bae60e30af54ca16e48678802" |
| 342 | 342 | |
| 343 | 343 | /* |
| 344 | 344 | ** CAPI3REF: Run-Time Library Version Numbers |
| 345 | 345 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 346 | 346 | ** |
| | @@ -5410,11 +5410,11 @@ |
| 5410 | 5410 | ** METHOD: sqlite3 |
| 5411 | 5411 | ** |
| 5412 | 5412 | ** ^The sqlite3_update_hook() interface registers a callback function |
| 5413 | 5413 | ** with the [database connection] identified by the first argument |
| 5414 | 5414 | ** to be invoked whenever a row is updated, inserted or deleted in |
| 5415 | | -** a rowid table. |
| 5415 | +** a [rowid table]. |
| 5416 | 5416 | ** ^Any callback set by a previous call to this function |
| 5417 | 5417 | ** for the same database connection is overridden. |
| 5418 | 5418 | ** |
| 5419 | 5419 | ** ^The second argument is a pointer to the function to invoke when a |
| 5420 | 5420 | ** row is updated, inserted or deleted in a rowid table. |
| | @@ -5449,12 +5449,12 @@ |
| 5449 | 5449 | ** ^The sqlite3_update_hook(D,C,P) function |
| 5450 | 5450 | ** returns the P argument from the previous call |
| 5451 | 5451 | ** on the same [database connection] D, or NULL for |
| 5452 | 5452 | ** the first call on D. |
| 5453 | 5453 | ** |
| 5454 | | -** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] |
| 5455 | | -** interfaces. |
| 5454 | +** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], |
| 5455 | +** and [sqlite3_preupdate_hook()] interfaces. |
| 5456 | 5456 | */ |
| 5457 | 5457 | SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook( |
| 5458 | 5458 | sqlite3*, |
| 5459 | 5459 | void(*)(void *,int ,char const *,char const *,sqlite3_int64), |
| 5460 | 5460 | void* |
| | @@ -7360,11 +7360,11 @@ |
| 7360 | 7360 | ** and database name of the source database, respectively. |
| 7361 | 7361 | ** ^The source and destination [database connections] (parameters S and D) |
| 7362 | 7362 | ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with |
| 7363 | 7363 | ** an error. |
| 7364 | 7364 | ** |
| 7365 | | -** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if |
| 7365 | +** ^A call to sqlite3_backup_init() will fail, returning NULL, if |
| 7366 | 7366 | ** there is already a read or read-write transaction open on the |
| 7367 | 7367 | ** destination database. |
| 7368 | 7368 | ** |
| 7369 | 7369 | ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is |
| 7370 | 7370 | ** returned and an error code and error message are stored in the |
| | @@ -8138,15 +8138,111 @@ |
| 8138 | 8138 | ** ^This function does not set the database handle error code or message |
| 8139 | 8139 | ** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. |
| 8140 | 8140 | */ |
| 8141 | 8141 | SQLITE_API int SQLITE_STDCALL sqlite3_db_cacheflush(sqlite3*); |
| 8142 | 8142 | |
| 8143 | +/* |
| 8144 | +** CAPI3REF: The pre-update hook. |
| 8145 | +** |
| 8146 | +** ^These interfaces are only available if SQLite is compiled using the |
| 8147 | +** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. |
| 8148 | +** |
| 8149 | +** ^The [sqlite3_preupdate_hook()] interface registers a callback function |
| 8150 | +** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation |
| 8151 | +** on a [rowid table]. |
| 8152 | +** ^At most one preupdate hook may be registered at a time on a single |
| 8153 | +** [database connection]; each call to [sqlite3_preupdate_hook()] overrides |
| 8154 | +** the previous setting. |
| 8155 | +** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] |
| 8156 | +** with a NULL pointer as the second parameter. |
| 8157 | +** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as |
| 8158 | +** the first parameter to callbacks. |
| 8159 | +** |
| 8160 | +** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate |
| 8161 | +** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID] |
| 8162 | +** tables. |
| 8163 | +** |
| 8164 | +** ^The second parameter to the preupdate callback is a pointer to |
| 8165 | +** the [database connection] that registered the preupdate hook. |
| 8166 | +** ^The third parameter to the preupdate callback is one of the constants |
| 8167 | +** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to indentify the |
| 8168 | +** kind of update operation that is about to occur. |
| 8169 | +** ^(The fourth parameter to the preupdate callback is the name of the |
| 8170 | +** database within the database connection that is being modified. This |
| 8171 | +** will be "main" for the main database or "temp" for TEMP tables or |
| 8172 | +** the name given after the AS keyword in the [ATTACH] statement for attached |
| 8173 | +** databases.)^ |
| 8174 | +** ^The fifth parameter to the preupdate callback is the name of the |
| 8175 | +** table that is being modified. |
| 8176 | +** ^The sixth parameter to the preupdate callback is the initial [rowid] of the |
| 8177 | +** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is |
| 8178 | +** undefined for SQLITE_INSERT changes. |
| 8179 | +** ^The seventh parameter to the preupdate callback is the final [rowid] of |
| 8180 | +** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is |
| 8181 | +** undefined for SQLITE_DELETE changes. |
| 8182 | +** |
| 8183 | +** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], |
| 8184 | +** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces |
| 8185 | +** provide additional information about a preupdate event. These routines |
| 8186 | +** may only be called from within a preupdate callback. Invoking any of |
| 8187 | +** these routines from outside of a preupdate callback or with a |
| 8188 | +** [database connection] pointer that is different from the one supplied |
| 8189 | +** to the preupdate callback results in undefined and probably undesirable |
| 8190 | +** behavior. |
| 8191 | +** |
| 8192 | +** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns |
| 8193 | +** in the row that is being inserted, updated, or deleted. |
| 8194 | +** |
| 8195 | +** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to |
| 8196 | +** a [protected sqlite3_value] that contains the value of the Nth column of |
| 8197 | +** the table row before it is updated. The N parameter must be between 0 |
| 8198 | +** and one less than the number of columns or the behavior will be |
| 8199 | +** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE |
| 8200 | +** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the |
| 8201 | +** behavior is undefined. The [sqlite3_value] that P points to |
| 8202 | +** will be destroyed when the preupdate callback returns. |
| 8203 | +** |
| 8204 | +** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to |
| 8205 | +** a [protected sqlite3_value] that contains the value of the Nth column of |
| 8206 | +** the table row after it is updated. The N parameter must be between 0 |
| 8207 | +** and one less than the number of columns or the behavior will be |
| 8208 | +** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE |
| 8209 | +** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the |
| 8210 | +** behavior is undefined. The [sqlite3_value] that P points to |
| 8211 | +** will be destroyed when the preupdate callback returns. |
| 8212 | +** |
| 8213 | +** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate |
| 8214 | +** callback was invoked as a result of a direct insert, update, or delete |
| 8215 | +** operation; or 1 for inserts, updates, or deletes invoked by top-level |
| 8216 | +** triggers; or 2 for changes resulting from triggers called by top-level |
| 8217 | +** triggers; and so forth. |
| 8218 | +** |
| 8219 | +** See also: [sqlite3_update_hook()] |
| 8220 | +*/ |
| 8221 | +SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_preupdate_hook( |
| 8222 | + sqlite3 *db, |
| 8223 | + void(*xPreUpdate)( |
| 8224 | + void *pCtx, /* Copy of third arg to preupdate_hook() */ |
| 8225 | + sqlite3 *db, /* Database handle */ |
| 8226 | + int op, /* SQLITE_UPDATE, DELETE or INSERT */ |
| 8227 | + char const *zDb, /* Database name */ |
| 8228 | + char const *zName, /* Table name */ |
| 8229 | + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ |
| 8230 | + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ |
| 8231 | + ), |
| 8232 | + void* |
| 8233 | +); |
| 8234 | +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); |
| 8235 | +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_count(sqlite3 *); |
| 8236 | +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_depth(sqlite3 *); |
| 8237 | +SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); |
| 8238 | + |
| 8143 | 8239 | /* |
| 8144 | 8240 | ** CAPI3REF: Low-level system error code |
| 8145 | 8241 | ** |
| 8146 | 8242 | ** ^Attempt to return the underlying operating system error code or error |
| 8147 | | -** number that caused the most reason I/O error or failure to open a file. |
| 8243 | +** number that caused the most recent I/O error or failure to open a file. |
| 8148 | 8244 | ** The return value is OS-dependent. For example, on unix systems, after |
| 8149 | 8245 | ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be |
| 8150 | 8246 | ** called to get back the underlying "errno" that caused the problem, such |
| 8151 | 8247 | ** as ENOSPC, EAUTH, EISDIR, and so forth. |
| 8152 | 8248 | */ |
| | @@ -8259,10 +8355,11 @@ |
| 8259 | 8355 | #if 0 |
| 8260 | 8356 | } /* End of the 'extern "C"' block */ |
| 8261 | 8357 | #endif |
| 8262 | 8358 | #endif /* _SQLITE3_H_ */ |
| 8263 | 8359 | |
| 8360 | +/******** Begin file sqlite3rtree.h *********/ |
| 8264 | 8361 | /* |
| 8265 | 8362 | ** 2010 August 30 |
| 8266 | 8363 | ** |
| 8267 | 8364 | ** The author disclaims copyright to this source code. In place of |
| 8268 | 8365 | ** a legal notice, here is a blessing: |
| | @@ -8376,10 +8473,1291 @@ |
| 8376 | 8473 | } /* end of the 'extern "C"' block */ |
| 8377 | 8474 | #endif |
| 8378 | 8475 | |
| 8379 | 8476 | #endif /* ifndef _SQLITE3RTREE_H_ */ |
| 8380 | 8477 | |
| 8478 | +/******** End of sqlite3rtree.h *********/ |
| 8479 | +/******** Begin file sqlite3session.h *********/ |
| 8480 | + |
| 8481 | +#ifndef __SQLITESESSION_H_ |
| 8482 | +#define __SQLITESESSION_H_ 1 |
| 8483 | + |
| 8484 | +/* |
| 8485 | +** Make sure we can call this stuff from C++. |
| 8486 | +*/ |
| 8487 | +#if 0 |
| 8488 | +extern "C" { |
| 8489 | +#endif |
| 8490 | + |
| 8491 | + |
| 8492 | +/* |
| 8493 | +** CAPI3REF: Session Object Handle |
| 8494 | +*/ |
| 8495 | +typedef struct sqlite3_session sqlite3_session; |
| 8496 | + |
| 8497 | +/* |
| 8498 | +** CAPI3REF: Changeset Iterator Handle |
| 8499 | +*/ |
| 8500 | +typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; |
| 8501 | + |
| 8502 | +/* |
| 8503 | +** CAPI3REF: Create A New Session Object |
| 8504 | +** |
| 8505 | +** Create a new session object attached to database handle db. If successful, |
| 8506 | +** a pointer to the new object is written to *ppSession and SQLITE_OK is |
| 8507 | +** returned. If an error occurs, *ppSession is set to NULL and an SQLite |
| 8508 | +** error code (e.g. SQLITE_NOMEM) is returned. |
| 8509 | +** |
| 8510 | +** It is possible to create multiple session objects attached to a single |
| 8511 | +** database handle. |
| 8512 | +** |
| 8513 | +** Session objects created using this function should be deleted using the |
| 8514 | +** [sqlite3session_delete()] function before the database handle that they |
| 8515 | +** are attached to is itself closed. If the database handle is closed before |
| 8516 | +** the session object is deleted, then the results of calling any session |
| 8517 | +** module function, including [sqlite3session_delete()] on the session object |
| 8518 | +** are undefined. |
| 8519 | +** |
| 8520 | +** Because the session module uses the [sqlite3_preupdate_hook()] API, it |
| 8521 | +** is not possible for an application to register a pre-update hook on a |
| 8522 | +** database handle that has one or more session objects attached. Nor is |
| 8523 | +** it possible to create a session object attached to a database handle for |
| 8524 | +** which a pre-update hook is already defined. The results of attempting |
| 8525 | +** either of these things are undefined. |
| 8526 | +** |
| 8527 | +** The session object will be used to create changesets for tables in |
| 8528 | +** database zDb, where zDb is either "main", or "temp", or the name of an |
| 8529 | +** attached database. It is not an error if database zDb is not attached |
| 8530 | +** to the database when the session object is created. |
| 8531 | +*/ |
| 8532 | +int sqlite3session_create( |
| 8533 | + sqlite3 *db, /* Database handle */ |
| 8534 | + const char *zDb, /* Name of db (e.g. "main") */ |
| 8535 | + sqlite3_session **ppSession /* OUT: New session object */ |
| 8536 | +); |
| 8537 | + |
| 8538 | +/* |
| 8539 | +** CAPI3REF: Delete A Session Object |
| 8540 | +** |
| 8541 | +** Delete a session object previously allocated using |
| 8542 | +** [sqlite3session_create()]. Once a session object has been deleted, the |
| 8543 | +** results of attempting to use pSession with any other session module |
| 8544 | +** function are undefined. |
| 8545 | +** |
| 8546 | +** Session objects must be deleted before the database handle to which they |
| 8547 | +** are attached is closed. Refer to the documentation for |
| 8548 | +** [sqlite3session_create()] for details. |
| 8549 | +*/ |
| 8550 | +void sqlite3session_delete(sqlite3_session *pSession); |
| 8551 | + |
| 8552 | + |
| 8553 | +/* |
| 8554 | +** CAPI3REF: Enable Or Disable A Session Object |
| 8555 | +** |
| 8556 | +** Enable or disable the recording of changes by a session object. When |
| 8557 | +** enabled, a session object records changes made to the database. When |
| 8558 | +** disabled - it does not. A newly created session object is enabled. |
| 8559 | +** Refer to the documentation for [sqlite3session_changeset()] for further |
| 8560 | +** details regarding how enabling and disabling a session object affects |
| 8561 | +** the eventual changesets. |
| 8562 | +** |
| 8563 | +** Passing zero to this function disables the session. Passing a value |
| 8564 | +** greater than zero enables it. Passing a value less than zero is a |
| 8565 | +** no-op, and may be used to query the current state of the session. |
| 8566 | +** |
| 8567 | +** The return value indicates the final state of the session object: 0 if |
| 8568 | +** the session is disabled, or 1 if it is enabled. |
| 8569 | +*/ |
| 8570 | +int sqlite3session_enable(sqlite3_session *pSession, int bEnable); |
| 8571 | + |
| 8572 | +/* |
| 8573 | +** CAPI3REF: Set Or Clear the Indirect Change Flag |
| 8574 | +** |
| 8575 | +** Each change recorded by a session object is marked as either direct or |
| 8576 | +** indirect. A change is marked as indirect if either: |
| 8577 | +** |
| 8578 | +** <ul> |
| 8579 | +** <li> The session object "indirect" flag is set when the change is |
| 8580 | +** made, or |
| 8581 | +** <li> The change is made by an SQL trigger or foreign key action |
| 8582 | +** instead of directly as a result of a users SQL statement. |
| 8583 | +** </ul> |
| 8584 | +** |
| 8585 | +** If a single row is affected by more than one operation within a session, |
| 8586 | +** then the change is considered indirect if all operations meet the criteria |
| 8587 | +** for an indirect change above, or direct otherwise. |
| 8588 | +** |
| 8589 | +** This function is used to set, clear or query the session object indirect |
| 8590 | +** flag. If the second argument passed to this function is zero, then the |
| 8591 | +** indirect flag is cleared. If it is greater than zero, the indirect flag |
| 8592 | +** is set. Passing a value less than zero does not modify the current value |
| 8593 | +** of the indirect flag, and may be used to query the current state of the |
| 8594 | +** indirect flag for the specified session object. |
| 8595 | +** |
| 8596 | +** The return value indicates the final state of the indirect flag: 0 if |
| 8597 | +** it is clear, or 1 if it is set. |
| 8598 | +*/ |
| 8599 | +int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); |
| 8600 | + |
| 8601 | +/* |
| 8602 | +** CAPI3REF: Attach A Table To A Session Object |
| 8603 | +** |
| 8604 | +** If argument zTab is not NULL, then it is the name of a table to attach |
| 8605 | +** to the session object passed as the first argument. All subsequent changes |
| 8606 | +** made to the table while the session object is enabled will be recorded. See |
| 8607 | +** documentation for [sqlite3session_changeset()] for further details. |
| 8608 | +** |
| 8609 | +** Or, if argument zTab is NULL, then changes are recorded for all tables |
| 8610 | +** in the database. If additional tables are added to the database (by |
| 8611 | +** executing "CREATE TABLE" statements) after this call is made, changes for |
| 8612 | +** the new tables are also recorded. |
| 8613 | +** |
| 8614 | +** Changes can only be recorded for tables that have a PRIMARY KEY explicitly |
| 8615 | +** defined as part of their CREATE TABLE statement. It does not matter if the |
| 8616 | +** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY |
| 8617 | +** KEY may consist of a single column, or may be a composite key. |
| 8618 | +** |
| 8619 | +** It is not an error if the named table does not exist in the database. Nor |
| 8620 | +** is it an error if the named table does not have a PRIMARY KEY. However, |
| 8621 | +** no changes will be recorded in either of these scenarios. |
| 8622 | +** |
| 8623 | +** Changes are not recorded for individual rows that have NULL values stored |
| 8624 | +** in one or more of their PRIMARY KEY columns. |
| 8625 | +** |
| 8626 | +** SQLITE_OK is returned if the call completes without error. Or, if an error |
| 8627 | +** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. |
| 8628 | +*/ |
| 8629 | +int sqlite3session_attach( |
| 8630 | + sqlite3_session *pSession, /* Session object */ |
| 8631 | + const char *zTab /* Table name */ |
| 8632 | +); |
| 8633 | + |
| 8634 | +/* |
| 8635 | +** CAPI3REF: Set a table filter on a Session Object. |
| 8636 | +** |
| 8637 | +** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8638 | +** in tables that are not attached to the Session oject, the filter is called |
| 8639 | +** to determine whether changes to the table's rows should be tracked or not. |
| 8640 | +** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8641 | +** attached, xFilter will not be called again. |
| 8642 | +*/ |
| 8643 | +void sqlite3session_table_filter( |
| 8644 | + sqlite3_session *pSession, /* Session object */ |
| 8645 | + int(*xFilter)( |
| 8646 | + void *pCtx, /* Copy of third arg to _filter_table() */ |
| 8647 | + const char *zTab /* Table name */ |
| 8648 | + ), |
| 8649 | + void *pCtx /* First argument passed to xFilter */ |
| 8650 | +); |
| 8651 | + |
| 8652 | +/* |
| 8653 | +** CAPI3REF: Generate A Changeset From A Session Object |
| 8654 | +** |
| 8655 | +** Obtain a changeset containing changes to the tables attached to the |
| 8656 | +** session object passed as the first argument. If successful, |
| 8657 | +** set *ppChangeset to point to a buffer containing the changeset |
| 8658 | +** and *pnChangeset to the size of the changeset in bytes before returning |
| 8659 | +** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to |
| 8660 | +** zero and return an SQLite error code. |
| 8661 | +** |
| 8662 | +** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, |
| 8663 | +** each representing a change to a single row of an attached table. An INSERT |
| 8664 | +** change contains the values of each field of a new database row. A DELETE |
| 8665 | +** contains the original values of each field of a deleted database row. An |
| 8666 | +** UPDATE change contains the original values of each field of an updated |
| 8667 | +** database row along with the updated values for each updated non-primary-key |
| 8668 | +** column. It is not possible for an UPDATE change to represent a change that |
| 8669 | +** modifies the values of primary key columns. If such a change is made, it |
| 8670 | +** is represented in a changeset as a DELETE followed by an INSERT. |
| 8671 | +** |
| 8672 | +** Changes are not recorded for rows that have NULL values stored in one or |
| 8673 | +** more of their PRIMARY KEY columns. If such a row is inserted or deleted, |
| 8674 | +** no corresponding change is present in the changesets returned by this |
| 8675 | +** function. If an existing row with one or more NULL values stored in |
| 8676 | +** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, |
| 8677 | +** only an INSERT is appears in the changeset. Similarly, if an existing row |
| 8678 | +** with non-NULL PRIMARY KEY values is updated so that one or more of its |
| 8679 | +** PRIMARY KEY columns are set to NULL, the resulting changeset contains a |
| 8680 | +** DELETE change only. |
| 8681 | +** |
| 8682 | +** The contents of a changeset may be traversed using an iterator created |
| 8683 | +** using the [sqlite3changeset_start()] API. A changeset may be applied to |
| 8684 | +** a database with a compatible schema using the [sqlite3changeset_apply()] |
| 8685 | +** API. |
| 8686 | +** |
| 8687 | +** Within a changeset generated by this function, all changes related to a |
| 8688 | +** single table are grouped together. In other words, when iterating through |
| 8689 | +** a changeset or when applying a changeset to a database, all changes related |
| 8690 | +** to a single table are processed before moving on to the next table. Tables |
| 8691 | +** are sorted in the same order in which they were attached (or auto-attached) |
| 8692 | +** to the sqlite3_session object. The order in which the changes related to |
| 8693 | +** a single table are stored is undefined. |
| 8694 | +** |
| 8695 | +** Following a successful call to this function, it is the responsibility of |
| 8696 | +** the caller to eventually free the buffer that *ppChangeset points to using |
| 8697 | +** [sqlite3_free()]. |
| 8698 | +** |
| 8699 | +** <h3>Changeset Generation</h3> |
| 8700 | +** |
| 8701 | +** Once a table has been attached to a session object, the session object |
| 8702 | +** records the primary key values of all new rows inserted into the table. |
| 8703 | +** It also records the original primary key and other column values of any |
| 8704 | +** deleted or updated rows. For each unique primary key value, data is only |
| 8705 | +** recorded once - the first time a row with said primary key is inserted, |
| 8706 | +** updated or deleted in the lifetime of the session. |
| 8707 | +** |
| 8708 | +** There is one exception to the previous paragraph: when a row is inserted, |
| 8709 | +** updated or deleted, if one or more of its primary key columns contain a |
| 8710 | +** NULL value, no record of the change is made. |
| 8711 | +** |
| 8712 | +** The session object therefore accumulates two types of records - those |
| 8713 | +** that consist of primary key values only (created when the user inserts |
| 8714 | +** a new record) and those that consist of the primary key values and the |
| 8715 | +** original values of other table columns (created when the users deletes |
| 8716 | +** or updates a record). |
| 8717 | +** |
| 8718 | +** When this function is called, the requested changeset is created using |
| 8719 | +** both the accumulated records and the current contents of the database |
| 8720 | +** file. Specifically: |
| 8721 | +** |
| 8722 | +** <ul> |
| 8723 | +** <li> For each record generated by an insert, the database is queried |
| 8724 | +** for a row with a matching primary key. If one is found, an INSERT |
| 8725 | +** change is added to the changeset. If no such row is found, no change |
| 8726 | +** is added to the changeset. |
| 8727 | +** |
| 8728 | +** <li> For each record generated by an update or delete, the database is |
| 8729 | +** queried for a row with a matching primary key. If such a row is |
| 8730 | +** found and one or more of the non-primary key fields have been |
| 8731 | +** modified from their original values, an UPDATE change is added to |
| 8732 | +** the changeset. Or, if no such row is found in the table, a DELETE |
| 8733 | +** change is added to the changeset. If there is a row with a matching |
| 8734 | +** primary key in the database, but all fields contain their original |
| 8735 | +** values, no change is added to the changeset. |
| 8736 | +** </ul> |
| 8737 | +** |
| 8738 | +** This means, amongst other things, that if a row is inserted and then later |
| 8739 | +** deleted while a session object is active, neither the insert nor the delete |
| 8740 | +** will be present in the changeset. Or if a row is deleted and then later a |
| 8741 | +** row with the same primary key values inserted while a session object is |
| 8742 | +** active, the resulting changeset will contain an UPDATE change instead of |
| 8743 | +** a DELETE and an INSERT. |
| 8744 | +** |
| 8745 | +** When a session object is disabled (see the [sqlite3session_enable()] API), |
| 8746 | +** it does not accumulate records when rows are inserted, updated or deleted. |
| 8747 | +** This may appear to have some counter-intuitive effects if a single row |
| 8748 | +** is written to more than once during a session. For example, if a row |
| 8749 | +** is inserted while a session object is enabled, then later deleted while |
| 8750 | +** the same session object is disabled, no INSERT record will appear in the |
| 8751 | +** changeset, even though the delete took place while the session was disabled. |
| 8752 | +** Or, if one field of a row is updated while a session is disabled, and |
| 8753 | +** another field of the same row is updated while the session is enabled, the |
| 8754 | +** resulting changeset will contain an UPDATE change that updates both fields. |
| 8755 | +*/ |
| 8756 | +int sqlite3session_changeset( |
| 8757 | + sqlite3_session *pSession, /* Session object */ |
| 8758 | + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ |
| 8759 | + void **ppChangeset /* OUT: Buffer containing changeset */ |
| 8760 | +); |
| 8761 | + |
| 8762 | +/* |
| 8763 | +** CAPI3REF: Load The Difference Between Tables Into A Session |
| 8764 | +** |
| 8765 | +** If it is not already attached to the session object passed as the first |
| 8766 | +** argument, this function attaches table zTbl in the same manner as the |
| 8767 | +** [sqlite3session_attach()] function. If zTbl does not exist, or if it |
| 8768 | +** does not have a primary key, this function is a no-op (but does not return |
| 8769 | +** an error). |
| 8770 | +** |
| 8771 | +** Argument zFromDb must be the name of a database ("main", "temp" etc.) |
| 8772 | +** attached to the same database handle as the session object that contains |
| 8773 | +** a table compatible with the table attached to the session by this function. |
| 8774 | +** A table is considered compatible if it: |
| 8775 | +** |
| 8776 | +** <ul> |
| 8777 | +** <li> Has the same name, |
| 8778 | +** <li> Has the same set of columns declared in the same order, and |
| 8779 | +** <li> Has the same PRIMARY KEY definition. |
| 8780 | +** </ul> |
| 8781 | +** |
| 8782 | +** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables |
| 8783 | +** are compatible but do not have any PRIMARY KEY columns, it is not an error |
| 8784 | +** but no changes are added to the session object. As with other session |
| 8785 | +** APIs, tables without PRIMARY KEYs are simply ignored. |
| 8786 | +** |
| 8787 | +** This function adds a set of changes to the session object that could be |
| 8788 | +** used to update the table in database zFrom (call this the "from-table") |
| 8789 | +** so that its content is the same as the table attached to the session |
| 8790 | +** object (call this the "to-table"). Specifically: |
| 8791 | +** |
| 8792 | +** <ul> |
| 8793 | +** <li> For each row (primary key) that exists in the to-table but not in |
| 8794 | +** the from-table, an INSERT record is added to the session object. |
| 8795 | +** |
| 8796 | +** <li> For each row (primary key) that exists in the to-table but not in |
| 8797 | +** the from-table, a DELETE record is added to the session object. |
| 8798 | +** |
| 8799 | +** <li> For each row (primary key) that exists in both tables, but features |
| 8800 | +** different in each, an UPDATE record is added to the session. |
| 8801 | +** </ul> |
| 8802 | +** |
| 8803 | +** To clarify, if this function is called and then a changeset constructed |
| 8804 | +** using [sqlite3session_changeset()], then after applying that changeset to |
| 8805 | +** database zFrom the contents of the two compatible tables would be |
| 8806 | +** identical. |
| 8807 | +** |
| 8808 | +** It an error if database zFrom does not exist or does not contain the |
| 8809 | +** required compatible table. |
| 8810 | +** |
| 8811 | +** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite |
| 8812 | +** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg |
| 8813 | +** may be set to point to a buffer containing an English language error |
| 8814 | +** message. It is the responsibility of the caller to free this buffer using |
| 8815 | +** sqlite3_free(). |
| 8816 | +*/ |
| 8817 | +int sqlite3session_diff( |
| 8818 | + sqlite3_session *pSession, |
| 8819 | + const char *zFromDb, |
| 8820 | + const char *zTbl, |
| 8821 | + char **pzErrMsg |
| 8822 | +); |
| 8823 | + |
| 8824 | + |
| 8825 | +/* |
| 8826 | +** CAPI3REF: Generate A Patchset From A Session Object |
| 8827 | +** |
| 8828 | +** The differences between a patchset and a changeset are that: |
| 8829 | +** |
| 8830 | +** <ul> |
| 8831 | +** <li> DELETE records consist of the primary key fields only. The |
| 8832 | +** original values of other fields are omitted. |
| 8833 | +** <li> The original values of any modified fields are omitted from |
| 8834 | +** UPDATE records. |
| 8835 | +** </ul> |
| 8836 | +** |
| 8837 | +** A patchset blob may be used with up to date versions of all |
| 8838 | +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), |
| 8839 | +** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, |
| 8840 | +** attempting to use a patchset blob with old versions of the |
| 8841 | +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. |
| 8842 | +** |
| 8843 | +** Because the non-primary key "old.*" fields are omitted, no |
| 8844 | +** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset |
| 8845 | +** is passed to the sqlite3changeset_apply() API. Other conflict types work |
| 8846 | +** in the same way as for changesets. |
| 8847 | +** |
| 8848 | +** Changes within a patchset are ordered in the same way as for changesets |
| 8849 | +** generated by the sqlite3session_changeset() function (i.e. all changes for |
| 8850 | +** a single table are grouped together, tables appear in the order in which |
| 8851 | +** they were attached to the session object). |
| 8852 | +*/ |
| 8853 | +int sqlite3session_patchset( |
| 8854 | + sqlite3_session *pSession, /* Session object */ |
| 8855 | + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ |
| 8856 | + void **ppPatchset /* OUT: Buffer containing changeset */ |
| 8857 | +); |
| 8858 | + |
| 8859 | +/* |
| 8860 | +** CAPI3REF: Test if a changeset has recorded any changes. |
| 8861 | +** |
| 8862 | +** Return non-zero if no changes to attached tables have been recorded by |
| 8863 | +** the session object passed as the first argument. Otherwise, if one or |
| 8864 | +** more changes have been recorded, return zero. |
| 8865 | +** |
| 8866 | +** Even if this function returns zero, it is possible that calling |
| 8867 | +** [sqlite3session_changeset()] on the session handle may still return a |
| 8868 | +** changeset that contains no changes. This can happen when a row in |
| 8869 | +** an attached table is modified and then later on the original values |
| 8870 | +** are restored. However, if this function returns non-zero, then it is |
| 8871 | +** guaranteed that a call to sqlite3session_changeset() will return a |
| 8872 | +** changeset containing zero changes. |
| 8873 | +*/ |
| 8874 | +int sqlite3session_isempty(sqlite3_session *pSession); |
| 8875 | + |
| 8876 | +/* |
| 8877 | +** CAPI3REF: Create An Iterator To Traverse A Changeset |
| 8878 | +** |
| 8879 | +** Create an iterator used to iterate through the contents of a changeset. |
| 8880 | +** If successful, *pp is set to point to the iterator handle and SQLITE_OK |
| 8881 | +** is returned. Otherwise, if an error occurs, *pp is set to zero and an |
| 8882 | +** SQLite error code is returned. |
| 8883 | +** |
| 8884 | +** The following functions can be used to advance and query a changeset |
| 8885 | +** iterator created by this function: |
| 8886 | +** |
| 8887 | +** <ul> |
| 8888 | +** <li> [sqlite3changeset_next()] |
| 8889 | +** <li> [sqlite3changeset_op()] |
| 8890 | +** <li> [sqlite3changeset_new()] |
| 8891 | +** <li> [sqlite3changeset_old()] |
| 8892 | +** </ul> |
| 8893 | +** |
| 8894 | +** It is the responsibility of the caller to eventually destroy the iterator |
| 8895 | +** by passing it to [sqlite3changeset_finalize()]. The buffer containing the |
| 8896 | +** changeset (pChangeset) must remain valid until after the iterator is |
| 8897 | +** destroyed. |
| 8898 | +** |
| 8899 | +** Assuming the changeset blob was created by one of the |
| 8900 | +** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 8901 | +** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 8902 | +** that apply to a single table are grouped together. This means that when |
| 8903 | +** an application iterates through a changeset using an iterator created by |
| 8904 | +** this function, all changes that relate to a single table are visted |
| 8905 | +** consecutively. There is no chance that the iterator will visit a change |
| 8906 | +** the applies to table X, then one for table Y, and then later on visit |
| 8907 | +** another change for table X. |
| 8908 | +*/ |
| 8909 | +int sqlite3changeset_start( |
| 8910 | + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ |
| 8911 | + int nChangeset, /* Size of changeset blob in bytes */ |
| 8912 | + void *pChangeset /* Pointer to blob containing changeset */ |
| 8913 | +); |
| 8914 | + |
| 8915 | + |
| 8916 | +/* |
| 8917 | +** CAPI3REF: Advance A Changeset Iterator |
| 8918 | +** |
| 8919 | +** This function may only be used with iterators created by function |
| 8920 | +** [sqlite3changeset_start()]. If it is called on an iterator passed to |
| 8921 | +** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE |
| 8922 | +** is returned and the call has no effect. |
| 8923 | +** |
| 8924 | +** Immediately after an iterator is created by sqlite3changeset_start(), it |
| 8925 | +** does not point to any change in the changeset. Assuming the changeset |
| 8926 | +** is not empty, the first call to this function advances the iterator to |
| 8927 | +** point to the first change in the changeset. Each subsequent call advances |
| 8928 | +** the iterator to point to the next change in the changeset (if any). If |
| 8929 | +** no error occurs and the iterator points to a valid change after a call |
| 8930 | +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. |
| 8931 | +** Otherwise, if all changes in the changeset have already been visited, |
| 8932 | +** SQLITE_DONE is returned. |
| 8933 | +** |
| 8934 | +** If an error occurs, an SQLite error code is returned. Possible error |
| 8935 | +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or |
| 8936 | +** SQLITE_NOMEM. |
| 8937 | +*/ |
| 8938 | +int sqlite3changeset_next(sqlite3_changeset_iter *pIter); |
| 8939 | + |
| 8940 | +/* |
| 8941 | +** CAPI3REF: Obtain The Current Operation From A Changeset Iterator |
| 8942 | +** |
| 8943 | +** The pIter argument passed to this function may either be an iterator |
| 8944 | +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator |
| 8945 | +** created by [sqlite3changeset_start()]. In the latter case, the most recent |
| 8946 | +** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this |
| 8947 | +** is not the case, this function returns [SQLITE_MISUSE]. |
| 8948 | +** |
| 8949 | +** If argument pzTab is not NULL, then *pzTab is set to point to a |
| 8950 | +** nul-terminated utf-8 encoded string containing the name of the table |
| 8951 | +** affected by the current change. The buffer remains valid until either |
| 8952 | +** sqlite3changeset_next() is called on the iterator or until the |
| 8953 | +** conflict-handler function returns. If pnCol is not NULL, then *pnCol is |
| 8954 | +** set to the number of columns in the table affected by the change. If |
| 8955 | +** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change |
| 8956 | +** is an indirect change, or false (0) otherwise. See the documentation for |
| 8957 | +** [sqlite3session_indirect()] for a description of direct and indirect |
| 8958 | +** changes. Finally, if pOp is not NULL, then *pOp is set to one of |
| 8959 | +** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the |
| 8960 | +** type of change that the iterator currently points to. |
| 8961 | +** |
| 8962 | +** If no error occurs, SQLITE_OK is returned. If an error does occur, an |
| 8963 | +** SQLite error code is returned. The values of the output variables may not |
| 8964 | +** be trusted in this case. |
| 8965 | +*/ |
| 8966 | +int sqlite3changeset_op( |
| 8967 | + sqlite3_changeset_iter *pIter, /* Iterator object */ |
| 8968 | + const char **pzTab, /* OUT: Pointer to table name */ |
| 8969 | + int *pnCol, /* OUT: Number of columns in table */ |
| 8970 | + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ |
| 8971 | + int *pbIndirect /* OUT: True for an 'indirect' change */ |
| 8972 | +); |
| 8973 | + |
| 8974 | +/* |
| 8975 | +** CAPI3REF: Obtain The Primary Key Definition Of A Table |
| 8976 | +** |
| 8977 | +** For each modified table, a changeset includes the following: |
| 8978 | +** |
| 8979 | +** <ul> |
| 8980 | +** <li> The number of columns in the table, and |
| 8981 | +** <li> Which of those columns make up the tables PRIMARY KEY. |
| 8982 | +** </ul> |
| 8983 | +** |
| 8984 | +** This function is used to find which columns comprise the PRIMARY KEY of |
| 8985 | +** the table modified by the change that iterator pIter currently points to. |
| 8986 | +** If successful, *pabPK is set to point to an array of nCol entries, where |
| 8987 | +** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 8988 | +** 0x01 if the corresponding column is part of the tables primary key, or |
| 8989 | +** 0x00 if it is not. |
| 8990 | +** |
| 8991 | +** If argumet pnCol is not NULL, then *pnCol is set to the number of columns |
| 8992 | +** in the table. |
| 8993 | +** |
| 8994 | +** If this function is called when the iterator does not point to a valid |
| 8995 | +** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 8996 | +** SQLITE_OK is returned and the output variables populated as described |
| 8997 | +** above. |
| 8998 | +*/ |
| 8999 | +int sqlite3changeset_pk( |
| 9000 | + sqlite3_changeset_iter *pIter, /* Iterator object */ |
| 9001 | + unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ |
| 9002 | + int *pnCol /* OUT: Number of entries in output array */ |
| 9003 | +); |
| 9004 | + |
| 9005 | +/* |
| 9006 | +** CAPI3REF: Obtain old.* Values From A Changeset Iterator |
| 9007 | +** |
| 9008 | +** The pIter argument passed to this function may either be an iterator |
| 9009 | +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator |
| 9010 | +** created by [sqlite3changeset_start()]. In the latter case, the most recent |
| 9011 | +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. |
| 9012 | +** Furthermore, it may only be called if the type of change that the iterator |
| 9013 | +** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, |
| 9014 | +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. |
| 9015 | +** |
| 9016 | +** Argument iVal must be greater than or equal to 0, and less than the number |
| 9017 | +** of columns in the table affected by the current change. Otherwise, |
| 9018 | +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. |
| 9019 | +** |
| 9020 | +** If successful, this function sets *ppValue to point to a protected |
| 9021 | +** sqlite3_value object containing the iVal'th value from the vector of |
| 9022 | +** original row values stored as part of the UPDATE or DELETE change and |
| 9023 | +** returns SQLITE_OK. The name of the function comes from the fact that this |
| 9024 | +** is similar to the "old.*" columns available to update or delete triggers. |
| 9025 | +** |
| 9026 | +** If some other error occurs (e.g. an OOM condition), an SQLite error code |
| 9027 | +** is returned and *ppValue is set to NULL. |
| 9028 | +*/ |
| 9029 | +int sqlite3changeset_old( |
| 9030 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 9031 | + int iVal, /* Column number */ |
| 9032 | + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ |
| 9033 | +); |
| 9034 | + |
| 9035 | +/* |
| 9036 | +** CAPI3REF: Obtain new.* Values From A Changeset Iterator |
| 9037 | +** |
| 9038 | +** The pIter argument passed to this function may either be an iterator |
| 9039 | +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator |
| 9040 | +** created by [sqlite3changeset_start()]. In the latter case, the most recent |
| 9041 | +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. |
| 9042 | +** Furthermore, it may only be called if the type of change that the iterator |
| 9043 | +** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, |
| 9044 | +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. |
| 9045 | +** |
| 9046 | +** Argument iVal must be greater than or equal to 0, and less than the number |
| 9047 | +** of columns in the table affected by the current change. Otherwise, |
| 9048 | +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. |
| 9049 | +** |
| 9050 | +** If successful, this function sets *ppValue to point to a protected |
| 9051 | +** sqlite3_value object containing the iVal'th value from the vector of |
| 9052 | +** new row values stored as part of the UPDATE or INSERT change and |
| 9053 | +** returns SQLITE_OK. If the change is an UPDATE and does not include |
| 9054 | +** a new value for the requested column, *ppValue is set to NULL and |
| 9055 | +** SQLITE_OK returned. The name of the function comes from the fact that |
| 9056 | +** this is similar to the "new.*" columns available to update or delete |
| 9057 | +** triggers. |
| 9058 | +** |
| 9059 | +** If some other error occurs (e.g. an OOM condition), an SQLite error code |
| 9060 | +** is returned and *ppValue is set to NULL. |
| 9061 | +*/ |
| 9062 | +int sqlite3changeset_new( |
| 9063 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 9064 | + int iVal, /* Column number */ |
| 9065 | + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ |
| 9066 | +); |
| 9067 | + |
| 9068 | +/* |
| 9069 | +** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator |
| 9070 | +** |
| 9071 | +** This function should only be used with iterator objects passed to a |
| 9072 | +** conflict-handler callback by [sqlite3changeset_apply()] with either |
| 9073 | +** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function |
| 9074 | +** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue |
| 9075 | +** is set to NULL. |
| 9076 | +** |
| 9077 | +** Argument iVal must be greater than or equal to 0, and less than the number |
| 9078 | +** of columns in the table affected by the current change. Otherwise, |
| 9079 | +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. |
| 9080 | +** |
| 9081 | +** If successful, this function sets *ppValue to point to a protected |
| 9082 | +** sqlite3_value object containing the iVal'th value from the |
| 9083 | +** "conflicting row" associated with the current conflict-handler callback |
| 9084 | +** and returns SQLITE_OK. |
| 9085 | +** |
| 9086 | +** If some other error occurs (e.g. an OOM condition), an SQLite error code |
| 9087 | +** is returned and *ppValue is set to NULL. |
| 9088 | +*/ |
| 9089 | +int sqlite3changeset_conflict( |
| 9090 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 9091 | + int iVal, /* Column number */ |
| 9092 | + sqlite3_value **ppValue /* OUT: Value from conflicting row */ |
| 9093 | +); |
| 9094 | + |
| 9095 | +/* |
| 9096 | +** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations |
| 9097 | +** |
| 9098 | +** This function may only be called with an iterator passed to an |
| 9099 | +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case |
| 9100 | +** it sets the output variable to the total number of known foreign key |
| 9101 | +** violations in the destination database and returns SQLITE_OK. |
| 9102 | +** |
| 9103 | +** In all other cases this function returns SQLITE_MISUSE. |
| 9104 | +*/ |
| 9105 | +int sqlite3changeset_fk_conflicts( |
| 9106 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 9107 | + int *pnOut /* OUT: Number of FK violations */ |
| 9108 | +); |
| 9109 | + |
| 9110 | + |
| 9111 | +/* |
| 9112 | +** CAPI3REF: Finalize A Changeset Iterator |
| 9113 | +** |
| 9114 | +** This function is used to finalize an iterator allocated with |
| 9115 | +** [sqlite3changeset_start()]. |
| 9116 | +** |
| 9117 | +** This function should only be called on iterators created using the |
| 9118 | +** [sqlite3changeset_start()] function. If an application calls this |
| 9119 | +** function with an iterator passed to a conflict-handler by |
| 9120 | +** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the |
| 9121 | +** call has no effect. |
| 9122 | +** |
| 9123 | +** If an error was encountered within a call to an sqlite3changeset_xxx() |
| 9124 | +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an |
| 9125 | +** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding |
| 9126 | +** to that error is returned by this function. Otherwise, SQLITE_OK is |
| 9127 | +** returned. This is to allow the following pattern (pseudo-code): |
| 9128 | +** |
| 9129 | +** sqlite3changeset_start(); |
| 9130 | +** while( SQLITE_ROW==sqlite3changeset_next() ){ |
| 9131 | +** // Do something with change. |
| 9132 | +** } |
| 9133 | +** rc = sqlite3changeset_finalize(); |
| 9134 | +** if( rc!=SQLITE_OK ){ |
| 9135 | +** // An error has occurred |
| 9136 | +** } |
| 9137 | +*/ |
| 9138 | +int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); |
| 9139 | + |
| 9140 | +/* |
| 9141 | +** CAPI3REF: Invert A Changeset |
| 9142 | +** |
| 9143 | +** This function is used to "invert" a changeset object. Applying an inverted |
| 9144 | +** changeset to a database reverses the effects of applying the uninverted |
| 9145 | +** changeset. Specifically: |
| 9146 | +** |
| 9147 | +** <ul> |
| 9148 | +** <li> Each DELETE change is changed to an INSERT, and |
| 9149 | +** <li> Each INSERT change is changed to a DELETE, and |
| 9150 | +** <li> For each UPDATE change, the old.* and new.* values are exchanged. |
| 9151 | +** </ul> |
| 9152 | +** |
| 9153 | +** This function does not change the order in which changes appear within |
| 9154 | +** the changeset. It merely reverses the sense of each individual change. |
| 9155 | +** |
| 9156 | +** If successful, a pointer to a buffer containing the inverted changeset |
| 9157 | +** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and |
| 9158 | +** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are |
| 9159 | +** zeroed and an SQLite error code returned. |
| 9160 | +** |
| 9161 | +** It is the responsibility of the caller to eventually call sqlite3_free() |
| 9162 | +** on the *ppOut pointer to free the buffer allocation following a successful |
| 9163 | +** call to this function. |
| 9164 | +** |
| 9165 | +** WARNING/TODO: This function currently assumes that the input is a valid |
| 9166 | +** changeset. If it is not, the results are undefined. |
| 9167 | +*/ |
| 9168 | +int sqlite3changeset_invert( |
| 9169 | + int nIn, const void *pIn, /* Input changeset */ |
| 9170 | + int *pnOut, void **ppOut /* OUT: Inverse of input */ |
| 9171 | +); |
| 9172 | + |
| 9173 | +/* |
| 9174 | +** CAPI3REF: Concatenate Two Changeset Objects |
| 9175 | +** |
| 9176 | +** This function is used to concatenate two changesets, A and B, into a |
| 9177 | +** single changeset. The result is a changeset equivalent to applying |
| 9178 | +** changeset A followed by changeset B. |
| 9179 | +** |
| 9180 | +** This function combines the two input changesets using an |
| 9181 | +** sqlite3_changegroup object. Calling it produces similar results as the |
| 9182 | +** following code fragment: |
| 9183 | +** |
| 9184 | +** sqlite3_changegroup *pGrp; |
| 9185 | +** rc = sqlite3_changegroup_new(&pGrp); |
| 9186 | +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA); |
| 9187 | +** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB); |
| 9188 | +** if( rc==SQLITE_OK ){ |
| 9189 | +** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); |
| 9190 | +** }else{ |
| 9191 | +** *ppOut = 0; |
| 9192 | +** *pnOut = 0; |
| 9193 | +** } |
| 9194 | +** |
| 9195 | +** Refer to the sqlite3_changegroup documentation below for details. |
| 9196 | +*/ |
| 9197 | +int sqlite3changeset_concat( |
| 9198 | + int nA, /* Number of bytes in buffer pA */ |
| 9199 | + void *pA, /* Pointer to buffer containing changeset A */ |
| 9200 | + int nB, /* Number of bytes in buffer pB */ |
| 9201 | + void *pB, /* Pointer to buffer containing changeset B */ |
| 9202 | + int *pnOut, /* OUT: Number of bytes in output changeset */ |
| 9203 | + void **ppOut /* OUT: Buffer containing output changeset */ |
| 9204 | +); |
| 9205 | + |
| 9206 | + |
| 9207 | +/* |
| 9208 | +** Changegroup handle. |
| 9209 | +*/ |
| 9210 | +typedef struct sqlite3_changegroup sqlite3_changegroup; |
| 9211 | + |
| 9212 | +/* |
| 9213 | +** CAPI3REF: Combine two or more changesets into a single changeset. |
| 9214 | +** |
| 9215 | +** An sqlite3_changegroup object is used to combine two or more changesets |
| 9216 | +** (or patchsets) into a single changeset (or patchset). A single changegroup |
| 9217 | +** object may combine changesets or patchsets, but not both. The output is |
| 9218 | +** always in the same format as the input. |
| 9219 | +** |
| 9220 | +** If successful, this function returns SQLITE_OK and populates (*pp) with |
| 9221 | +** a pointer to a new sqlite3_changegroup object before returning. The caller |
| 9222 | +** should eventually free the returned object using a call to |
| 9223 | +** sqlite3changegroup_delete(). If an error occurs, an SQLite error code |
| 9224 | +** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. |
| 9225 | +** |
| 9226 | +** The usual usage pattern for an sqlite3_changegroup object is as follows: |
| 9227 | +** |
| 9228 | +** <ul> |
| 9229 | +** <li> It is created using a call to sqlite3changegroup_new(). |
| 9230 | +** |
| 9231 | +** <li> Zero or more changesets (or patchsets) are added to the object |
| 9232 | +** by calling sqlite3changegroup_add(). |
| 9233 | +** |
| 9234 | +** <li> The result of combining all input changesets together is obtained |
| 9235 | +** by the application via a call to sqlite3changegroup_output(). |
| 9236 | +** |
| 9237 | +** <li> The object is deleted using a call to sqlite3changegroup_delete(). |
| 9238 | +** </ul> |
| 9239 | +** |
| 9240 | +** Any number of calls to add() and output() may be made between the calls to |
| 9241 | +** new() and delete(), and in any order. |
| 9242 | +** |
| 9243 | +** As well as the regular sqlite3changegroup_add() and |
| 9244 | +** sqlite3changegroup_output() functions, also available are the streaming |
| 9245 | +** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). |
| 9246 | +*/ |
| 9247 | +int sqlite3changegroup_new(sqlite3_changegroup **pp); |
| 9248 | + |
| 9249 | +/* |
| 9250 | +** Add all changes within the changeset (or patchset) in buffer pData (size |
| 9251 | +** nData bytes) to the changegroup. |
| 9252 | +** |
| 9253 | +** If the buffer contains a patchset, then all prior calls to this function |
| 9254 | +** on the same changegroup object must also have specified patchsets. Or, if |
| 9255 | +** the buffer contains a changeset, so must have the earlier calls to this |
| 9256 | +** function. Otherwise, SQLITE_ERROR is returned and no changes are added |
| 9257 | +** to the changegroup. |
| 9258 | +** |
| 9259 | +** Rows within the changeset and changegroup are identified by the values in |
| 9260 | +** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9261 | +** apply to the same row as a change already present in the changegroup if |
| 9262 | +** the two rows have the same primary key. |
| 9263 | +** |
| 9264 | +** Changes to rows that that do not already appear in the changegroup are |
| 9265 | +** simply copied into it. Or, if both the new changeset and the changegroup |
| 9266 | +** contain changes that apply to a single row, the final contents of the |
| 9267 | +** changegroup depends on the type of each change, as follows: |
| 9268 | +** |
| 9269 | +** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| 9270 | +** <tr><th style="white-space:pre">Existing Change </th> |
| 9271 | +** <th style="white-space:pre">New Change </th> |
| 9272 | +** <th>Output Change |
| 9273 | +** <tr><td>INSERT <td>INSERT <td> |
| 9274 | +** The new change is ignored. This case does not occur if the new |
| 9275 | +** changeset was recorded immediately after the changesets already |
| 9276 | +** added to the changegroup. |
| 9277 | +** <tr><td>INSERT <td>UPDATE <td> |
| 9278 | +** The INSERT change remains in the changegroup. The values in the |
| 9279 | +** INSERT change are modified as if the row was inserted by the |
| 9280 | +** existing change and then updated according to the new change. |
| 9281 | +** <tr><td>INSERT <td>DELETE <td> |
| 9282 | +** The existing INSERT is removed from the changegroup. The DELETE is |
| 9283 | +** not added. |
| 9284 | +** <tr><td>UPDATE <td>INSERT <td> |
| 9285 | +** The new change is ignored. This case does not occur if the new |
| 9286 | +** changeset was recorded immediately after the changesets already |
| 9287 | +** added to the changegroup. |
| 9288 | +** <tr><td>UPDATE <td>UPDATE <td> |
| 9289 | +** The existing UPDATE remains within the changegroup. It is amended |
| 9290 | +** so that the accompanying values are as if the row was updated once |
| 9291 | +** by the existing change and then again by the new change. |
| 9292 | +** <tr><td>UPDATE <td>DELETE <td> |
| 9293 | +** The existing UPDATE is replaced by the new DELETE within the |
| 9294 | +** changegroup. |
| 9295 | +** <tr><td>DELETE <td>INSERT <td> |
| 9296 | +** If one or more of the column values in the row inserted by the |
| 9297 | +** new change differ from those in the row deleted by the existing |
| 9298 | +** change, the existing DELETE is replaced by an UPDATE within the |
| 9299 | +** changegroup. Otherwise, if the inserted row is exactly the same |
| 9300 | +** as the deleted row, the existing DELETE is simply discarded. |
| 9301 | +** <tr><td>DELETE <td>UPDATE <td> |
| 9302 | +** The new change is ignored. This case does not occur if the new |
| 9303 | +** changeset was recorded immediately after the changesets already |
| 9304 | +** added to the changegroup. |
| 9305 | +** <tr><td>DELETE <td>DELETE <td> |
| 9306 | +** The new change is ignored. This case does not occur if the new |
| 9307 | +** changeset was recorded immediately after the changesets already |
| 9308 | +** added to the changegroup. |
| 9309 | +** </table> |
| 9310 | +** |
| 9311 | +** If the new changeset contains changes to a table that is already present |
| 9312 | +** in the changegroup, then the number of columns and the position of the |
| 9313 | +** primary key columns for the table must be consistent. If this is not the |
| 9314 | +** case, this function fails with SQLITE_SCHEMA. If the input changeset |
| 9315 | +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is |
| 9316 | +** returned. Or, if an out-of-memory condition occurs during processing, this |
| 9317 | +** function returns SQLITE_NOMEM. In all cases, if an error occurs the |
| 9318 | +** final contents of the changegroup is undefined. |
| 9319 | +** |
| 9320 | +** If no error occurs, SQLITE_OK is returned. |
| 9321 | +*/ |
| 9322 | +int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); |
| 9323 | + |
| 9324 | +/* |
| 9325 | +** Obtain a buffer containing a changeset (or patchset) representing the |
| 9326 | +** current contents of the changegroup. If the inputs to the changegroup |
| 9327 | +** were themselves changesets, the output is a changeset. Or, if the |
| 9328 | +** inputs were patchsets, the output is also a patchset. |
| 9329 | +** |
| 9330 | +** As with the output of the sqlite3session_changeset() and |
| 9331 | +** sqlite3session_patchset() functions, all changes related to a single |
| 9332 | +** table are grouped together in the output of this function. Tables appear |
| 9333 | +** in the same order as for the very first changeset added to the changegroup. |
| 9334 | +** If the second or subsequent changesets added to the changegroup contain |
| 9335 | +** changes for tables that do not appear in the first changeset, they are |
| 9336 | +** appended onto the end of the output changeset, again in the order in |
| 9337 | +** which they are first encountered. |
| 9338 | +** |
| 9339 | +** If an error occurs, an SQLite error code is returned and the output |
| 9340 | +** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK |
| 9341 | +** is returned and the output variables are set to the size of and a |
| 9342 | +** pointer to the output buffer, respectively. In this case it is the |
| 9343 | +** responsibility of the caller to eventually free the buffer using a |
| 9344 | +** call to sqlite3_free(). |
| 9345 | +*/ |
| 9346 | +int sqlite3changegroup_output( |
| 9347 | + sqlite3_changegroup*, |
| 9348 | + int *pnData, /* OUT: Size of output buffer in bytes */ |
| 9349 | + void **ppData /* OUT: Pointer to output buffer */ |
| 9350 | +); |
| 9351 | + |
| 9352 | +/* |
| 9353 | +** Delete a changegroup object. |
| 9354 | +*/ |
| 9355 | +void sqlite3changegroup_delete(sqlite3_changegroup*); |
| 9356 | + |
| 9357 | +/* |
| 9358 | +** CAPI3REF: Apply A Changeset To A Database |
| 9359 | +** |
| 9360 | +** Apply a changeset to a database. This function attempts to update the |
| 9361 | +** "main" database attached to handle db with the changes found in the |
| 9362 | +** changeset passed via the second and third arguments. |
| 9363 | +** |
| 9364 | +** The fourth argument (xFilter) passed to this function is the "filter |
| 9365 | +** callback". If it is not NULL, then for each table affected by at least one |
| 9366 | +** change in the changeset, the filter callback is invoked with |
| 9367 | +** the table name as the second argument, and a copy of the context pointer |
| 9368 | +** passed as the sixth argument to this function as the first. If the "filter |
| 9369 | +** callback" returns zero, then no attempt is made to apply any changes to |
| 9370 | +** the table. Otherwise, if the return value is non-zero or the xFilter |
| 9371 | +** argument to this function is NULL, all changes related to the table are |
| 9372 | +** attempted. |
| 9373 | +** |
| 9374 | +** For each table that is not excluded by the filter callback, this function |
| 9375 | +** tests that the target database contains a compatible table. A table is |
| 9376 | +** considered compatible if all of the following are true: |
| 9377 | +** |
| 9378 | +** <ul> |
| 9379 | +** <li> The table has the same name as the name recorded in the |
| 9380 | +** changeset, and |
| 9381 | +** <li> The table has the same number of columns as recorded in the |
| 9382 | +** changeset, and |
| 9383 | +** <li> The table has primary key columns in the same position as |
| 9384 | +** recorded in the changeset. |
| 9385 | +** </ul> |
| 9386 | +** |
| 9387 | +** If there is no compatible table, it is not an error, but none of the |
| 9388 | +** changes associated with the table are applied. A warning message is issued |
| 9389 | +** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most |
| 9390 | +** one such warning is issued for each table in the changeset. |
| 9391 | +** |
| 9392 | +** For each change for which there is a compatible table, an attempt is made |
| 9393 | +** to modify the table contents according to the UPDATE, INSERT or DELETE |
| 9394 | +** change. If a change cannot be applied cleanly, the conflict handler |
| 9395 | +** function passed as the fifth argument to sqlite3changeset_apply() may be |
| 9396 | +** invoked. A description of exactly when the conflict handler is invoked for |
| 9397 | +** each type of change is below. |
| 9398 | +** |
| 9399 | +** Unlike the xFilter argument, xConflict may not be passed NULL. The results |
| 9400 | +** of passing anything other than a valid function pointer as the xConflict |
| 9401 | +** argument are undefined. |
| 9402 | +** |
| 9403 | +** Each time the conflict handler function is invoked, it must return one |
| 9404 | +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or |
| 9405 | +** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned |
| 9406 | +** if the second argument passed to the conflict handler is either |
| 9407 | +** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler |
| 9408 | +** returns an illegal value, any changes already made are rolled back and |
| 9409 | +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different |
| 9410 | +** actions are taken by sqlite3changeset_apply() depending on the value |
| 9411 | +** returned by each invocation of the conflict-handler function. Refer to |
| 9412 | +** the documentation for the three |
| 9413 | +** [SQLITE_CHANGESET_OMIT|available return values] for details. |
| 9414 | +** |
| 9415 | +** <dl> |
| 9416 | +** <dt>DELETE Changes<dd> |
| 9417 | +** For each DELETE change, this function checks if the target database |
| 9418 | +** contains a row with the same primary key value (or values) as the |
| 9419 | +** original row values stored in the changeset. If it does, and the values |
| 9420 | +** stored in all non-primary key columns also match the values stored in |
| 9421 | +** the changeset the row is deleted from the target database. |
| 9422 | +** |
| 9423 | +** If a row with matching primary key values is found, but one or more of |
| 9424 | +** the non-primary key fields contains a value different from the original |
| 9425 | +** row value stored in the changeset, the conflict-handler function is |
| 9426 | +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. |
| 9427 | +** |
| 9428 | +** If no row with matching primary key values is found in the database, |
| 9429 | +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] |
| 9430 | +** passed as the second argument. |
| 9431 | +** |
| 9432 | +** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT |
| 9433 | +** (which can only happen if a foreign key constraint is violated), the |
| 9434 | +** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT] |
| 9435 | +** passed as the second argument. This includes the case where the DELETE |
| 9436 | +** operation is attempted because an earlier call to the conflict handler |
| 9437 | +** function returned [SQLITE_CHANGESET_REPLACE]. |
| 9438 | +** |
| 9439 | +** <dt>INSERT Changes<dd> |
| 9440 | +** For each INSERT change, an attempt is made to insert the new row into |
| 9441 | +** the database. |
| 9442 | +** |
| 9443 | +** If the attempt to insert the row fails because the database already |
| 9444 | +** contains a row with the same primary key values, the conflict handler |
| 9445 | +** function is invoked with the second argument set to |
| 9446 | +** [SQLITE_CHANGESET_CONFLICT]. |
| 9447 | +** |
| 9448 | +** If the attempt to insert the row fails because of some other constraint |
| 9449 | +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is |
| 9450 | +** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. |
| 9451 | +** This includes the case where the INSERT operation is re-attempted because |
| 9452 | +** an earlier call to the conflict handler function returned |
| 9453 | +** [SQLITE_CHANGESET_REPLACE]. |
| 9454 | +** |
| 9455 | +** <dt>UPDATE Changes<dd> |
| 9456 | +** For each UPDATE change, this function checks if the target database |
| 9457 | +** contains a row with the same primary key value (or values) as the |
| 9458 | +** original row values stored in the changeset. If it does, and the values |
| 9459 | +** stored in all non-primary key columns also match the values stored in |
| 9460 | +** the changeset the row is updated within the target database. |
| 9461 | +** |
| 9462 | +** If a row with matching primary key values is found, but one or more of |
| 9463 | +** the non-primary key fields contains a value different from an original |
| 9464 | +** row value stored in the changeset, the conflict-handler function is |
| 9465 | +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since |
| 9466 | +** UPDATE changes only contain values for non-primary key fields that are |
| 9467 | +** to be modified, only those fields need to match the original values to |
| 9468 | +** avoid the SQLITE_CHANGESET_DATA conflict-handler callback. |
| 9469 | +** |
| 9470 | +** If no row with matching primary key values is found in the database, |
| 9471 | +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] |
| 9472 | +** passed as the second argument. |
| 9473 | +** |
| 9474 | +** If the UPDATE operation is attempted, but SQLite returns |
| 9475 | +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with |
| 9476 | +** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. |
| 9477 | +** This includes the case where the UPDATE operation is attempted after |
| 9478 | +** an earlier call to the conflict handler function returned |
| 9479 | +** [SQLITE_CHANGESET_REPLACE]. |
| 9480 | +** </dl> |
| 9481 | +** |
| 9482 | +** It is safe to execute SQL statements, including those that write to the |
| 9483 | +** table that the callback related to, from within the xConflict callback. |
| 9484 | +** This can be used to further customize the applications conflict |
| 9485 | +** resolution strategy. |
| 9486 | +** |
| 9487 | +** All changes made by this function are enclosed in a savepoint transaction. |
| 9488 | +** If any other error (aside from a constraint failure when attempting to |
| 9489 | +** write to the target database) occurs, then the savepoint transaction is |
| 9490 | +** rolled back, restoring the target database to its original state, and an |
| 9491 | +** SQLite error code returned. |
| 9492 | +*/ |
| 9493 | +int sqlite3changeset_apply( |
| 9494 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 9495 | + int nChangeset, /* Size of changeset in bytes */ |
| 9496 | + void *pChangeset, /* Changeset blob */ |
| 9497 | + int(*xFilter)( |
| 9498 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 9499 | + const char *zTab /* Table name */ |
| 9500 | + ), |
| 9501 | + int(*xConflict)( |
| 9502 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 9503 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 9504 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 9505 | + ), |
| 9506 | + void *pCtx /* First argument passed to xConflict */ |
| 9507 | +); |
| 9508 | + |
| 9509 | +/* |
| 9510 | +** CAPI3REF: Constants Passed To The Conflict Handler |
| 9511 | +** |
| 9512 | +** Values that may be passed as the second argument to a conflict-handler. |
| 9513 | +** |
| 9514 | +** <dl> |
| 9515 | +** <dt>SQLITE_CHANGESET_DATA<dd> |
| 9516 | +** The conflict handler is invoked with CHANGESET_DATA as the second argument |
| 9517 | +** when processing a DELETE or UPDATE change if a row with the required |
| 9518 | +** PRIMARY KEY fields is present in the database, but one or more other |
| 9519 | +** (non primary-key) fields modified by the update do not contain the |
| 9520 | +** expected "before" values. |
| 9521 | +** |
| 9522 | +** The conflicting row, in this case, is the database row with the matching |
| 9523 | +** primary key. |
| 9524 | +** |
| 9525 | +** <dt>SQLITE_CHANGESET_NOTFOUND<dd> |
| 9526 | +** The conflict handler is invoked with CHANGESET_NOTFOUND as the second |
| 9527 | +** argument when processing a DELETE or UPDATE change if a row with the |
| 9528 | +** required PRIMARY KEY fields is not present in the database. |
| 9529 | +** |
| 9530 | +** There is no conflicting row in this case. The results of invoking the |
| 9531 | +** sqlite3changeset_conflict() API are undefined. |
| 9532 | +** |
| 9533 | +** <dt>SQLITE_CHANGESET_CONFLICT<dd> |
| 9534 | +** CHANGESET_CONFLICT is passed as the second argument to the conflict |
| 9535 | +** handler while processing an INSERT change if the operation would result |
| 9536 | +** in duplicate primary key values. |
| 9537 | +** |
| 9538 | +** The conflicting row in this case is the database row with the matching |
| 9539 | +** primary key. |
| 9540 | +** |
| 9541 | +** <dt>SQLITE_CHANGESET_FOREIGN_KEY<dd> |
| 9542 | +** If foreign key handling is enabled, and applying a changeset leaves the |
| 9543 | +** database in a state containing foreign key violations, the conflict |
| 9544 | +** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument |
| 9545 | +** exactly once before the changeset is committed. If the conflict handler |
| 9546 | +** returns CHANGESET_OMIT, the changes, including those that caused the |
| 9547 | +** foreign key constraint violation, are committed. Or, if it returns |
| 9548 | +** CHANGESET_ABORT, the changeset is rolled back. |
| 9549 | +** |
| 9550 | +** No current or conflicting row information is provided. The only function |
| 9551 | +** it is possible to call on the supplied sqlite3_changeset_iter handle |
| 9552 | +** is sqlite3changeset_fk_conflicts(). |
| 9553 | +** |
| 9554 | +** <dt>SQLITE_CHANGESET_CONSTRAINT<dd> |
| 9555 | +** If any other constraint violation occurs while applying a change (i.e. |
| 9556 | +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is |
| 9557 | +** invoked with CHANGESET_CONSTRAINT as the second argument. |
| 9558 | +** |
| 9559 | +** There is no conflicting row in this case. The results of invoking the |
| 9560 | +** sqlite3changeset_conflict() API are undefined. |
| 9561 | +** |
| 9562 | +** </dl> |
| 9563 | +*/ |
| 9564 | +#define SQLITE_CHANGESET_DATA 1 |
| 9565 | +#define SQLITE_CHANGESET_NOTFOUND 2 |
| 9566 | +#define SQLITE_CHANGESET_CONFLICT 3 |
| 9567 | +#define SQLITE_CHANGESET_CONSTRAINT 4 |
| 9568 | +#define SQLITE_CHANGESET_FOREIGN_KEY 5 |
| 9569 | + |
| 9570 | +/* |
| 9571 | +** CAPI3REF: Constants Returned By The Conflict Handler |
| 9572 | +** |
| 9573 | +** A conflict handler callback must return one of the following three values. |
| 9574 | +** |
| 9575 | +** <dl> |
| 9576 | +** <dt>SQLITE_CHANGESET_OMIT<dd> |
| 9577 | +** If a conflict handler returns this value no special action is taken. The |
| 9578 | +** change that caused the conflict is not applied. The session module |
| 9579 | +** continues to the next change in the changeset. |
| 9580 | +** |
| 9581 | +** <dt>SQLITE_CHANGESET_REPLACE<dd> |
| 9582 | +** This value may only be returned if the second argument to the conflict |
| 9583 | +** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this |
| 9584 | +** is not the case, any changes applied so far are rolled back and the |
| 9585 | +** call to sqlite3changeset_apply() returns SQLITE_MISUSE. |
| 9586 | +** |
| 9587 | +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict |
| 9588 | +** handler, then the conflicting row is either updated or deleted, depending |
| 9589 | +** on the type of change. |
| 9590 | +** |
| 9591 | +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict |
| 9592 | +** handler, then the conflicting row is removed from the database and a |
| 9593 | +** second attempt to apply the change is made. If this second attempt fails, |
| 9594 | +** the original row is restored to the database before continuing. |
| 9595 | +** |
| 9596 | +** <dt>SQLITE_CHANGESET_ABORT<dd> |
| 9597 | +** If this value is returned, any changes applied so far are rolled back |
| 9598 | +** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. |
| 9599 | +** </dl> |
| 9600 | +*/ |
| 9601 | +#define SQLITE_CHANGESET_OMIT 0 |
| 9602 | +#define SQLITE_CHANGESET_REPLACE 1 |
| 9603 | +#define SQLITE_CHANGESET_ABORT 2 |
| 9604 | + |
| 9605 | +/* |
| 9606 | +** CAPI3REF: Streaming Versions of API functions. |
| 9607 | +** |
| 9608 | +** The six streaming API xxx_strm() functions serve similar purposes to the |
| 9609 | +** corresponding non-streaming API functions: |
| 9610 | +** |
| 9611 | +** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| 9612 | +** <tr><th>Streaming function<th>Non-streaming equivalent</th> |
| 9613 | +** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply] |
| 9614 | +** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat] |
| 9615 | +** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert] |
| 9616 | +** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start] |
| 9617 | +** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset] |
| 9618 | +** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset] |
| 9619 | +** </table> |
| 9620 | +** |
| 9621 | +** Non-streaming functions that accept changesets (or patchsets) as input |
| 9622 | +** require that the entire changeset be stored in a single buffer in memory. |
| 9623 | +** Similarly, those that return a changeset or patchset do so by returning |
| 9624 | +** a pointer to a single large buffer allocated using sqlite3_malloc(). |
| 9625 | +** Normally this is convenient. However, if an application running in a |
| 9626 | +** low-memory environment is required to handle very large changesets, the |
| 9627 | +** large contiguous memory allocations required can become onerous. |
| 9628 | +** |
| 9629 | +** In order to avoid this problem, instead of a single large buffer, input |
| 9630 | +** is passed to a streaming API functions by way of a callback function that |
| 9631 | +** the sessions module invokes to incrementally request input data as it is |
| 9632 | +** required. In all cases, a pair of API function parameters such as |
| 9633 | +** |
| 9634 | +** <pre> |
| 9635 | +** int nChangeset, |
| 9636 | +** void *pChangeset, |
| 9637 | +** </pre> |
| 9638 | +** |
| 9639 | +** Is replaced by: |
| 9640 | +** |
| 9641 | +** <pre> |
| 9642 | +** int (*xInput)(void *pIn, void *pData, int *pnData), |
| 9643 | +** void *pIn, |
| 9644 | +** </pre> |
| 9645 | +** |
| 9646 | +** Each time the xInput callback is invoked by the sessions module, the first |
| 9647 | +** argument passed is a copy of the supplied pIn context pointer. The second |
| 9648 | +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no |
| 9649 | +** error occurs the xInput method should copy up to (*pnData) bytes of data |
| 9650 | +** into the buffer and set (*pnData) to the actual number of bytes copied |
| 9651 | +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) |
| 9652 | +** should be set to zero to indicate this. Or, if an error occurs, an SQLite |
| 9653 | +** error code should be returned. In all cases, if an xInput callback returns |
| 9654 | +** an error, all processing is abandoned and the streaming API function |
| 9655 | +** returns a copy of the error code to the caller. |
| 9656 | +** |
| 9657 | +** In the case of sqlite3changeset_start_strm(), the xInput callback may be |
| 9658 | +** invoked by the sessions module at any point during the lifetime of the |
| 9659 | +** iterator. If such an xInput callback returns an error, the iterator enters |
| 9660 | +** an error state, whereby all subsequent calls to iterator functions |
| 9661 | +** immediately fail with the same error code as returned by xInput. |
| 9662 | +** |
| 9663 | +** Similarly, streaming API functions that return changesets (or patchsets) |
| 9664 | +** return them in chunks by way of a callback function instead of via a |
| 9665 | +** pointer to a single large buffer. In this case, a pair of parameters such |
| 9666 | +** as: |
| 9667 | +** |
| 9668 | +** <pre> |
| 9669 | +** int *pnChangeset, |
| 9670 | +** void **ppChangeset, |
| 9671 | +** </pre> |
| 9672 | +** |
| 9673 | +** Is replaced by: |
| 9674 | +** |
| 9675 | +** <pre> |
| 9676 | +** int (*xOutput)(void *pOut, const void *pData, int nData), |
| 9677 | +** void *pOut |
| 9678 | +** </pre> |
| 9679 | +** |
| 9680 | +** The xOutput callback is invoked zero or more times to return data to |
| 9681 | +** the application. The first parameter passed to each call is a copy of the |
| 9682 | +** pOut pointer supplied by the application. The second parameter, pData, |
| 9683 | +** points to a buffer nData bytes in size containing the chunk of output |
| 9684 | +** data being returned. If the xOutput callback successfully processes the |
| 9685 | +** supplied data, it should return SQLITE_OK to indicate success. Otherwise, |
| 9686 | +** it should return some other SQLite error code. In this case processing |
| 9687 | +** is immediately abandoned and the streaming API function returns a copy |
| 9688 | +** of the xOutput error code to the application. |
| 9689 | +** |
| 9690 | +** The sessions module never invokes an xOutput callback with the third |
| 9691 | +** parameter set to a value less than or equal to zero. Other than this, |
| 9692 | +** no guarantees are made as to the size of the chunks of data returned. |
| 9693 | +*/ |
| 9694 | +int sqlite3changeset_apply_strm( |
| 9695 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 9696 | + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ |
| 9697 | + void *pIn, /* First arg for xInput */ |
| 9698 | + int(*xFilter)( |
| 9699 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 9700 | + const char *zTab /* Table name */ |
| 9701 | + ), |
| 9702 | + int(*xConflict)( |
| 9703 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 9704 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 9705 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 9706 | + ), |
| 9707 | + void *pCtx /* First argument passed to xConflict */ |
| 9708 | +); |
| 9709 | +int sqlite3changeset_concat_strm( |
| 9710 | + int (*xInputA)(void *pIn, void *pData, int *pnData), |
| 9711 | + void *pInA, |
| 9712 | + int (*xInputB)(void *pIn, void *pData, int *pnData), |
| 9713 | + void *pInB, |
| 9714 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 9715 | + void *pOut |
| 9716 | +); |
| 9717 | +int sqlite3changeset_invert_strm( |
| 9718 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 9719 | + void *pIn, |
| 9720 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 9721 | + void *pOut |
| 9722 | +); |
| 9723 | +int sqlite3changeset_start_strm( |
| 9724 | + sqlite3_changeset_iter **pp, |
| 9725 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 9726 | + void *pIn |
| 9727 | +); |
| 9728 | +int sqlite3session_changeset_strm( |
| 9729 | + sqlite3_session *pSession, |
| 9730 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 9731 | + void *pOut |
| 9732 | +); |
| 9733 | +int sqlite3session_patchset_strm( |
| 9734 | + sqlite3_session *pSession, |
| 9735 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 9736 | + void *pOut |
| 9737 | +); |
| 9738 | +int sqlite3changegroup_add_strm(sqlite3_changegroup*, |
| 9739 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 9740 | + void *pIn |
| 9741 | +); |
| 9742 | +int sqlite3changegroup_output_strm(sqlite3_changegroup*, |
| 9743 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 9744 | + void *pOut |
| 9745 | +); |
| 9746 | + |
| 9747 | + |
| 9748 | +/* |
| 9749 | +** Make sure we can call this stuff from C++. |
| 9750 | +*/ |
| 9751 | +#if 0 |
| 9752 | +} |
| 9753 | +#endif |
| 9754 | + |
| 9755 | +#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 9756 | + |
| 9757 | +/******** End of sqlite3session.h *********/ |
| 9758 | +/******** Begin file fts5.h *********/ |
| 8381 | 9759 | /* |
| 8382 | 9760 | ** 2014 May 31 |
| 8383 | 9761 | ** |
| 8384 | 9762 | ** The author disclaims copyright to this source code. In place of |
| 8385 | 9763 | ** a legal notice, here is a blessing: |
| | @@ -8954,10 +10332,11 @@ |
| 8954 | 10332 | #endif |
| 8955 | 10333 | |
| 8956 | 10334 | #endif /* _FTS5_H */ |
| 8957 | 10335 | |
| 8958 | 10336 | |
| 10337 | +/******** End of fts5.h *********/ |
| 8959 | 10338 | |
| 8960 | 10339 | /************** End of sqlite3.h *********************************************/ |
| 8961 | 10340 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| 8962 | 10341 | |
| 8963 | 10342 | /* |
| | @@ -10311,10 +11690,11 @@ |
| 10311 | 11690 | typedef struct Lookaside Lookaside; |
| 10312 | 11691 | typedef struct LookasideSlot LookasideSlot; |
| 10313 | 11692 | typedef struct Module Module; |
| 10314 | 11693 | typedef struct NameContext NameContext; |
| 10315 | 11694 | typedef struct Parse Parse; |
| 11695 | +typedef struct PreUpdate PreUpdate; |
| 10316 | 11696 | typedef struct PrintfArguments PrintfArguments; |
| 10317 | 11697 | typedef struct RowSet RowSet; |
| 10318 | 11698 | typedef struct Savepoint Savepoint; |
| 10319 | 11699 | typedef struct Select Select; |
| 10320 | 11700 | typedef struct SQLiteThread SQLiteThread; |
| | @@ -10742,10 +12122,11 @@ |
| 10742 | 12122 | Mem *pMem; /* Used when p4type is P4_MEM */ |
| 10743 | 12123 | VTable *pVtab; /* Used when p4type is P4_VTAB */ |
| 10744 | 12124 | KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ |
| 10745 | 12125 | int *ai; /* Used when p4type is P4_INTARRAY */ |
| 10746 | 12126 | SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ |
| 12127 | + Table *pTab; /* Used when p4type is P4_TABLE */ |
| 10747 | 12128 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 10748 | 12129 | Expr *pExpr; /* Used when p4type is P4_EXPR */ |
| 10749 | 12130 | #endif |
| 10750 | 12131 | int (*xAdvance)(BtCursor *, int *); |
| 10751 | 12132 | } p4; |
| | @@ -10806,11 +12187,12 @@ |
| 10806 | 12187 | #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ |
| 10807 | 12188 | #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ |
| 10808 | 12189 | #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ |
| 10809 | 12190 | #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ |
| 10810 | 12191 | #define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ |
| 10811 | | -#define P4_FUNCCTX (-20) /* P4 is a pointer to an sqlite3_context object */ |
| 12192 | +#define P4_TABLE (-20) /* P4 is a pointer to a Table structure */ |
| 12193 | +#define P4_FUNCCTX (-21) /* P4 is a pointer to an sqlite3_context object */ |
| 10812 | 12194 | |
| 10813 | 12195 | /* Error message codes for OP_Halt */ |
| 10814 | 12196 | #define P5_ConstraintNotNull 1 |
| 10815 | 12197 | #define P5_ConstraintUnique 2 |
| 10816 | 12198 | #define P5_ConstraintCheck 3 |
| | @@ -12206,10 +13588,17 @@ |
| 12206 | 13588 | int (*xCommitCallback)(void*); /* Invoked at every commit. */ |
| 12207 | 13589 | void *pRollbackArg; /* Argument to xRollbackCallback() */ |
| 12208 | 13590 | void (*xRollbackCallback)(void*); /* Invoked at every commit. */ |
| 12209 | 13591 | void *pUpdateArg; |
| 12210 | 13592 | void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); |
| 13593 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 13594 | + void *pPreUpdateArg; /* First argument to xPreUpdateCallback */ |
| 13595 | + void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ |
| 13596 | + void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64 |
| 13597 | + ); |
| 13598 | + PreUpdate *pPreUpdate; /* Context for active pre-update callback */ |
| 13599 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 12211 | 13600 | #ifndef SQLITE_OMIT_WAL |
| 12212 | 13601 | int (*xWalCallback)(void *, sqlite3 *, const char *, int); |
| 12213 | 13602 | void *pWalArg; |
| 12214 | 13603 | #endif |
| 12215 | 13604 | void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); |
| | @@ -13861,10 +15250,13 @@ |
| 13861 | 15250 | #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ |
| 13862 | 15251 | #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ |
| 13863 | 15252 | #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ |
| 13864 | 15253 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ |
| 13865 | 15254 | #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ |
| 15255 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 15256 | +#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ |
| 15257 | +#endif |
| 13866 | 15258 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 13867 | 15259 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 13868 | 15260 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 13869 | 15261 | #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ |
| 13870 | 15262 | #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ |
| | @@ -14391,10 +15783,11 @@ |
| 14391 | 15783 | SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); |
| 14392 | 15784 | SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); |
| 14393 | 15785 | SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); |
| 14394 | 15786 | SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); |
| 14395 | 15787 | SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); |
| 15788 | +SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*); |
| 14396 | 15789 | SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*); |
| 14397 | 15790 | SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int); |
| 14398 | 15791 | SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); |
| 14399 | 15792 | SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16); |
| 14400 | 15793 | SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); |
| | @@ -16270,10 +17663,29 @@ |
| 16270 | 17663 | #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ |
| 16271 | 17664 | #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ |
| 16272 | 17665 | #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ |
| 16273 | 17666 | #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ |
| 16274 | 17667 | |
| 17668 | +/* |
| 17669 | +** Structure used to store the context required by the |
| 17670 | +** sqlite3_preupdate_*() API functions. |
| 17671 | +*/ |
| 17672 | +struct PreUpdate { |
| 17673 | + Vdbe *v; |
| 17674 | + VdbeCursor *pCsr; /* Cursor to read old values from */ |
| 17675 | + int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ |
| 17676 | + u8 *aRecord; /* old.* database record */ |
| 17677 | + KeyInfo keyinfo; |
| 17678 | + UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 17679 | + UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 17680 | + int iNewReg; /* Register for new.* values */ |
| 17681 | + i64 iKey1; /* First key value passed to hook */ |
| 17682 | + i64 iKey2; /* Second key value passed to hook */ |
| 17683 | + int iPKey; /* If not negative index of IPK column */ |
| 17684 | + Mem *aNew; /* Array of new.* values */ |
| 17685 | +}; |
| 17686 | + |
| 16275 | 17687 | /* |
| 16276 | 17688 | ** Function prototypes |
| 16277 | 17689 | */ |
| 16278 | 17690 | SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); |
| 16279 | 17691 | SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); |
| | @@ -16329,10 +17741,13 @@ |
| 16329 | 17741 | SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); |
| 16330 | 17742 | SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); |
| 16331 | 17743 | SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); |
| 16332 | 17744 | SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); |
| 16333 | 17745 | SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); |
| 17746 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 17747 | +SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); |
| 17748 | +#endif |
| 16334 | 17749 | SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); |
| 16335 | 17750 | |
| 16336 | 17751 | SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); |
| 16337 | 17752 | SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *); |
| 16338 | 17753 | SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); |
| | @@ -26836,11 +28251,10 @@ |
| 26836 | 28251 | ** Note that this routine is only used when one or more of various |
| 26837 | 28252 | ** non-standard compile-time options is enabled. |
| 26838 | 28253 | */ |
| 26839 | 28254 | SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ |
| 26840 | 28255 | u64 n; |
| 26841 | | - if( x<10 ) return 1; |
| 26842 | 28256 | n = x%10; |
| 26843 | 28257 | x /= 10; |
| 26844 | 28258 | if( n>=5 ) n -= 2; |
| 26845 | 28259 | else if( n>=1 ) n -= 1; |
| 26846 | 28260 | #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ |
| | @@ -29008,20 +30422,26 @@ |
| 29008 | 30422 | static int unixLock(sqlite3_file *id, int eFileLock){ |
| 29009 | 30423 | /* The following describes the implementation of the various locks and |
| 29010 | 30424 | ** lock transitions in terms of the POSIX advisory shared and exclusive |
| 29011 | 30425 | ** lock primitives (called read-locks and write-locks below, to avoid |
| 29012 | 30426 | ** confusion with SQLite lock names). The algorithms are complicated |
| 29013 | | - ** slightly in order to be compatible with windows systems simultaneously |
| 30427 | + ** slightly in order to be compatible with Windows95 systems simultaneously |
| 29014 | 30428 | ** accessing the same database file, in case that is ever required. |
| 29015 | 30429 | ** |
| 29016 | 30430 | ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved |
| 29017 | 30431 | ** byte', each single bytes at well known offsets, and the 'shared byte |
| 29018 | 30432 | ** range', a range of 510 bytes at a well known offset. |
| 29019 | 30433 | ** |
| 29020 | 30434 | ** To obtain a SHARED lock, a read-lock is obtained on the 'pending |
| 29021 | | - ** byte'. If this is successful, a random byte from the 'shared byte |
| 29022 | | - ** range' is read-locked and the lock on the 'pending byte' released. |
| 30435 | + ** byte'. If this is successful, 'shared byte range' is read-locked |
| 30436 | + ** and the lock on the 'pending byte' released. (Legacy note: When |
| 30437 | + ** SQLite was first developed, Windows95 systems were still very common, |
| 30438 | + ** and Widnows95 lacks a shared-lock capability. So on Windows95, a |
| 30439 | + ** single randomly selected by from the 'shared byte range' is locked. |
| 30440 | + ** Windows95 is now pretty much extinct, but this work-around for the |
| 30441 | + ** lack of shared-locks on Windows95 lives on, for backwards |
| 30442 | + ** compatibility.) |
| 29023 | 30443 | ** |
| 29024 | 30444 | ** A process may only obtain a RESERVED lock after it has a SHARED lock. |
| 29025 | 30445 | ** A RESERVED lock is implemented by grabbing a write-lock on the |
| 29026 | 30446 | ** 'reserved byte'. |
| 29027 | 30447 | ** |
| | @@ -29036,15 +30456,10 @@ |
| 29036 | 30456 | ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is |
| 29037 | 30457 | ** implemented by obtaining a write-lock on the entire 'shared byte |
| 29038 | 30458 | ** range'. Since all other locks require a read-lock on one of the bytes |
| 29039 | 30459 | ** within this range, this ensures that no other locks are held on the |
| 29040 | 30460 | ** database. |
| 29041 | | - ** |
| 29042 | | - ** The reason a single byte cannot be used instead of the 'shared byte |
| 29043 | | - ** range' is that some versions of windows do not support read-locks. By |
| 29044 | | - ** locking a random byte from a range, concurrent SHARED locks may exist |
| 29045 | | - ** even if the locking primitive used is always a write-lock. |
| 29046 | 30461 | */ |
| 29047 | 30462 | int rc = SQLITE_OK; |
| 29048 | 30463 | unixFile *pFile = (unixFile*)id; |
| 29049 | 30464 | unixInodeInfo *pInode; |
| 29050 | 30465 | struct flock lock; |
| | @@ -36594,10 +38009,16 @@ |
| 36594 | 38009 | SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int nBuf){ |
| 36595 | 38010 | char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; |
| 36596 | 38011 | int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ |
| 36597 | 38012 | if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ |
| 36598 | 38013 | assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE ); |
| 38014 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38015 | + if( !zBuf ){ |
| 38016 | + (void)SQLITE_MISUSE_BKPT; |
| 38017 | + return; |
| 38018 | + } |
| 38019 | +#endif |
| 36599 | 38020 | #if defined(SQLITE_WIN32_HAS_ANSI) |
| 36600 | 38021 | if( nMin>0 ){ |
| 36601 | 38022 | memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); |
| 36602 | 38023 | memcpy(zDbgBuf, zBuf, nMin); |
| 36603 | 38024 | osOutputDebugStringA(zDbgBuf); |
| | @@ -36919,151 +38340,248 @@ |
| 36919 | 38340 | sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32()); |
| 36920 | 38341 | } |
| 36921 | 38342 | #endif /* SQLITE_WIN32_MALLOC */ |
| 36922 | 38343 | |
| 36923 | 38344 | /* |
| 36924 | | -** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). |
| 38345 | +** Convert a UTF-8 string to Microsoft Unicode. |
| 36925 | 38346 | ** |
| 36926 | | -** Space to hold the returned string is obtained from malloc. |
| 38347 | +** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 36927 | 38348 | */ |
| 36928 | | -static LPWSTR winUtf8ToUnicode(const char *zFilename){ |
| 38349 | +static LPWSTR winUtf8ToUnicode(const char *zText){ |
| 36929 | 38350 | int nChar; |
| 36930 | | - LPWSTR zWideFilename; |
| 38351 | + LPWSTR zWideText; |
| 36931 | 38352 | |
| 36932 | | - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); |
| 38353 | + nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0); |
| 36933 | 38354 | if( nChar==0 ){ |
| 36934 | 38355 | return 0; |
| 36935 | 38356 | } |
| 36936 | | - zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) ); |
| 36937 | | - if( zWideFilename==0 ){ |
| 38357 | + zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) ); |
| 38358 | + if( zWideText==0 ){ |
| 36938 | 38359 | return 0; |
| 36939 | 38360 | } |
| 36940 | | - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, |
| 38361 | + nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, |
| 36941 | 38362 | nChar); |
| 36942 | 38363 | if( nChar==0 ){ |
| 36943 | | - sqlite3_free(zWideFilename); |
| 36944 | | - zWideFilename = 0; |
| 38364 | + sqlite3_free(zWideText); |
| 38365 | + zWideText = 0; |
| 36945 | 38366 | } |
| 36946 | | - return zWideFilename; |
| 38367 | + return zWideText; |
| 36947 | 38368 | } |
| 36948 | 38369 | |
| 36949 | 38370 | /* |
| 36950 | | -** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is |
| 36951 | | -** obtained from sqlite3_malloc(). |
| 38371 | +** Convert a Microsoft Unicode string to UTF-8. |
| 38372 | +** |
| 38373 | +** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 36952 | 38374 | */ |
| 36953 | | -static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ |
| 38375 | +static char *winUnicodeToUtf8(LPCWSTR zWideText){ |
| 36954 | 38376 | int nByte; |
| 36955 | | - char *zFilename; |
| 38377 | + char *zText; |
| 36956 | 38378 | |
| 36957 | | - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); |
| 38379 | + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0); |
| 36958 | 38380 | if( nByte == 0 ){ |
| 36959 | 38381 | return 0; |
| 36960 | 38382 | } |
| 36961 | | - zFilename = sqlite3MallocZero( nByte ); |
| 36962 | | - if( zFilename==0 ){ |
| 38383 | + zText = sqlite3MallocZero( nByte ); |
| 38384 | + if( zText==0 ){ |
| 36963 | 38385 | return 0; |
| 36964 | 38386 | } |
| 36965 | | - nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, |
| 38387 | + nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte, |
| 36966 | 38388 | 0, 0); |
| 36967 | 38389 | if( nByte == 0 ){ |
| 36968 | | - sqlite3_free(zFilename); |
| 36969 | | - zFilename = 0; |
| 38390 | + sqlite3_free(zText); |
| 38391 | + zText = 0; |
| 36970 | 38392 | } |
| 36971 | | - return zFilename; |
| 38393 | + return zText; |
| 36972 | 38394 | } |
| 36973 | 38395 | |
| 36974 | 38396 | /* |
| 36975 | | -** Convert an ANSI string to Microsoft Unicode, based on the |
| 36976 | | -** current codepage settings for file apis. |
| 38397 | +** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM |
| 38398 | +** code page. |
| 36977 | 38399 | ** |
| 36978 | | -** Space to hold the returned string is obtained |
| 36979 | | -** from sqlite3_malloc. |
| 38400 | +** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 36980 | 38401 | */ |
| 36981 | | -static LPWSTR winMbcsToUnicode(const char *zFilename){ |
| 38402 | +static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){ |
| 36982 | 38403 | int nByte; |
| 36983 | | - LPWSTR zMbcsFilename; |
| 36984 | | - int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; |
| 38404 | + LPWSTR zMbcsText; |
| 38405 | + int codepage = useAnsi ? CP_ACP : CP_OEMCP; |
| 36985 | 38406 | |
| 36986 | | - nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, |
| 38407 | + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL, |
| 36987 | 38408 | 0)*sizeof(WCHAR); |
| 36988 | 38409 | if( nByte==0 ){ |
| 36989 | 38410 | return 0; |
| 36990 | 38411 | } |
| 36991 | | - zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) ); |
| 36992 | | - if( zMbcsFilename==0 ){ |
| 36993 | | - return 0; |
| 36994 | | - } |
| 36995 | | - nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, |
| 36996 | | - nByte); |
| 36997 | | - if( nByte==0 ){ |
| 36998 | | - sqlite3_free(zMbcsFilename); |
| 36999 | | - zMbcsFilename = 0; |
| 37000 | | - } |
| 37001 | | - return zMbcsFilename; |
| 37002 | | -} |
| 37003 | | - |
| 37004 | | -/* |
| 37005 | | -** Convert Microsoft Unicode to multi-byte character string, based on the |
| 37006 | | -** user's ANSI codepage. |
| 37007 | | -** |
| 37008 | | -** Space to hold the returned string is obtained from |
| 37009 | | -** sqlite3_malloc(). |
| 37010 | | -*/ |
| 37011 | | -static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ |
| 37012 | | - int nByte; |
| 37013 | | - char *zFilename; |
| 37014 | | - int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; |
| 37015 | | - |
| 37016 | | - nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); |
| 37017 | | - if( nByte == 0 ){ |
| 37018 | | - return 0; |
| 37019 | | - } |
| 37020 | | - zFilename = sqlite3MallocZero( nByte ); |
| 37021 | | - if( zFilename==0 ){ |
| 37022 | | - return 0; |
| 37023 | | - } |
| 37024 | | - nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, |
| 37025 | | - nByte, 0, 0); |
| 37026 | | - if( nByte == 0 ){ |
| 37027 | | - sqlite3_free(zFilename); |
| 37028 | | - zFilename = 0; |
| 37029 | | - } |
| 37030 | | - return zFilename; |
| 37031 | | -} |
| 37032 | | - |
| 37033 | | -/* |
| 37034 | | -** Convert multibyte character string to UTF-8. Space to hold the |
| 37035 | | -** returned string is obtained from sqlite3_malloc(). |
| 37036 | | -*/ |
| 37037 | | -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename){ |
| 37038 | | - char *zFilenameUtf8; |
| 37039 | | - LPWSTR zTmpWide; |
| 37040 | | - |
| 37041 | | - zTmpWide = winMbcsToUnicode(zFilename); |
| 37042 | | - if( zTmpWide==0 ){ |
| 37043 | | - return 0; |
| 37044 | | - } |
| 37045 | | - zFilenameUtf8 = winUnicodeToUtf8(zTmpWide); |
| 37046 | | - sqlite3_free(zTmpWide); |
| 37047 | | - return zFilenameUtf8; |
| 37048 | | -} |
| 37049 | | - |
| 37050 | | -/* |
| 37051 | | -** Convert UTF-8 to multibyte character string. Space to hold the |
| 37052 | | -** returned string is obtained from sqlite3_malloc(). |
| 37053 | | -*/ |
| 37054 | | -SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename){ |
| 37055 | | - char *zFilenameMbcs; |
| 37056 | | - LPWSTR zTmpWide; |
| 37057 | | - |
| 37058 | | - zTmpWide = winUtf8ToUnicode(zFilename); |
| 37059 | | - if( zTmpWide==0 ){ |
| 37060 | | - return 0; |
| 37061 | | - } |
| 37062 | | - zFilenameMbcs = winUnicodeToMbcs(zTmpWide); |
| 37063 | | - sqlite3_free(zTmpWide); |
| 37064 | | - return zFilenameMbcs; |
| 38412 | + zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) ); |
| 38413 | + if( zMbcsText==0 ){ |
| 38414 | + return 0; |
| 38415 | + } |
| 38416 | + nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, |
| 38417 | + nByte); |
| 38418 | + if( nByte==0 ){ |
| 38419 | + sqlite3_free(zMbcsText); |
| 38420 | + zMbcsText = 0; |
| 38421 | + } |
| 38422 | + return zMbcsText; |
| 38423 | +} |
| 38424 | + |
| 38425 | +/* |
| 38426 | +** Convert a Microsoft Unicode string to a multi-byte character string, |
| 38427 | +** using the ANSI or OEM code page. |
| 38428 | +** |
| 38429 | +** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 38430 | +*/ |
| 38431 | +static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){ |
| 38432 | + int nByte; |
| 38433 | + char *zText; |
| 38434 | + int codepage = useAnsi ? CP_ACP : CP_OEMCP; |
| 38435 | + |
| 38436 | + nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0); |
| 38437 | + if( nByte == 0 ){ |
| 38438 | + return 0; |
| 38439 | + } |
| 38440 | + zText = sqlite3MallocZero( nByte ); |
| 38441 | + if( zText==0 ){ |
| 38442 | + return 0; |
| 38443 | + } |
| 38444 | + nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText, |
| 38445 | + nByte, 0, 0); |
| 38446 | + if( nByte == 0 ){ |
| 38447 | + sqlite3_free(zText); |
| 38448 | + zText = 0; |
| 38449 | + } |
| 38450 | + return zText; |
| 38451 | +} |
| 38452 | + |
| 38453 | +/* |
| 38454 | +** Convert a multi-byte character string to UTF-8. |
| 38455 | +** |
| 38456 | +** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 38457 | +*/ |
| 38458 | +static char *winMbcsToUtf8(const char *zText, int useAnsi){ |
| 38459 | + char *zTextUtf8; |
| 38460 | + LPWSTR zTmpWide; |
| 38461 | + |
| 38462 | + zTmpWide = winMbcsToUnicode(zText, useAnsi); |
| 38463 | + if( zTmpWide==0 ){ |
| 38464 | + return 0; |
| 38465 | + } |
| 38466 | + zTextUtf8 = winUnicodeToUtf8(zTmpWide); |
| 38467 | + sqlite3_free(zTmpWide); |
| 38468 | + return zTextUtf8; |
| 38469 | +} |
| 38470 | + |
| 38471 | +/* |
| 38472 | +** Convert a UTF-8 string to a multi-byte character string. |
| 38473 | +** |
| 38474 | +** Space to hold the returned string is obtained from sqlite3_malloc(). |
| 38475 | +*/ |
| 38476 | +static char *winUtf8ToMbcs(const char *zText, int useAnsi){ |
| 38477 | + char *zTextMbcs; |
| 38478 | + LPWSTR zTmpWide; |
| 38479 | + |
| 38480 | + zTmpWide = winUtf8ToUnicode(zText); |
| 38481 | + if( zTmpWide==0 ){ |
| 38482 | + return 0; |
| 38483 | + } |
| 38484 | + zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi); |
| 38485 | + sqlite3_free(zTmpWide); |
| 38486 | + return zTextMbcs; |
| 38487 | +} |
| 38488 | + |
| 38489 | +/* |
| 38490 | +** This is a public wrapper for the winUtf8ToUnicode() function. |
| 38491 | +*/ |
| 38492 | +SQLITE_API LPWSTR SQLITE_STDCALL sqlite3_win32_utf8_to_unicode(const char *zText){ |
| 38493 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38494 | + if( !zText ){ |
| 38495 | + (void)SQLITE_MISUSE_BKPT; |
| 38496 | + return 0; |
| 38497 | + } |
| 38498 | +#endif |
| 38499 | +#ifndef SQLITE_OMIT_AUTOINIT |
| 38500 | + if( sqlite3_initialize() ) return 0; |
| 38501 | +#endif |
| 38502 | + return winUtf8ToUnicode(zText); |
| 38503 | +} |
| 38504 | + |
| 38505 | +/* |
| 38506 | +** This is a public wrapper for the winUnicodeToUtf8() function. |
| 38507 | +*/ |
| 38508 | +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){ |
| 38509 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38510 | + if( !zWideText ){ |
| 38511 | + (void)SQLITE_MISUSE_BKPT; |
| 38512 | + return 0; |
| 38513 | + } |
| 38514 | +#endif |
| 38515 | +#ifndef SQLITE_OMIT_AUTOINIT |
| 38516 | + if( sqlite3_initialize() ) return 0; |
| 38517 | +#endif |
| 38518 | + return winUnicodeToUtf8(zWideText); |
| 38519 | +} |
| 38520 | + |
| 38521 | +/* |
| 38522 | +** This is a public wrapper for the winMbcsToUtf8() function. |
| 38523 | +*/ |
| 38524 | +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zText){ |
| 38525 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38526 | + if( !zText ){ |
| 38527 | + (void)SQLITE_MISUSE_BKPT; |
| 38528 | + return 0; |
| 38529 | + } |
| 38530 | +#endif |
| 38531 | +#ifndef SQLITE_OMIT_AUTOINIT |
| 38532 | + if( sqlite3_initialize() ) return 0; |
| 38533 | +#endif |
| 38534 | + return winMbcsToUtf8(zText, osAreFileApisANSI()); |
| 38535 | +} |
| 38536 | + |
| 38537 | +/* |
| 38538 | +** This is a public wrapper for the winMbcsToUtf8() function. |
| 38539 | +*/ |
| 38540 | +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){ |
| 38541 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38542 | + if( !zText ){ |
| 38543 | + (void)SQLITE_MISUSE_BKPT; |
| 38544 | + return 0; |
| 38545 | + } |
| 38546 | +#endif |
| 38547 | +#ifndef SQLITE_OMIT_AUTOINIT |
| 38548 | + if( sqlite3_initialize() ) return 0; |
| 38549 | +#endif |
| 38550 | + return winMbcsToUtf8(zText, useAnsi); |
| 38551 | +} |
| 38552 | + |
| 38553 | +/* |
| 38554 | +** This is a public wrapper for the winUtf8ToMbcs() function. |
| 38555 | +*/ |
| 38556 | +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zText){ |
| 38557 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38558 | + if( !zText ){ |
| 38559 | + (void)SQLITE_MISUSE_BKPT; |
| 38560 | + return 0; |
| 38561 | + } |
| 38562 | +#endif |
| 38563 | +#ifndef SQLITE_OMIT_AUTOINIT |
| 38564 | + if( sqlite3_initialize() ) return 0; |
| 38565 | +#endif |
| 38566 | + return winUtf8ToMbcs(zText, osAreFileApisANSI()); |
| 38567 | +} |
| 38568 | + |
| 38569 | +/* |
| 38570 | +** This is a public wrapper for the winUtf8ToMbcs() function. |
| 38571 | +*/ |
| 38572 | +SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){ |
| 38573 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 38574 | + if( !zText ){ |
| 38575 | + (void)SQLITE_MISUSE_BKPT; |
| 38576 | + return 0; |
| 38577 | + } |
| 38578 | +#endif |
| 38579 | +#ifndef SQLITE_OMIT_AUTOINIT |
| 38580 | + if( sqlite3_initialize() ) return 0; |
| 38581 | +#endif |
| 38582 | + return winUtf8ToMbcs(zText, useAnsi); |
| 37065 | 38583 | } |
| 37066 | 38584 | |
| 37067 | 38585 | /* |
| 37068 | 38586 | ** This function sets the data directory or the temporary directory based on |
| 37069 | 38587 | ** the provided arguments. The type argument must be 1 in order to set the |
| | @@ -37161,11 +38679,11 @@ |
| 37161 | 38679 | 0, |
| 37162 | 38680 | 0); |
| 37163 | 38681 | if( dwLen > 0 ){ |
| 37164 | 38682 | /* allocate a buffer and convert to UTF8 */ |
| 37165 | 38683 | sqlite3BeginBenignMalloc(); |
| 37166 | | - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); |
| 38684 | + zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); |
| 37167 | 38685 | sqlite3EndBenignMalloc(); |
| 37168 | 38686 | /* free the system buffer allocated by FormatMessage */ |
| 37169 | 38687 | osLocalFree(zTemp); |
| 37170 | 38688 | } |
| 37171 | 38689 | } |
| | @@ -39606,11 +41124,11 @@ |
| 39606 | 41124 | if( osIsNT() ){ |
| 39607 | 41125 | zConverted = winUnicodeToUtf8(zFilename); |
| 39608 | 41126 | } |
| 39609 | 41127 | #ifdef SQLITE_WIN32_HAS_ANSI |
| 39610 | 41128 | else{ |
| 39611 | | - zConverted = sqlite3_win32_mbcs_to_utf8(zFilename); |
| 41129 | + zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI()); |
| 39612 | 41130 | } |
| 39613 | 41131 | #endif |
| 39614 | 41132 | /* caller will handle out of memory */ |
| 39615 | 41133 | return zConverted; |
| 39616 | 41134 | } |
| | @@ -39627,11 +41145,11 @@ |
| 39627 | 41145 | if( osIsNT() ){ |
| 39628 | 41146 | zConverted = winUtf8ToUnicode(zFilename); |
| 39629 | 41147 | } |
| 39630 | 41148 | #ifdef SQLITE_WIN32_HAS_ANSI |
| 39631 | 41149 | else{ |
| 39632 | | - zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); |
| 41150 | + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); |
| 39633 | 41151 | } |
| 39634 | 41152 | #endif |
| 39635 | 41153 | /* caller will handle out of memory */ |
| 39636 | 41154 | return zConverted; |
| 39637 | 41155 | } |
| | @@ -39828,11 +41346,11 @@ |
| 39828 | 41346 | sqlite3_free(zBuf); |
| 39829 | 41347 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n")); |
| 39830 | 41348 | return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), |
| 39831 | 41349 | "winGetTempname3", 0); |
| 39832 | 41350 | } |
| 39833 | | - zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); |
| 41351 | + zUtf8 = winMbcsToUtf8(zMbcsPath, osAreFileApisANSI()); |
| 39834 | 41352 | if( zUtf8 ){ |
| 39835 | 41353 | sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); |
| 39836 | 41354 | sqlite3_free(zUtf8); |
| 39837 | 41355 | }else{ |
| 39838 | 41356 | sqlite3_free(zBuf); |
| | @@ -40606,11 +42124,11 @@ |
| 40606 | 42124 | sqlite3_free(zTemp); |
| 40607 | 42125 | return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 40608 | 42126 | "winFullPathname4", zRelative); |
| 40609 | 42127 | } |
| 40610 | 42128 | sqlite3_free(zConverted); |
| 40611 | | - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); |
| 42129 | + zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI()); |
| 40612 | 42130 | sqlite3_free(zTemp); |
| 40613 | 42131 | } |
| 40614 | 42132 | #endif |
| 40615 | 42133 | if( zOut ){ |
| 40616 | 42134 | sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); |
| | @@ -62343,12 +63861,12 @@ |
| 62343 | 63861 | for(i=iFirst; i<iEnd; i++){ |
| 62344 | 63862 | int sz, rc; |
| 62345 | 63863 | u8 *pSlot; |
| 62346 | 63864 | sz = cachedCellSize(pCArray, i); |
| 62347 | 63865 | if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ |
| 63866 | + if( (pData - pBegin)<sz ) return 1; |
| 62348 | 63867 | pData -= sz; |
| 62349 | | - if( pData<pBegin ) return 1; |
| 62350 | 63868 | pSlot = pData; |
| 62351 | 63869 | } |
| 62352 | 63870 | /* pSlot and pCArray->apCell[i] will never overlap on a well-formed |
| 62353 | 63871 | ** database. But they might for a corrupt database. Hence use memmove() |
| 62354 | 63872 | ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */ |
| | @@ -62506,11 +64024,11 @@ |
| 62506 | 64024 | |
| 62507 | 64025 | #ifdef SQLITE_DEBUG |
| 62508 | 64026 | for(i=0; i<nNew && !CORRUPT_DB; i++){ |
| 62509 | 64027 | u8 *pCell = pCArray->apCell[i+iNew]; |
| 62510 | 64028 | int iOff = get2byteAligned(&pPg->aCellIdx[i*2]); |
| 62511 | | - if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){ |
| 64029 | + if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){ |
| 62512 | 64030 | pCell = &pTmp[pCell - aData]; |
| 62513 | 64031 | } |
| 62514 | 64032 | assert( 0==memcmp(pCell, &aData[iOff], |
| 62515 | 64033 | pCArray->pRef->xCellSize(pCArray->pRef, pCArray->apCell[i+iNew])) ); |
| 62516 | 64034 | } |
| | @@ -67110,14 +68628,10 @@ |
| 67110 | 68628 | ** freed before the copy is made. |
| 67111 | 68629 | */ |
| 67112 | 68630 | SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ |
| 67113 | 68631 | int rc = SQLITE_OK; |
| 67114 | 68632 | |
| 67115 | | - /* The pFrom==0 case in the following assert() is when an sqlite3_value |
| 67116 | | - ** from sqlite3_value_dup() is used as the argument |
| 67117 | | - ** to sqlite3_result_value(). */ |
| 67118 | | - assert( pTo->db==pFrom->db || pFrom->db==0 ); |
| 67119 | 68633 | assert( (pFrom->flags & MEM_RowSet)==0 ); |
| 67120 | 68634 | if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); |
| 67121 | 68635 | memcpy(pTo, pFrom, MEMCELLSIZE); |
| 67122 | 68636 | pTo->flags &= ~MEM_Dyn; |
| 67123 | 68637 | if( pTo->flags&(MEM_Str|MEM_Blob) ){ |
| | @@ -68101,10 +69615,11 @@ |
| 68101 | 69615 | ** Swap all content between two VDBE structures. |
| 68102 | 69616 | */ |
| 68103 | 69617 | SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ |
| 68104 | 69618 | Vdbe tmp, *pTmp; |
| 68105 | 69619 | char *zTmp; |
| 69620 | + assert( pA->db==pB->db ); |
| 68106 | 69621 | tmp = *pA; |
| 68107 | 69622 | *pA = *pB; |
| 68108 | 69623 | *pB = tmp; |
| 68109 | 69624 | pTmp = pA->pNext; |
| 68110 | 69625 | pA->pNext = pB->pNext; |
| | @@ -68813,56 +70328,54 @@ |
| 68813 | 70328 | |
| 68814 | 70329 | /* |
| 68815 | 70330 | ** Delete a P4 value if necessary. |
| 68816 | 70331 | */ |
| 68817 | 70332 | static void freeP4(sqlite3 *db, int p4type, void *p4){ |
| 68818 | | - if( p4 ){ |
| 68819 | | - assert( db ); |
| 68820 | | - switch( p4type ){ |
| 68821 | | - case P4_FUNCCTX: { |
| 68822 | | - freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc); |
| 68823 | | - /* Fall through into the next case */ |
| 68824 | | - } |
| 68825 | | - case P4_REAL: |
| 68826 | | - case P4_INT64: |
| 68827 | | - case P4_DYNAMIC: |
| 68828 | | - case P4_INTARRAY: { |
| 68829 | | - sqlite3DbFree(db, p4); |
| 68830 | | - break; |
| 68831 | | - } |
| 68832 | | - case P4_KEYINFO: { |
| 68833 | | - if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); |
| 68834 | | - break; |
| 68835 | | - } |
| 70333 | + assert( db ); |
| 70334 | + switch( p4type ){ |
| 70335 | + case P4_FUNCCTX: { |
| 70336 | + freeEphemeralFunction(db, ((sqlite3_context*)p4)->pFunc); |
| 70337 | + /* Fall through into the next case */ |
| 70338 | + } |
| 70339 | + case P4_REAL: |
| 70340 | + case P4_INT64: |
| 70341 | + case P4_DYNAMIC: |
| 70342 | + case P4_INTARRAY: { |
| 70343 | + sqlite3DbFree(db, p4); |
| 70344 | + break; |
| 70345 | + } |
| 70346 | + case P4_KEYINFO: { |
| 70347 | + if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); |
| 70348 | + break; |
| 70349 | + } |
| 68836 | 70350 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 68837 | | - case P4_EXPR: { |
| 68838 | | - sqlite3ExprDelete(db, (Expr*)p4); |
| 68839 | | - break; |
| 68840 | | - } |
| 68841 | | -#endif |
| 68842 | | - case P4_MPRINTF: { |
| 68843 | | - if( db->pnBytesFreed==0 ) sqlite3_free(p4); |
| 68844 | | - break; |
| 68845 | | - } |
| 68846 | | - case P4_FUNCDEF: { |
| 68847 | | - freeEphemeralFunction(db, (FuncDef*)p4); |
| 68848 | | - break; |
| 68849 | | - } |
| 68850 | | - case P4_MEM: { |
| 68851 | | - if( db->pnBytesFreed==0 ){ |
| 68852 | | - sqlite3ValueFree((sqlite3_value*)p4); |
| 68853 | | - }else{ |
| 68854 | | - Mem *p = (Mem*)p4; |
| 68855 | | - if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); |
| 68856 | | - sqlite3DbFree(db, p); |
| 68857 | | - } |
| 68858 | | - break; |
| 68859 | | - } |
| 68860 | | - case P4_VTAB : { |
| 68861 | | - if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); |
| 68862 | | - break; |
| 68863 | | - } |
| 70351 | + case P4_EXPR: { |
| 70352 | + sqlite3ExprDelete(db, (Expr*)p4); |
| 70353 | + break; |
| 70354 | + } |
| 70355 | +#endif |
| 70356 | + case P4_MPRINTF: { |
| 70357 | + if( db->pnBytesFreed==0 ) sqlite3_free(p4); |
| 70358 | + break; |
| 70359 | + } |
| 70360 | + case P4_FUNCDEF: { |
| 70361 | + freeEphemeralFunction(db, (FuncDef*)p4); |
| 70362 | + break; |
| 70363 | + } |
| 70364 | + case P4_MEM: { |
| 70365 | + if( db->pnBytesFreed==0 ){ |
| 70366 | + sqlite3ValueFree((sqlite3_value*)p4); |
| 70367 | + }else{ |
| 70368 | + Mem *p = (Mem*)p4; |
| 70369 | + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); |
| 70370 | + sqlite3DbFree(db, p); |
| 70371 | + } |
| 70372 | + break; |
| 70373 | + } |
| 70374 | + case P4_VTAB : { |
| 70375 | + if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); |
| 70376 | + break; |
| 68864 | 70377 | } |
| 68865 | 70378 | } |
| 68866 | 70379 | } |
| 68867 | 70380 | |
| 68868 | 70381 | /* |
| | @@ -69339,10 +70852,14 @@ |
| 69339 | 70852 | break; |
| 69340 | 70853 | } |
| 69341 | 70854 | case P4_ADVANCE: { |
| 69342 | 70855 | zTemp[0] = 0; |
| 69343 | 70856 | break; |
| 70857 | + } |
| 70858 | + case P4_TABLE: { |
| 70859 | + sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName); |
| 70860 | + break; |
| 69344 | 70861 | } |
| 69345 | 70862 | default: { |
| 69346 | 70863 | zP4 = pOp->p4.z; |
| 69347 | 70864 | if( zP4==0 ){ |
| 69348 | 70865 | zP4 = zTemp; |
| | @@ -71530,10 +73047,11 @@ |
| 71530 | 73047 | idx += getVarint32(&aKey[idx], serial_type); |
| 71531 | 73048 | pMem->enc = pKeyInfo->enc; |
| 71532 | 73049 | pMem->db = pKeyInfo->db; |
| 71533 | 73050 | /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ |
| 71534 | 73051 | pMem->szMalloc = 0; |
| 73052 | + pMem->z = 0; |
| 71535 | 73053 | d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); |
| 71536 | 73054 | pMem++; |
| 71537 | 73055 | if( (++u)>=p->nField ) break; |
| 71538 | 73056 | } |
| 71539 | 73057 | assert( u<=pKeyInfo->nField + 1 ); |
| | @@ -72510,10 +74028,94 @@ |
| 72510 | 74028 | pVtab->zErrMsg = 0; |
| 72511 | 74029 | } |
| 72512 | 74030 | } |
| 72513 | 74031 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 72514 | 74032 | |
| 74033 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 74034 | + |
| 74035 | +/* |
| 74036 | +** If the second argument is not NULL, release any allocations associated |
| 74037 | +** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord |
| 74038 | +** structure itself, using sqlite3DbFree(). |
| 74039 | +** |
| 74040 | +** This function is used to free UnpackedRecord structures allocated by |
| 74041 | +** the vdbeUnpackRecord() function found in vdbeapi.c. |
| 74042 | +*/ |
| 74043 | +static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){ |
| 74044 | + if( p ){ |
| 74045 | + int i; |
| 74046 | + for(i=0; i<p->nField; i++){ |
| 74047 | + Mem *pMem = &p->aMem[i]; |
| 74048 | + if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); |
| 74049 | + } |
| 74050 | + sqlite3DbFree(db, p); |
| 74051 | + } |
| 74052 | +} |
| 74053 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 74054 | + |
| 74055 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 74056 | +/* |
| 74057 | +** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, |
| 74058 | +** then cursor passed as the second argument should point to the row about |
| 74059 | +** to be update or deleted. If the application calls sqlite3_preupdate_old(), |
| 74060 | +** the required value will be read from the row the cursor points to. |
| 74061 | +*/ |
| 74062 | +SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( |
| 74063 | + Vdbe *v, /* Vdbe pre-update hook is invoked by */ |
| 74064 | + VdbeCursor *pCsr, /* Cursor to grab old.* values from */ |
| 74065 | + int op, /* SQLITE_INSERT, UPDATE or DELETE */ |
| 74066 | + const char *zDb, /* Database name */ |
| 74067 | + Table *pTab, /* Modified table */ |
| 74068 | + i64 iKey1, /* Initial key value */ |
| 74069 | + int iReg /* Register for new.* record */ |
| 74070 | +){ |
| 74071 | + sqlite3 *db = v->db; |
| 74072 | + i64 iKey2; |
| 74073 | + PreUpdate preupdate; |
| 74074 | + const char *zTbl = pTab->zName; |
| 74075 | + static const u8 fakeSortOrder = 0; |
| 74076 | + |
| 74077 | + assert( db->pPreUpdate==0 ); |
| 74078 | + memset(&preupdate, 0, sizeof(PreUpdate)); |
| 74079 | + if( op==SQLITE_UPDATE ){ |
| 74080 | + iKey2 = v->aMem[iReg].u.i; |
| 74081 | + }else{ |
| 74082 | + iKey2 = iKey1; |
| 74083 | + } |
| 74084 | + |
| 74085 | + assert( pCsr->nField==pTab->nCol |
| 74086 | + || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) |
| 74087 | + ); |
| 74088 | + |
| 74089 | + preupdate.v = v; |
| 74090 | + preupdate.pCsr = pCsr; |
| 74091 | + preupdate.op = op; |
| 74092 | + preupdate.iNewReg = iReg; |
| 74093 | + preupdate.keyinfo.db = db; |
| 74094 | + preupdate.keyinfo.enc = ENC(db); |
| 74095 | + preupdate.keyinfo.nField = pTab->nCol; |
| 74096 | + preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 74097 | + preupdate.iKey1 = iKey1; |
| 74098 | + preupdate.iKey2 = iKey2; |
| 74099 | + preupdate.iPKey = pTab->iPKey; |
| 74100 | + |
| 74101 | + db->pPreUpdate = &preupdate; |
| 74102 | + db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 74103 | + db->pPreUpdate = 0; |
| 74104 | + sqlite3DbFree(db, preupdate.aRecord); |
| 74105 | + vdbeFreeUnpacked(db, preupdate.pUnpacked); |
| 74106 | + vdbeFreeUnpacked(db, preupdate.pNewUnpacked); |
| 74107 | + if( preupdate.aNew ){ |
| 74108 | + int i; |
| 74109 | + for(i=0; i<pCsr->nField; i++){ |
| 74110 | + sqlite3VdbeMemRelease(&preupdate.aNew[i]); |
| 74111 | + } |
| 74112 | + sqlite3DbFree(db, preupdate.aNew); |
| 74113 | + } |
| 74114 | +} |
| 74115 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 74116 | + |
| 72515 | 74117 | /************** End of vdbeaux.c *********************************************/ |
| 72516 | 74118 | /************** Begin file vdbeapi.c *****************************************/ |
| 72517 | 74119 | /* |
| 72518 | 74120 | ** 2004 May 26 |
| 72519 | 74121 | ** |
| | @@ -74118,10 +75720,191 @@ |
| 74118 | 75720 | v = pVdbe->aCounter[op]; |
| 74119 | 75721 | if( resetFlag ) pVdbe->aCounter[op] = 0; |
| 74120 | 75722 | return (int)v; |
| 74121 | 75723 | } |
| 74122 | 75724 | |
| 75725 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 75726 | +/* |
| 75727 | +** Allocate and populate an UnpackedRecord structure based on the serialized |
| 75728 | +** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure |
| 75729 | +** if successful, or a NULL pointer if an OOM error is encountered. |
| 75730 | +*/ |
| 75731 | +static UnpackedRecord *vdbeUnpackRecord( |
| 75732 | + KeyInfo *pKeyInfo, |
| 75733 | + int nKey, |
| 75734 | + const void *pKey |
| 75735 | +){ |
| 75736 | + char *dummy; /* Dummy argument for AllocUnpackedRecord() */ |
| 75737 | + UnpackedRecord *pRet; /* Return value */ |
| 75738 | + |
| 75739 | + pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy); |
| 75740 | + if( pRet ){ |
| 75741 | + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); |
| 75742 | + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); |
| 75743 | + } |
| 75744 | + return pRet; |
| 75745 | +} |
| 75746 | + |
| 75747 | +/* |
| 75748 | +** This function is called from within a pre-update callback to retrieve |
| 75749 | +** a field of the row currently being updated or deleted. |
| 75750 | +*/ |
| 75751 | +SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ |
| 75752 | + PreUpdate *p = db->pPreUpdate; |
| 75753 | + int rc = SQLITE_OK; |
| 75754 | + |
| 75755 | + /* Test that this call is being made from within an SQLITE_DELETE or |
| 75756 | + ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ |
| 75757 | + if( !p || p->op==SQLITE_INSERT ){ |
| 75758 | + rc = SQLITE_MISUSE_BKPT; |
| 75759 | + goto preupdate_old_out; |
| 75760 | + } |
| 75761 | + if( iIdx>=p->pCsr->nField || iIdx<0 ){ |
| 75762 | + rc = SQLITE_RANGE; |
| 75763 | + goto preupdate_old_out; |
| 75764 | + } |
| 75765 | + |
| 75766 | + /* If the old.* record has not yet been loaded into memory, do so now. */ |
| 75767 | + if( p->pUnpacked==0 ){ |
| 75768 | + u32 nRec; |
| 75769 | + u8 *aRec; |
| 75770 | + |
| 75771 | + rc = sqlite3BtreeDataSize(p->pCsr->uc.pCursor, &nRec); |
| 75772 | + if( rc!=SQLITE_OK ) goto preupdate_old_out; |
| 75773 | + aRec = sqlite3DbMallocRaw(db, nRec); |
| 75774 | + if( !aRec ) goto preupdate_old_out; |
| 75775 | + rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec); |
| 75776 | + if( rc==SQLITE_OK ){ |
| 75777 | + p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec); |
| 75778 | + if( !p->pUnpacked ) rc = SQLITE_NOMEM; |
| 75779 | + } |
| 75780 | + if( rc!=SQLITE_OK ){ |
| 75781 | + sqlite3DbFree(db, aRec); |
| 75782 | + goto preupdate_old_out; |
| 75783 | + } |
| 75784 | + p->aRecord = aRec; |
| 75785 | + } |
| 75786 | + |
| 75787 | + if( iIdx>=p->pUnpacked->nField ){ |
| 75788 | + *ppValue = (sqlite3_value *)columnNullValue(); |
| 75789 | + }else{ |
| 75790 | + *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 75791 | + if( iIdx==p->iPKey ){ |
| 75792 | + sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); |
| 75793 | + } |
| 75794 | + } |
| 75795 | + |
| 75796 | + preupdate_old_out: |
| 75797 | + sqlite3Error(db, rc); |
| 75798 | + return sqlite3ApiExit(db, rc); |
| 75799 | +} |
| 75800 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 75801 | + |
| 75802 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 75803 | +/* |
| 75804 | +** This function is called from within a pre-update callback to retrieve |
| 75805 | +** the number of columns in the row being updated, deleted or inserted. |
| 75806 | +*/ |
| 75807 | +SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_count(sqlite3 *db){ |
| 75808 | + PreUpdate *p = db->pPreUpdate; |
| 75809 | + return (p ? p->keyinfo.nField : 0); |
| 75810 | +} |
| 75811 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 75812 | + |
| 75813 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 75814 | +/* |
| 75815 | +** This function is designed to be called from within a pre-update callback |
| 75816 | +** only. It returns zero if the change that caused the callback was made |
| 75817 | +** immediately by a user SQL statement. Or, if the change was made by a |
| 75818 | +** trigger program, it returns the number of trigger programs currently |
| 75819 | +** on the stack (1 for a top-level trigger, 2 for a trigger fired by a |
| 75820 | +** top-level trigger etc.). |
| 75821 | +** |
| 75822 | +** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL |
| 75823 | +** or SET DEFAULT action is considered a trigger. |
| 75824 | +*/ |
| 75825 | +SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_depth(sqlite3 *db){ |
| 75826 | + PreUpdate *p = db->pPreUpdate; |
| 75827 | + return (p ? p->v->nFrame : 0); |
| 75828 | +} |
| 75829 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 75830 | + |
| 75831 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 75832 | +/* |
| 75833 | +** This function is called from within a pre-update callback to retrieve |
| 75834 | +** a field of the row currently being updated or inserted. |
| 75835 | +*/ |
| 75836 | +SQLITE_API int SQLITE_STDCALL sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ |
| 75837 | + PreUpdate *p = db->pPreUpdate; |
| 75838 | + int rc = SQLITE_OK; |
| 75839 | + Mem *pMem; |
| 75840 | + |
| 75841 | + if( !p || p->op==SQLITE_DELETE ){ |
| 75842 | + rc = SQLITE_MISUSE_BKPT; |
| 75843 | + goto preupdate_new_out; |
| 75844 | + } |
| 75845 | + if( iIdx>=p->pCsr->nField || iIdx<0 ){ |
| 75846 | + rc = SQLITE_RANGE; |
| 75847 | + goto preupdate_new_out; |
| 75848 | + } |
| 75849 | + |
| 75850 | + if( p->op==SQLITE_INSERT ){ |
| 75851 | + /* For an INSERT, memory cell p->iNewReg contains the serialized record |
| 75852 | + ** that is being inserted. Deserialize it. */ |
| 75853 | + UnpackedRecord *pUnpack = p->pNewUnpacked; |
| 75854 | + if( !pUnpack ){ |
| 75855 | + Mem *pData = &p->v->aMem[p->iNewReg]; |
| 75856 | + rc = sqlite3VdbeMemExpandBlob(pData); |
| 75857 | + if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 75858 | + pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z); |
| 75859 | + if( !pUnpack ){ |
| 75860 | + rc = SQLITE_NOMEM; |
| 75861 | + goto preupdate_new_out; |
| 75862 | + } |
| 75863 | + p->pNewUnpacked = pUnpack; |
| 75864 | + } |
| 75865 | + if( iIdx>=pUnpack->nField ){ |
| 75866 | + pMem = (sqlite3_value *)columnNullValue(); |
| 75867 | + }else{ |
| 75868 | + pMem = &pUnpack->aMem[iIdx]; |
| 75869 | + if( iIdx==p->iPKey ){ |
| 75870 | + sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 75871 | + } |
| 75872 | + } |
| 75873 | + }else{ |
| 75874 | + /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| 75875 | + ** value. Make a copy of the cell contents and return a pointer to it. |
| 75876 | + ** It is not safe to return a pointer to the memory cell itself as the |
| 75877 | + ** caller may modify the value text encoding. |
| 75878 | + */ |
| 75879 | + assert( p->op==SQLITE_UPDATE ); |
| 75880 | + if( !p->aNew ){ |
| 75881 | + p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField); |
| 75882 | + if( !p->aNew ){ |
| 75883 | + rc = SQLITE_NOMEM; |
| 75884 | + goto preupdate_new_out; |
| 75885 | + } |
| 75886 | + } |
| 75887 | + assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 75888 | + pMem = &p->aNew[iIdx]; |
| 75889 | + if( pMem->flags==0 ){ |
| 75890 | + if( iIdx==p->iPKey ){ |
| 75891 | + sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 75892 | + }else{ |
| 75893 | + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 75894 | + if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 75895 | + } |
| 75896 | + } |
| 75897 | + } |
| 75898 | + *ppValue = pMem; |
| 75899 | + |
| 75900 | + preupdate_new_out: |
| 75901 | + sqlite3Error(db, rc); |
| 75902 | + return sqlite3ApiExit(db, rc); |
| 75903 | +} |
| 75904 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 75905 | + |
| 74123 | 75906 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 74124 | 75907 | /* |
| 74125 | 75908 | ** Return status data for a single loop within query pStmt. |
| 74126 | 75909 | */ |
| 74127 | 75910 | SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus( |
| | @@ -74468,10 +76251,20 @@ |
| 74468 | 76251 | sqlite3_max_blobsize = p->n; |
| 74469 | 76252 | } |
| 74470 | 76253 | } |
| 74471 | 76254 | #endif |
| 74472 | 76255 | |
| 76256 | +/* |
| 76257 | +** This macro evaluates to true if either the update hook or the preupdate |
| 76258 | +** hook are enabled for database connect DB. |
| 76259 | +*/ |
| 76260 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 76261 | +# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback) |
| 76262 | +#else |
| 76263 | +# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback) |
| 76264 | +#endif |
| 76265 | + |
| 74473 | 76266 | /* |
| 74474 | 76267 | ** The next global variable is incremented each time the OP_Found opcode |
| 74475 | 76268 | ** is executed. This is used to test whether or not the foreign key |
| 74476 | 76269 | ** operation implemented using OP_FkIsZero is working. This variable |
| 74477 | 76270 | ** has no function other than to help verify the correct operation of the |
| | @@ -76477,15 +78270,17 @@ |
| 76477 | 78270 | } |
| 76478 | 78271 | }else{ |
| 76479 | 78272 | /* Neither operand is NULL. Do a comparison. */ |
| 76480 | 78273 | affinity = pOp->p5 & SQLITE_AFF_MASK; |
| 76481 | 78274 | if( affinity>=SQLITE_AFF_NUMERIC ){ |
| 76482 | | - if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ |
| 76483 | | - applyNumericAffinity(pIn1,0); |
| 76484 | | - } |
| 76485 | | - if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ |
| 76486 | | - applyNumericAffinity(pIn3,0); |
| 78275 | + if( (flags1 | flags3)&MEM_Str ){ |
| 78276 | + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ |
| 78277 | + applyNumericAffinity(pIn1,0); |
| 78278 | + } |
| 78279 | + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ |
| 78280 | + applyNumericAffinity(pIn3,0); |
| 78281 | + } |
| 76487 | 78282 | } |
| 76488 | 78283 | }else if( affinity==SQLITE_AFF_TEXT ){ |
| 76489 | 78284 | if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){ |
| 76490 | 78285 | testcase( pIn1->flags & MEM_Int ); |
| 76491 | 78286 | testcase( pIn1->flags & MEM_Real ); |
| | @@ -77214,11 +79009,13 @@ |
| 77214 | 79009 | } |
| 77215 | 79010 | nData += len; |
| 77216 | 79011 | testcase( serial_type==127 ); |
| 77217 | 79012 | testcase( serial_type==128 ); |
| 77218 | 79013 | nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); |
| 77219 | | - }while( (--pRec)>=pData0 ); |
| 79014 | + if( pRec==pData0 ) break; |
| 79015 | + pRec--; |
| 79016 | + }while(1); |
| 77220 | 79017 | |
| 77221 | 79018 | /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint |
| 77222 | 79019 | ** which determines the total number of bytes in the header. The varint |
| 77223 | 79020 | ** value is the size of the header in bytes including the size varint |
| 77224 | 79021 | ** itself. */ |
| | @@ -77362,11 +79159,11 @@ |
| 77362 | 79159 | db->autoCommit = 0; |
| 77363 | 79160 | db->isTransactionSavepoint = 1; |
| 77364 | 79161 | }else{ |
| 77365 | 79162 | db->nSavepoint++; |
| 77366 | 79163 | } |
| 77367 | | - |
| 79164 | + |
| 77368 | 79165 | /* Link the new savepoint into the database handle's list. */ |
| 77369 | 79166 | pNew->pNext = db->pSavepoint; |
| 77370 | 79167 | db->pSavepoint = pNew; |
| 77371 | 79168 | pNew->nDeferredCons = db->nDeferredCons; |
| 77372 | 79169 | pNew->nDeferredImmCons = db->nDeferredImmCons; |
| | @@ -78719,13 +80516,13 @@ |
| 78719 | 80516 | ** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an |
| 78720 | 80517 | ** UPDATE operation. Otherwise (if the flag is clear) then this opcode |
| 78721 | 80518 | ** is part of an INSERT operation. The difference is only important to |
| 78722 | 80519 | ** the update hook. |
| 78723 | 80520 | ** |
| 78724 | | -** Parameter P4 may point to a string containing the table-name, or |
| 78725 | | -** may be NULL. If it is not NULL, then the update-hook |
| 78726 | | -** (sqlite3.xUpdateCallback) is invoked following a successful insert. |
| 80521 | +** Parameter P4 may point to a Table structure, or may be NULL. If it is |
| 80522 | +** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked |
| 80523 | +** following a successful insert. |
| 78727 | 80524 | ** |
| 78728 | 80525 | ** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically |
| 78729 | 80526 | ** allocated, then ownership of P2 is transferred to the pseudo-cursor |
| 78730 | 80527 | ** and register P2 becomes ephemeral. If the cursor is changed, the |
| 78731 | 80528 | ** value of register P2 will then change. Make sure this does not |
| | @@ -78747,21 +80544,23 @@ |
| 78747 | 80544 | i64 iKey; /* The integer ROWID or key for the record to be inserted */ |
| 78748 | 80545 | VdbeCursor *pC; /* Cursor to table into which insert is written */ |
| 78749 | 80546 | int nZero; /* Number of zero-bytes to append */ |
| 78750 | 80547 | int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ |
| 78751 | 80548 | const char *zDb; /* database name - used by the update hook */ |
| 78752 | | - const char *zTbl; /* Table name - used by the opdate hook */ |
| 80549 | + Table *pTab; /* Table structure - used by update and pre-update hooks */ |
| 78753 | 80550 | int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ |
| 78754 | 80551 | |
| 80552 | + op = 0; |
| 78755 | 80553 | pData = &aMem[pOp->p2]; |
| 78756 | 80554 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 78757 | 80555 | assert( memIsValid(pData) ); |
| 78758 | 80556 | pC = p->apCsr[pOp->p1]; |
| 78759 | 80557 | assert( pC!=0 ); |
| 78760 | 80558 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 78761 | 80559 | assert( pC->uc.pCursor!=0 ); |
| 78762 | 80560 | assert( pC->isTable ); |
| 80561 | + assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); |
| 78763 | 80562 | REGISTER_TRACE(pOp->p2, pData); |
| 78764 | 80563 | |
| 78765 | 80564 | if( pOp->opcode==OP_Insert ){ |
| 78766 | 80565 | pKey = &aMem[pOp->p3]; |
| 78767 | 80566 | assert( pKey->flags & MEM_Int ); |
| | @@ -78770,10 +80569,32 @@ |
| 78770 | 80569 | iKey = pKey->u.i; |
| 78771 | 80570 | }else{ |
| 78772 | 80571 | assert( pOp->opcode==OP_InsertInt ); |
| 78773 | 80572 | iKey = pOp->p3; |
| 78774 | 80573 | } |
| 80574 | + |
| 80575 | + if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ |
| 80576 | + assert( pC->isTable ); |
| 80577 | + assert( pC->iDb>=0 ); |
| 80578 | + zDb = db->aDb[pC->iDb].zName; |
| 80579 | + pTab = pOp->p4.pTab; |
| 80580 | + assert( HasRowid(pTab) ); |
| 80581 | + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); |
| 80582 | + }else{ |
| 80583 | + pTab = 0; /* Not needed. Silence a comiler warning. */ |
| 80584 | + zDb = 0; /* Not needed. Silence a compiler warning. */ |
| 80585 | + } |
| 80586 | + |
| 80587 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 80588 | + /* Invoke the pre-update hook, if any */ |
| 80589 | + if( db->xPreUpdateCallback |
| 80590 | + && pOp->p4type==P4_TABLE |
| 80591 | + && !(pOp->p5 & OPFLAG_ISUPDATE) |
| 80592 | + ){ |
| 80593 | + sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, iKey, pOp->p2); |
| 80594 | + } |
| 80595 | +#endif |
| 78775 | 80596 | |
| 78776 | 80597 | if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; |
| 78777 | 80598 | if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey; |
| 78778 | 80599 | if( pData->flags & MEM_Null ){ |
| 78779 | 80600 | pData->z = 0; |
| | @@ -78794,22 +80615,17 @@ |
| 78794 | 80615 | pC->deferredMoveto = 0; |
| 78795 | 80616 | pC->cacheStatus = CACHE_STALE; |
| 78796 | 80617 | |
| 78797 | 80618 | /* Invoke the update-hook if required. */ |
| 78798 | 80619 | if( rc ) goto abort_due_to_error; |
| 78799 | | - if( db->xUpdateCallback && pOp->p4.z ){ |
| 78800 | | - zDb = db->aDb[pC->iDb].zName; |
| 78801 | | - zTbl = pOp->p4.z; |
| 78802 | | - op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); |
| 78803 | | - assert( pC->isTable ); |
| 78804 | | - db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); |
| 78805 | | - assert( pC->iDb>=0 ); |
| 80620 | + if( db->xUpdateCallback && op ){ |
| 80621 | + db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, iKey); |
| 78806 | 80622 | } |
| 78807 | 80623 | break; |
| 78808 | 80624 | } |
| 78809 | 80625 | |
| 78810 | | -/* Opcode: Delete P1 P2 * P4 P5 |
| 80626 | +/* Opcode: Delete P1 P2 P3 P4 P5 |
| 78811 | 80627 | ** |
| 78812 | 80628 | ** Delete the record at which the P1 cursor is currently pointing. |
| 78813 | 80629 | ** |
| 78814 | 80630 | ** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then |
| 78815 | 80631 | ** the cursor will be left pointing at either the next or the previous |
| | @@ -78829,42 +80645,77 @@ |
| 78829 | 80645 | ** change count is incremented (otherwise not). |
| 78830 | 80646 | ** |
| 78831 | 80647 | ** P1 must not be pseudo-table. It has to be a real table with |
| 78832 | 80648 | ** multiple rows. |
| 78833 | 80649 | ** |
| 78834 | | -** If P4 is not NULL, then it is the name of the table that P1 is |
| 78835 | | -** pointing to. The update hook will be invoked, if it exists. |
| 78836 | | -** If P4 is not NULL then the P1 cursor must have been positioned |
| 78837 | | -** using OP_NotFound prior to invoking this opcode. |
| 80650 | +** If P4 is not NULL then it points to a Table struture. In this case either |
| 80651 | +** the update or pre-update hook, or both, may be invoked. The P1 cursor must |
| 80652 | +** have been positioned using OP_NotFound prior to invoking this opcode in |
| 80653 | +** this case. Specifically, if one is configured, the pre-update hook is |
| 80654 | +** invoked if P4 is not NULL. The update-hook is invoked if one is configured, |
| 80655 | +** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. |
| 80656 | +** |
| 80657 | +** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address |
| 80658 | +** of the memory cell that contains the value that the rowid of the row will |
| 80659 | +** be set to by the update. |
| 78838 | 80660 | */ |
| 78839 | 80661 | case OP_Delete: { |
| 78840 | 80662 | VdbeCursor *pC; |
| 78841 | | - u8 hasUpdateCallback; |
| 80663 | + const char *zDb; |
| 80664 | + Table *pTab; |
| 80665 | + int opflags; |
| 78842 | 80666 | |
| 80667 | + opflags = pOp->p2; |
| 78843 | 80668 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 78844 | 80669 | pC = p->apCsr[pOp->p1]; |
| 78845 | 80670 | assert( pC!=0 ); |
| 78846 | 80671 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 78847 | 80672 | assert( pC->uc.pCursor!=0 ); |
| 78848 | 80673 | assert( pC->deferredMoveto==0 ); |
| 78849 | 80674 | |
| 78850 | | - hasUpdateCallback = db->xUpdateCallback && pOp->p4.z && pC->isTable; |
| 78851 | | - if( pOp->p5 && hasUpdateCallback ){ |
| 78852 | | - sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); |
| 78853 | | - } |
| 78854 | | - |
| 78855 | 80675 | #ifdef SQLITE_DEBUG |
| 78856 | | - /* The seek operation that positioned the cursor prior to OP_Delete will |
| 78857 | | - ** have also set the pC->movetoTarget field to the rowid of the row that |
| 78858 | | - ** is being deleted */ |
| 78859 | | - if( pOp->p4.z && pC->isTable && pOp->p5==0 ){ |
| 80676 | + if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ |
| 80677 | + /* If p5 is zero, the seek operation that positioned the cursor prior to |
| 80678 | + ** OP_Delete will have also set the pC->movetoTarget field to the rowid of |
| 80679 | + ** the row that is being deleted */ |
| 78860 | 80680 | i64 iKey = 0; |
| 78861 | 80681 | sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); |
| 78862 | | - assert( pC->movetoTarget==iKey ); |
| 80682 | + assert( pC->movetoTarget==iKey ); |
| 78863 | 80683 | } |
| 78864 | 80684 | #endif |
| 78865 | 80685 | |
| 80686 | + /* If the update-hook or pre-update-hook will be invoked, set zDb to |
| 80687 | + ** the name of the db to pass as to it. Also set local pTab to a copy |
| 80688 | + ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was |
| 80689 | + ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set |
| 80690 | + ** VdbeCursor.movetoTarget to the current rowid. */ |
| 80691 | + if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ |
| 80692 | + assert( pC->iDb>=0 ); |
| 80693 | + assert( pOp->p4.pTab!=0 ); |
| 80694 | + zDb = db->aDb[pC->iDb].zName; |
| 80695 | + pTab = pOp->p4.pTab; |
| 80696 | + if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ |
| 80697 | + sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); |
| 80698 | + } |
| 80699 | + }else{ |
| 80700 | + zDb = 0; /* Not needed. Silence a compiler warning. */ |
| 80701 | + pTab = 0; /* Not needed. Silence a compiler warning. */ |
| 80702 | + } |
| 80703 | + |
| 80704 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 80705 | + /* Invoke the pre-update-hook if required. */ |
| 80706 | + if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){ |
| 80707 | + assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); |
| 80708 | + sqlite3VdbePreUpdateHook(p, pC, |
| 80709 | + (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, |
| 80710 | + zDb, pTab, pC->movetoTarget, |
| 80711 | + pOp->p3 |
| 80712 | + ); |
| 80713 | + } |
| 80714 | + if( opflags & OPFLAG_ISNOOP ) break; |
| 80715 | +#endif |
| 80716 | + |
| 78866 | 80717 | /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ |
| 78867 | 80718 | assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); |
| 78868 | 80719 | assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); |
| 78869 | 80720 | assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); |
| 78870 | 80721 | |
| | @@ -78882,19 +80733,22 @@ |
| 78882 | 80733 | } |
| 78883 | 80734 | #endif |
| 78884 | 80735 | |
| 78885 | 80736 | rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); |
| 78886 | 80737 | pC->cacheStatus = CACHE_STALE; |
| 80738 | + if( rc ) goto abort_due_to_error; |
| 78887 | 80739 | |
| 78888 | 80740 | /* Invoke the update-hook if required. */ |
| 78889 | | - if( rc ) goto abort_due_to_error; |
| 78890 | | - if( hasUpdateCallback ){ |
| 78891 | | - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, |
| 78892 | | - db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget); |
| 78893 | | - assert( pC->iDb>=0 ); |
| 80741 | + if( opflags & OPFLAG_NCHANGE ){ |
| 80742 | + p->nChange++; |
| 80743 | + if( db->xUpdateCallback && HasRowid(pTab) ){ |
| 80744 | + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, |
| 80745 | + pC->movetoTarget); |
| 80746 | + assert( pC->iDb>=0 ); |
| 80747 | + } |
| 78894 | 80748 | } |
| 78895 | | - if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; |
| 80749 | + |
| 78896 | 80750 | break; |
| 78897 | 80751 | } |
| 78898 | 80752 | /* Opcode: ResetCount * * * * * |
| 78899 | 80753 | ** |
| 78900 | 80754 | ** The value of the change counter is copied to the database handle |
| | @@ -81385,10 +83239,12 @@ |
| 81385 | 83239 | int iOffset; /* Byte offset of blob in cursor data */ |
| 81386 | 83240 | int iCol; /* Table column this handle is open on */ |
| 81387 | 83241 | BtCursor *pCsr; /* Cursor pointing at blob row */ |
| 81388 | 83242 | sqlite3_stmt *pStmt; /* Statement holding cursor open */ |
| 81389 | 83243 | sqlite3 *db; /* The associated database */ |
| 83244 | + char *zDb; /* Database name */ |
| 83245 | + Table *pTab; /* Table object */ |
| 81390 | 83246 | }; |
| 81391 | 83247 | |
| 81392 | 83248 | |
| 81393 | 83249 | /* |
| 81394 | 83250 | ** This function is used by both blob_open() and blob_reopen(). It seeks |
| | @@ -81528,10 +83384,12 @@ |
| 81528 | 83384 | } |
| 81529 | 83385 | rc = SQLITE_ERROR; |
| 81530 | 83386 | sqlite3BtreeLeaveAll(db); |
| 81531 | 83387 | goto blob_open_out; |
| 81532 | 83388 | } |
| 83389 | + pBlob->pTab = pTab; |
| 83390 | + pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zName; |
| 81533 | 83391 | |
| 81534 | 83392 | /* Now search pTab for the exact column. */ |
| 81535 | 83393 | for(iCol=0; iCol<pTab->nCol; iCol++) { |
| 81536 | 83394 | if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ |
| 81537 | 83395 | break; |
| | @@ -81749,10 +83607,34 @@ |
| 81749 | 83607 | /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is |
| 81750 | 83608 | ** returned, clean-up the statement handle. |
| 81751 | 83609 | */ |
| 81752 | 83610 | assert( db == v->db ); |
| 81753 | 83611 | sqlite3BtreeEnterCursor(p->pCsr); |
| 83612 | + |
| 83613 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 83614 | + if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){ |
| 83615 | + /* If a pre-update hook is registered and this is a write cursor, |
| 83616 | + ** invoke it here. |
| 83617 | + ** |
| 83618 | + ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this |
| 83619 | + ** operation should really be an SQLITE_UPDATE. This is probably |
| 83620 | + ** incorrect, but is convenient because at this point the new.* values |
| 83621 | + ** are not easily obtainable. And for the sessions module, an |
| 83622 | + ** SQLITE_UPDATE where the PK columns do not change is handled in the |
| 83623 | + ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually |
| 83624 | + ** slightly more efficient). Since you cannot write to a PK column |
| 83625 | + ** using the incremental-blob API, this works. For the sessions module |
| 83626 | + ** anyhow. |
| 83627 | + */ |
| 83628 | + sqlite3_int64 iKey; |
| 83629 | + sqlite3BtreeKeySize(p->pCsr, &iKey); |
| 83630 | + sqlite3VdbePreUpdateHook( |
| 83631 | + v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1 |
| 83632 | + ); |
| 83633 | + } |
| 83634 | +#endif |
| 83635 | + |
| 81754 | 83636 | rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); |
| 81755 | 83637 | sqlite3BtreeLeaveCursor(p->pCsr); |
| 81756 | 83638 | if( rc==SQLITE_ABORT ){ |
| 81757 | 83639 | sqlite3VdbeFinalize(v); |
| 81758 | 83640 | p->pStmt = 0; |
| | @@ -84672,10 +86554,11 @@ |
| 84672 | 86554 | return SQLITE_IOERR_SHORT_READ; |
| 84673 | 86555 | } |
| 84674 | 86556 | #endif |
| 84675 | 86557 | |
| 84676 | 86558 | assert( (iAmt+iOfst)<=p->endpoint.iOffset ); |
| 86559 | + assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 ); |
| 84677 | 86560 | if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ |
| 84678 | 86561 | sqlite3_int64 iOff = 0; |
| 84679 | 86562 | for(pChunk=p->pFirst; |
| 84680 | 86563 | ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst; |
| 84681 | 86564 | pChunk=pChunk->pNext |
| | @@ -84682,10 +86565,11 @@ |
| 84682 | 86565 | ){ |
| 84683 | 86566 | iOff += p->nChunkSize; |
| 84684 | 86567 | } |
| 84685 | 86568 | }else{ |
| 84686 | 86569 | pChunk = p->readpoint.pChunk; |
| 86570 | + assert( pChunk!=0 ); |
| 84687 | 86571 | } |
| 84688 | 86572 | |
| 84689 | 86573 | iChunkOffset = (int)(iOfst%p->nChunkSize); |
| 84690 | 86574 | do { |
| 84691 | 86575 | int iSpace = p->nChunkSize - iChunkOffset; |
| | @@ -84693,11 +86577,11 @@ |
| 84693 | 86577 | memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy); |
| 84694 | 86578 | zOut += nCopy; |
| 84695 | 86579 | nRead -= iSpace; |
| 84696 | 86580 | iChunkOffset = 0; |
| 84697 | 86581 | } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); |
| 84698 | | - p->readpoint.iOffset = iOfst+iAmt; |
| 86582 | + p->readpoint.iOffset = pChunk ? iOfst+iAmt : 0; |
| 84699 | 86583 | p->readpoint.pChunk = pChunk; |
| 84700 | 86584 | |
| 84701 | 86585 | return SQLITE_OK; |
| 84702 | 86586 | } |
| 84703 | 86587 | |
| | @@ -93564,43 +95448,46 @@ |
| 93564 | 95448 | */ |
| 93565 | 95449 | SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ |
| 93566 | 95450 | analysisInfo sInfo; |
| 93567 | 95451 | HashElem *i; |
| 93568 | 95452 | char *zSql; |
| 93569 | | - int rc; |
| 95453 | + int rc = SQLITE_OK; |
| 93570 | 95454 | |
| 93571 | 95455 | assert( iDb>=0 && iDb<db->nDb ); |
| 93572 | 95456 | assert( db->aDb[iDb].pBt!=0 ); |
| 93573 | 95457 | |
| 93574 | 95458 | /* Clear any prior statistics */ |
| 93575 | 95459 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 93576 | 95460 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 93577 | 95461 | Index *pIdx = sqliteHashData(i); |
| 93578 | | - sqlite3DefaultRowEst(pIdx); |
| 95462 | + pIdx->aiRowLogEst[0] = 0; |
| 93579 | 95463 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 93580 | 95464 | sqlite3DeleteIndexSamples(db, pIdx); |
| 93581 | 95465 | pIdx->aSample = 0; |
| 93582 | 95466 | #endif |
| 93583 | 95467 | } |
| 93584 | 95468 | |
| 93585 | | - /* Check to make sure the sqlite_stat1 table exists */ |
| 95469 | + /* Load new statistics out of the sqlite_stat1 table */ |
| 93586 | 95470 | sInfo.db = db; |
| 93587 | 95471 | sInfo.zDatabase = db->aDb[iDb].zName; |
| 93588 | | - if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ |
| 93589 | | - return SQLITE_ERROR; |
| 95472 | + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){ |
| 95473 | + zSql = sqlite3MPrintf(db, |
| 95474 | + "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); |
| 95475 | + if( zSql==0 ){ |
| 95476 | + rc = SQLITE_NOMEM_BKPT; |
| 95477 | + }else{ |
| 95478 | + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); |
| 95479 | + sqlite3DbFree(db, zSql); |
| 95480 | + } |
| 93590 | 95481 | } |
| 93591 | 95482 | |
| 93592 | | - /* Load new statistics out of the sqlite_stat1 table */ |
| 93593 | | - zSql = sqlite3MPrintf(db, |
| 93594 | | - "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); |
| 93595 | | - if( zSql==0 ){ |
| 93596 | | - rc = SQLITE_NOMEM_BKPT; |
| 93597 | | - }else{ |
| 93598 | | - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); |
| 93599 | | - sqlite3DbFree(db, zSql); |
| 93600 | | - } |
| 93601 | | - |
| 95483 | + /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ |
| 95484 | + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 95485 | + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 95486 | + Index *pIdx = sqliteHashData(i); |
| 95487 | + if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx); |
| 95488 | + } |
| 93602 | 95489 | |
| 93603 | 95490 | /* Load the statistics from the sqlite_stat4 table. */ |
| 93604 | 95491 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 93605 | 95492 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 93606 | 95493 | db->lookaside.bDisable++; |
| | @@ -96648,48 +98535,59 @@ |
| 96648 | 98535 | ** to the elements of the FROM clause. But we do not want these changes |
| 96649 | 98536 | ** to be permanent. So the computation is done on a copy of the SELECT |
| 96650 | 98537 | ** statement that defines the view. |
| 96651 | 98538 | */ |
| 96652 | 98539 | assert( pTable->pSelect ); |
| 96653 | | - if( pTable->pCheck ){ |
| 96654 | | - db->lookaside.bDisable++; |
| 96655 | | - sqlite3ColumnsFromExprList(pParse, pTable->pCheck, |
| 96656 | | - &pTable->nCol, &pTable->aCol); |
| 96657 | | - db->lookaside.bDisable--; |
| 96658 | | - }else{ |
| 96659 | | - pSel = sqlite3SelectDup(db, pTable->pSelect, 0); |
| 96660 | | - if( pSel ){ |
| 96661 | | - n = pParse->nTab; |
| 96662 | | - sqlite3SrcListAssignCursors(pParse, pSel->pSrc); |
| 96663 | | - pTable->nCol = -1; |
| 96664 | | - db->lookaside.bDisable++; |
| 96665 | | -#ifndef SQLITE_OMIT_AUTHORIZATION |
| 96666 | | - xAuth = db->xAuth; |
| 96667 | | - db->xAuth = 0; |
| 96668 | | - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96669 | | - db->xAuth = xAuth; |
| 96670 | | -#else |
| 96671 | | - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96672 | | -#endif |
| 96673 | | - db->lookaside.bDisable--; |
| 96674 | | - pParse->nTab = n; |
| 96675 | | - if( pSelTab ){ |
| 96676 | | - assert( pTable->aCol==0 ); |
| 96677 | | - pTable->nCol = pSelTab->nCol; |
| 96678 | | - pTable->aCol = pSelTab->aCol; |
| 96679 | | - pSelTab->nCol = 0; |
| 96680 | | - pSelTab->aCol = 0; |
| 96681 | | - sqlite3DeleteTable(db, pSelTab); |
| 96682 | | - assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); |
| 96683 | | - }else{ |
| 96684 | | - pTable->nCol = 0; |
| 96685 | | - nErr++; |
| 96686 | | - } |
| 96687 | | - sqlite3SelectDelete(db, pSel); |
| 96688 | | - } else { |
| 96689 | | - nErr++; |
| 96690 | | - } |
| 98540 | + pSel = sqlite3SelectDup(db, pTable->pSelect, 0); |
| 98541 | + if( pSel ){ |
| 98542 | + n = pParse->nTab; |
| 98543 | + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); |
| 98544 | + pTable->nCol = -1; |
| 98545 | + db->lookaside.bDisable++; |
| 98546 | +#ifndef SQLITE_OMIT_AUTHORIZATION |
| 98547 | + xAuth = db->xAuth; |
| 98548 | + db->xAuth = 0; |
| 98549 | + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 98550 | + db->xAuth = xAuth; |
| 98551 | +#else |
| 98552 | + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 98553 | +#endif |
| 98554 | + pParse->nTab = n; |
| 98555 | + if( pTable->pCheck ){ |
| 98556 | + /* CREATE VIEW name(arglist) AS ... |
| 98557 | + ** The names of the columns in the table are taken from |
| 98558 | + ** arglist which is stored in pTable->pCheck. The pCheck field |
| 98559 | + ** normally holds CHECK constraints on an ordinary table, but for |
| 98560 | + ** a VIEW it holds the list of column names. |
| 98561 | + */ |
| 98562 | + sqlite3ColumnsFromExprList(pParse, pTable->pCheck, |
| 98563 | + &pTable->nCol, &pTable->aCol); |
| 98564 | + if( db->mallocFailed==0 |
| 98565 | + && pParse->nErr==0 |
| 98566 | + && pTable->nCol==pSel->pEList->nExpr |
| 98567 | + ){ |
| 98568 | + sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel); |
| 98569 | + } |
| 98570 | + }else if( pSelTab ){ |
| 98571 | + /* CREATE VIEW name AS... without an argument list. Construct |
| 98572 | + ** the column names from the SELECT statement that defines the view. |
| 98573 | + */ |
| 98574 | + assert( pTable->aCol==0 ); |
| 98575 | + pTable->nCol = pSelTab->nCol; |
| 98576 | + pTable->aCol = pSelTab->aCol; |
| 98577 | + pSelTab->nCol = 0; |
| 98578 | + pSelTab->aCol = 0; |
| 98579 | + assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); |
| 98580 | + }else{ |
| 98581 | + pTable->nCol = 0; |
| 98582 | + nErr++; |
| 98583 | + } |
| 98584 | + if( pSelTab ) sqlite3DeleteTable(db, pSelTab); |
| 98585 | + sqlite3SelectDelete(db, pSel); |
| 98586 | + db->lookaside.bDisable--; |
| 98587 | + } else { |
| 98588 | + nErr++; |
| 96691 | 98589 | } |
| 96692 | 98590 | pTable->pSchema->schemaFlags |= DB_UnresetViews; |
| 96693 | 98591 | #endif /* SQLITE_OMIT_VIEW */ |
| 96694 | 98592 | return nErr; |
| 96695 | 98593 | } |
| | @@ -97234,10 +99132,11 @@ |
| 97234 | 99132 | tnum = memRootPage; |
| 97235 | 99133 | }else{ |
| 97236 | 99134 | tnum = pIndex->tnum; |
| 97237 | 99135 | } |
| 97238 | 99136 | pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); |
| 99137 | + assert( pKey!=0 || db->mallocFailed || pParse->nErr ); |
| 97239 | 99138 | |
| 97240 | 99139 | /* Open the sorter cursor if we are to use one. */ |
| 97241 | 99140 | iSorter = pParse->nTab++; |
| 97242 | 99141 | sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*) |
| 97243 | 99142 | sqlite3KeyInfoRef(pKey), P4_KEYINFO); |
| | @@ -97257,12 +99156,11 @@ |
| 97257 | 99156 | sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, |
| 97258 | 99157 | (char *)pKey, P4_KEYINFO); |
| 97259 | 99158 | sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); |
| 97260 | 99159 | |
| 97261 | 99160 | addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); |
| 97262 | | - assert( pKey!=0 || db->mallocFailed || pParse->nErr ); |
| 97263 | | - if( IsUniqueIndex(pIndex) && pKey!=0 ){ |
| 99161 | + if( IsUniqueIndex(pIndex) ){ |
| 97264 | 99162 | int j2 = sqlite3VdbeCurrentAddr(v) + 3; |
| 97265 | 99163 | sqlite3VdbeGoto(v, j2); |
| 97266 | 99164 | addr2 = sqlite3VdbeCurrentAddr(v); |
| 97267 | 99165 | sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, |
| 97268 | 99166 | pIndex->nKeyCol); VdbeCoverage(v); |
| | @@ -99735,10 +101633,13 @@ |
| 99735 | 101633 | ** API function sqlite3_count_changes) to be set incorrectly. */ |
| 99736 | 101634 | if( rcauth==SQLITE_OK |
| 99737 | 101635 | && pWhere==0 |
| 99738 | 101636 | && !bComplex |
| 99739 | 101637 | && !IsVirtual(pTab) |
| 101638 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 101639 | + && db->xPreUpdateCallback==0 |
| 101640 | +#endif |
| 99740 | 101641 | ){ |
| 99741 | 101642 | assert( !isView ); |
| 99742 | 101643 | sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); |
| 99743 | 101644 | if( HasRowid(pTab) ){ |
| 99744 | 101645 | sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, |
| | @@ -100084,18 +101985,23 @@ |
| 100084 | 101985 | sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); |
| 100085 | 101986 | } |
| 100086 | 101987 | |
| 100087 | 101988 | /* Delete the index and table entries. Skip this step if pTab is really |
| 100088 | 101989 | ** a view (in which case the only effect of the DELETE statement is to |
| 100089 | | - ** fire the INSTEAD OF triggers). */ |
| 101990 | + ** fire the INSTEAD OF triggers). |
| 101991 | + ** |
| 101992 | + ** If variable 'count' is non-zero, then this OP_Delete instruction should |
| 101993 | + ** invoke the update-hook. The pre-update-hook, on the other hand should |
| 101994 | + ** be invoked unless table pTab is a system table. The difference is that |
| 101995 | + ** the update-hook is not invoked for rows removed by REPLACE, but the |
| 101996 | + ** pre-update-hook is. |
| 101997 | + */ |
| 100090 | 101998 | if( pTab->pSelect==0 ){ |
| 100091 | 101999 | u8 p5 = 0; |
| 100092 | 102000 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
| 100093 | 102001 | sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
| 100094 | | - if( count ){ |
| 100095 | | - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); |
| 100096 | | - } |
| 102002 | + sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); |
| 100097 | 102003 | if( eMode!=ONEPASS_OFF ){ |
| 100098 | 102004 | sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); |
| 100099 | 102005 | } |
| 100100 | 102006 | if( iIdxNoSeek>=0 ){ |
| 100101 | 102007 | sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
| | @@ -103254,11 +105160,10 @@ |
| 103254 | 105160 | |
| 103255 | 105161 | action = pFKey->aAction[iAction]; |
| 103256 | 105162 | if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ |
| 103257 | 105163 | return 0; |
| 103258 | 105164 | } |
| 103259 | | - |
| 103260 | 105165 | pTrigger = pFKey->apTrigger[iAction]; |
| 103261 | 105166 | |
| 103262 | 105167 | if( action!=OE_None && !pTrigger ){ |
| 103263 | 105168 | char const *zFrom; /* Name of child table */ |
| 103264 | 105169 | int nFrom; /* Length in bytes of zFrom */ |
| | @@ -104931,13 +106836,22 @@ |
| 104931 | 106836 | pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
| 104932 | 106837 | } |
| 104933 | 106838 | if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ |
| 104934 | 106839 | sqlite3MultiWrite(pParse); |
| 104935 | 106840 | sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, |
| 104936 | | - regNewData, 1, 0, OE_Replace, |
| 104937 | | - ONEPASS_SINGLE, -1); |
| 106841 | + regNewData, 1, 0, OE_Replace, 1, -1); |
| 104938 | 106842 | }else{ |
| 106843 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 106844 | + if( HasRowid(pTab) ){ |
| 106845 | + /* This OP_Delete opcode fires the pre-update-hook only. It does |
| 106846 | + ** not modify the b-tree. It is more efficient to let the coming |
| 106847 | + ** OP_Insert replace the existing entry than it is to delete the |
| 106848 | + ** existing entry and then insert a new one. */ |
| 106849 | + sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); |
| 106850 | + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); |
| 106851 | + } |
| 106852 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 104939 | 106853 | if( pTab->pIndex ){ |
| 104940 | 106854 | sqlite3MultiWrite(pParse); |
| 104941 | 106855 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); |
| 104942 | 106856 | } |
| 104943 | 106857 | } |
| | @@ -105203,11 +107117,11 @@ |
| 105203 | 107117 | if( useSeekResult ){ |
| 105204 | 107118 | pik_flags |= OPFLAG_USESEEKRESULT; |
| 105205 | 107119 | } |
| 105206 | 107120 | sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); |
| 105207 | 107121 | if( !pParse->nested ){ |
| 105208 | | - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); |
| 107122 | + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); |
| 105209 | 107123 | } |
| 105210 | 107124 | sqlite3VdbeChangeP5(v, pik_flags); |
| 105211 | 107125 | } |
| 105212 | 107126 | |
| 105213 | 107127 | /* |
| | @@ -105603,11 +107517,11 @@ |
| 105603 | 107517 | addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); |
| 105604 | 107518 | assert( (pDest->tabFlags & TF_Autoincrement)==0 ); |
| 105605 | 107519 | } |
| 105606 | 107520 | sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); |
| 105607 | 107521 | sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, |
| 105608 | | - pDest->zName, 0); |
| 107522 | + (char*)pDest, P4_TABLE); |
| 105609 | 107523 | sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); |
| 105610 | 107524 | sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); |
| 105611 | 107525 | sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); |
| 105612 | 107526 | sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
| 105613 | 107527 | }else{ |
| | @@ -112191,11 +114105,11 @@ |
| 112191 | 114105 | ** routine goes through and adds the types and collations. |
| 112192 | 114106 | ** |
| 112193 | 114107 | ** This routine requires that all identifiers in the SELECT |
| 112194 | 114108 | ** statement be resolved. |
| 112195 | 114109 | */ |
| 112196 | | -static void selectAddColumnTypeAndCollation( |
| 114110 | +SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation( |
| 112197 | 114111 | Parse *pParse, /* Parsing contexts */ |
| 112198 | 114112 | Table *pTab, /* Add column type information to this table */ |
| 112199 | 114113 | Select *pSelect /* SELECT used to determine types and collations */ |
| 112200 | 114114 | ){ |
| 112201 | 114115 | sqlite3 *db = pParse->db; |
| | @@ -112213,14 +114127,24 @@ |
| 112213 | 114127 | if( db->mallocFailed ) return; |
| 112214 | 114128 | memset(&sNC, 0, sizeof(sNC)); |
| 112215 | 114129 | sNC.pSrcList = pSelect->pSrc; |
| 112216 | 114130 | a = pSelect->pEList->a; |
| 112217 | 114131 | for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ |
| 114132 | + const char *zType; |
| 114133 | + int n, m; |
| 112218 | 114134 | p = a[i].pExpr; |
| 112219 | | - columnType(&sNC, p, 0, 0, 0, &pCol->szEst); |
| 114135 | + zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); |
| 112220 | 114136 | szAll += pCol->szEst; |
| 112221 | 114137 | pCol->affinity = sqlite3ExprAffinity(p); |
| 114138 | + if( zType && (m = sqlite3Strlen30(zType))>0 ){ |
| 114139 | + n = sqlite3Strlen30(pCol->zName); |
| 114140 | + pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2); |
| 114141 | + if( pCol->zName ){ |
| 114142 | + memcpy(&pCol->zName[n+1], zType, m+1); |
| 114143 | + pCol->colFlags |= COLFLAG_HASTYPE; |
| 114144 | + } |
| 114145 | + } |
| 112222 | 114146 | if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; |
| 112223 | 114147 | pColl = sqlite3ExprCollSeq(pParse, p); |
| 112224 | 114148 | if( pColl && pCol->zColl==0 ){ |
| 112225 | 114149 | pCol->zColl = sqlite3DbStrDup(db, pColl->zName); |
| 112226 | 114150 | } |
| | @@ -112253,11 +114177,11 @@ |
| 112253 | 114177 | assert( db->lookaside.bDisable ); |
| 112254 | 114178 | pTab->nRef = 1; |
| 112255 | 114179 | pTab->zName = 0; |
| 112256 | 114180 | pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 112257 | 114181 | sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
| 112258 | | - selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| 114182 | + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| 112259 | 114183 | pTab->iPKey = -1; |
| 112260 | 114184 | if( db->mallocFailed ){ |
| 112261 | 114185 | sqlite3DeleteTable(db, pTab); |
| 112262 | 114186 | return 0; |
| 112263 | 114187 | } |
| | @@ -115037,11 +116961,11 @@ |
| 115037 | 116961 | if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
| 115038 | 116962 | /* A sub-query in the FROM clause of a SELECT */ |
| 115039 | 116963 | Select *pSel = pFrom->pSelect; |
| 115040 | 116964 | if( pSel ){ |
| 115041 | 116965 | while( pSel->pPrior ) pSel = pSel->pPrior; |
| 115042 | | - selectAddColumnTypeAndCollation(pParse, pTab, pSel); |
| 116966 | + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel); |
| 115043 | 116967 | } |
| 115044 | 116968 | } |
| 115045 | 116969 | } |
| 115046 | 116970 | } |
| 115047 | 116971 | #endif |
| | @@ -118045,15 +119969,34 @@ |
| 118045 | 119969 | addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); |
| 118046 | 119970 | } |
| 118047 | 119971 | VdbeCoverageNeverTaken(v); |
| 118048 | 119972 | } |
| 118049 | 119973 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); |
| 118050 | | - |
| 118051 | | - /* If changing the record number, delete the old record. */ |
| 119974 | + |
| 119975 | + /* If changing the rowid value, or if there are foreign key constraints |
| 119976 | + ** to process, delete the old record. Otherwise, add a noop OP_Delete |
| 119977 | + ** to invoke the pre-update hook. |
| 119978 | + ** |
| 119979 | + ** That (regNew==regnewRowid+1) is true is also important for the |
| 119980 | + ** pre-update hook. If the caller invokes preupdate_new(), the returned |
| 119981 | + ** value is copied from memory cell (regNewRowid+1+iCol), where iCol |
| 119982 | + ** is the column index supplied by the user. |
| 119983 | + */ |
| 119984 | + assert( regNew==regNewRowid+1 ); |
| 119985 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 119986 | + sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, |
| 119987 | + OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP), |
| 119988 | + regNewRowid |
| 119989 | + ); |
| 119990 | + if( !pParse->nested ){ |
| 119991 | + sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); |
| 119992 | + } |
| 119993 | +#else |
| 118052 | 119994 | if( hasFK || chngKey || pPk!=0 ){ |
| 118053 | 119995 | sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); |
| 118054 | 119996 | } |
| 119997 | +#endif |
| 118055 | 119998 | if( bReplace || chngKey ){ |
| 118056 | 119999 | sqlite3VdbeJumpHere(v, addr1); |
| 118057 | 120000 | } |
| 118058 | 120001 | |
| 118059 | 120002 | if( hasFK ){ |
| | @@ -125726,12 +127669,10 @@ |
| 125726 | 127669 | |
| 125727 | 127670 | assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); |
| 125728 | 127671 | assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); |
| 125729 | 127672 | if( pNew->wsFlags & WHERE_BTM_LIMIT ){ |
| 125730 | 127673 | opMask = WO_LT|WO_LE; |
| 125731 | | - }else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){ |
| 125732 | | - opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; |
| 125733 | 127674 | }else{ |
| 125734 | 127675 | opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; |
| 125735 | 127676 | } |
| 125736 | 127677 | if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); |
| 125737 | 127678 | |
| | @@ -125764,10 +127705,22 @@ |
| 125764 | 127705 | if( pTerm->prereqRight & pNew->maskSelf ) continue; |
| 125765 | 127706 | |
| 125766 | 127707 | /* Do not allow the upper bound of a LIKE optimization range constraint |
| 125767 | 127708 | ** to mix with a lower range bound from some other source */ |
| 125768 | 127709 | if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; |
| 127710 | + |
| 127711 | + /* Do not allow IS constraints from the WHERE clause to be used by the |
| 127712 | + ** right table of a LEFT JOIN. Only constraints in the ON clause are |
| 127713 | + ** allowed */ |
| 127714 | + if( (pSrc->fg.jointype & JT_LEFT)!=0 |
| 127715 | + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) |
| 127716 | + && (eOp & (WO_IS|WO_ISNULL))!=0 |
| 127717 | + ){ |
| 127718 | + testcase( eOp & WO_IS ); |
| 127719 | + testcase( eOp & WO_ISNULL ); |
| 127720 | + continue; |
| 127721 | + } |
| 125769 | 127722 | |
| 125770 | 127723 | pNew->wsFlags = saved_wsFlags; |
| 125771 | 127724 | pNew->u.btree.nEq = saved_nEq; |
| 125772 | 127725 | pNew->nLTerm = saved_nLTerm; |
| 125773 | 127726 | if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ |
| | @@ -135114,10 +137067,31 @@ |
| 135114 | 137067 | db->pRollbackArg = pArg; |
| 135115 | 137068 | sqlite3_mutex_leave(db->mutex); |
| 135116 | 137069 | return pRet; |
| 135117 | 137070 | } |
| 135118 | 137071 | |
| 137072 | +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 137073 | +/* |
| 137074 | +** Register a callback to be invoked each time a row is updated, |
| 137075 | +** inserted or deleted using this database connection. |
| 137076 | +*/ |
| 137077 | +SQLITE_API void *SQLITE_STDCALL sqlite3_preupdate_hook( |
| 137078 | + sqlite3 *db, /* Attach the hook to this database */ |
| 137079 | + void(*xCallback)( /* Callback function */ |
| 137080 | + void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64), |
| 137081 | + void *pArg /* First callback argument */ |
| 137082 | +){ |
| 137083 | + void *pRet; |
| 137084 | + sqlite3_mutex_enter(db->mutex); |
| 137085 | + pRet = db->pPreUpdateArg; |
| 137086 | + db->xPreUpdateCallback = xCallback; |
| 137087 | + db->pPreUpdateArg = pArg; |
| 137088 | + sqlite3_mutex_leave(db->mutex); |
| 137089 | + return pRet; |
| 137090 | +} |
| 137091 | +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 137092 | + |
| 135119 | 137093 | #ifndef SQLITE_OMIT_WAL |
| 135120 | 137094 | /* |
| 135121 | 137095 | ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). |
| 135122 | 137096 | ** Invoke sqlite3_wal_checkpoint if the number of frames in the log file |
| 135123 | 137097 | ** is greater than sqlite3.pWalArg cast to an integer (the value configured by |
| | @@ -166423,10 +168397,4651 @@ |
| 166423 | 168397 | #elif defined(SQLITE_ENABLE_DBSTAT_VTAB) |
| 166424 | 168398 | SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; } |
| 166425 | 168399 | #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ |
| 166426 | 168400 | |
| 166427 | 168401 | /************** End of dbstat.c **********************************************/ |
| 168402 | +/************** Begin file sqlite3session.c **********************************/ |
| 168403 | + |
| 168404 | +#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) |
| 168405 | +/* #include "sqlite3session.h" */ |
| 168406 | +/* #include <assert.h> */ |
| 168407 | +/* #include <string.h> */ |
| 168408 | + |
| 168409 | +#ifndef SQLITE_AMALGAMATION |
| 168410 | +/* # include "sqliteInt.h" */ |
| 168411 | +/* # include "vdbeInt.h" */ |
| 168412 | +#endif |
| 168413 | + |
| 168414 | +typedef struct SessionTable SessionTable; |
| 168415 | +typedef struct SessionChange SessionChange; |
| 168416 | +typedef struct SessionBuffer SessionBuffer; |
| 168417 | +typedef struct SessionInput SessionInput; |
| 168418 | + |
| 168419 | +/* |
| 168420 | +** Minimum chunk size used by streaming versions of functions. |
| 168421 | +*/ |
| 168422 | +#ifndef SESSIONS_STRM_CHUNK_SIZE |
| 168423 | +# ifdef SQLITE_TEST |
| 168424 | +# define SESSIONS_STRM_CHUNK_SIZE 64 |
| 168425 | +# else |
| 168426 | +# define SESSIONS_STRM_CHUNK_SIZE 1024 |
| 168427 | +# endif |
| 168428 | +#endif |
| 168429 | + |
| 168430 | +typedef struct SessionHook SessionHook; |
| 168431 | +struct SessionHook { |
| 168432 | + void *pCtx; |
| 168433 | + int (*xOld)(void*,int,sqlite3_value**); |
| 168434 | + int (*xNew)(void*,int,sqlite3_value**); |
| 168435 | + int (*xCount)(void*); |
| 168436 | + int (*xDepth)(void*); |
| 168437 | +}; |
| 168438 | + |
| 168439 | +/* |
| 168440 | +** Session handle structure. |
| 168441 | +*/ |
| 168442 | +struct sqlite3_session { |
| 168443 | + sqlite3 *db; /* Database handle session is attached to */ |
| 168444 | + char *zDb; /* Name of database session is attached to */ |
| 168445 | + int bEnable; /* True if currently recording */ |
| 168446 | + int bIndirect; /* True if all changes are indirect */ |
| 168447 | + int bAutoAttach; /* True to auto-attach tables */ |
| 168448 | + int rc; /* Non-zero if an error has occurred */ |
| 168449 | + void *pFilterCtx; /* First argument to pass to xTableFilter */ |
| 168450 | + int (*xTableFilter)(void *pCtx, const char *zTab); |
| 168451 | + sqlite3_session *pNext; /* Next session object on same db. */ |
| 168452 | + SessionTable *pTable; /* List of attached tables */ |
| 168453 | + SessionHook hook; /* APIs to grab new and old data with */ |
| 168454 | +}; |
| 168455 | + |
| 168456 | +/* |
| 168457 | +** Instances of this structure are used to build strings or binary records. |
| 168458 | +*/ |
| 168459 | +struct SessionBuffer { |
| 168460 | + u8 *aBuf; /* Pointer to changeset buffer */ |
| 168461 | + int nBuf; /* Size of buffer aBuf */ |
| 168462 | + int nAlloc; /* Size of allocation containing aBuf */ |
| 168463 | +}; |
| 168464 | + |
| 168465 | +/* |
| 168466 | +** An object of this type is used internally as an abstraction for |
| 168467 | +** input data. Input data may be supplied either as a single large buffer |
| 168468 | +** (e.g. sqlite3changeset_start()) or using a stream function (e.g. |
| 168469 | +** sqlite3changeset_start_strm()). |
| 168470 | +*/ |
| 168471 | +struct SessionInput { |
| 168472 | + int bNoDiscard; /* If true, discard no data */ |
| 168473 | + int iCurrent; /* Offset in aData[] of current change */ |
| 168474 | + int iNext; /* Offset in aData[] of next change */ |
| 168475 | + u8 *aData; /* Pointer to buffer containing changeset */ |
| 168476 | + int nData; /* Number of bytes in aData */ |
| 168477 | + |
| 168478 | + SessionBuffer buf; /* Current read buffer */ |
| 168479 | + int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */ |
| 168480 | + void *pIn; /* First argument to xInput */ |
| 168481 | + int bEof; /* Set to true after xInput finished */ |
| 168482 | +}; |
| 168483 | + |
| 168484 | +/* |
| 168485 | +** Structure for changeset iterators. |
| 168486 | +*/ |
| 168487 | +struct sqlite3_changeset_iter { |
| 168488 | + SessionInput in; /* Input buffer or stream */ |
| 168489 | + SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ |
| 168490 | + int bPatchset; /* True if this is a patchset */ |
| 168491 | + int rc; /* Iterator error code */ |
| 168492 | + sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ |
| 168493 | + char *zTab; /* Current table */ |
| 168494 | + int nCol; /* Number of columns in zTab */ |
| 168495 | + int op; /* Current operation */ |
| 168496 | + int bIndirect; /* True if current change was indirect */ |
| 168497 | + u8 *abPK; /* Primary key array */ |
| 168498 | + sqlite3_value **apValue; /* old.* and new.* values */ |
| 168499 | +}; |
| 168500 | + |
| 168501 | +/* |
| 168502 | +** Each session object maintains a set of the following structures, one |
| 168503 | +** for each table the session object is monitoring. The structures are |
| 168504 | +** stored in a linked list starting at sqlite3_session.pTable. |
| 168505 | +** |
| 168506 | +** The keys of the SessionTable.aChange[] hash table are all rows that have |
| 168507 | +** been modified in any way since the session object was attached to the |
| 168508 | +** table. |
| 168509 | +** |
| 168510 | +** The data associated with each hash-table entry is a structure containing |
| 168511 | +** a subset of the initial values that the modified row contained at the |
| 168512 | +** start of the session. Or no initial values if the row was inserted. |
| 168513 | +*/ |
| 168514 | +struct SessionTable { |
| 168515 | + SessionTable *pNext; |
| 168516 | + char *zName; /* Local name of table */ |
| 168517 | + int nCol; /* Number of columns in table zName */ |
| 168518 | + const char **azCol; /* Column names */ |
| 168519 | + u8 *abPK; /* Array of primary key flags */ |
| 168520 | + int nEntry; /* Total number of entries in hash table */ |
| 168521 | + int nChange; /* Size of apChange[] array */ |
| 168522 | + SessionChange **apChange; /* Hash table buckets */ |
| 168523 | +}; |
| 168524 | + |
| 168525 | +/* |
| 168526 | +** RECORD FORMAT: |
| 168527 | +** |
| 168528 | +** The following record format is similar to (but not compatible with) that |
| 168529 | +** used in SQLite database files. This format is used as part of the |
| 168530 | +** change-set binary format, and so must be architecture independent. |
| 168531 | +** |
| 168532 | +** Unlike the SQLite database record format, each field is self-contained - |
| 168533 | +** there is no separation of header and data. Each field begins with a |
| 168534 | +** single byte describing its type, as follows: |
| 168535 | +** |
| 168536 | +** 0x00: Undefined value. |
| 168537 | +** 0x01: Integer value. |
| 168538 | +** 0x02: Real value. |
| 168539 | +** 0x03: Text value. |
| 168540 | +** 0x04: Blob value. |
| 168541 | +** 0x05: SQL NULL value. |
| 168542 | +** |
| 168543 | +** Note that the above match the definitions of SQLITE_INTEGER, SQLITE_TEXT |
| 168544 | +** and so on in sqlite3.h. For undefined and NULL values, the field consists |
| 168545 | +** only of the single type byte. For other types of values, the type byte |
| 168546 | +** is followed by: |
| 168547 | +** |
| 168548 | +** Text values: |
| 168549 | +** A varint containing the number of bytes in the value (encoded using |
| 168550 | +** UTF-8). Followed by a buffer containing the UTF-8 representation |
| 168551 | +** of the text value. There is no nul terminator. |
| 168552 | +** |
| 168553 | +** Blob values: |
| 168554 | +** A varint containing the number of bytes in the value, followed by |
| 168555 | +** a buffer containing the value itself. |
| 168556 | +** |
| 168557 | +** Integer values: |
| 168558 | +** An 8-byte big-endian integer value. |
| 168559 | +** |
| 168560 | +** Real values: |
| 168561 | +** An 8-byte big-endian IEEE 754-2008 real value. |
| 168562 | +** |
| 168563 | +** Varint values are encoded in the same way as varints in the SQLite |
| 168564 | +** record format. |
| 168565 | +** |
| 168566 | +** CHANGESET FORMAT: |
| 168567 | +** |
| 168568 | +** A changeset is a collection of DELETE, UPDATE and INSERT operations on |
| 168569 | +** one or more tables. Operations on a single table are grouped together, |
| 168570 | +** but may occur in any order (i.e. deletes, updates and inserts are all |
| 168571 | +** mixed together). |
| 168572 | +** |
| 168573 | +** Each group of changes begins with a table header: |
| 168574 | +** |
| 168575 | +** 1 byte: Constant 0x54 (capital 'T') |
| 168576 | +** Varint: Number of columns in the table. |
| 168577 | +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. |
| 168578 | +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. |
| 168579 | +** |
| 168580 | +** Followed by one or more changes to the table. |
| 168581 | +** |
| 168582 | +** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09). |
| 168583 | +** 1 byte: The "indirect-change" flag. |
| 168584 | +** old.* record: (delete and update only) |
| 168585 | +** new.* record: (insert and update only) |
| 168586 | +** |
| 168587 | +** The "old.*" and "new.*" records, if present, are N field records in the |
| 168588 | +** format described above under "RECORD FORMAT", where N is the number of |
| 168589 | +** columns in the table. The i'th field of each record is associated with |
| 168590 | +** the i'th column of the table, counting from left to right in the order |
| 168591 | +** in which columns were declared in the CREATE TABLE statement. |
| 168592 | +** |
| 168593 | +** The new.* record that is part of each INSERT change contains the values |
| 168594 | +** that make up the new row. Similarly, the old.* record that is part of each |
| 168595 | +** DELETE change contains the values that made up the row that was deleted |
| 168596 | +** from the database. In the changeset format, the records that are part |
| 168597 | +** of INSERT or DELETE changes never contain any undefined (type byte 0x00) |
| 168598 | +** fields. |
| 168599 | +** |
| 168600 | +** Within the old.* record associated with an UPDATE change, all fields |
| 168601 | +** associated with table columns that are not PRIMARY KEY columns and are |
| 168602 | +** not modified by the UPDATE change are set to "undefined". Other fields |
| 168603 | +** are set to the values that made up the row before the UPDATE that the |
| 168604 | +** change records took place. Within the new.* record, fields associated |
| 168605 | +** with table columns modified by the UPDATE change contain the new |
| 168606 | +** values. Fields associated with table columns that are not modified |
| 168607 | +** are set to "undefined". |
| 168608 | +** |
| 168609 | +** PATCHSET FORMAT: |
| 168610 | +** |
| 168611 | +** A patchset is also a collection of changes. It is similar to a changeset, |
| 168612 | +** but leaves undefined those fields that are not useful if no conflict |
| 168613 | +** resolution is required when applying the changeset. |
| 168614 | +** |
| 168615 | +** Each group of changes begins with a table header: |
| 168616 | +** |
| 168617 | +** 1 byte: Constant 0x50 (capital 'P') |
| 168618 | +** Varint: Number of columns in the table. |
| 168619 | +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. |
| 168620 | +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. |
| 168621 | +** |
| 168622 | +** Followed by one or more changes to the table. |
| 168623 | +** |
| 168624 | +** 1 byte: Either SQLITE_INSERT (0x12), UPDATE (0x17) or DELETE (0x09). |
| 168625 | +** 1 byte: The "indirect-change" flag. |
| 168626 | +** single record: (PK fields for DELETE, PK and modified fields for UPDATE, |
| 168627 | +** full record for INSERT). |
| 168628 | +** |
| 168629 | +** As in the changeset format, each field of the single record that is part |
| 168630 | +** of a patchset change is associated with the correspondingly positioned |
| 168631 | +** table column, counting from left to right within the CREATE TABLE |
| 168632 | +** statement. |
| 168633 | +** |
| 168634 | +** For a DELETE change, all fields within the record except those associated |
| 168635 | +** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields |
| 168636 | +** contain the values identifying the row to delete. |
| 168637 | +** |
| 168638 | +** For an UPDATE change, all fields except those associated with PRIMARY KEY |
| 168639 | +** columns and columns that are modified by the UPDATE are set to "undefined". |
| 168640 | +** PRIMARY KEY fields contain the values identifying the table row to update, |
| 168641 | +** and fields associated with modified columns contain the new column values. |
| 168642 | +** |
| 168643 | +** The records associated with INSERT changes are in the same format as for |
| 168644 | +** changesets. It is not possible for a record associated with an INSERT |
| 168645 | +** change to contain a field set to "undefined". |
| 168646 | +*/ |
| 168647 | + |
| 168648 | +/* |
| 168649 | +** For each row modified during a session, there exists a single instance of |
| 168650 | +** this structure stored in a SessionTable.aChange[] hash table. |
| 168651 | +*/ |
| 168652 | +struct SessionChange { |
| 168653 | + int op; /* One of UPDATE, DELETE, INSERT */ |
| 168654 | + int bIndirect; /* True if this change is "indirect" */ |
| 168655 | + int nRecord; /* Number of bytes in buffer aRecord[] */ |
| 168656 | + u8 *aRecord; /* Buffer containing old.* record */ |
| 168657 | + SessionChange *pNext; /* For hash-table collisions */ |
| 168658 | +}; |
| 168659 | + |
| 168660 | +/* |
| 168661 | +** Write a varint with value iVal into the buffer at aBuf. Return the |
| 168662 | +** number of bytes written. |
| 168663 | +*/ |
| 168664 | +static int sessionVarintPut(u8 *aBuf, int iVal){ |
| 168665 | + return putVarint32(aBuf, iVal); |
| 168666 | +} |
| 168667 | + |
| 168668 | +/* |
| 168669 | +** Return the number of bytes required to store value iVal as a varint. |
| 168670 | +*/ |
| 168671 | +static int sessionVarintLen(int iVal){ |
| 168672 | + return sqlite3VarintLen(iVal); |
| 168673 | +} |
| 168674 | + |
| 168675 | +/* |
| 168676 | +** Read a varint value from aBuf[] into *piVal. Return the number of |
| 168677 | +** bytes read. |
| 168678 | +*/ |
| 168679 | +static int sessionVarintGet(u8 *aBuf, int *piVal){ |
| 168680 | + return getVarint32(aBuf, *piVal); |
| 168681 | +} |
| 168682 | + |
| 168683 | +/* |
| 168684 | +** Read a 64-bit big-endian integer value from buffer aRec[]. Return |
| 168685 | +** the value read. |
| 168686 | +*/ |
| 168687 | +static sqlite3_int64 sessionGetI64(u8 *aRec){ |
| 168688 | + return (((sqlite3_int64)aRec[0]) << 56) |
| 168689 | + + (((sqlite3_int64)aRec[1]) << 48) |
| 168690 | + + (((sqlite3_int64)aRec[2]) << 40) |
| 168691 | + + (((sqlite3_int64)aRec[3]) << 32) |
| 168692 | + + (((sqlite3_int64)aRec[4]) << 24) |
| 168693 | + + (((sqlite3_int64)aRec[5]) << 16) |
| 168694 | + + (((sqlite3_int64)aRec[6]) << 8) |
| 168695 | + + (((sqlite3_int64)aRec[7]) << 0); |
| 168696 | +} |
| 168697 | + |
| 168698 | +/* |
| 168699 | +** Write a 64-bit big-endian integer value to the buffer aBuf[]. |
| 168700 | +*/ |
| 168701 | +static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){ |
| 168702 | + aBuf[0] = (i>>56) & 0xFF; |
| 168703 | + aBuf[1] = (i>>48) & 0xFF; |
| 168704 | + aBuf[2] = (i>>40) & 0xFF; |
| 168705 | + aBuf[3] = (i>>32) & 0xFF; |
| 168706 | + aBuf[4] = (i>>24) & 0xFF; |
| 168707 | + aBuf[5] = (i>>16) & 0xFF; |
| 168708 | + aBuf[6] = (i>> 8) & 0xFF; |
| 168709 | + aBuf[7] = (i>> 0) & 0xFF; |
| 168710 | +} |
| 168711 | + |
| 168712 | +/* |
| 168713 | +** This function is used to serialize the contents of value pValue (see |
| 168714 | +** comment titled "RECORD FORMAT" above). |
| 168715 | +** |
| 168716 | +** If it is non-NULL, the serialized form of the value is written to |
| 168717 | +** buffer aBuf. *pnWrite is set to the number of bytes written before |
| 168718 | +** returning. Or, if aBuf is NULL, the only thing this function does is |
| 168719 | +** set *pnWrite. |
| 168720 | +** |
| 168721 | +** If no error occurs, SQLITE_OK is returned. Or, if an OOM error occurs |
| 168722 | +** within a call to sqlite3_value_text() (may fail if the db is utf-16)) |
| 168723 | +** SQLITE_NOMEM is returned. |
| 168724 | +*/ |
| 168725 | +static int sessionSerializeValue( |
| 168726 | + u8 *aBuf, /* If non-NULL, write serialized value here */ |
| 168727 | + sqlite3_value *pValue, /* Value to serialize */ |
| 168728 | + int *pnWrite /* IN/OUT: Increment by bytes written */ |
| 168729 | +){ |
| 168730 | + int nByte; /* Size of serialized value in bytes */ |
| 168731 | + |
| 168732 | + if( pValue ){ |
| 168733 | + int eType; /* Value type (SQLITE_NULL, TEXT etc.) */ |
| 168734 | + |
| 168735 | + eType = sqlite3_value_type(pValue); |
| 168736 | + if( aBuf ) aBuf[0] = eType; |
| 168737 | + |
| 168738 | + switch( eType ){ |
| 168739 | + case SQLITE_NULL: |
| 168740 | + nByte = 1; |
| 168741 | + break; |
| 168742 | + |
| 168743 | + case SQLITE_INTEGER: |
| 168744 | + case SQLITE_FLOAT: |
| 168745 | + if( aBuf ){ |
| 168746 | + /* TODO: SQLite does something special to deal with mixed-endian |
| 168747 | + ** floating point values (e.g. ARM7). This code probably should |
| 168748 | + ** too. */ |
| 168749 | + u64 i; |
| 168750 | + if( eType==SQLITE_INTEGER ){ |
| 168751 | + i = (u64)sqlite3_value_int64(pValue); |
| 168752 | + }else{ |
| 168753 | + double r; |
| 168754 | + assert( sizeof(double)==8 && sizeof(u64)==8 ); |
| 168755 | + r = sqlite3_value_double(pValue); |
| 168756 | + memcpy(&i, &r, 8); |
| 168757 | + } |
| 168758 | + sessionPutI64(&aBuf[1], i); |
| 168759 | + } |
| 168760 | + nByte = 9; |
| 168761 | + break; |
| 168762 | + |
| 168763 | + default: { |
| 168764 | + u8 *z; |
| 168765 | + int n; |
| 168766 | + int nVarint; |
| 168767 | + |
| 168768 | + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); |
| 168769 | + if( eType==SQLITE_TEXT ){ |
| 168770 | + z = (u8 *)sqlite3_value_text(pValue); |
| 168771 | + }else{ |
| 168772 | + z = (u8 *)sqlite3_value_blob(pValue); |
| 168773 | + } |
| 168774 | + n = sqlite3_value_bytes(pValue); |
| 168775 | + if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; |
| 168776 | + nVarint = sessionVarintLen(n); |
| 168777 | + |
| 168778 | + if( aBuf ){ |
| 168779 | + sessionVarintPut(&aBuf[1], n); |
| 168780 | + memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? |
| 168781 | + sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n |
| 168782 | + ); |
| 168783 | + } |
| 168784 | + |
| 168785 | + nByte = 1 + nVarint + n; |
| 168786 | + break; |
| 168787 | + } |
| 168788 | + } |
| 168789 | + }else{ |
| 168790 | + nByte = 1; |
| 168791 | + if( aBuf ) aBuf[0] = '\0'; |
| 168792 | + } |
| 168793 | + |
| 168794 | + if( pnWrite ) *pnWrite += nByte; |
| 168795 | + return SQLITE_OK; |
| 168796 | +} |
| 168797 | + |
| 168798 | + |
| 168799 | +/* |
| 168800 | +** This macro is used to calculate hash key values for data structures. In |
| 168801 | +** order to use this macro, the entire data structure must be represented |
| 168802 | +** as a series of unsigned integers. In order to calculate a hash-key value |
| 168803 | +** for a data structure represented as three such integers, the macro may |
| 168804 | +** then be used as follows: |
| 168805 | +** |
| 168806 | +** int hash_key_value; |
| 168807 | +** hash_key_value = HASH_APPEND(0, <value 1>); |
| 168808 | +** hash_key_value = HASH_APPEND(hash_key_value, <value 2>); |
| 168809 | +** hash_key_value = HASH_APPEND(hash_key_value, <value 3>); |
| 168810 | +** |
| 168811 | +** In practice, the data structures this macro is used for are the primary |
| 168812 | +** key values of modified rows. |
| 168813 | +*/ |
| 168814 | +#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (unsigned int)(add) |
| 168815 | + |
| 168816 | +/* |
| 168817 | +** Append the hash of the 64-bit integer passed as the second argument to the |
| 168818 | +** hash-key value passed as the first. Return the new hash-key value. |
| 168819 | +*/ |
| 168820 | +static unsigned int sessionHashAppendI64(unsigned int h, i64 i){ |
| 168821 | + h = HASH_APPEND(h, i & 0xFFFFFFFF); |
| 168822 | + return HASH_APPEND(h, (i>>32)&0xFFFFFFFF); |
| 168823 | +} |
| 168824 | + |
| 168825 | +/* |
| 168826 | +** Append the hash of the blob passed via the second and third arguments to |
| 168827 | +** the hash-key value passed as the first. Return the new hash-key value. |
| 168828 | +*/ |
| 168829 | +static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){ |
| 168830 | + int i; |
| 168831 | + for(i=0; i<n; i++) h = HASH_APPEND(h, z[i]); |
| 168832 | + return h; |
| 168833 | +} |
| 168834 | + |
| 168835 | +/* |
| 168836 | +** Append the hash of the data type passed as the second argument to the |
| 168837 | +** hash-key value passed as the first. Return the new hash-key value. |
| 168838 | +*/ |
| 168839 | +static unsigned int sessionHashAppendType(unsigned int h, int eType){ |
| 168840 | + return HASH_APPEND(h, eType); |
| 168841 | +} |
| 168842 | + |
| 168843 | +/* |
| 168844 | +** This function may only be called from within a pre-update callback. |
| 168845 | +** It calculates a hash based on the primary key values of the old.* or |
| 168846 | +** new.* row currently available and, assuming no error occurs, writes it to |
| 168847 | +** *piHash before returning. If the primary key contains one or more NULL |
| 168848 | +** values, *pbNullPK is set to true before returning. |
| 168849 | +** |
| 168850 | +** If an error occurs, an SQLite error code is returned and the final values |
| 168851 | +** of *piHash asn *pbNullPK are undefined. Otherwise, SQLITE_OK is returned |
| 168852 | +** and the output variables are set as described above. |
| 168853 | +*/ |
| 168854 | +static int sessionPreupdateHash( |
| 168855 | + sqlite3_session *pSession, /* Session object that owns pTab */ |
| 168856 | + SessionTable *pTab, /* Session table handle */ |
| 168857 | + int bNew, /* True to hash the new.* PK */ |
| 168858 | + int *piHash, /* OUT: Hash value */ |
| 168859 | + int *pbNullPK /* OUT: True if there are NULL values in PK */ |
| 168860 | +){ |
| 168861 | + unsigned int h = 0; /* Hash value to return */ |
| 168862 | + int i; /* Used to iterate through columns */ |
| 168863 | + |
| 168864 | + assert( *pbNullPK==0 ); |
| 168865 | + assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) ); |
| 168866 | + for(i=0; i<pTab->nCol; i++){ |
| 168867 | + if( pTab->abPK[i] ){ |
| 168868 | + int rc; |
| 168869 | + int eType; |
| 168870 | + sqlite3_value *pVal; |
| 168871 | + |
| 168872 | + if( bNew ){ |
| 168873 | + rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); |
| 168874 | + }else{ |
| 168875 | + rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); |
| 168876 | + } |
| 168877 | + if( rc!=SQLITE_OK ) return rc; |
| 168878 | + |
| 168879 | + eType = sqlite3_value_type(pVal); |
| 168880 | + h = sessionHashAppendType(h, eType); |
| 168881 | + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 168882 | + i64 iVal; |
| 168883 | + if( eType==SQLITE_INTEGER ){ |
| 168884 | + iVal = sqlite3_value_int64(pVal); |
| 168885 | + }else{ |
| 168886 | + double rVal = sqlite3_value_double(pVal); |
| 168887 | + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); |
| 168888 | + memcpy(&iVal, &rVal, 8); |
| 168889 | + } |
| 168890 | + h = sessionHashAppendI64(h, iVal); |
| 168891 | + }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ |
| 168892 | + const u8 *z; |
| 168893 | + int n; |
| 168894 | + if( eType==SQLITE_TEXT ){ |
| 168895 | + z = (const u8 *)sqlite3_value_text(pVal); |
| 168896 | + }else{ |
| 168897 | + z = (const u8 *)sqlite3_value_blob(pVal); |
| 168898 | + } |
| 168899 | + n = sqlite3_value_bytes(pVal); |
| 168900 | + if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; |
| 168901 | + h = sessionHashAppendBlob(h, n, z); |
| 168902 | + }else{ |
| 168903 | + assert( eType==SQLITE_NULL ); |
| 168904 | + *pbNullPK = 1; |
| 168905 | + } |
| 168906 | + } |
| 168907 | + } |
| 168908 | + |
| 168909 | + *piHash = (h % pTab->nChange); |
| 168910 | + return SQLITE_OK; |
| 168911 | +} |
| 168912 | + |
| 168913 | +/* |
| 168914 | +** The buffer that the argument points to contains a serialized SQL value. |
| 168915 | +** Return the number of bytes of space occupied by the value (including |
| 168916 | +** the type byte). |
| 168917 | +*/ |
| 168918 | +static int sessionSerialLen(u8 *a){ |
| 168919 | + int e = *a; |
| 168920 | + int n; |
| 168921 | + if( e==0 ) return 1; |
| 168922 | + if( e==SQLITE_NULL ) return 1; |
| 168923 | + if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; |
| 168924 | + return sessionVarintGet(&a[1], &n) + 1 + n; |
| 168925 | +} |
| 168926 | + |
| 168927 | +/* |
| 168928 | +** Based on the primary key values stored in change aRecord, calculate a |
| 168929 | +** hash key. Assume the has table has nBucket buckets. The hash keys |
| 168930 | +** calculated by this function are compatible with those calculated by |
| 168931 | +** sessionPreupdateHash(). |
| 168932 | +** |
| 168933 | +** The bPkOnly argument is non-zero if the record at aRecord[] is from |
| 168934 | +** a patchset DELETE. In this case the non-PK fields are omitted entirely. |
| 168935 | +*/ |
| 168936 | +static unsigned int sessionChangeHash( |
| 168937 | + SessionTable *pTab, /* Table handle */ |
| 168938 | + int bPkOnly, /* Record consists of PK fields only */ |
| 168939 | + u8 *aRecord, /* Change record */ |
| 168940 | + int nBucket /* Assume this many buckets in hash table */ |
| 168941 | +){ |
| 168942 | + unsigned int h = 0; /* Value to return */ |
| 168943 | + int i; /* Used to iterate through columns */ |
| 168944 | + u8 *a = aRecord; /* Used to iterate through change record */ |
| 168945 | + |
| 168946 | + for(i=0; i<pTab->nCol; i++){ |
| 168947 | + int eType = *a; |
| 168948 | + int isPK = pTab->abPK[i]; |
| 168949 | + if( bPkOnly && isPK==0 ) continue; |
| 168950 | + |
| 168951 | + /* It is not possible for eType to be SQLITE_NULL here. The session |
| 168952 | + ** module does not record changes for rows with NULL values stored in |
| 168953 | + ** primary key columns. */ |
| 168954 | + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT |
| 168955 | + || eType==SQLITE_TEXT || eType==SQLITE_BLOB |
| 168956 | + || eType==SQLITE_NULL || eType==0 |
| 168957 | + ); |
| 168958 | + assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); |
| 168959 | + |
| 168960 | + if( isPK ){ |
| 168961 | + a++; |
| 168962 | + h = sessionHashAppendType(h, eType); |
| 168963 | + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 168964 | + h = sessionHashAppendI64(h, sessionGetI64(a)); |
| 168965 | + a += 8; |
| 168966 | + }else{ |
| 168967 | + int n; |
| 168968 | + a += sessionVarintGet(a, &n); |
| 168969 | + h = sessionHashAppendBlob(h, n, a); |
| 168970 | + a += n; |
| 168971 | + } |
| 168972 | + }else{ |
| 168973 | + a += sessionSerialLen(a); |
| 168974 | + } |
| 168975 | + } |
| 168976 | + return (h % nBucket); |
| 168977 | +} |
| 168978 | + |
| 168979 | +/* |
| 168980 | +** Arguments aLeft and aRight are pointers to change records for table pTab. |
| 168981 | +** This function returns true if the two records apply to the same row (i.e. |
| 168982 | +** have the same values stored in the primary key columns), or false |
| 168983 | +** otherwise. |
| 168984 | +*/ |
| 168985 | +static int sessionChangeEqual( |
| 168986 | + SessionTable *pTab, /* Table used for PK definition */ |
| 168987 | + int bLeftPkOnly, /* True if aLeft[] contains PK fields only */ |
| 168988 | + u8 *aLeft, /* Change record */ |
| 168989 | + int bRightPkOnly, /* True if aRight[] contains PK fields only */ |
| 168990 | + u8 *aRight /* Change record */ |
| 168991 | +){ |
| 168992 | + u8 *a1 = aLeft; /* Cursor to iterate through aLeft */ |
| 168993 | + u8 *a2 = aRight; /* Cursor to iterate through aRight */ |
| 168994 | + int iCol; /* Used to iterate through table columns */ |
| 168995 | + |
| 168996 | + for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 168997 | + int n1 = sessionSerialLen(a1); |
| 168998 | + int n2 = sessionSerialLen(a2); |
| 168999 | + |
| 169000 | + if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ |
| 169001 | + return 0; |
| 169002 | + } |
| 169003 | + if( pTab->abPK[iCol] || bLeftPkOnly==0 ) a1 += n1; |
| 169004 | + if( pTab->abPK[iCol] || bRightPkOnly==0 ) a2 += n2; |
| 169005 | + } |
| 169006 | + |
| 169007 | + return 1; |
| 169008 | +} |
| 169009 | + |
| 169010 | +/* |
| 169011 | +** Arguments aLeft and aRight both point to buffers containing change |
| 169012 | +** records with nCol columns. This function "merges" the two records into |
| 169013 | +** a single records which is written to the buffer at *paOut. *paOut is |
| 169014 | +** then set to point to one byte after the last byte written before |
| 169015 | +** returning. |
| 169016 | +** |
| 169017 | +** The merging of records is done as follows: For each column, if the |
| 169018 | +** aRight record contains a value for the column, copy the value from |
| 169019 | +** their. Otherwise, if aLeft contains a value, copy it. If neither |
| 169020 | +** record contains a value for a given column, then neither does the |
| 169021 | +** output record. |
| 169022 | +*/ |
| 169023 | +static void sessionMergeRecord( |
| 169024 | + u8 **paOut, |
| 169025 | + int nCol, |
| 169026 | + u8 *aLeft, |
| 169027 | + u8 *aRight |
| 169028 | +){ |
| 169029 | + u8 *a1 = aLeft; /* Cursor used to iterate through aLeft */ |
| 169030 | + u8 *a2 = aRight; /* Cursor used to iterate through aRight */ |
| 169031 | + u8 *aOut = *paOut; /* Output cursor */ |
| 169032 | + int iCol; /* Used to iterate from 0 to nCol */ |
| 169033 | + |
| 169034 | + for(iCol=0; iCol<nCol; iCol++){ |
| 169035 | + int n1 = sessionSerialLen(a1); |
| 169036 | + int n2 = sessionSerialLen(a2); |
| 169037 | + if( *a2 ){ |
| 169038 | + memcpy(aOut, a2, n2); |
| 169039 | + aOut += n2; |
| 169040 | + }else{ |
| 169041 | + memcpy(aOut, a1, n1); |
| 169042 | + aOut += n1; |
| 169043 | + } |
| 169044 | + a1 += n1; |
| 169045 | + a2 += n2; |
| 169046 | + } |
| 169047 | + |
| 169048 | + *paOut = aOut; |
| 169049 | +} |
| 169050 | + |
| 169051 | +/* |
| 169052 | +** This is a helper function used by sessionMergeUpdate(). |
| 169053 | +** |
| 169054 | +** When this function is called, both *paOne and *paTwo point to a value |
| 169055 | +** within a change record. Before it returns, both have been advanced so |
| 169056 | +** as to point to the next value in the record. |
| 169057 | +** |
| 169058 | +** If, when this function is called, *paTwo points to a valid value (i.e. |
| 169059 | +** *paTwo[0] is not 0x00 - the "no value" placeholder), a copy of the *paTwo |
| 169060 | +** pointer is returned and *pnVal is set to the number of bytes in the |
| 169061 | +** serialized value. Otherwise, a copy of *paOne is returned and *pnVal |
| 169062 | +** set to the number of bytes in the value at *paOne. If *paOne points |
| 169063 | +** to the "no value" placeholder, *pnVal is set to 1. In other words: |
| 169064 | +** |
| 169065 | +** if( *paTwo is valid ) return *paTwo; |
| 169066 | +** return *paOne; |
| 169067 | +** |
| 169068 | +*/ |
| 169069 | +static u8 *sessionMergeValue( |
| 169070 | + u8 **paOne, /* IN/OUT: Left-hand buffer pointer */ |
| 169071 | + u8 **paTwo, /* IN/OUT: Right-hand buffer pointer */ |
| 169072 | + int *pnVal /* OUT: Bytes in returned value */ |
| 169073 | +){ |
| 169074 | + u8 *a1 = *paOne; |
| 169075 | + u8 *a2 = *paTwo; |
| 169076 | + u8 *pRet = 0; |
| 169077 | + int n1; |
| 169078 | + |
| 169079 | + assert( a1 ); |
| 169080 | + if( a2 ){ |
| 169081 | + int n2 = sessionSerialLen(a2); |
| 169082 | + if( *a2 ){ |
| 169083 | + *pnVal = n2; |
| 169084 | + pRet = a2; |
| 169085 | + } |
| 169086 | + *paTwo = &a2[n2]; |
| 169087 | + } |
| 169088 | + |
| 169089 | + n1 = sessionSerialLen(a1); |
| 169090 | + if( pRet==0 ){ |
| 169091 | + *pnVal = n1; |
| 169092 | + pRet = a1; |
| 169093 | + } |
| 169094 | + *paOne = &a1[n1]; |
| 169095 | + |
| 169096 | + return pRet; |
| 169097 | +} |
| 169098 | + |
| 169099 | +/* |
| 169100 | +** This function is used by changeset_concat() to merge two UPDATE changes |
| 169101 | +** on the same row. |
| 169102 | +*/ |
| 169103 | +static int sessionMergeUpdate( |
| 169104 | + u8 **paOut, /* IN/OUT: Pointer to output buffer */ |
| 169105 | + SessionTable *pTab, /* Table change pertains to */ |
| 169106 | + int bPatchset, /* True if records are patchset records */ |
| 169107 | + u8 *aOldRecord1, /* old.* record for first change */ |
| 169108 | + u8 *aOldRecord2, /* old.* record for second change */ |
| 169109 | + u8 *aNewRecord1, /* new.* record for first change */ |
| 169110 | + u8 *aNewRecord2 /* new.* record for second change */ |
| 169111 | +){ |
| 169112 | + u8 *aOld1 = aOldRecord1; |
| 169113 | + u8 *aOld2 = aOldRecord2; |
| 169114 | + u8 *aNew1 = aNewRecord1; |
| 169115 | + u8 *aNew2 = aNewRecord2; |
| 169116 | + |
| 169117 | + u8 *aOut = *paOut; |
| 169118 | + int i; |
| 169119 | + |
| 169120 | + if( bPatchset==0 ){ |
| 169121 | + int bRequired = 0; |
| 169122 | + |
| 169123 | + assert( aOldRecord1 && aNewRecord1 ); |
| 169124 | + |
| 169125 | + /* Write the old.* vector first. */ |
| 169126 | + for(i=0; i<pTab->nCol; i++){ |
| 169127 | + int nOld; |
| 169128 | + u8 *aOld; |
| 169129 | + int nNew; |
| 169130 | + u8 *aNew; |
| 169131 | + |
| 169132 | + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); |
| 169133 | + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); |
| 169134 | + if( pTab->abPK[i] || nOld!=nNew || memcmp(aOld, aNew, nNew) ){ |
| 169135 | + if( pTab->abPK[i]==0 ) bRequired = 1; |
| 169136 | + memcpy(aOut, aOld, nOld); |
| 169137 | + aOut += nOld; |
| 169138 | + }else{ |
| 169139 | + *(aOut++) = '\0'; |
| 169140 | + } |
| 169141 | + } |
| 169142 | + |
| 169143 | + if( !bRequired ) return 0; |
| 169144 | + } |
| 169145 | + |
| 169146 | + /* Write the new.* vector */ |
| 169147 | + aOld1 = aOldRecord1; |
| 169148 | + aOld2 = aOldRecord2; |
| 169149 | + aNew1 = aNewRecord1; |
| 169150 | + aNew2 = aNewRecord2; |
| 169151 | + for(i=0; i<pTab->nCol; i++){ |
| 169152 | + int nOld; |
| 169153 | + u8 *aOld; |
| 169154 | + int nNew; |
| 169155 | + u8 *aNew; |
| 169156 | + |
| 169157 | + aOld = sessionMergeValue(&aOld1, &aOld2, &nOld); |
| 169158 | + aNew = sessionMergeValue(&aNew1, &aNew2, &nNew); |
| 169159 | + if( bPatchset==0 |
| 169160 | + && (pTab->abPK[i] || (nOld==nNew && 0==memcmp(aOld, aNew, nNew))) |
| 169161 | + ){ |
| 169162 | + *(aOut++) = '\0'; |
| 169163 | + }else{ |
| 169164 | + memcpy(aOut, aNew, nNew); |
| 169165 | + aOut += nNew; |
| 169166 | + } |
| 169167 | + } |
| 169168 | + |
| 169169 | + *paOut = aOut; |
| 169170 | + return 1; |
| 169171 | +} |
| 169172 | + |
| 169173 | +/* |
| 169174 | +** This function is only called from within a pre-update-hook callback. |
| 169175 | +** It determines if the current pre-update-hook change affects the same row |
| 169176 | +** as the change stored in argument pChange. If so, it returns true. Otherwise |
| 169177 | +** if the pre-update-hook does not affect the same row as pChange, it returns |
| 169178 | +** false. |
| 169179 | +*/ |
| 169180 | +static int sessionPreupdateEqual( |
| 169181 | + sqlite3_session *pSession, /* Session object that owns SessionTable */ |
| 169182 | + SessionTable *pTab, /* Table associated with change */ |
| 169183 | + SessionChange *pChange, /* Change to compare to */ |
| 169184 | + int op /* Current pre-update operation */ |
| 169185 | +){ |
| 169186 | + int iCol; /* Used to iterate through columns */ |
| 169187 | + u8 *a = pChange->aRecord; /* Cursor used to scan change record */ |
| 169188 | + |
| 169189 | + assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); |
| 169190 | + for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 169191 | + if( !pTab->abPK[iCol] ){ |
| 169192 | + a += sessionSerialLen(a); |
| 169193 | + }else{ |
| 169194 | + sqlite3_value *pVal; /* Value returned by preupdate_new/old */ |
| 169195 | + int rc; /* Error code from preupdate_new/old */ |
| 169196 | + int eType = *a++; /* Type of value from change record */ |
| 169197 | + |
| 169198 | + /* The following calls to preupdate_new() and preupdate_old() can not |
| 169199 | + ** fail. This is because they cache their return values, and by the |
| 169200 | + ** time control flows to here they have already been called once from |
| 169201 | + ** within sessionPreupdateHash(). The first two asserts below verify |
| 169202 | + ** this (that the method has already been called). */ |
| 169203 | + if( op==SQLITE_INSERT ){ |
| 169204 | + /* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */ |
| 169205 | + rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal); |
| 169206 | + }else{ |
| 169207 | + /* assert( db->pPreUpdate->pUnpacked ); */ |
| 169208 | + rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal); |
| 169209 | + } |
| 169210 | + assert( rc==SQLITE_OK ); |
| 169211 | + if( sqlite3_value_type(pVal)!=eType ) return 0; |
| 169212 | + |
| 169213 | + /* A SessionChange object never has a NULL value in a PK column */ |
| 169214 | + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT |
| 169215 | + || eType==SQLITE_BLOB || eType==SQLITE_TEXT |
| 169216 | + ); |
| 169217 | + |
| 169218 | + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 169219 | + i64 iVal = sessionGetI64(a); |
| 169220 | + a += 8; |
| 169221 | + if( eType==SQLITE_INTEGER ){ |
| 169222 | + if( sqlite3_value_int64(pVal)!=iVal ) return 0; |
| 169223 | + }else{ |
| 169224 | + double rVal; |
| 169225 | + assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); |
| 169226 | + memcpy(&rVal, &iVal, 8); |
| 169227 | + if( sqlite3_value_double(pVal)!=rVal ) return 0; |
| 169228 | + } |
| 169229 | + }else{ |
| 169230 | + int n; |
| 169231 | + const u8 *z; |
| 169232 | + a += sessionVarintGet(a, &n); |
| 169233 | + if( sqlite3_value_bytes(pVal)!=n ) return 0; |
| 169234 | + if( eType==SQLITE_TEXT ){ |
| 169235 | + z = sqlite3_value_text(pVal); |
| 169236 | + }else{ |
| 169237 | + z = sqlite3_value_blob(pVal); |
| 169238 | + } |
| 169239 | + if( memcmp(a, z, n) ) return 0; |
| 169240 | + a += n; |
| 169241 | + break; |
| 169242 | + } |
| 169243 | + } |
| 169244 | + } |
| 169245 | + |
| 169246 | + return 1; |
| 169247 | +} |
| 169248 | + |
| 169249 | +/* |
| 169250 | +** If required, grow the hash table used to store changes on table pTab |
| 169251 | +** (part of the session pSession). If a fatal OOM error occurs, set the |
| 169252 | +** session object to failed and return SQLITE_ERROR. Otherwise, return |
| 169253 | +** SQLITE_OK. |
| 169254 | +** |
| 169255 | +** It is possible that a non-fatal OOM error occurs in this function. In |
| 169256 | +** that case the hash-table does not grow, but SQLITE_OK is returned anyway. |
| 169257 | +** Growing the hash table in this case is a performance optimization only, |
| 169258 | +** it is not required for correct operation. |
| 169259 | +*/ |
| 169260 | +static int sessionGrowHash(int bPatchset, SessionTable *pTab){ |
| 169261 | + if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ |
| 169262 | + int i; |
| 169263 | + SessionChange **apNew; |
| 169264 | + int nNew = (pTab->nChange ? pTab->nChange : 128) * 2; |
| 169265 | + |
| 169266 | + apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew); |
| 169267 | + if( apNew==0 ){ |
| 169268 | + if( pTab->nChange==0 ){ |
| 169269 | + return SQLITE_ERROR; |
| 169270 | + } |
| 169271 | + return SQLITE_OK; |
| 169272 | + } |
| 169273 | + memset(apNew, 0, sizeof(SessionChange *) * nNew); |
| 169274 | + |
| 169275 | + for(i=0; i<pTab->nChange; i++){ |
| 169276 | + SessionChange *p; |
| 169277 | + SessionChange *pNext; |
| 169278 | + for(p=pTab->apChange[i]; p; p=pNext){ |
| 169279 | + int bPkOnly = (p->op==SQLITE_DELETE && bPatchset); |
| 169280 | + int iHash = sessionChangeHash(pTab, bPkOnly, p->aRecord, nNew); |
| 169281 | + pNext = p->pNext; |
| 169282 | + p->pNext = apNew[iHash]; |
| 169283 | + apNew[iHash] = p; |
| 169284 | + } |
| 169285 | + } |
| 169286 | + |
| 169287 | + sqlite3_free(pTab->apChange); |
| 169288 | + pTab->nChange = nNew; |
| 169289 | + pTab->apChange = apNew; |
| 169290 | + } |
| 169291 | + |
| 169292 | + return SQLITE_OK; |
| 169293 | +} |
| 169294 | + |
| 169295 | +/* |
| 169296 | +** This function queries the database for the names of the columns of table |
| 169297 | +** zThis, in schema zDb. It is expected that the table has nCol columns. If |
| 169298 | +** not, SQLITE_SCHEMA is returned and none of the output variables are |
| 169299 | +** populated. |
| 169300 | +** |
| 169301 | +** Otherwise, if they are not NULL, variable *pnCol is set to the number |
| 169302 | +** of columns in the database table and variable *pzTab is set to point to a |
| 169303 | +** nul-terminated copy of the table name. *pazCol (if not NULL) is set to |
| 169304 | +** point to an array of pointers to column names. And *pabPK (again, if not |
| 169305 | +** NULL) is set to point to an array of booleans - true if the corresponding |
| 169306 | +** column is part of the primary key. |
| 169307 | +** |
| 169308 | +** For example, if the table is declared as: |
| 169309 | +** |
| 169310 | +** CREATE TABLE tbl1(w, x, y, z, PRIMARY KEY(w, z)); |
| 169311 | +** |
| 169312 | +** Then the four output variables are populated as follows: |
| 169313 | +** |
| 169314 | +** *pnCol = 4 |
| 169315 | +** *pzTab = "tbl1" |
| 169316 | +** *pazCol = {"w", "x", "y", "z"} |
| 169317 | +** *pabPK = {1, 0, 0, 1} |
| 169318 | +** |
| 169319 | +** All returned buffers are part of the same single allocation, which must |
| 169320 | +** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then |
| 169321 | +** pointer *pazCol should be freed to release all memory. Otherwise, pointer |
| 169322 | +** *pabPK. It is illegal for both pazCol and pabPK to be NULL. |
| 169323 | +*/ |
| 169324 | +static int sessionTableInfo( |
| 169325 | + sqlite3 *db, /* Database connection */ |
| 169326 | + const char *zDb, /* Name of attached database (e.g. "main") */ |
| 169327 | + const char *zThis, /* Table name */ |
| 169328 | + int *pnCol, /* OUT: number of columns */ |
| 169329 | + const char **pzTab, /* OUT: Copy of zThis */ |
| 169330 | + const char ***pazCol, /* OUT: Array of column names for table */ |
| 169331 | + u8 **pabPK /* OUT: Array of booleans - true for PK col */ |
| 169332 | +){ |
| 169333 | + char *zPragma; |
| 169334 | + sqlite3_stmt *pStmt; |
| 169335 | + int rc; |
| 169336 | + int nByte; |
| 169337 | + int nDbCol = 0; |
| 169338 | + int nThis; |
| 169339 | + int i; |
| 169340 | + u8 *pAlloc; |
| 169341 | + char **azCol = 0; |
| 169342 | + u8 *abPK; |
| 169343 | + |
| 169344 | + assert( pazCol && pabPK ); |
| 169345 | + |
| 169346 | + nThis = sqlite3Strlen30(zThis); |
| 169347 | + zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); |
| 169348 | + if( !zPragma ) return SQLITE_NOMEM; |
| 169349 | + |
| 169350 | + rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); |
| 169351 | + sqlite3_free(zPragma); |
| 169352 | + if( rc!=SQLITE_OK ) return rc; |
| 169353 | + |
| 169354 | + nByte = nThis + 1; |
| 169355 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 169356 | + nByte += sqlite3_column_bytes(pStmt, 1); |
| 169357 | + nDbCol++; |
| 169358 | + } |
| 169359 | + rc = sqlite3_reset(pStmt); |
| 169360 | + |
| 169361 | + if( rc==SQLITE_OK ){ |
| 169362 | + nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); |
| 169363 | + pAlloc = sqlite3_malloc(nByte); |
| 169364 | + if( pAlloc==0 ){ |
| 169365 | + rc = SQLITE_NOMEM; |
| 169366 | + } |
| 169367 | + } |
| 169368 | + if( rc==SQLITE_OK ){ |
| 169369 | + azCol = (char **)pAlloc; |
| 169370 | + pAlloc = (u8 *)&azCol[nDbCol]; |
| 169371 | + abPK = (u8 *)pAlloc; |
| 169372 | + pAlloc = &abPK[nDbCol]; |
| 169373 | + if( pzTab ){ |
| 169374 | + memcpy(pAlloc, zThis, nThis+1); |
| 169375 | + *pzTab = (char *)pAlloc; |
| 169376 | + pAlloc += nThis+1; |
| 169377 | + } |
| 169378 | + |
| 169379 | + i = 0; |
| 169380 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 169381 | + int nName = sqlite3_column_bytes(pStmt, 1); |
| 169382 | + const unsigned char *zName = sqlite3_column_text(pStmt, 1); |
| 169383 | + if( zName==0 ) break; |
| 169384 | + memcpy(pAlloc, zName, nName+1); |
| 169385 | + azCol[i] = (char *)pAlloc; |
| 169386 | + pAlloc += nName+1; |
| 169387 | + abPK[i] = sqlite3_column_int(pStmt, 5); |
| 169388 | + i++; |
| 169389 | + } |
| 169390 | + rc = sqlite3_reset(pStmt); |
| 169391 | + |
| 169392 | + } |
| 169393 | + |
| 169394 | + /* If successful, populate the output variables. Otherwise, zero them and |
| 169395 | + ** free any allocation made. An error code will be returned in this case. |
| 169396 | + */ |
| 169397 | + if( rc==SQLITE_OK ){ |
| 169398 | + *pazCol = (const char **)azCol; |
| 169399 | + *pabPK = abPK; |
| 169400 | + *pnCol = nDbCol; |
| 169401 | + }else{ |
| 169402 | + *pazCol = 0; |
| 169403 | + *pabPK = 0; |
| 169404 | + *pnCol = 0; |
| 169405 | + if( pzTab ) *pzTab = 0; |
| 169406 | + sqlite3_free(azCol); |
| 169407 | + } |
| 169408 | + sqlite3_finalize(pStmt); |
| 169409 | + return rc; |
| 169410 | +} |
| 169411 | + |
| 169412 | +/* |
| 169413 | +** This function is only called from within a pre-update handler for a |
| 169414 | +** write to table pTab, part of session pSession. If this is the first |
| 169415 | +** write to this table, initalize the SessionTable.nCol, azCol[] and |
| 169416 | +** abPK[] arrays accordingly. |
| 169417 | +** |
| 169418 | +** If an error occurs, an error code is stored in sqlite3_session.rc and |
| 169419 | +** non-zero returned. Or, if no error occurs but the table has no primary |
| 169420 | +** key, sqlite3_session.rc is left set to SQLITE_OK and non-zero returned to |
| 169421 | +** indicate that updates on this table should be ignored. SessionTable.abPK |
| 169422 | +** is set to NULL in this case. |
| 169423 | +*/ |
| 169424 | +static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ |
| 169425 | + if( pTab->nCol==0 ){ |
| 169426 | + u8 *abPK; |
| 169427 | + assert( pTab->azCol==0 || pTab->abPK==0 ); |
| 169428 | + pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, |
| 169429 | + pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK |
| 169430 | + ); |
| 169431 | + if( pSession->rc==SQLITE_OK ){ |
| 169432 | + int i; |
| 169433 | + for(i=0; i<pTab->nCol; i++){ |
| 169434 | + if( abPK[i] ){ |
| 169435 | + pTab->abPK = abPK; |
| 169436 | + break; |
| 169437 | + } |
| 169438 | + } |
| 169439 | + } |
| 169440 | + } |
| 169441 | + return (pSession->rc || pTab->abPK==0); |
| 169442 | +} |
| 169443 | + |
| 169444 | +/* |
| 169445 | +** This function is only called from with a pre-update-hook reporting a |
| 169446 | +** change on table pTab (attached to session pSession). The type of change |
| 169447 | +** (UPDATE, INSERT, DELETE) is specified by the first argument. |
| 169448 | +** |
| 169449 | +** Unless one is already present or an error occurs, an entry is added |
| 169450 | +** to the changed-rows hash table associated with table pTab. |
| 169451 | +*/ |
| 169452 | +static void sessionPreupdateOneChange( |
| 169453 | + int op, /* One of SQLITE_UPDATE, INSERT, DELETE */ |
| 169454 | + sqlite3_session *pSession, /* Session object pTab is attached to */ |
| 169455 | + SessionTable *pTab /* Table that change applies to */ |
| 169456 | +){ |
| 169457 | + int iHash; |
| 169458 | + int bNull = 0; |
| 169459 | + int rc = SQLITE_OK; |
| 169460 | + |
| 169461 | + if( pSession->rc ) return; |
| 169462 | + |
| 169463 | + /* Load table details if required */ |
| 169464 | + if( sessionInitTable(pSession, pTab) ) return; |
| 169465 | + |
| 169466 | + /* Check the number of columns in this xPreUpdate call matches the |
| 169467 | + ** number of columns in the table. */ |
| 169468 | + if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ |
| 169469 | + pSession->rc = SQLITE_SCHEMA; |
| 169470 | + return; |
| 169471 | + } |
| 169472 | + |
| 169473 | + /* Grow the hash table if required */ |
| 169474 | + if( sessionGrowHash(0, pTab) ){ |
| 169475 | + pSession->rc = SQLITE_NOMEM; |
| 169476 | + return; |
| 169477 | + } |
| 169478 | + |
| 169479 | + /* Calculate the hash-key for this change. If the primary key of the row |
| 169480 | + ** includes a NULL value, exit early. Such changes are ignored by the |
| 169481 | + ** session module. */ |
| 169482 | + rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull); |
| 169483 | + if( rc!=SQLITE_OK ) goto error_out; |
| 169484 | + |
| 169485 | + if( bNull==0 ){ |
| 169486 | + /* Search the hash table for an existing record for this row. */ |
| 169487 | + SessionChange *pC; |
| 169488 | + for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ |
| 169489 | + if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break; |
| 169490 | + } |
| 169491 | + |
| 169492 | + if( pC==0 ){ |
| 169493 | + /* Create a new change object containing all the old values (if |
| 169494 | + ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK |
| 169495 | + ** values (if this is an INSERT). */ |
| 169496 | + SessionChange *pChange; /* New change object */ |
| 169497 | + int nByte; /* Number of bytes to allocate */ |
| 169498 | + int i; /* Used to iterate through columns */ |
| 169499 | + |
| 169500 | + assert( rc==SQLITE_OK ); |
| 169501 | + pTab->nEntry++; |
| 169502 | + |
| 169503 | + /* Figure out how large an allocation is required */ |
| 169504 | + nByte = sizeof(SessionChange); |
| 169505 | + for(i=0; i<pTab->nCol; i++){ |
| 169506 | + sqlite3_value *p = 0; |
| 169507 | + if( op!=SQLITE_INSERT ){ |
| 169508 | + TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); |
| 169509 | + assert( trc==SQLITE_OK ); |
| 169510 | + }else if( pTab->abPK[i] ){ |
| 169511 | + TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); |
| 169512 | + assert( trc==SQLITE_OK ); |
| 169513 | + } |
| 169514 | + |
| 169515 | + /* This may fail if SQLite value p contains a utf-16 string that must |
| 169516 | + ** be converted to utf-8 and an OOM error occurs while doing so. */ |
| 169517 | + rc = sessionSerializeValue(0, p, &nByte); |
| 169518 | + if( rc!=SQLITE_OK ) goto error_out; |
| 169519 | + } |
| 169520 | + |
| 169521 | + /* Allocate the change object */ |
| 169522 | + pChange = (SessionChange *)sqlite3_malloc(nByte); |
| 169523 | + if( !pChange ){ |
| 169524 | + rc = SQLITE_NOMEM; |
| 169525 | + goto error_out; |
| 169526 | + }else{ |
| 169527 | + memset(pChange, 0, sizeof(SessionChange)); |
| 169528 | + pChange->aRecord = (u8 *)&pChange[1]; |
| 169529 | + } |
| 169530 | + |
| 169531 | + /* Populate the change object. None of the preupdate_old(), |
| 169532 | + ** preupdate_new() or SerializeValue() calls below may fail as all |
| 169533 | + ** required values and encodings have already been cached in memory. |
| 169534 | + ** It is not possible for an OOM to occur in this block. */ |
| 169535 | + nByte = 0; |
| 169536 | + for(i=0; i<pTab->nCol; i++){ |
| 169537 | + sqlite3_value *p = 0; |
| 169538 | + if( op!=SQLITE_INSERT ){ |
| 169539 | + pSession->hook.xOld(pSession->hook.pCtx, i, &p); |
| 169540 | + }else if( pTab->abPK[i] ){ |
| 169541 | + pSession->hook.xNew(pSession->hook.pCtx, i, &p); |
| 169542 | + } |
| 169543 | + sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte); |
| 169544 | + } |
| 169545 | + |
| 169546 | + /* Add the change to the hash-table */ |
| 169547 | + if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){ |
| 169548 | + pChange->bIndirect = 1; |
| 169549 | + } |
| 169550 | + pChange->nRecord = nByte; |
| 169551 | + pChange->op = op; |
| 169552 | + pChange->pNext = pTab->apChange[iHash]; |
| 169553 | + pTab->apChange[iHash] = pChange; |
| 169554 | + |
| 169555 | + }else if( pC->bIndirect ){ |
| 169556 | + /* If the existing change is considered "indirect", but this current |
| 169557 | + ** change is "direct", mark the change object as direct. */ |
| 169558 | + if( pSession->hook.xDepth(pSession->hook.pCtx)==0 |
| 169559 | + && pSession->bIndirect==0 |
| 169560 | + ){ |
| 169561 | + pC->bIndirect = 0; |
| 169562 | + } |
| 169563 | + } |
| 169564 | + } |
| 169565 | + |
| 169566 | + /* If an error has occurred, mark the session object as failed. */ |
| 169567 | + error_out: |
| 169568 | + if( rc!=SQLITE_OK ){ |
| 169569 | + pSession->rc = rc; |
| 169570 | + } |
| 169571 | +} |
| 169572 | + |
| 169573 | +static int sessionFindTable( |
| 169574 | + sqlite3_session *pSession, |
| 169575 | + const char *zName, |
| 169576 | + SessionTable **ppTab |
| 169577 | +){ |
| 169578 | + int rc = SQLITE_OK; |
| 169579 | + int nName = sqlite3Strlen30(zName); |
| 169580 | + SessionTable *pRet; |
| 169581 | + |
| 169582 | + /* Search for an existing table */ |
| 169583 | + for(pRet=pSession->pTable; pRet; pRet=pRet->pNext){ |
| 169584 | + if( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ) break; |
| 169585 | + } |
| 169586 | + |
| 169587 | + if( pRet==0 && pSession->bAutoAttach ){ |
| 169588 | + /* If there is a table-filter configured, invoke it. If it returns 0, |
| 169589 | + ** do not automatically add the new table. */ |
| 169590 | + if( pSession->xTableFilter==0 |
| 169591 | + || pSession->xTableFilter(pSession->pFilterCtx, zName) |
| 169592 | + ){ |
| 169593 | + rc = sqlite3session_attach(pSession, zName); |
| 169594 | + if( rc==SQLITE_OK ){ |
| 169595 | + for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext); |
| 169596 | + assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) ); |
| 169597 | + } |
| 169598 | + } |
| 169599 | + } |
| 169600 | + |
| 169601 | + assert( rc==SQLITE_OK || pRet==0 ); |
| 169602 | + *ppTab = pRet; |
| 169603 | + return rc; |
| 169604 | +} |
| 169605 | + |
| 169606 | +/* |
| 169607 | +** The 'pre-update' hook registered by this module with SQLite databases. |
| 169608 | +*/ |
| 169609 | +static void xPreUpdate( |
| 169610 | + void *pCtx, /* Copy of third arg to preupdate_hook() */ |
| 169611 | + sqlite3 *db, /* Database handle */ |
| 169612 | + int op, /* SQLITE_UPDATE, DELETE or INSERT */ |
| 169613 | + char const *zDb, /* Database name */ |
| 169614 | + char const *zName, /* Table name */ |
| 169615 | + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ |
| 169616 | + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ |
| 169617 | +){ |
| 169618 | + sqlite3_session *pSession; |
| 169619 | + int nDb = sqlite3Strlen30(zDb); |
| 169620 | + |
| 169621 | + assert( sqlite3_mutex_held(db->mutex) ); |
| 169622 | + |
| 169623 | + for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){ |
| 169624 | + SessionTable *pTab; |
| 169625 | + |
| 169626 | + /* If this session is attached to a different database ("main", "temp" |
| 169627 | + ** etc.), or if it is not currently enabled, there is nothing to do. Skip |
| 169628 | + ** to the next session object attached to this database. */ |
| 169629 | + if( pSession->bEnable==0 ) continue; |
| 169630 | + if( pSession->rc ) continue; |
| 169631 | + if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; |
| 169632 | + |
| 169633 | + pSession->rc = sessionFindTable(pSession, zName, &pTab); |
| 169634 | + if( pTab ){ |
| 169635 | + assert( pSession->rc==SQLITE_OK ); |
| 169636 | + sessionPreupdateOneChange(op, pSession, pTab); |
| 169637 | + if( op==SQLITE_UPDATE ){ |
| 169638 | + sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); |
| 169639 | + } |
| 169640 | + } |
| 169641 | + } |
| 169642 | +} |
| 169643 | + |
| 169644 | +/* |
| 169645 | +** The pre-update hook implementations. |
| 169646 | +*/ |
| 169647 | +static int sessionPreupdateOld(void *pCtx, int iVal, sqlite3_value **ppVal){ |
| 169648 | + return sqlite3_preupdate_old((sqlite3*)pCtx, iVal, ppVal); |
| 169649 | +} |
| 169650 | +static int sessionPreupdateNew(void *pCtx, int iVal, sqlite3_value **ppVal){ |
| 169651 | + return sqlite3_preupdate_new((sqlite3*)pCtx, iVal, ppVal); |
| 169652 | +} |
| 169653 | +static int sessionPreupdateCount(void *pCtx){ |
| 169654 | + return sqlite3_preupdate_count((sqlite3*)pCtx); |
| 169655 | +} |
| 169656 | +static int sessionPreupdateDepth(void *pCtx){ |
| 169657 | + return sqlite3_preupdate_depth((sqlite3*)pCtx); |
| 169658 | +} |
| 169659 | + |
| 169660 | +/* |
| 169661 | +** Install the pre-update hooks on the session object passed as the only |
| 169662 | +** argument. |
| 169663 | +*/ |
| 169664 | +static void sessionPreupdateHooks( |
| 169665 | + sqlite3_session *pSession |
| 169666 | +){ |
| 169667 | + pSession->hook.pCtx = (void*)pSession->db; |
| 169668 | + pSession->hook.xOld = sessionPreupdateOld; |
| 169669 | + pSession->hook.xNew = sessionPreupdateNew; |
| 169670 | + pSession->hook.xCount = sessionPreupdateCount; |
| 169671 | + pSession->hook.xDepth = sessionPreupdateDepth; |
| 169672 | +} |
| 169673 | + |
| 169674 | +typedef struct SessionDiffCtx SessionDiffCtx; |
| 169675 | +struct SessionDiffCtx { |
| 169676 | + sqlite3_stmt *pStmt; |
| 169677 | + int nOldOff; |
| 169678 | +}; |
| 169679 | + |
| 169680 | +/* |
| 169681 | +** The diff hook implementations. |
| 169682 | +*/ |
| 169683 | +static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){ |
| 169684 | + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; |
| 169685 | + *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff); |
| 169686 | + return SQLITE_OK; |
| 169687 | +} |
| 169688 | +static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){ |
| 169689 | + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; |
| 169690 | + *ppVal = sqlite3_column_value(p->pStmt, iVal); |
| 169691 | + return SQLITE_OK; |
| 169692 | +} |
| 169693 | +static int sessionDiffCount(void *pCtx){ |
| 169694 | + SessionDiffCtx *p = (SessionDiffCtx*)pCtx; |
| 169695 | + return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt); |
| 169696 | +} |
| 169697 | +static int sessionDiffDepth(void *pCtx){ |
| 169698 | + return 0; |
| 169699 | +} |
| 169700 | + |
| 169701 | +/* |
| 169702 | +** Install the diff hooks on the session object passed as the only |
| 169703 | +** argument. |
| 169704 | +*/ |
| 169705 | +static void sessionDiffHooks( |
| 169706 | + sqlite3_session *pSession, |
| 169707 | + SessionDiffCtx *pDiffCtx |
| 169708 | +){ |
| 169709 | + pSession->hook.pCtx = (void*)pDiffCtx; |
| 169710 | + pSession->hook.xOld = sessionDiffOld; |
| 169711 | + pSession->hook.xNew = sessionDiffNew; |
| 169712 | + pSession->hook.xCount = sessionDiffCount; |
| 169713 | + pSession->hook.xDepth = sessionDiffDepth; |
| 169714 | +} |
| 169715 | + |
| 169716 | +static char *sessionExprComparePK( |
| 169717 | + int nCol, |
| 169718 | + const char *zDb1, const char *zDb2, |
| 169719 | + const char *zTab, |
| 169720 | + const char **azCol, u8 *abPK |
| 169721 | +){ |
| 169722 | + int i; |
| 169723 | + const char *zSep = ""; |
| 169724 | + char *zRet = 0; |
| 169725 | + |
| 169726 | + for(i=0; i<nCol; i++){ |
| 169727 | + if( abPK[i] ){ |
| 169728 | + zRet = sqlite3_mprintf("%z%s\"%w\".\"%w\".\"%w\"=\"%w\".\"%w\".\"%w\"", |
| 169729 | + zRet, zSep, zDb1, zTab, azCol[i], zDb2, zTab, azCol[i] |
| 169730 | + ); |
| 169731 | + zSep = " AND "; |
| 169732 | + if( zRet==0 ) break; |
| 169733 | + } |
| 169734 | + } |
| 169735 | + |
| 169736 | + return zRet; |
| 169737 | +} |
| 169738 | + |
| 169739 | +static char *sessionExprCompareOther( |
| 169740 | + int nCol, |
| 169741 | + const char *zDb1, const char *zDb2, |
| 169742 | + const char *zTab, |
| 169743 | + const char **azCol, u8 *abPK |
| 169744 | +){ |
| 169745 | + int i; |
| 169746 | + const char *zSep = ""; |
| 169747 | + char *zRet = 0; |
| 169748 | + int bHave = 0; |
| 169749 | + |
| 169750 | + for(i=0; i<nCol; i++){ |
| 169751 | + if( abPK[i]==0 ){ |
| 169752 | + bHave = 1; |
| 169753 | + zRet = sqlite3_mprintf( |
| 169754 | + "%z%s\"%w\".\"%w\".\"%w\" IS NOT \"%w\".\"%w\".\"%w\"", |
| 169755 | + zRet, zSep, zDb1, zTab, azCol[i], zDb2, zTab, azCol[i] |
| 169756 | + ); |
| 169757 | + zSep = " OR "; |
| 169758 | + if( zRet==0 ) break; |
| 169759 | + } |
| 169760 | + } |
| 169761 | + |
| 169762 | + if( bHave==0 ){ |
| 169763 | + assert( zRet==0 ); |
| 169764 | + zRet = sqlite3_mprintf("0"); |
| 169765 | + } |
| 169766 | + |
| 169767 | + return zRet; |
| 169768 | +} |
| 169769 | + |
| 169770 | +static char *sessionSelectFindNew( |
| 169771 | + int nCol, |
| 169772 | + const char *zDb1, /* Pick rows in this db only */ |
| 169773 | + const char *zDb2, /* But not in this one */ |
| 169774 | + const char *zTbl, /* Table name */ |
| 169775 | + const char *zExpr |
| 169776 | +){ |
| 169777 | + char *zRet = sqlite3_mprintf( |
| 169778 | + "SELECT * FROM \"%w\".\"%w\" WHERE NOT EXISTS (" |
| 169779 | + " SELECT 1 FROM \"%w\".\"%w\" WHERE %s" |
| 169780 | + ")", |
| 169781 | + zDb1, zTbl, zDb2, zTbl, zExpr |
| 169782 | + ); |
| 169783 | + return zRet; |
| 169784 | +} |
| 169785 | + |
| 169786 | +static int sessionDiffFindNew( |
| 169787 | + int op, |
| 169788 | + sqlite3_session *pSession, |
| 169789 | + SessionTable *pTab, |
| 169790 | + const char *zDb1, |
| 169791 | + const char *zDb2, |
| 169792 | + char *zExpr |
| 169793 | +){ |
| 169794 | + int rc = SQLITE_OK; |
| 169795 | + char *zStmt = sessionSelectFindNew(pTab->nCol, zDb1, zDb2, pTab->zName,zExpr); |
| 169796 | + |
| 169797 | + if( zStmt==0 ){ |
| 169798 | + rc = SQLITE_NOMEM; |
| 169799 | + }else{ |
| 169800 | + sqlite3_stmt *pStmt; |
| 169801 | + rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); |
| 169802 | + if( rc==SQLITE_OK ){ |
| 169803 | + SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; |
| 169804 | + pDiffCtx->pStmt = pStmt; |
| 169805 | + pDiffCtx->nOldOff = 0; |
| 169806 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 169807 | + sessionPreupdateOneChange(op, pSession, pTab); |
| 169808 | + } |
| 169809 | + rc = sqlite3_finalize(pStmt); |
| 169810 | + } |
| 169811 | + sqlite3_free(zStmt); |
| 169812 | + } |
| 169813 | + |
| 169814 | + return rc; |
| 169815 | +} |
| 169816 | + |
| 169817 | +static int sessionDiffFindModified( |
| 169818 | + sqlite3_session *pSession, |
| 169819 | + SessionTable *pTab, |
| 169820 | + const char *zFrom, |
| 169821 | + const char *zExpr |
| 169822 | +){ |
| 169823 | + int rc = SQLITE_OK; |
| 169824 | + |
| 169825 | + char *zExpr2 = sessionExprCompareOther(pTab->nCol, |
| 169826 | + pSession->zDb, zFrom, pTab->zName, pTab->azCol, pTab->abPK |
| 169827 | + ); |
| 169828 | + if( zExpr2==0 ){ |
| 169829 | + rc = SQLITE_NOMEM; |
| 169830 | + }else{ |
| 169831 | + char *zStmt = sqlite3_mprintf( |
| 169832 | + "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", |
| 169833 | + pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 |
| 169834 | + ); |
| 169835 | + if( zStmt==0 ){ |
| 169836 | + rc = SQLITE_NOMEM; |
| 169837 | + }else{ |
| 169838 | + sqlite3_stmt *pStmt; |
| 169839 | + rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); |
| 169840 | + |
| 169841 | + if( rc==SQLITE_OK ){ |
| 169842 | + SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; |
| 169843 | + pDiffCtx->pStmt = pStmt; |
| 169844 | + pDiffCtx->nOldOff = pTab->nCol; |
| 169845 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 169846 | + sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab); |
| 169847 | + } |
| 169848 | + rc = sqlite3_finalize(pStmt); |
| 169849 | + } |
| 169850 | + sqlite3_free(zStmt); |
| 169851 | + } |
| 169852 | + } |
| 169853 | + |
| 169854 | + return rc; |
| 169855 | +} |
| 169856 | + |
| 169857 | +SQLITE_API int SQLITE_STDCALL sqlite3session_diff( |
| 169858 | + sqlite3_session *pSession, |
| 169859 | + const char *zFrom, |
| 169860 | + const char *zTbl, |
| 169861 | + char **pzErrMsg |
| 169862 | +){ |
| 169863 | + const char *zDb = pSession->zDb; |
| 169864 | + int rc = pSession->rc; |
| 169865 | + SessionDiffCtx d; |
| 169866 | + |
| 169867 | + memset(&d, 0, sizeof(d)); |
| 169868 | + sessionDiffHooks(pSession, &d); |
| 169869 | + |
| 169870 | + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); |
| 169871 | + if( pzErrMsg ) *pzErrMsg = 0; |
| 169872 | + if( rc==SQLITE_OK ){ |
| 169873 | + char *zExpr = 0; |
| 169874 | + sqlite3 *db = pSession->db; |
| 169875 | + SessionTable *pTo; /* Table zTbl */ |
| 169876 | + |
| 169877 | + /* Locate and if necessary initialize the target table object */ |
| 169878 | + rc = sessionFindTable(pSession, zTbl, &pTo); |
| 169879 | + if( pTo==0 ) goto diff_out; |
| 169880 | + if( sessionInitTable(pSession, pTo) ){ |
| 169881 | + rc = pSession->rc; |
| 169882 | + goto diff_out; |
| 169883 | + } |
| 169884 | + |
| 169885 | + /* Check the table schemas match */ |
| 169886 | + if( rc==SQLITE_OK ){ |
| 169887 | + int bHasPk = 0; |
| 169888 | + int bMismatch = 0; |
| 169889 | + int nCol; /* Columns in zFrom.zTbl */ |
| 169890 | + u8 *abPK; |
| 169891 | + const char **azCol = 0; |
| 169892 | + rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); |
| 169893 | + if( rc==SQLITE_OK ){ |
| 169894 | + if( pTo->nCol!=nCol ){ |
| 169895 | + bMismatch = 1; |
| 169896 | + }else{ |
| 169897 | + int i; |
| 169898 | + for(i=0; i<nCol; i++){ |
| 169899 | + if( pTo->abPK[i]!=abPK[i] ) bMismatch = 1; |
| 169900 | + if( sqlite3_stricmp(azCol[i], pTo->azCol[i]) ) bMismatch = 1; |
| 169901 | + if( abPK[i] ) bHasPk = 1; |
| 169902 | + } |
| 169903 | + } |
| 169904 | + |
| 169905 | + } |
| 169906 | + sqlite3_free((char*)azCol); |
| 169907 | + if( bMismatch ){ |
| 169908 | + *pzErrMsg = sqlite3_mprintf("table schemas do not match"); |
| 169909 | + rc = SQLITE_SCHEMA; |
| 169910 | + } |
| 169911 | + if( bHasPk==0 ){ |
| 169912 | + /* Ignore tables with no primary keys */ |
| 169913 | + goto diff_out; |
| 169914 | + } |
| 169915 | + } |
| 169916 | + |
| 169917 | + if( rc==SQLITE_OK ){ |
| 169918 | + zExpr = sessionExprComparePK(pTo->nCol, |
| 169919 | + zDb, zFrom, pTo->zName, pTo->azCol, pTo->abPK |
| 169920 | + ); |
| 169921 | + } |
| 169922 | + |
| 169923 | + /* Find new rows */ |
| 169924 | + if( rc==SQLITE_OK ){ |
| 169925 | + rc = sessionDiffFindNew(SQLITE_INSERT, pSession, pTo, zDb, zFrom, zExpr); |
| 169926 | + } |
| 169927 | + |
| 169928 | + /* Find old rows */ |
| 169929 | + if( rc==SQLITE_OK ){ |
| 169930 | + rc = sessionDiffFindNew(SQLITE_DELETE, pSession, pTo, zFrom, zDb, zExpr); |
| 169931 | + } |
| 169932 | + |
| 169933 | + /* Find modified rows */ |
| 169934 | + if( rc==SQLITE_OK ){ |
| 169935 | + rc = sessionDiffFindModified(pSession, pTo, zFrom, zExpr); |
| 169936 | + } |
| 169937 | + |
| 169938 | + sqlite3_free(zExpr); |
| 169939 | + } |
| 169940 | + |
| 169941 | + diff_out: |
| 169942 | + sessionPreupdateHooks(pSession); |
| 169943 | + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); |
| 169944 | + return rc; |
| 169945 | +} |
| 169946 | + |
| 169947 | +/* |
| 169948 | +** Create a session object. This session object will record changes to |
| 169949 | +** database zDb attached to connection db. |
| 169950 | +*/ |
| 169951 | +SQLITE_API int SQLITE_STDCALL sqlite3session_create( |
| 169952 | + sqlite3 *db, /* Database handle */ |
| 169953 | + const char *zDb, /* Name of db (e.g. "main") */ |
| 169954 | + sqlite3_session **ppSession /* OUT: New session object */ |
| 169955 | +){ |
| 169956 | + sqlite3_session *pNew; /* Newly allocated session object */ |
| 169957 | + sqlite3_session *pOld; /* Session object already attached to db */ |
| 169958 | + int nDb = sqlite3Strlen30(zDb); /* Length of zDb in bytes */ |
| 169959 | + |
| 169960 | + /* Zero the output value in case an error occurs. */ |
| 169961 | + *ppSession = 0; |
| 169962 | + |
| 169963 | + /* Allocate and populate the new session object. */ |
| 169964 | + pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1); |
| 169965 | + if( !pNew ) return SQLITE_NOMEM; |
| 169966 | + memset(pNew, 0, sizeof(sqlite3_session)); |
| 169967 | + pNew->db = db; |
| 169968 | + pNew->zDb = (char *)&pNew[1]; |
| 169969 | + pNew->bEnable = 1; |
| 169970 | + memcpy(pNew->zDb, zDb, nDb+1); |
| 169971 | + sessionPreupdateHooks(pNew); |
| 169972 | + |
| 169973 | + /* Add the new session object to the linked list of session objects |
| 169974 | + ** attached to database handle $db. Do this under the cover of the db |
| 169975 | + ** handle mutex. */ |
| 169976 | + sqlite3_mutex_enter(sqlite3_db_mutex(db)); |
| 169977 | + pOld = (sqlite3_session*)sqlite3_preupdate_hook(db, xPreUpdate, (void*)pNew); |
| 169978 | + pNew->pNext = pOld; |
| 169979 | + sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 169980 | + |
| 169981 | + *ppSession = pNew; |
| 169982 | + return SQLITE_OK; |
| 169983 | +} |
| 169984 | + |
| 169985 | +/* |
| 169986 | +** Free the list of table objects passed as the first argument. The contents |
| 169987 | +** of the changed-rows hash tables are also deleted. |
| 169988 | +*/ |
| 169989 | +static void sessionDeleteTable(SessionTable *pList){ |
| 169990 | + SessionTable *pNext; |
| 169991 | + SessionTable *pTab; |
| 169992 | + |
| 169993 | + for(pTab=pList; pTab; pTab=pNext){ |
| 169994 | + int i; |
| 169995 | + pNext = pTab->pNext; |
| 169996 | + for(i=0; i<pTab->nChange; i++){ |
| 169997 | + SessionChange *p; |
| 169998 | + SessionChange *pNext; |
| 169999 | + for(p=pTab->apChange[i]; p; p=pNext){ |
| 170000 | + pNext = p->pNext; |
| 170001 | + sqlite3_free(p); |
| 170002 | + } |
| 170003 | + } |
| 170004 | + sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */ |
| 170005 | + sqlite3_free(pTab->apChange); |
| 170006 | + sqlite3_free(pTab); |
| 170007 | + } |
| 170008 | +} |
| 170009 | + |
| 170010 | +/* |
| 170011 | +** Delete a session object previously allocated using sqlite3session_create(). |
| 170012 | +*/ |
| 170013 | +SQLITE_API void SQLITE_STDCALL sqlite3session_delete(sqlite3_session *pSession){ |
| 170014 | + sqlite3 *db = pSession->db; |
| 170015 | + sqlite3_session *pHead; |
| 170016 | + sqlite3_session **pp; |
| 170017 | + |
| 170018 | + /* Unlink the session from the linked list of sessions attached to the |
| 170019 | + ** database handle. Hold the db mutex while doing so. */ |
| 170020 | + sqlite3_mutex_enter(sqlite3_db_mutex(db)); |
| 170021 | + pHead = (sqlite3_session*)sqlite3_preupdate_hook(db, 0, 0); |
| 170022 | + for(pp=&pHead; ALWAYS((*pp)!=0); pp=&((*pp)->pNext)){ |
| 170023 | + if( (*pp)==pSession ){ |
| 170024 | + *pp = (*pp)->pNext; |
| 170025 | + if( pHead ) sqlite3_preupdate_hook(db, xPreUpdate, (void*)pHead); |
| 170026 | + break; |
| 170027 | + } |
| 170028 | + } |
| 170029 | + sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 170030 | + |
| 170031 | + /* Delete all attached table objects. And the contents of their |
| 170032 | + ** associated hash-tables. */ |
| 170033 | + sessionDeleteTable(pSession->pTable); |
| 170034 | + |
| 170035 | + /* Free the session object itself. */ |
| 170036 | + sqlite3_free(pSession); |
| 170037 | +} |
| 170038 | + |
| 170039 | +/* |
| 170040 | +** Set a table filter on a Session Object. |
| 170041 | +*/ |
| 170042 | +SQLITE_API void SQLITE_STDCALL sqlite3session_table_filter( |
| 170043 | + sqlite3_session *pSession, |
| 170044 | + int(*xFilter)(void*, const char*), |
| 170045 | + void *pCtx /* First argument passed to xFilter */ |
| 170046 | +){ |
| 170047 | + pSession->bAutoAttach = 1; |
| 170048 | + pSession->pFilterCtx = pCtx; |
| 170049 | + pSession->xTableFilter = xFilter; |
| 170050 | +} |
| 170051 | + |
| 170052 | +/* |
| 170053 | +** Attach a table to a session. All subsequent changes made to the table |
| 170054 | +** while the session object is enabled will be recorded. |
| 170055 | +** |
| 170056 | +** Only tables that have a PRIMARY KEY defined may be attached. It does |
| 170057 | +** not matter if the PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) |
| 170058 | +** or not. |
| 170059 | +*/ |
| 170060 | +SQLITE_API int SQLITE_STDCALL sqlite3session_attach( |
| 170061 | + sqlite3_session *pSession, /* Session object */ |
| 170062 | + const char *zName /* Table name */ |
| 170063 | +){ |
| 170064 | + int rc = SQLITE_OK; |
| 170065 | + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); |
| 170066 | + |
| 170067 | + if( !zName ){ |
| 170068 | + pSession->bAutoAttach = 1; |
| 170069 | + }else{ |
| 170070 | + SessionTable *pTab; /* New table object (if required) */ |
| 170071 | + int nName; /* Number of bytes in string zName */ |
| 170072 | + |
| 170073 | + /* First search for an existing entry. If one is found, this call is |
| 170074 | + ** a no-op. Return early. */ |
| 170075 | + nName = sqlite3Strlen30(zName); |
| 170076 | + for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){ |
| 170077 | + if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break; |
| 170078 | + } |
| 170079 | + |
| 170080 | + if( !pTab ){ |
| 170081 | + /* Allocate new SessionTable object. */ |
| 170082 | + pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1); |
| 170083 | + if( !pTab ){ |
| 170084 | + rc = SQLITE_NOMEM; |
| 170085 | + }else{ |
| 170086 | + /* Populate the new SessionTable object and link it into the list. |
| 170087 | + ** The new object must be linked onto the end of the list, not |
| 170088 | + ** simply added to the start of it in order to ensure that tables |
| 170089 | + ** appear in the correct order when a changeset or patchset is |
| 170090 | + ** eventually generated. */ |
| 170091 | + SessionTable **ppTab; |
| 170092 | + memset(pTab, 0, sizeof(SessionTable)); |
| 170093 | + pTab->zName = (char *)&pTab[1]; |
| 170094 | + memcpy(pTab->zName, zName, nName+1); |
| 170095 | + for(ppTab=&pSession->pTable; *ppTab; ppTab=&(*ppTab)->pNext); |
| 170096 | + *ppTab = pTab; |
| 170097 | + } |
| 170098 | + } |
| 170099 | + } |
| 170100 | + |
| 170101 | + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); |
| 170102 | + return rc; |
| 170103 | +} |
| 170104 | + |
| 170105 | +/* |
| 170106 | +** Ensure that there is room in the buffer to append nByte bytes of data. |
| 170107 | +** If not, use sqlite3_realloc() to grow the buffer so that there is. |
| 170108 | +** |
| 170109 | +** If successful, return zero. Otherwise, if an OOM condition is encountered, |
| 170110 | +** set *pRc to SQLITE_NOMEM and return non-zero. |
| 170111 | +*/ |
| 170112 | +static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ |
| 170113 | + if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){ |
| 170114 | + u8 *aNew; |
| 170115 | + int nNew = p->nAlloc ? p->nAlloc : 128; |
| 170116 | + do { |
| 170117 | + nNew = nNew*2; |
| 170118 | + }while( nNew<(p->nBuf+nByte) ); |
| 170119 | + |
| 170120 | + aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); |
| 170121 | + if( 0==aNew ){ |
| 170122 | + *pRc = SQLITE_NOMEM; |
| 170123 | + }else{ |
| 170124 | + p->aBuf = aNew; |
| 170125 | + p->nAlloc = nNew; |
| 170126 | + } |
| 170127 | + } |
| 170128 | + return (*pRc!=SQLITE_OK); |
| 170129 | +} |
| 170130 | + |
| 170131 | +/* |
| 170132 | +** Append the value passed as the second argument to the buffer passed |
| 170133 | +** as the first. |
| 170134 | +** |
| 170135 | +** This function is a no-op if *pRc is non-zero when it is called. |
| 170136 | +** Otherwise, if an error occurs, *pRc is set to an SQLite error code |
| 170137 | +** before returning. |
| 170138 | +*/ |
| 170139 | +static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){ |
| 170140 | + int rc = *pRc; |
| 170141 | + if( rc==SQLITE_OK ){ |
| 170142 | + int nByte = 0; |
| 170143 | + rc = sessionSerializeValue(0, pVal, &nByte); |
| 170144 | + sessionBufferGrow(p, nByte, &rc); |
| 170145 | + if( rc==SQLITE_OK ){ |
| 170146 | + rc = sessionSerializeValue(&p->aBuf[p->nBuf], pVal, 0); |
| 170147 | + p->nBuf += nByte; |
| 170148 | + }else{ |
| 170149 | + *pRc = rc; |
| 170150 | + } |
| 170151 | + } |
| 170152 | +} |
| 170153 | + |
| 170154 | +/* |
| 170155 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170156 | +** called. Otherwise, append a single byte to the buffer. |
| 170157 | +** |
| 170158 | +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before |
| 170159 | +** returning. |
| 170160 | +*/ |
| 170161 | +static void sessionAppendByte(SessionBuffer *p, u8 v, int *pRc){ |
| 170162 | + if( 0==sessionBufferGrow(p, 1, pRc) ){ |
| 170163 | + p->aBuf[p->nBuf++] = v; |
| 170164 | + } |
| 170165 | +} |
| 170166 | + |
| 170167 | +/* |
| 170168 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170169 | +** called. Otherwise, append a single varint to the buffer. |
| 170170 | +** |
| 170171 | +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before |
| 170172 | +** returning. |
| 170173 | +*/ |
| 170174 | +static void sessionAppendVarint(SessionBuffer *p, int v, int *pRc){ |
| 170175 | + if( 0==sessionBufferGrow(p, 9, pRc) ){ |
| 170176 | + p->nBuf += sessionVarintPut(&p->aBuf[p->nBuf], v); |
| 170177 | + } |
| 170178 | +} |
| 170179 | + |
| 170180 | +/* |
| 170181 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170182 | +** called. Otherwise, append a blob of data to the buffer. |
| 170183 | +** |
| 170184 | +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before |
| 170185 | +** returning. |
| 170186 | +*/ |
| 170187 | +static void sessionAppendBlob( |
| 170188 | + SessionBuffer *p, |
| 170189 | + const u8 *aBlob, |
| 170190 | + int nBlob, |
| 170191 | + int *pRc |
| 170192 | +){ |
| 170193 | + if( 0==sessionBufferGrow(p, nBlob, pRc) ){ |
| 170194 | + memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); |
| 170195 | + p->nBuf += nBlob; |
| 170196 | + } |
| 170197 | +} |
| 170198 | + |
| 170199 | +/* |
| 170200 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170201 | +** called. Otherwise, append a string to the buffer. All bytes in the string |
| 170202 | +** up to (but not including) the nul-terminator are written to the buffer. |
| 170203 | +** |
| 170204 | +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before |
| 170205 | +** returning. |
| 170206 | +*/ |
| 170207 | +static void sessionAppendStr( |
| 170208 | + SessionBuffer *p, |
| 170209 | + const char *zStr, |
| 170210 | + int *pRc |
| 170211 | +){ |
| 170212 | + int nStr = sqlite3Strlen30(zStr); |
| 170213 | + if( 0==sessionBufferGrow(p, nStr, pRc) ){ |
| 170214 | + memcpy(&p->aBuf[p->nBuf], zStr, nStr); |
| 170215 | + p->nBuf += nStr; |
| 170216 | + } |
| 170217 | +} |
| 170218 | + |
| 170219 | +/* |
| 170220 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170221 | +** called. Otherwise, append the string representation of integer iVal |
| 170222 | +** to the buffer. No nul-terminator is written. |
| 170223 | +** |
| 170224 | +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before |
| 170225 | +** returning. |
| 170226 | +*/ |
| 170227 | +static void sessionAppendInteger( |
| 170228 | + SessionBuffer *p, /* Buffer to append to */ |
| 170229 | + int iVal, /* Value to write the string rep. of */ |
| 170230 | + int *pRc /* IN/OUT: Error code */ |
| 170231 | +){ |
| 170232 | + char aBuf[24]; |
| 170233 | + sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); |
| 170234 | + sessionAppendStr(p, aBuf, pRc); |
| 170235 | +} |
| 170236 | + |
| 170237 | +/* |
| 170238 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170239 | +** called. Otherwise, append the string zStr enclosed in quotes (") and |
| 170240 | +** with any embedded quote characters escaped to the buffer. No |
| 170241 | +** nul-terminator byte is written. |
| 170242 | +** |
| 170243 | +** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before |
| 170244 | +** returning. |
| 170245 | +*/ |
| 170246 | +static void sessionAppendIdent( |
| 170247 | + SessionBuffer *p, /* Buffer to a append to */ |
| 170248 | + const char *zStr, /* String to quote, escape and append */ |
| 170249 | + int *pRc /* IN/OUT: Error code */ |
| 170250 | +){ |
| 170251 | + int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1; |
| 170252 | + if( 0==sessionBufferGrow(p, nStr, pRc) ){ |
| 170253 | + char *zOut = (char *)&p->aBuf[p->nBuf]; |
| 170254 | + const char *zIn = zStr; |
| 170255 | + *zOut++ = '"'; |
| 170256 | + while( *zIn ){ |
| 170257 | + if( *zIn=='"' ) *zOut++ = '"'; |
| 170258 | + *zOut++ = *(zIn++); |
| 170259 | + } |
| 170260 | + *zOut++ = '"'; |
| 170261 | + p->nBuf = (int)((u8 *)zOut - p->aBuf); |
| 170262 | + } |
| 170263 | +} |
| 170264 | + |
| 170265 | +/* |
| 170266 | +** This function is a no-op if *pRc is other than SQLITE_OK when it is |
| 170267 | +** called. Otherwse, it appends the serialized version of the value stored |
| 170268 | +** in column iCol of the row that SQL statement pStmt currently points |
| 170269 | +** to to the buffer. |
| 170270 | +*/ |
| 170271 | +static void sessionAppendCol( |
| 170272 | + SessionBuffer *p, /* Buffer to append to */ |
| 170273 | + sqlite3_stmt *pStmt, /* Handle pointing to row containing value */ |
| 170274 | + int iCol, /* Column to read value from */ |
| 170275 | + int *pRc /* IN/OUT: Error code */ |
| 170276 | +){ |
| 170277 | + if( *pRc==SQLITE_OK ){ |
| 170278 | + int eType = sqlite3_column_type(pStmt, iCol); |
| 170279 | + sessionAppendByte(p, (u8)eType, pRc); |
| 170280 | + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 170281 | + sqlite3_int64 i; |
| 170282 | + u8 aBuf[8]; |
| 170283 | + if( eType==SQLITE_INTEGER ){ |
| 170284 | + i = sqlite3_column_int64(pStmt, iCol); |
| 170285 | + }else{ |
| 170286 | + double r = sqlite3_column_double(pStmt, iCol); |
| 170287 | + memcpy(&i, &r, 8); |
| 170288 | + } |
| 170289 | + sessionPutI64(aBuf, i); |
| 170290 | + sessionAppendBlob(p, aBuf, 8, pRc); |
| 170291 | + } |
| 170292 | + if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){ |
| 170293 | + u8 *z; |
| 170294 | + int nByte; |
| 170295 | + if( eType==SQLITE_BLOB ){ |
| 170296 | + z = (u8 *)sqlite3_column_blob(pStmt, iCol); |
| 170297 | + }else{ |
| 170298 | + z = (u8 *)sqlite3_column_text(pStmt, iCol); |
| 170299 | + } |
| 170300 | + nByte = sqlite3_column_bytes(pStmt, iCol); |
| 170301 | + if( z || (eType==SQLITE_BLOB && nByte==0) ){ |
| 170302 | + sessionAppendVarint(p, nByte, pRc); |
| 170303 | + sessionAppendBlob(p, z, nByte, pRc); |
| 170304 | + }else{ |
| 170305 | + *pRc = SQLITE_NOMEM; |
| 170306 | + } |
| 170307 | + } |
| 170308 | + } |
| 170309 | +} |
| 170310 | + |
| 170311 | +/* |
| 170312 | +** |
| 170313 | +** This function appends an update change to the buffer (see the comments |
| 170314 | +** under "CHANGESET FORMAT" at the top of the file). An update change |
| 170315 | +** consists of: |
| 170316 | +** |
| 170317 | +** 1 byte: SQLITE_UPDATE (0x17) |
| 170318 | +** n bytes: old.* record (see RECORD FORMAT) |
| 170319 | +** m bytes: new.* record (see RECORD FORMAT) |
| 170320 | +** |
| 170321 | +** The SessionChange object passed as the third argument contains the |
| 170322 | +** values that were stored in the row when the session began (the old.* |
| 170323 | +** values). The statement handle passed as the second argument points |
| 170324 | +** at the current version of the row (the new.* values). |
| 170325 | +** |
| 170326 | +** If all of the old.* values are equal to their corresponding new.* value |
| 170327 | +** (i.e. nothing has changed), then no data at all is appended to the buffer. |
| 170328 | +** |
| 170329 | +** Otherwise, the old.* record contains all primary key values and the |
| 170330 | +** original values of any fields that have been modified. The new.* record |
| 170331 | +** contains the new values of only those fields that have been modified. |
| 170332 | +*/ |
| 170333 | +static int sessionAppendUpdate( |
| 170334 | + SessionBuffer *pBuf, /* Buffer to append to */ |
| 170335 | + int bPatchset, /* True for "patchset", 0 for "changeset" */ |
| 170336 | + sqlite3_stmt *pStmt, /* Statement handle pointing at new row */ |
| 170337 | + SessionChange *p, /* Object containing old values */ |
| 170338 | + u8 *abPK /* Boolean array - true for PK columns */ |
| 170339 | +){ |
| 170340 | + int rc = SQLITE_OK; |
| 170341 | + SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */ |
| 170342 | + int bNoop = 1; /* Set to zero if any values are modified */ |
| 170343 | + int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */ |
| 170344 | + int i; /* Used to iterate through columns */ |
| 170345 | + u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */ |
| 170346 | + |
| 170347 | + sessionAppendByte(pBuf, SQLITE_UPDATE, &rc); |
| 170348 | + sessionAppendByte(pBuf, p->bIndirect, &rc); |
| 170349 | + for(i=0; i<sqlite3_column_count(pStmt); i++){ |
| 170350 | + int bChanged = 0; |
| 170351 | + int nAdvance; |
| 170352 | + int eType = *pCsr; |
| 170353 | + switch( eType ){ |
| 170354 | + case SQLITE_NULL: |
| 170355 | + nAdvance = 1; |
| 170356 | + if( sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 170357 | + bChanged = 1; |
| 170358 | + } |
| 170359 | + break; |
| 170360 | + |
| 170361 | + case SQLITE_FLOAT: |
| 170362 | + case SQLITE_INTEGER: { |
| 170363 | + nAdvance = 9; |
| 170364 | + if( eType==sqlite3_column_type(pStmt, i) ){ |
| 170365 | + sqlite3_int64 iVal = sessionGetI64(&pCsr[1]); |
| 170366 | + if( eType==SQLITE_INTEGER ){ |
| 170367 | + if( iVal==sqlite3_column_int64(pStmt, i) ) break; |
| 170368 | + }else{ |
| 170369 | + double dVal; |
| 170370 | + memcpy(&dVal, &iVal, 8); |
| 170371 | + if( dVal==sqlite3_column_double(pStmt, i) ) break; |
| 170372 | + } |
| 170373 | + } |
| 170374 | + bChanged = 1; |
| 170375 | + break; |
| 170376 | + } |
| 170377 | + |
| 170378 | + default: { |
| 170379 | + int nByte; |
| 170380 | + int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte); |
| 170381 | + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); |
| 170382 | + nAdvance = nHdr + nByte; |
| 170383 | + if( eType==sqlite3_column_type(pStmt, i) |
| 170384 | + && nByte==sqlite3_column_bytes(pStmt, i) |
| 170385 | + && 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), nByte) |
| 170386 | + ){ |
| 170387 | + break; |
| 170388 | + } |
| 170389 | + bChanged = 1; |
| 170390 | + } |
| 170391 | + } |
| 170392 | + |
| 170393 | + /* If at least one field has been modified, this is not a no-op. */ |
| 170394 | + if( bChanged ) bNoop = 0; |
| 170395 | + |
| 170396 | + /* Add a field to the old.* record. This is omitted if this modules is |
| 170397 | + ** currently generating a patchset. */ |
| 170398 | + if( bPatchset==0 ){ |
| 170399 | + if( bChanged || abPK[i] ){ |
| 170400 | + sessionAppendBlob(pBuf, pCsr, nAdvance, &rc); |
| 170401 | + }else{ |
| 170402 | + sessionAppendByte(pBuf, 0, &rc); |
| 170403 | + } |
| 170404 | + } |
| 170405 | + |
| 170406 | + /* Add a field to the new.* record. Or the only record if currently |
| 170407 | + ** generating a patchset. */ |
| 170408 | + if( bChanged || (bPatchset && abPK[i]) ){ |
| 170409 | + sessionAppendCol(&buf2, pStmt, i, &rc); |
| 170410 | + }else{ |
| 170411 | + sessionAppendByte(&buf2, 0, &rc); |
| 170412 | + } |
| 170413 | + |
| 170414 | + pCsr += nAdvance; |
| 170415 | + } |
| 170416 | + |
| 170417 | + if( bNoop ){ |
| 170418 | + pBuf->nBuf = nRewind; |
| 170419 | + }else{ |
| 170420 | + sessionAppendBlob(pBuf, buf2.aBuf, buf2.nBuf, &rc); |
| 170421 | + } |
| 170422 | + sqlite3_free(buf2.aBuf); |
| 170423 | + |
| 170424 | + return rc; |
| 170425 | +} |
| 170426 | + |
| 170427 | +/* |
| 170428 | +** Append a DELETE change to the buffer passed as the first argument. Use |
| 170429 | +** the changeset format if argument bPatchset is zero, or the patchset |
| 170430 | +** format otherwise. |
| 170431 | +*/ |
| 170432 | +static int sessionAppendDelete( |
| 170433 | + SessionBuffer *pBuf, /* Buffer to append to */ |
| 170434 | + int bPatchset, /* True for "patchset", 0 for "changeset" */ |
| 170435 | + SessionChange *p, /* Object containing old values */ |
| 170436 | + int nCol, /* Number of columns in table */ |
| 170437 | + u8 *abPK /* Boolean array - true for PK columns */ |
| 170438 | +){ |
| 170439 | + int rc = SQLITE_OK; |
| 170440 | + |
| 170441 | + sessionAppendByte(pBuf, SQLITE_DELETE, &rc); |
| 170442 | + sessionAppendByte(pBuf, p->bIndirect, &rc); |
| 170443 | + |
| 170444 | + if( bPatchset==0 ){ |
| 170445 | + sessionAppendBlob(pBuf, p->aRecord, p->nRecord, &rc); |
| 170446 | + }else{ |
| 170447 | + int i; |
| 170448 | + u8 *a = p->aRecord; |
| 170449 | + for(i=0; i<nCol; i++){ |
| 170450 | + u8 *pStart = a; |
| 170451 | + int eType = *a++; |
| 170452 | + |
| 170453 | + switch( eType ){ |
| 170454 | + case 0: |
| 170455 | + case SQLITE_NULL: |
| 170456 | + assert( abPK[i]==0 ); |
| 170457 | + break; |
| 170458 | + |
| 170459 | + case SQLITE_FLOAT: |
| 170460 | + case SQLITE_INTEGER: |
| 170461 | + a += 8; |
| 170462 | + break; |
| 170463 | + |
| 170464 | + default: { |
| 170465 | + int n; |
| 170466 | + a += sessionVarintGet(a, &n); |
| 170467 | + a += n; |
| 170468 | + break; |
| 170469 | + } |
| 170470 | + } |
| 170471 | + if( abPK[i] ){ |
| 170472 | + sessionAppendBlob(pBuf, pStart, (int)(a-pStart), &rc); |
| 170473 | + } |
| 170474 | + } |
| 170475 | + assert( (a - p->aRecord)==p->nRecord ); |
| 170476 | + } |
| 170477 | + |
| 170478 | + return rc; |
| 170479 | +} |
| 170480 | + |
| 170481 | +/* |
| 170482 | +** Formulate and prepare a SELECT statement to retrieve a row from table |
| 170483 | +** zTab in database zDb based on its primary key. i.e. |
| 170484 | +** |
| 170485 | +** SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ... |
| 170486 | +*/ |
| 170487 | +static int sessionSelectStmt( |
| 170488 | + sqlite3 *db, /* Database handle */ |
| 170489 | + const char *zDb, /* Database name */ |
| 170490 | + const char *zTab, /* Table name */ |
| 170491 | + int nCol, /* Number of columns in table */ |
| 170492 | + const char **azCol, /* Names of table columns */ |
| 170493 | + u8 *abPK, /* PRIMARY KEY array */ |
| 170494 | + sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ |
| 170495 | +){ |
| 170496 | + int rc = SQLITE_OK; |
| 170497 | + int i; |
| 170498 | + const char *zSep = ""; |
| 170499 | + SessionBuffer buf = {0, 0, 0}; |
| 170500 | + |
| 170501 | + sessionAppendStr(&buf, "SELECT * FROM ", &rc); |
| 170502 | + sessionAppendIdent(&buf, zDb, &rc); |
| 170503 | + sessionAppendStr(&buf, ".", &rc); |
| 170504 | + sessionAppendIdent(&buf, zTab, &rc); |
| 170505 | + sessionAppendStr(&buf, " WHERE ", &rc); |
| 170506 | + for(i=0; i<nCol; i++){ |
| 170507 | + if( abPK[i] ){ |
| 170508 | + sessionAppendStr(&buf, zSep, &rc); |
| 170509 | + sessionAppendIdent(&buf, azCol[i], &rc); |
| 170510 | + sessionAppendStr(&buf, " = ?", &rc); |
| 170511 | + sessionAppendInteger(&buf, i+1, &rc); |
| 170512 | + zSep = " AND "; |
| 170513 | + } |
| 170514 | + } |
| 170515 | + if( rc==SQLITE_OK ){ |
| 170516 | + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, ppStmt, 0); |
| 170517 | + } |
| 170518 | + sqlite3_free(buf.aBuf); |
| 170519 | + return rc; |
| 170520 | +} |
| 170521 | + |
| 170522 | +/* |
| 170523 | +** Bind the PRIMARY KEY values from the change passed in argument pChange |
| 170524 | +** to the SELECT statement passed as the first argument. The SELECT statement |
| 170525 | +** is as prepared by function sessionSelectStmt(). |
| 170526 | +** |
| 170527 | +** Return SQLITE_OK if all PK values are successfully bound, or an SQLite |
| 170528 | +** error code (e.g. SQLITE_NOMEM) otherwise. |
| 170529 | +*/ |
| 170530 | +static int sessionSelectBind( |
| 170531 | + sqlite3_stmt *pSelect, /* SELECT from sessionSelectStmt() */ |
| 170532 | + int nCol, /* Number of columns in table */ |
| 170533 | + u8 *abPK, /* PRIMARY KEY array */ |
| 170534 | + SessionChange *pChange /* Change structure */ |
| 170535 | +){ |
| 170536 | + int i; |
| 170537 | + int rc = SQLITE_OK; |
| 170538 | + u8 *a = pChange->aRecord; |
| 170539 | + |
| 170540 | + for(i=0; i<nCol && rc==SQLITE_OK; i++){ |
| 170541 | + int eType = *a++; |
| 170542 | + |
| 170543 | + switch( eType ){ |
| 170544 | + case 0: |
| 170545 | + case SQLITE_NULL: |
| 170546 | + assert( abPK[i]==0 ); |
| 170547 | + break; |
| 170548 | + |
| 170549 | + case SQLITE_INTEGER: { |
| 170550 | + if( abPK[i] ){ |
| 170551 | + i64 iVal = sessionGetI64(a); |
| 170552 | + rc = sqlite3_bind_int64(pSelect, i+1, iVal); |
| 170553 | + } |
| 170554 | + a += 8; |
| 170555 | + break; |
| 170556 | + } |
| 170557 | + |
| 170558 | + case SQLITE_FLOAT: { |
| 170559 | + if( abPK[i] ){ |
| 170560 | + double rVal; |
| 170561 | + i64 iVal = sessionGetI64(a); |
| 170562 | + memcpy(&rVal, &iVal, 8); |
| 170563 | + rc = sqlite3_bind_double(pSelect, i+1, rVal); |
| 170564 | + } |
| 170565 | + a += 8; |
| 170566 | + break; |
| 170567 | + } |
| 170568 | + |
| 170569 | + case SQLITE_TEXT: { |
| 170570 | + int n; |
| 170571 | + a += sessionVarintGet(a, &n); |
| 170572 | + if( abPK[i] ){ |
| 170573 | + rc = sqlite3_bind_text(pSelect, i+1, (char *)a, n, SQLITE_TRANSIENT); |
| 170574 | + } |
| 170575 | + a += n; |
| 170576 | + break; |
| 170577 | + } |
| 170578 | + |
| 170579 | + default: { |
| 170580 | + int n; |
| 170581 | + assert( eType==SQLITE_BLOB ); |
| 170582 | + a += sessionVarintGet(a, &n); |
| 170583 | + if( abPK[i] ){ |
| 170584 | + rc = sqlite3_bind_blob(pSelect, i+1, a, n, SQLITE_TRANSIENT); |
| 170585 | + } |
| 170586 | + a += n; |
| 170587 | + break; |
| 170588 | + } |
| 170589 | + } |
| 170590 | + } |
| 170591 | + |
| 170592 | + return rc; |
| 170593 | +} |
| 170594 | + |
| 170595 | +/* |
| 170596 | +** This function is a no-op if *pRc is set to other than SQLITE_OK when it |
| 170597 | +** is called. Otherwise, append a serialized table header (part of the binary |
| 170598 | +** changeset format) to buffer *pBuf. If an error occurs, set *pRc to an |
| 170599 | +** SQLite error code before returning. |
| 170600 | +*/ |
| 170601 | +static void sessionAppendTableHdr( |
| 170602 | + SessionBuffer *pBuf, /* Append header to this buffer */ |
| 170603 | + int bPatchset, /* Use the patchset format if true */ |
| 170604 | + SessionTable *pTab, /* Table object to append header for */ |
| 170605 | + int *pRc /* IN/OUT: Error code */ |
| 170606 | +){ |
| 170607 | + /* Write a table header */ |
| 170608 | + sessionAppendByte(pBuf, (bPatchset ? 'P' : 'T'), pRc); |
| 170609 | + sessionAppendVarint(pBuf, pTab->nCol, pRc); |
| 170610 | + sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc); |
| 170611 | + sessionAppendBlob(pBuf, (u8 *)pTab->zName, (int)strlen(pTab->zName)+1, pRc); |
| 170612 | +} |
| 170613 | + |
| 170614 | +/* |
| 170615 | +** Generate either a changeset (if argument bPatchset is zero) or a patchset |
| 170616 | +** (if it is non-zero) based on the current contents of the session object |
| 170617 | +** passed as the first argument. |
| 170618 | +** |
| 170619 | +** If no error occurs, SQLITE_OK is returned and the new changeset/patchset |
| 170620 | +** stored in output variables *pnChangeset and *ppChangeset. Or, if an error |
| 170621 | +** occurs, an SQLite error code is returned and both output variables set |
| 170622 | +** to 0. |
| 170623 | +*/ |
| 170624 | +static int sessionGenerateChangeset( |
| 170625 | + sqlite3_session *pSession, /* Session object */ |
| 170626 | + int bPatchset, /* True for patchset, false for changeset */ |
| 170627 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 170628 | + void *pOut, /* First argument for xOutput */ |
| 170629 | + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ |
| 170630 | + void **ppChangeset /* OUT: Buffer containing changeset */ |
| 170631 | +){ |
| 170632 | + sqlite3 *db = pSession->db; /* Source database handle */ |
| 170633 | + SessionTable *pTab; /* Used to iterate through attached tables */ |
| 170634 | + SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ |
| 170635 | + int rc; /* Return code */ |
| 170636 | + |
| 170637 | + assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) ); |
| 170638 | + |
| 170639 | + /* Zero the output variables in case an error occurs. If this session |
| 170640 | + ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), |
| 170641 | + ** this call will be a no-op. */ |
| 170642 | + if( xOutput==0 ){ |
| 170643 | + *pnChangeset = 0; |
| 170644 | + *ppChangeset = 0; |
| 170645 | + } |
| 170646 | + |
| 170647 | + if( pSession->rc ) return pSession->rc; |
| 170648 | + rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); |
| 170649 | + if( rc!=SQLITE_OK ) return rc; |
| 170650 | + |
| 170651 | + sqlite3_mutex_enter(sqlite3_db_mutex(db)); |
| 170652 | + |
| 170653 | + for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ |
| 170654 | + if( pTab->nEntry ){ |
| 170655 | + const char *zName = pTab->zName; |
| 170656 | + int nCol; /* Number of columns in table */ |
| 170657 | + u8 *abPK; /* Primary key array */ |
| 170658 | + const char **azCol = 0; /* Table columns */ |
| 170659 | + int i; /* Used to iterate through hash buckets */ |
| 170660 | + sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ |
| 170661 | + int nRewind = buf.nBuf; /* Initial size of write buffer */ |
| 170662 | + int nNoop; /* Size of buffer after writing tbl header */ |
| 170663 | + |
| 170664 | + /* Check the table schema is still Ok. */ |
| 170665 | + rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK); |
| 170666 | + if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){ |
| 170667 | + rc = SQLITE_SCHEMA; |
| 170668 | + } |
| 170669 | + |
| 170670 | + /* Write a table header */ |
| 170671 | + sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); |
| 170672 | + |
| 170673 | + /* Build and compile a statement to execute: */ |
| 170674 | + if( rc==SQLITE_OK ){ |
| 170675 | + rc = sessionSelectStmt( |
| 170676 | + db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); |
| 170677 | + } |
| 170678 | + |
| 170679 | + nNoop = buf.nBuf; |
| 170680 | + for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){ |
| 170681 | + SessionChange *p; /* Used to iterate through changes */ |
| 170682 | + |
| 170683 | + for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ |
| 170684 | + rc = sessionSelectBind(pSel, nCol, abPK, p); |
| 170685 | + if( rc!=SQLITE_OK ) continue; |
| 170686 | + if( sqlite3_step(pSel)==SQLITE_ROW ){ |
| 170687 | + if( p->op==SQLITE_INSERT ){ |
| 170688 | + int iCol; |
| 170689 | + sessionAppendByte(&buf, SQLITE_INSERT, &rc); |
| 170690 | + sessionAppendByte(&buf, p->bIndirect, &rc); |
| 170691 | + for(iCol=0; iCol<nCol; iCol++){ |
| 170692 | + sessionAppendCol(&buf, pSel, iCol, &rc); |
| 170693 | + } |
| 170694 | + }else{ |
| 170695 | + rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK); |
| 170696 | + } |
| 170697 | + }else if( p->op!=SQLITE_INSERT ){ |
| 170698 | + rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK); |
| 170699 | + } |
| 170700 | + if( rc==SQLITE_OK ){ |
| 170701 | + rc = sqlite3_reset(pSel); |
| 170702 | + } |
| 170703 | + |
| 170704 | + /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass |
| 170705 | + ** its contents to the xOutput() callback. */ |
| 170706 | + if( xOutput |
| 170707 | + && rc==SQLITE_OK |
| 170708 | + && buf.nBuf>nNoop |
| 170709 | + && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE |
| 170710 | + ){ |
| 170711 | + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); |
| 170712 | + nNoop = -1; |
| 170713 | + buf.nBuf = 0; |
| 170714 | + } |
| 170715 | + |
| 170716 | + } |
| 170717 | + } |
| 170718 | + |
| 170719 | + sqlite3_finalize(pSel); |
| 170720 | + if( buf.nBuf==nNoop ){ |
| 170721 | + buf.nBuf = nRewind; |
| 170722 | + } |
| 170723 | + sqlite3_free((char*)azCol); /* cast works around VC++ bug */ |
| 170724 | + } |
| 170725 | + } |
| 170726 | + |
| 170727 | + if( rc==SQLITE_OK ){ |
| 170728 | + if( xOutput==0 ){ |
| 170729 | + *pnChangeset = buf.nBuf; |
| 170730 | + *ppChangeset = buf.aBuf; |
| 170731 | + buf.aBuf = 0; |
| 170732 | + }else if( buf.nBuf>0 ){ |
| 170733 | + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); |
| 170734 | + } |
| 170735 | + } |
| 170736 | + |
| 170737 | + sqlite3_free(buf.aBuf); |
| 170738 | + sqlite3_exec(db, "RELEASE changeset", 0, 0, 0); |
| 170739 | + sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 170740 | + return rc; |
| 170741 | +} |
| 170742 | + |
| 170743 | +/* |
| 170744 | +** Obtain a changeset object containing all changes recorded by the |
| 170745 | +** session object passed as the first argument. |
| 170746 | +** |
| 170747 | +** It is the responsibility of the caller to eventually free the buffer |
| 170748 | +** using sqlite3_free(). |
| 170749 | +*/ |
| 170750 | +SQLITE_API int SQLITE_STDCALL sqlite3session_changeset( |
| 170751 | + sqlite3_session *pSession, /* Session object */ |
| 170752 | + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ |
| 170753 | + void **ppChangeset /* OUT: Buffer containing changeset */ |
| 170754 | +){ |
| 170755 | + return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset); |
| 170756 | +} |
| 170757 | + |
| 170758 | +/* |
| 170759 | +** Streaming version of sqlite3session_changeset(). |
| 170760 | +*/ |
| 170761 | +SQLITE_API int SQLITE_STDCALL sqlite3session_changeset_strm( |
| 170762 | + sqlite3_session *pSession, |
| 170763 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 170764 | + void *pOut |
| 170765 | +){ |
| 170766 | + return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0); |
| 170767 | +} |
| 170768 | + |
| 170769 | +/* |
| 170770 | +** Streaming version of sqlite3session_patchset(). |
| 170771 | +*/ |
| 170772 | +SQLITE_API int SQLITE_STDCALL sqlite3session_patchset_strm( |
| 170773 | + sqlite3_session *pSession, |
| 170774 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 170775 | + void *pOut |
| 170776 | +){ |
| 170777 | + return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0); |
| 170778 | +} |
| 170779 | + |
| 170780 | +/* |
| 170781 | +** Obtain a patchset object containing all changes recorded by the |
| 170782 | +** session object passed as the first argument. |
| 170783 | +** |
| 170784 | +** It is the responsibility of the caller to eventually free the buffer |
| 170785 | +** using sqlite3_free(). |
| 170786 | +*/ |
| 170787 | +SQLITE_API int SQLITE_STDCALL sqlite3session_patchset( |
| 170788 | + sqlite3_session *pSession, /* Session object */ |
| 170789 | + int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ |
| 170790 | + void **ppPatchset /* OUT: Buffer containing changeset */ |
| 170791 | +){ |
| 170792 | + return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset); |
| 170793 | +} |
| 170794 | + |
| 170795 | +/* |
| 170796 | +** Enable or disable the session object passed as the first argument. |
| 170797 | +*/ |
| 170798 | +SQLITE_API int SQLITE_STDCALL sqlite3session_enable(sqlite3_session *pSession, int bEnable){ |
| 170799 | + int ret; |
| 170800 | + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); |
| 170801 | + if( bEnable>=0 ){ |
| 170802 | + pSession->bEnable = bEnable; |
| 170803 | + } |
| 170804 | + ret = pSession->bEnable; |
| 170805 | + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); |
| 170806 | + return ret; |
| 170807 | +} |
| 170808 | + |
| 170809 | +/* |
| 170810 | +** Enable or disable the session object passed as the first argument. |
| 170811 | +*/ |
| 170812 | +SQLITE_API int SQLITE_STDCALL sqlite3session_indirect(sqlite3_session *pSession, int bIndirect){ |
| 170813 | + int ret; |
| 170814 | + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); |
| 170815 | + if( bIndirect>=0 ){ |
| 170816 | + pSession->bIndirect = bIndirect; |
| 170817 | + } |
| 170818 | + ret = pSession->bIndirect; |
| 170819 | + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); |
| 170820 | + return ret; |
| 170821 | +} |
| 170822 | + |
| 170823 | +/* |
| 170824 | +** Return true if there have been no changes to monitored tables recorded |
| 170825 | +** by the session object passed as the only argument. |
| 170826 | +*/ |
| 170827 | +SQLITE_API int SQLITE_STDCALL sqlite3session_isempty(sqlite3_session *pSession){ |
| 170828 | + int ret = 0; |
| 170829 | + SessionTable *pTab; |
| 170830 | + |
| 170831 | + sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); |
| 170832 | + for(pTab=pSession->pTable; pTab && ret==0; pTab=pTab->pNext){ |
| 170833 | + ret = (pTab->nEntry>0); |
| 170834 | + } |
| 170835 | + sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); |
| 170836 | + |
| 170837 | + return (ret==0); |
| 170838 | +} |
| 170839 | + |
| 170840 | +/* |
| 170841 | +** Do the work for either sqlite3changeset_start() or start_strm(). |
| 170842 | +*/ |
| 170843 | +static int sessionChangesetStart( |
| 170844 | + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ |
| 170845 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 170846 | + void *pIn, |
| 170847 | + int nChangeset, /* Size of buffer pChangeset in bytes */ |
| 170848 | + void *pChangeset /* Pointer to buffer containing changeset */ |
| 170849 | +){ |
| 170850 | + sqlite3_changeset_iter *pRet; /* Iterator to return */ |
| 170851 | + int nByte; /* Number of bytes to allocate for iterator */ |
| 170852 | + |
| 170853 | + assert( xInput==0 || (pChangeset==0 && nChangeset==0) ); |
| 170854 | + |
| 170855 | + /* Zero the output variable in case an error occurs. */ |
| 170856 | + *pp = 0; |
| 170857 | + |
| 170858 | + /* Allocate and initialize the iterator structure. */ |
| 170859 | + nByte = sizeof(sqlite3_changeset_iter); |
| 170860 | + pRet = (sqlite3_changeset_iter *)sqlite3_malloc(nByte); |
| 170861 | + if( !pRet ) return SQLITE_NOMEM; |
| 170862 | + memset(pRet, 0, sizeof(sqlite3_changeset_iter)); |
| 170863 | + pRet->in.aData = (u8 *)pChangeset; |
| 170864 | + pRet->in.nData = nChangeset; |
| 170865 | + pRet->in.xInput = xInput; |
| 170866 | + pRet->in.pIn = pIn; |
| 170867 | + pRet->in.bEof = (xInput ? 0 : 1); |
| 170868 | + |
| 170869 | + /* Populate the output variable and return success. */ |
| 170870 | + *pp = pRet; |
| 170871 | + return SQLITE_OK; |
| 170872 | +} |
| 170873 | + |
| 170874 | +/* |
| 170875 | +** Create an iterator used to iterate through the contents of a changeset. |
| 170876 | +*/ |
| 170877 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_start( |
| 170878 | + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ |
| 170879 | + int nChangeset, /* Size of buffer pChangeset in bytes */ |
| 170880 | + void *pChangeset /* Pointer to buffer containing changeset */ |
| 170881 | +){ |
| 170882 | + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); |
| 170883 | +} |
| 170884 | + |
| 170885 | +/* |
| 170886 | +** Streaming version of sqlite3changeset_start(). |
| 170887 | +*/ |
| 170888 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_start_strm( |
| 170889 | + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ |
| 170890 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 170891 | + void *pIn |
| 170892 | +){ |
| 170893 | + return sessionChangesetStart(pp, xInput, pIn, 0, 0); |
| 170894 | +} |
| 170895 | + |
| 170896 | +/* |
| 170897 | +** If the SessionInput object passed as the only argument is a streaming |
| 170898 | +** object and the buffer is full, discard some data to free up space. |
| 170899 | +*/ |
| 170900 | +static void sessionDiscardData(SessionInput *pIn){ |
| 170901 | + if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ |
| 170902 | + int nMove = pIn->buf.nBuf - pIn->iNext; |
| 170903 | + assert( nMove>=0 ); |
| 170904 | + if( nMove>0 ){ |
| 170905 | + memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); |
| 170906 | + } |
| 170907 | + pIn->buf.nBuf -= pIn->iNext; |
| 170908 | + pIn->iNext = 0; |
| 170909 | + pIn->nData = pIn->buf.nBuf; |
| 170910 | + } |
| 170911 | +} |
| 170912 | + |
| 170913 | +/* |
| 170914 | +** Ensure that there are at least nByte bytes available in the buffer. Or, |
| 170915 | +** if there are not nByte bytes remaining in the input, that all available |
| 170916 | +** data is in the buffer. |
| 170917 | +** |
| 170918 | +** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. |
| 170919 | +*/ |
| 170920 | +static int sessionInputBuffer(SessionInput *pIn, int nByte){ |
| 170921 | + int rc = SQLITE_OK; |
| 170922 | + if( pIn->xInput ){ |
| 170923 | + while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ |
| 170924 | + int nNew = SESSIONS_STRM_CHUNK_SIZE; |
| 170925 | + |
| 170926 | + if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); |
| 170927 | + if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ |
| 170928 | + rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew); |
| 170929 | + if( nNew==0 ){ |
| 170930 | + pIn->bEof = 1; |
| 170931 | + }else{ |
| 170932 | + pIn->buf.nBuf += nNew; |
| 170933 | + } |
| 170934 | + } |
| 170935 | + |
| 170936 | + pIn->aData = pIn->buf.aBuf; |
| 170937 | + pIn->nData = pIn->buf.nBuf; |
| 170938 | + } |
| 170939 | + } |
| 170940 | + return rc; |
| 170941 | +} |
| 170942 | + |
| 170943 | +/* |
| 170944 | +** When this function is called, *ppRec points to the start of a record |
| 170945 | +** that contains nCol values. This function advances the pointer *ppRec |
| 170946 | +** until it points to the byte immediately following that record. |
| 170947 | +*/ |
| 170948 | +static void sessionSkipRecord( |
| 170949 | + u8 **ppRec, /* IN/OUT: Record pointer */ |
| 170950 | + int nCol /* Number of values in record */ |
| 170951 | +){ |
| 170952 | + u8 *aRec = *ppRec; |
| 170953 | + int i; |
| 170954 | + for(i=0; i<nCol; i++){ |
| 170955 | + int eType = *aRec++; |
| 170956 | + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ |
| 170957 | + int nByte; |
| 170958 | + aRec += sessionVarintGet((u8*)aRec, &nByte); |
| 170959 | + aRec += nByte; |
| 170960 | + }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 170961 | + aRec += 8; |
| 170962 | + } |
| 170963 | + } |
| 170964 | + |
| 170965 | + *ppRec = aRec; |
| 170966 | +} |
| 170967 | + |
| 170968 | +/* |
| 170969 | +** This function sets the value of the sqlite3_value object passed as the |
| 170970 | +** first argument to a copy of the string or blob held in the aData[] |
| 170971 | +** buffer. SQLITE_OK is returned if successful, or SQLITE_NOMEM if an OOM |
| 170972 | +** error occurs. |
| 170973 | +*/ |
| 170974 | +static int sessionValueSetStr( |
| 170975 | + sqlite3_value *pVal, /* Set the value of this object */ |
| 170976 | + u8 *aData, /* Buffer containing string or blob data */ |
| 170977 | + int nData, /* Size of buffer aData[] in bytes */ |
| 170978 | + u8 enc /* String encoding (0 for blobs) */ |
| 170979 | +){ |
| 170980 | + /* In theory this code could just pass SQLITE_TRANSIENT as the final |
| 170981 | + ** argument to sqlite3ValueSetStr() and have the copy created |
| 170982 | + ** automatically. But doing so makes it difficult to detect any OOM |
| 170983 | + ** error. Hence the code to create the copy externally. */ |
| 170984 | + u8 *aCopy = sqlite3_malloc(nData+1); |
| 170985 | + if( aCopy==0 ) return SQLITE_NOMEM; |
| 170986 | + memcpy(aCopy, aData, nData); |
| 170987 | + sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free); |
| 170988 | + return SQLITE_OK; |
| 170989 | +} |
| 170990 | + |
| 170991 | +/* |
| 170992 | +** Deserialize a single record from a buffer in memory. See "RECORD FORMAT" |
| 170993 | +** for details. |
| 170994 | +** |
| 170995 | +** When this function is called, *paChange points to the start of the record |
| 170996 | +** to deserialize. Assuming no error occurs, *paChange is set to point to |
| 170997 | +** one byte after the end of the same record before this function returns. |
| 170998 | +** If the argument abPK is NULL, then the record contains nCol values. Or, |
| 170999 | +** if abPK is other than NULL, then the record contains only the PK fields |
| 171000 | +** (in other words, it is a patchset DELETE record). |
| 171001 | +** |
| 171002 | +** If successful, each element of the apOut[] array (allocated by the caller) |
| 171003 | +** is set to point to an sqlite3_value object containing the value read |
| 171004 | +** from the corresponding position in the record. If that value is not |
| 171005 | +** included in the record (i.e. because the record is part of an UPDATE change |
| 171006 | +** and the field was not modified), the corresponding element of apOut[] is |
| 171007 | +** set to NULL. |
| 171008 | +** |
| 171009 | +** It is the responsibility of the caller to free all sqlite_value structures |
| 171010 | +** using sqlite3_free(). |
| 171011 | +** |
| 171012 | +** If an error occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. |
| 171013 | +** The apOut[] array may have been partially populated in this case. |
| 171014 | +*/ |
| 171015 | +static int sessionReadRecord( |
| 171016 | + SessionInput *pIn, /* Input data */ |
| 171017 | + int nCol, /* Number of values in record */ |
| 171018 | + u8 *abPK, /* Array of primary key flags, or NULL */ |
| 171019 | + sqlite3_value **apOut /* Write values to this array */ |
| 171020 | +){ |
| 171021 | + int i; /* Used to iterate through columns */ |
| 171022 | + int rc = SQLITE_OK; |
| 171023 | + |
| 171024 | + for(i=0; i<nCol && rc==SQLITE_OK; i++){ |
| 171025 | + int eType = 0; /* Type of value (SQLITE_NULL, TEXT etc.) */ |
| 171026 | + if( abPK && abPK[i]==0 ) continue; |
| 171027 | + rc = sessionInputBuffer(pIn, 9); |
| 171028 | + if( rc==SQLITE_OK ){ |
| 171029 | + eType = pIn->aData[pIn->iNext++]; |
| 171030 | + } |
| 171031 | + |
| 171032 | + assert( apOut[i]==0 ); |
| 171033 | + if( eType ){ |
| 171034 | + apOut[i] = sqlite3ValueNew(0); |
| 171035 | + if( !apOut[i] ) rc = SQLITE_NOMEM; |
| 171036 | + } |
| 171037 | + |
| 171038 | + if( rc==SQLITE_OK ){ |
| 171039 | + u8 *aVal = &pIn->aData[pIn->iNext]; |
| 171040 | + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ |
| 171041 | + int nByte; |
| 171042 | + pIn->iNext += sessionVarintGet(aVal, &nByte); |
| 171043 | + rc = sessionInputBuffer(pIn, nByte); |
| 171044 | + if( rc==SQLITE_OK ){ |
| 171045 | + u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); |
| 171046 | + rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); |
| 171047 | + } |
| 171048 | + pIn->iNext += nByte; |
| 171049 | + } |
| 171050 | + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 171051 | + sqlite3_int64 v = sessionGetI64(aVal); |
| 171052 | + if( eType==SQLITE_INTEGER ){ |
| 171053 | + sqlite3VdbeMemSetInt64(apOut[i], v); |
| 171054 | + }else{ |
| 171055 | + double d; |
| 171056 | + memcpy(&d, &v, 8); |
| 171057 | + sqlite3VdbeMemSetDouble(apOut[i], d); |
| 171058 | + } |
| 171059 | + pIn->iNext += 8; |
| 171060 | + } |
| 171061 | + } |
| 171062 | + } |
| 171063 | + |
| 171064 | + return rc; |
| 171065 | +} |
| 171066 | + |
| 171067 | +/* |
| 171068 | +** The input pointer currently points to the second byte of a table-header. |
| 171069 | +** Specifically, to the following: |
| 171070 | +** |
| 171071 | +** + number of columns in table (varint) |
| 171072 | +** + array of PK flags (1 byte per column), |
| 171073 | +** + table name (nul terminated). |
| 171074 | +** |
| 171075 | +** This function ensures that all of the above is present in the input |
| 171076 | +** buffer (i.e. that it can be accessed without any calls to xInput()). |
| 171077 | +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. |
| 171078 | +** The input pointer is not moved. |
| 171079 | +*/ |
| 171080 | +static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ |
| 171081 | + int rc = SQLITE_OK; |
| 171082 | + int nCol = 0; |
| 171083 | + int nRead = 0; |
| 171084 | + |
| 171085 | + rc = sessionInputBuffer(pIn, 9); |
| 171086 | + if( rc==SQLITE_OK ){ |
| 171087 | + nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); |
| 171088 | + rc = sessionInputBuffer(pIn, nRead+nCol+100); |
| 171089 | + nRead += nCol; |
| 171090 | + } |
| 171091 | + |
| 171092 | + while( rc==SQLITE_OK ){ |
| 171093 | + while( (pIn->iNext + nRead)<pIn->nData && pIn->aData[pIn->iNext + nRead] ){ |
| 171094 | + nRead++; |
| 171095 | + } |
| 171096 | + if( (pIn->iNext + nRead)<pIn->nData ) break; |
| 171097 | + rc = sessionInputBuffer(pIn, nRead + 100); |
| 171098 | + } |
| 171099 | + *pnByte = nRead+1; |
| 171100 | + return rc; |
| 171101 | +} |
| 171102 | + |
| 171103 | +/* |
| 171104 | +** The input pointer currently points to the first byte of the first field |
| 171105 | +** of a record consisting of nCol columns. This function ensures the entire |
| 171106 | +** record is buffered. It does not move the input pointer. |
| 171107 | +** |
| 171108 | +** If successful, SQLITE_OK is returned and *pnByte is set to the size of |
| 171109 | +** the record in bytes. Otherwise, an SQLite error code is returned. The |
| 171110 | +** final value of *pnByte is undefined in this case. |
| 171111 | +*/ |
| 171112 | +static int sessionChangesetBufferRecord( |
| 171113 | + SessionInput *pIn, /* Input data */ |
| 171114 | + int nCol, /* Number of columns in record */ |
| 171115 | + int *pnByte /* OUT: Size of record in bytes */ |
| 171116 | +){ |
| 171117 | + int rc = SQLITE_OK; |
| 171118 | + int nByte = 0; |
| 171119 | + int i; |
| 171120 | + for(i=0; rc==SQLITE_OK && i<nCol; i++){ |
| 171121 | + int eType; |
| 171122 | + rc = sessionInputBuffer(pIn, nByte + 10); |
| 171123 | + if( rc==SQLITE_OK ){ |
| 171124 | + eType = pIn->aData[pIn->iNext + nByte++]; |
| 171125 | + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ |
| 171126 | + int n; |
| 171127 | + nByte += sessionVarintGet(&pIn->aData[pIn->iNext+nByte], &n); |
| 171128 | + nByte += n; |
| 171129 | + rc = sessionInputBuffer(pIn, nByte); |
| 171130 | + }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ |
| 171131 | + nByte += 8; |
| 171132 | + } |
| 171133 | + } |
| 171134 | + } |
| 171135 | + *pnByte = nByte; |
| 171136 | + return rc; |
| 171137 | +} |
| 171138 | + |
| 171139 | +/* |
| 171140 | +** The input pointer currently points to the second byte of a table-header. |
| 171141 | +** Specifically, to the following: |
| 171142 | +** |
| 171143 | +** + number of columns in table (varint) |
| 171144 | +** + array of PK flags (1 byte per column), |
| 171145 | +** + table name (nul terminated). |
| 171146 | +** |
| 171147 | +** This function decodes the table-header and populates the p->nCol, |
| 171148 | +** p->zTab and p->abPK[] variables accordingly. The p->apValue[] array is |
| 171149 | +** also allocated or resized according to the new value of p->nCol. The |
| 171150 | +** input pointer is left pointing to the byte following the table header. |
| 171151 | +** |
| 171152 | +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code |
| 171153 | +** is returned and the final values of the various fields enumerated above |
| 171154 | +** are undefined. |
| 171155 | +*/ |
| 171156 | +static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ |
| 171157 | + int rc; |
| 171158 | + int nCopy; |
| 171159 | + assert( p->rc==SQLITE_OK ); |
| 171160 | + |
| 171161 | + rc = sessionChangesetBufferTblhdr(&p->in, &nCopy); |
| 171162 | + if( rc==SQLITE_OK ){ |
| 171163 | + int nByte; |
| 171164 | + int nVarint; |
| 171165 | + nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); |
| 171166 | + nCopy -= nVarint; |
| 171167 | + p->in.iNext += nVarint; |
| 171168 | + nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; |
| 171169 | + p->tblhdr.nBuf = 0; |
| 171170 | + sessionBufferGrow(&p->tblhdr, nByte, &rc); |
| 171171 | + } |
| 171172 | + |
| 171173 | + if( rc==SQLITE_OK ){ |
| 171174 | + int iPK = sizeof(sqlite3_value*)*p->nCol*2; |
| 171175 | + memset(p->tblhdr.aBuf, 0, iPK); |
| 171176 | + memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy); |
| 171177 | + p->in.iNext += nCopy; |
| 171178 | + } |
| 171179 | + |
| 171180 | + p->apValue = (sqlite3_value**)p->tblhdr.aBuf; |
| 171181 | + p->abPK = (u8*)&p->apValue[p->nCol*2]; |
| 171182 | + p->zTab = (char*)&p->abPK[p->nCol]; |
| 171183 | + return (p->rc = rc); |
| 171184 | +} |
| 171185 | + |
| 171186 | +/* |
| 171187 | +** Advance the changeset iterator to the next change. |
| 171188 | +** |
| 171189 | +** If both paRec and pnRec are NULL, then this function works like the public |
| 171190 | +** API sqlite3changeset_next(). If SQLITE_ROW is returned, then the |
| 171191 | +** sqlite3changeset_new() and old() APIs may be used to query for values. |
| 171192 | +** |
| 171193 | +** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change |
| 171194 | +** record is written to *paRec before returning and the number of bytes in |
| 171195 | +** the record to *pnRec. |
| 171196 | +** |
| 171197 | +** Either way, this function returns SQLITE_ROW if the iterator is |
| 171198 | +** successfully advanced to the next change in the changeset, an SQLite |
| 171199 | +** error code if an error occurs, or SQLITE_DONE if there are no further |
| 171200 | +** changes in the changeset. |
| 171201 | +*/ |
| 171202 | +static int sessionChangesetNext( |
| 171203 | + sqlite3_changeset_iter *p, /* Changeset iterator */ |
| 171204 | + u8 **paRec, /* If non-NULL, store record pointer here */ |
| 171205 | + int *pnRec /* If non-NULL, store size of record here */ |
| 171206 | +){ |
| 171207 | + int i; |
| 171208 | + u8 op; |
| 171209 | + |
| 171210 | + assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); |
| 171211 | + |
| 171212 | + /* If the iterator is in the error-state, return immediately. */ |
| 171213 | + if( p->rc!=SQLITE_OK ) return p->rc; |
| 171214 | + |
| 171215 | + /* Free the current contents of p->apValue[], if any. */ |
| 171216 | + if( p->apValue ){ |
| 171217 | + for(i=0; i<p->nCol*2; i++){ |
| 171218 | + sqlite3ValueFree(p->apValue[i]); |
| 171219 | + } |
| 171220 | + memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); |
| 171221 | + } |
| 171222 | + |
| 171223 | + /* Make sure the buffer contains at least 10 bytes of input data, or all |
| 171224 | + ** remaining data if there are less than 10 bytes available. This is |
| 171225 | + ** sufficient either for the 'T' or 'P' byte and the varint that follows |
| 171226 | + ** it, or for the two single byte values otherwise. */ |
| 171227 | + p->rc = sessionInputBuffer(&p->in, 2); |
| 171228 | + if( p->rc!=SQLITE_OK ) return p->rc; |
| 171229 | + |
| 171230 | + /* If the iterator is already at the end of the changeset, return DONE. */ |
| 171231 | + if( p->in.iNext>=p->in.nData ){ |
| 171232 | + return SQLITE_DONE; |
| 171233 | + } |
| 171234 | + |
| 171235 | + sessionDiscardData(&p->in); |
| 171236 | + p->in.iCurrent = p->in.iNext; |
| 171237 | + |
| 171238 | + op = p->in.aData[p->in.iNext++]; |
| 171239 | + if( op=='T' || op=='P' ){ |
| 171240 | + p->bPatchset = (op=='P'); |
| 171241 | + if( sessionChangesetReadTblhdr(p) ) return p->rc; |
| 171242 | + if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; |
| 171243 | + p->in.iCurrent = p->in.iNext; |
| 171244 | + op = p->in.aData[p->in.iNext++]; |
| 171245 | + } |
| 171246 | + |
| 171247 | + p->op = op; |
| 171248 | + p->bIndirect = p->in.aData[p->in.iNext++]; |
| 171249 | + if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ |
| 171250 | + return (p->rc = SQLITE_CORRUPT_BKPT); |
| 171251 | + } |
| 171252 | + |
| 171253 | + if( paRec ){ |
| 171254 | + int nVal; /* Number of values to buffer */ |
| 171255 | + if( p->bPatchset==0 && op==SQLITE_UPDATE ){ |
| 171256 | + nVal = p->nCol * 2; |
| 171257 | + }else if( p->bPatchset && op==SQLITE_DELETE ){ |
| 171258 | + nVal = 0; |
| 171259 | + for(i=0; i<p->nCol; i++) if( p->abPK[i] ) nVal++; |
| 171260 | + }else{ |
| 171261 | + nVal = p->nCol; |
| 171262 | + } |
| 171263 | + p->rc = sessionChangesetBufferRecord(&p->in, nVal, pnRec); |
| 171264 | + if( p->rc!=SQLITE_OK ) return p->rc; |
| 171265 | + *paRec = &p->in.aData[p->in.iNext]; |
| 171266 | + p->in.iNext += *pnRec; |
| 171267 | + }else{ |
| 171268 | + |
| 171269 | + /* If this is an UPDATE or DELETE, read the old.* record. */ |
| 171270 | + if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ |
| 171271 | + u8 *abPK = p->bPatchset ? p->abPK : 0; |
| 171272 | + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); |
| 171273 | + if( p->rc!=SQLITE_OK ) return p->rc; |
| 171274 | + } |
| 171275 | + |
| 171276 | + /* If this is an INSERT or UPDATE, read the new.* record. */ |
| 171277 | + if( p->op!=SQLITE_DELETE ){ |
| 171278 | + p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); |
| 171279 | + if( p->rc!=SQLITE_OK ) return p->rc; |
| 171280 | + } |
| 171281 | + |
| 171282 | + if( p->bPatchset && p->op==SQLITE_UPDATE ){ |
| 171283 | + /* If this is an UPDATE that is part of a patchset, then all PK and |
| 171284 | + ** modified fields are present in the new.* record. The old.* record |
| 171285 | + ** is currently completely empty. This block shifts the PK fields from |
| 171286 | + ** new.* to old.*, to accommodate the code that reads these arrays. */ |
| 171287 | + int i; |
| 171288 | + for(i=0; i<p->nCol; i++){ |
| 171289 | + assert( p->apValue[i]==0 ); |
| 171290 | + assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); |
| 171291 | + if( p->abPK[i] ){ |
| 171292 | + p->apValue[i] = p->apValue[i+p->nCol]; |
| 171293 | + p->apValue[i+p->nCol] = 0; |
| 171294 | + } |
| 171295 | + } |
| 171296 | + } |
| 171297 | + } |
| 171298 | + |
| 171299 | + return SQLITE_ROW; |
| 171300 | +} |
| 171301 | + |
| 171302 | +/* |
| 171303 | +** Advance an iterator created by sqlite3changeset_start() to the next |
| 171304 | +** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE |
| 171305 | +** or SQLITE_CORRUPT. |
| 171306 | +** |
| 171307 | +** This function may not be called on iterators passed to a conflict handler |
| 171308 | +** callback by changeset_apply(). |
| 171309 | +*/ |
| 171310 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_next(sqlite3_changeset_iter *p){ |
| 171311 | + return sessionChangesetNext(p, 0, 0); |
| 171312 | +} |
| 171313 | + |
| 171314 | +/* |
| 171315 | +** The following function extracts information on the current change |
| 171316 | +** from a changeset iterator. It may only be called after changeset_next() |
| 171317 | +** has returned SQLITE_ROW. |
| 171318 | +*/ |
| 171319 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_op( |
| 171320 | + sqlite3_changeset_iter *pIter, /* Iterator handle */ |
| 171321 | + const char **pzTab, /* OUT: Pointer to table name */ |
| 171322 | + int *pnCol, /* OUT: Number of columns in table */ |
| 171323 | + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ |
| 171324 | + int *pbIndirect /* OUT: True if change is indirect */ |
| 171325 | +){ |
| 171326 | + *pOp = pIter->op; |
| 171327 | + *pnCol = pIter->nCol; |
| 171328 | + *pzTab = pIter->zTab; |
| 171329 | + if( pbIndirect ) *pbIndirect = pIter->bIndirect; |
| 171330 | + return SQLITE_OK; |
| 171331 | +} |
| 171332 | + |
| 171333 | +/* |
| 171334 | +** Return information regarding the PRIMARY KEY and number of columns in |
| 171335 | +** the database table affected by the change that pIter currently points |
| 171336 | +** to. This function may only be called after changeset_next() returns |
| 171337 | +** SQLITE_ROW. |
| 171338 | +*/ |
| 171339 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_pk( |
| 171340 | + sqlite3_changeset_iter *pIter, /* Iterator object */ |
| 171341 | + unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ |
| 171342 | + int *pnCol /* OUT: Number of entries in output array */ |
| 171343 | +){ |
| 171344 | + *pabPK = pIter->abPK; |
| 171345 | + if( pnCol ) *pnCol = pIter->nCol; |
| 171346 | + return SQLITE_OK; |
| 171347 | +} |
| 171348 | + |
| 171349 | +/* |
| 171350 | +** This function may only be called while the iterator is pointing to an |
| 171351 | +** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()). |
| 171352 | +** Otherwise, SQLITE_MISUSE is returned. |
| 171353 | +** |
| 171354 | +** It sets *ppValue to point to an sqlite3_value structure containing the |
| 171355 | +** iVal'th value in the old.* record. Or, if that particular value is not |
| 171356 | +** included in the record (because the change is an UPDATE and the field |
| 171357 | +** was not modified and is not a PK column), set *ppValue to NULL. |
| 171358 | +** |
| 171359 | +** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is |
| 171360 | +** not modified. Otherwise, SQLITE_OK. |
| 171361 | +*/ |
| 171362 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_old( |
| 171363 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 171364 | + int iVal, /* Index of old.* value to retrieve */ |
| 171365 | + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ |
| 171366 | +){ |
| 171367 | + if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_DELETE ){ |
| 171368 | + return SQLITE_MISUSE; |
| 171369 | + } |
| 171370 | + if( iVal<0 || iVal>=pIter->nCol ){ |
| 171371 | + return SQLITE_RANGE; |
| 171372 | + } |
| 171373 | + *ppValue = pIter->apValue[iVal]; |
| 171374 | + return SQLITE_OK; |
| 171375 | +} |
| 171376 | + |
| 171377 | +/* |
| 171378 | +** This function may only be called while the iterator is pointing to an |
| 171379 | +** SQLITE_UPDATE or SQLITE_INSERT change (see sqlite3changeset_op()). |
| 171380 | +** Otherwise, SQLITE_MISUSE is returned. |
| 171381 | +** |
| 171382 | +** It sets *ppValue to point to an sqlite3_value structure containing the |
| 171383 | +** iVal'th value in the new.* record. Or, if that particular value is not |
| 171384 | +** included in the record (because the change is an UPDATE and the field |
| 171385 | +** was not modified), set *ppValue to NULL. |
| 171386 | +** |
| 171387 | +** If value iVal is out-of-range, SQLITE_RANGE is returned and *ppValue is |
| 171388 | +** not modified. Otherwise, SQLITE_OK. |
| 171389 | +*/ |
| 171390 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_new( |
| 171391 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 171392 | + int iVal, /* Index of new.* value to retrieve */ |
| 171393 | + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ |
| 171394 | +){ |
| 171395 | + if( pIter->op!=SQLITE_UPDATE && pIter->op!=SQLITE_INSERT ){ |
| 171396 | + return SQLITE_MISUSE; |
| 171397 | + } |
| 171398 | + if( iVal<0 || iVal>=pIter->nCol ){ |
| 171399 | + return SQLITE_RANGE; |
| 171400 | + } |
| 171401 | + *ppValue = pIter->apValue[pIter->nCol+iVal]; |
| 171402 | + return SQLITE_OK; |
| 171403 | +} |
| 171404 | + |
| 171405 | +/* |
| 171406 | +** The following two macros are used internally. They are similar to the |
| 171407 | +** sqlite3changeset_new() and sqlite3changeset_old() functions, except that |
| 171408 | +** they omit all error checking and return a pointer to the requested value. |
| 171409 | +*/ |
| 171410 | +#define sessionChangesetNew(pIter, iVal) (pIter)->apValue[(pIter)->nCol+(iVal)] |
| 171411 | +#define sessionChangesetOld(pIter, iVal) (pIter)->apValue[(iVal)] |
| 171412 | + |
| 171413 | +/* |
| 171414 | +** This function may only be called with a changeset iterator that has been |
| 171415 | +** passed to an SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT |
| 171416 | +** conflict-handler function. Otherwise, SQLITE_MISUSE is returned. |
| 171417 | +** |
| 171418 | +** If successful, *ppValue is set to point to an sqlite3_value structure |
| 171419 | +** containing the iVal'th value of the conflicting record. |
| 171420 | +** |
| 171421 | +** If value iVal is out-of-range or some other error occurs, an SQLite error |
| 171422 | +** code is returned. Otherwise, SQLITE_OK. |
| 171423 | +*/ |
| 171424 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_conflict( |
| 171425 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 171426 | + int iVal, /* Index of conflict record value to fetch */ |
| 171427 | + sqlite3_value **ppValue /* OUT: Value from conflicting row */ |
| 171428 | +){ |
| 171429 | + if( !pIter->pConflict ){ |
| 171430 | + return SQLITE_MISUSE; |
| 171431 | + } |
| 171432 | + if( iVal<0 || iVal>=sqlite3_column_count(pIter->pConflict) ){ |
| 171433 | + return SQLITE_RANGE; |
| 171434 | + } |
| 171435 | + *ppValue = sqlite3_column_value(pIter->pConflict, iVal); |
| 171436 | + return SQLITE_OK; |
| 171437 | +} |
| 171438 | + |
| 171439 | +/* |
| 171440 | +** This function may only be called with an iterator passed to an |
| 171441 | +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case |
| 171442 | +** it sets the output variable to the total number of known foreign key |
| 171443 | +** violations in the destination database and returns SQLITE_OK. |
| 171444 | +** |
| 171445 | +** In all other cases this function returns SQLITE_MISUSE. |
| 171446 | +*/ |
| 171447 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_fk_conflicts( |
| 171448 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 171449 | + int *pnOut /* OUT: Number of FK violations */ |
| 171450 | +){ |
| 171451 | + if( pIter->pConflict || pIter->apValue ){ |
| 171452 | + return SQLITE_MISUSE; |
| 171453 | + } |
| 171454 | + *pnOut = pIter->nCol; |
| 171455 | + return SQLITE_OK; |
| 171456 | +} |
| 171457 | + |
| 171458 | + |
| 171459 | +/* |
| 171460 | +** Finalize an iterator allocated with sqlite3changeset_start(). |
| 171461 | +** |
| 171462 | +** This function may not be called on iterators passed to a conflict handler |
| 171463 | +** callback by changeset_apply(). |
| 171464 | +*/ |
| 171465 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_finalize(sqlite3_changeset_iter *p){ |
| 171466 | + int rc = SQLITE_OK; |
| 171467 | + if( p ){ |
| 171468 | + int i; /* Used to iterate through p->apValue[] */ |
| 171469 | + rc = p->rc; |
| 171470 | + if( p->apValue ){ |
| 171471 | + for(i=0; i<p->nCol*2; i++) sqlite3ValueFree(p->apValue[i]); |
| 171472 | + } |
| 171473 | + sqlite3_free(p->tblhdr.aBuf); |
| 171474 | + sqlite3_free(p->in.buf.aBuf); |
| 171475 | + sqlite3_free(p); |
| 171476 | + } |
| 171477 | + return rc; |
| 171478 | +} |
| 171479 | + |
| 171480 | +static int sessionChangesetInvert( |
| 171481 | + SessionInput *pInput, /* Input changeset */ |
| 171482 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 171483 | + void *pOut, |
| 171484 | + int *pnInverted, /* OUT: Number of bytes in output changeset */ |
| 171485 | + void **ppInverted /* OUT: Inverse of pChangeset */ |
| 171486 | +){ |
| 171487 | + int rc = SQLITE_OK; /* Return value */ |
| 171488 | + SessionBuffer sOut; /* Output buffer */ |
| 171489 | + int nCol = 0; /* Number of cols in current table */ |
| 171490 | + u8 *abPK = 0; /* PK array for current table */ |
| 171491 | + sqlite3_value **apVal = 0; /* Space for values for UPDATE inversion */ |
| 171492 | + SessionBuffer sPK = {0, 0, 0}; /* PK array for current table */ |
| 171493 | + |
| 171494 | + /* Initialize the output buffer */ |
| 171495 | + memset(&sOut, 0, sizeof(SessionBuffer)); |
| 171496 | + |
| 171497 | + /* Zero the output variables in case an error occurs. */ |
| 171498 | + if( ppInverted ){ |
| 171499 | + *ppInverted = 0; |
| 171500 | + *pnInverted = 0; |
| 171501 | + } |
| 171502 | + |
| 171503 | + while( 1 ){ |
| 171504 | + u8 eType; |
| 171505 | + |
| 171506 | + /* Test for EOF. */ |
| 171507 | + if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert; |
| 171508 | + if( pInput->iNext>=pInput->nData ) break; |
| 171509 | + eType = pInput->aData[pInput->iNext]; |
| 171510 | + |
| 171511 | + switch( eType ){ |
| 171512 | + case 'T': { |
| 171513 | + /* A 'table' record consists of: |
| 171514 | + ** |
| 171515 | + ** * A constant 'T' character, |
| 171516 | + ** * Number of columns in said table (a varint), |
| 171517 | + ** * An array of nCol bytes (sPK), |
| 171518 | + ** * A nul-terminated table name. |
| 171519 | + */ |
| 171520 | + int nByte; |
| 171521 | + int nVar; |
| 171522 | + pInput->iNext++; |
| 171523 | + if( (rc = sessionChangesetBufferTblhdr(pInput, &nByte)) ){ |
| 171524 | + goto finished_invert; |
| 171525 | + } |
| 171526 | + nVar = sessionVarintGet(&pInput->aData[pInput->iNext], &nCol); |
| 171527 | + sPK.nBuf = 0; |
| 171528 | + sessionAppendBlob(&sPK, &pInput->aData[pInput->iNext+nVar], nCol, &rc); |
| 171529 | + sessionAppendByte(&sOut, eType, &rc); |
| 171530 | + sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc); |
| 171531 | + if( rc ) goto finished_invert; |
| 171532 | + |
| 171533 | + pInput->iNext += nByte; |
| 171534 | + sqlite3_free(apVal); |
| 171535 | + apVal = 0; |
| 171536 | + abPK = sPK.aBuf; |
| 171537 | + break; |
| 171538 | + } |
| 171539 | + |
| 171540 | + case SQLITE_INSERT: |
| 171541 | + case SQLITE_DELETE: { |
| 171542 | + int nByte; |
| 171543 | + int bIndirect = pInput->aData[pInput->iNext+1]; |
| 171544 | + int eType2 = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE); |
| 171545 | + pInput->iNext += 2; |
| 171546 | + assert( rc==SQLITE_OK ); |
| 171547 | + rc = sessionChangesetBufferRecord(pInput, nCol, &nByte); |
| 171548 | + sessionAppendByte(&sOut, eType2, &rc); |
| 171549 | + sessionAppendByte(&sOut, bIndirect, &rc); |
| 171550 | + sessionAppendBlob(&sOut, &pInput->aData[pInput->iNext], nByte, &rc); |
| 171551 | + pInput->iNext += nByte; |
| 171552 | + if( rc ) goto finished_invert; |
| 171553 | + break; |
| 171554 | + } |
| 171555 | + |
| 171556 | + case SQLITE_UPDATE: { |
| 171557 | + int iCol; |
| 171558 | + |
| 171559 | + if( 0==apVal ){ |
| 171560 | + apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2); |
| 171561 | + if( 0==apVal ){ |
| 171562 | + rc = SQLITE_NOMEM; |
| 171563 | + goto finished_invert; |
| 171564 | + } |
| 171565 | + memset(apVal, 0, sizeof(apVal[0])*nCol*2); |
| 171566 | + } |
| 171567 | + |
| 171568 | + /* Write the header for the new UPDATE change. Same as the original. */ |
| 171569 | + sessionAppendByte(&sOut, eType, &rc); |
| 171570 | + sessionAppendByte(&sOut, pInput->aData[pInput->iNext+1], &rc); |
| 171571 | + |
| 171572 | + /* Read the old.* and new.* records for the update change. */ |
| 171573 | + pInput->iNext += 2; |
| 171574 | + rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]); |
| 171575 | + if( rc==SQLITE_OK ){ |
| 171576 | + rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]); |
| 171577 | + } |
| 171578 | + |
| 171579 | + /* Write the new old.* record. Consists of the PK columns from the |
| 171580 | + ** original old.* record, and the other values from the original |
| 171581 | + ** new.* record. */ |
| 171582 | + for(iCol=0; iCol<nCol; iCol++){ |
| 171583 | + sqlite3_value *pVal = apVal[iCol + (abPK[iCol] ? 0 : nCol)]; |
| 171584 | + sessionAppendValue(&sOut, pVal, &rc); |
| 171585 | + } |
| 171586 | + |
| 171587 | + /* Write the new new.* record. Consists of a copy of all values |
| 171588 | + ** from the original old.* record, except for the PK columns, which |
| 171589 | + ** are set to "undefined". */ |
| 171590 | + for(iCol=0; iCol<nCol; iCol++){ |
| 171591 | + sqlite3_value *pVal = (abPK[iCol] ? 0 : apVal[iCol]); |
| 171592 | + sessionAppendValue(&sOut, pVal, &rc); |
| 171593 | + } |
| 171594 | + |
| 171595 | + for(iCol=0; iCol<nCol*2; iCol++){ |
| 171596 | + sqlite3ValueFree(apVal[iCol]); |
| 171597 | + } |
| 171598 | + memset(apVal, 0, sizeof(apVal[0])*nCol*2); |
| 171599 | + if( rc!=SQLITE_OK ){ |
| 171600 | + goto finished_invert; |
| 171601 | + } |
| 171602 | + |
| 171603 | + break; |
| 171604 | + } |
| 171605 | + |
| 171606 | + default: |
| 171607 | + rc = SQLITE_CORRUPT_BKPT; |
| 171608 | + goto finished_invert; |
| 171609 | + } |
| 171610 | + |
| 171611 | + assert( rc==SQLITE_OK ); |
| 171612 | + if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ |
| 171613 | + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); |
| 171614 | + sOut.nBuf = 0; |
| 171615 | + if( rc!=SQLITE_OK ) goto finished_invert; |
| 171616 | + } |
| 171617 | + } |
| 171618 | + |
| 171619 | + assert( rc==SQLITE_OK ); |
| 171620 | + if( pnInverted ){ |
| 171621 | + *pnInverted = sOut.nBuf; |
| 171622 | + *ppInverted = sOut.aBuf; |
| 171623 | + sOut.aBuf = 0; |
| 171624 | + }else if( sOut.nBuf>0 ){ |
| 171625 | + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); |
| 171626 | + } |
| 171627 | + |
| 171628 | + finished_invert: |
| 171629 | + sqlite3_free(sOut.aBuf); |
| 171630 | + sqlite3_free(apVal); |
| 171631 | + sqlite3_free(sPK.aBuf); |
| 171632 | + return rc; |
| 171633 | +} |
| 171634 | + |
| 171635 | + |
| 171636 | +/* |
| 171637 | +** Invert a changeset object. |
| 171638 | +*/ |
| 171639 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_invert( |
| 171640 | + int nChangeset, /* Number of bytes in input */ |
| 171641 | + const void *pChangeset, /* Input changeset */ |
| 171642 | + int *pnInverted, /* OUT: Number of bytes in output changeset */ |
| 171643 | + void **ppInverted /* OUT: Inverse of pChangeset */ |
| 171644 | +){ |
| 171645 | + SessionInput sInput; |
| 171646 | + |
| 171647 | + /* Set up the input stream */ |
| 171648 | + memset(&sInput, 0, sizeof(SessionInput)); |
| 171649 | + sInput.nData = nChangeset; |
| 171650 | + sInput.aData = (u8*)pChangeset; |
| 171651 | + |
| 171652 | + return sessionChangesetInvert(&sInput, 0, 0, pnInverted, ppInverted); |
| 171653 | +} |
| 171654 | + |
| 171655 | +/* |
| 171656 | +** Streaming version of sqlite3changeset_invert(). |
| 171657 | +*/ |
| 171658 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_invert_strm( |
| 171659 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 171660 | + void *pIn, |
| 171661 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 171662 | + void *pOut |
| 171663 | +){ |
| 171664 | + SessionInput sInput; |
| 171665 | + int rc; |
| 171666 | + |
| 171667 | + /* Set up the input stream */ |
| 171668 | + memset(&sInput, 0, sizeof(SessionInput)); |
| 171669 | + sInput.xInput = xInput; |
| 171670 | + sInput.pIn = pIn; |
| 171671 | + |
| 171672 | + rc = sessionChangesetInvert(&sInput, xOutput, pOut, 0, 0); |
| 171673 | + sqlite3_free(sInput.buf.aBuf); |
| 171674 | + return rc; |
| 171675 | +} |
| 171676 | + |
| 171677 | +typedef struct SessionApplyCtx SessionApplyCtx; |
| 171678 | +struct SessionApplyCtx { |
| 171679 | + sqlite3 *db; |
| 171680 | + sqlite3_stmt *pDelete; /* DELETE statement */ |
| 171681 | + sqlite3_stmt *pUpdate; /* UPDATE statement */ |
| 171682 | + sqlite3_stmt *pInsert; /* INSERT statement */ |
| 171683 | + sqlite3_stmt *pSelect; /* SELECT statement */ |
| 171684 | + int nCol; /* Size of azCol[] and abPK[] arrays */ |
| 171685 | + const char **azCol; /* Array of column names */ |
| 171686 | + u8 *abPK; /* Boolean array - true if column is in PK */ |
| 171687 | + |
| 171688 | + int bDeferConstraints; /* True to defer constraints */ |
| 171689 | + SessionBuffer constraints; /* Deferred constraints are stored here */ |
| 171690 | +}; |
| 171691 | + |
| 171692 | +/* |
| 171693 | +** Formulate a statement to DELETE a row from database db. Assuming a table |
| 171694 | +** structure like this: |
| 171695 | +** |
| 171696 | +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); |
| 171697 | +** |
| 171698 | +** The DELETE statement looks like this: |
| 171699 | +** |
| 171700 | +** DELETE FROM x WHERE a = :1 AND c = :3 AND (:5 OR b IS :2 AND d IS :4) |
| 171701 | +** |
| 171702 | +** Variable :5 (nCol+1) is a boolean. It should be set to 0 if we require |
| 171703 | +** matching b and d values, or 1 otherwise. The second case comes up if the |
| 171704 | +** conflict handler is invoked with NOTFOUND and returns CHANGESET_REPLACE. |
| 171705 | +** |
| 171706 | +** If successful, SQLITE_OK is returned and SessionApplyCtx.pDelete is left |
| 171707 | +** pointing to the prepared version of the SQL statement. |
| 171708 | +*/ |
| 171709 | +static int sessionDeleteRow( |
| 171710 | + sqlite3 *db, /* Database handle */ |
| 171711 | + const char *zTab, /* Table name */ |
| 171712 | + SessionApplyCtx *p /* Session changeset-apply context */ |
| 171713 | +){ |
| 171714 | + int i; |
| 171715 | + const char *zSep = ""; |
| 171716 | + int rc = SQLITE_OK; |
| 171717 | + SessionBuffer buf = {0, 0, 0}; |
| 171718 | + int nPk = 0; |
| 171719 | + |
| 171720 | + sessionAppendStr(&buf, "DELETE FROM ", &rc); |
| 171721 | + sessionAppendIdent(&buf, zTab, &rc); |
| 171722 | + sessionAppendStr(&buf, " WHERE ", &rc); |
| 171723 | + |
| 171724 | + for(i=0; i<p->nCol; i++){ |
| 171725 | + if( p->abPK[i] ){ |
| 171726 | + nPk++; |
| 171727 | + sessionAppendStr(&buf, zSep, &rc); |
| 171728 | + sessionAppendIdent(&buf, p->azCol[i], &rc); |
| 171729 | + sessionAppendStr(&buf, " = ?", &rc); |
| 171730 | + sessionAppendInteger(&buf, i+1, &rc); |
| 171731 | + zSep = " AND "; |
| 171732 | + } |
| 171733 | + } |
| 171734 | + |
| 171735 | + if( nPk<p->nCol ){ |
| 171736 | + sessionAppendStr(&buf, " AND (?", &rc); |
| 171737 | + sessionAppendInteger(&buf, p->nCol+1, &rc); |
| 171738 | + sessionAppendStr(&buf, " OR ", &rc); |
| 171739 | + |
| 171740 | + zSep = ""; |
| 171741 | + for(i=0; i<p->nCol; i++){ |
| 171742 | + if( !p->abPK[i] ){ |
| 171743 | + sessionAppendStr(&buf, zSep, &rc); |
| 171744 | + sessionAppendIdent(&buf, p->azCol[i], &rc); |
| 171745 | + sessionAppendStr(&buf, " IS ?", &rc); |
| 171746 | + sessionAppendInteger(&buf, i+1, &rc); |
| 171747 | + zSep = "AND "; |
| 171748 | + } |
| 171749 | + } |
| 171750 | + sessionAppendStr(&buf, ")", &rc); |
| 171751 | + } |
| 171752 | + |
| 171753 | + if( rc==SQLITE_OK ){ |
| 171754 | + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); |
| 171755 | + } |
| 171756 | + sqlite3_free(buf.aBuf); |
| 171757 | + |
| 171758 | + return rc; |
| 171759 | +} |
| 171760 | + |
| 171761 | +/* |
| 171762 | +** Formulate and prepare a statement to UPDATE a row from database db. |
| 171763 | +** Assuming a table structure like this: |
| 171764 | +** |
| 171765 | +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); |
| 171766 | +** |
| 171767 | +** The UPDATE statement looks like this: |
| 171768 | +** |
| 171769 | +** UPDATE x SET |
| 171770 | +** a = CASE WHEN ?2 THEN ?3 ELSE a END, |
| 171771 | +** b = CASE WHEN ?5 THEN ?6 ELSE b END, |
| 171772 | +** c = CASE WHEN ?8 THEN ?9 ELSE c END, |
| 171773 | +** d = CASE WHEN ?11 THEN ?12 ELSE d END |
| 171774 | +** WHERE a = ?1 AND c = ?7 AND (?13 OR |
| 171775 | +** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND |
| 171776 | +** ) |
| 171777 | +** |
| 171778 | +** For each column in the table, there are three variables to bind: |
| 171779 | +** |
| 171780 | +** ?(i*3+1) The old.* value of the column, if any. |
| 171781 | +** ?(i*3+2) A boolean flag indicating that the value is being modified. |
| 171782 | +** ?(i*3+3) The new.* value of the column, if any. |
| 171783 | +** |
| 171784 | +** Also, a boolean flag that, if set to true, causes the statement to update |
| 171785 | +** a row even if the non-PK values do not match. This is required if the |
| 171786 | +** conflict-handler is invoked with CHANGESET_DATA and returns |
| 171787 | +** CHANGESET_REPLACE. This is variable "?(nCol*3+1)". |
| 171788 | +** |
| 171789 | +** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left |
| 171790 | +** pointing to the prepared version of the SQL statement. |
| 171791 | +*/ |
| 171792 | +static int sessionUpdateRow( |
| 171793 | + sqlite3 *db, /* Database handle */ |
| 171794 | + const char *zTab, /* Table name */ |
| 171795 | + SessionApplyCtx *p /* Session changeset-apply context */ |
| 171796 | +){ |
| 171797 | + int rc = SQLITE_OK; |
| 171798 | + int i; |
| 171799 | + const char *zSep = ""; |
| 171800 | + SessionBuffer buf = {0, 0, 0}; |
| 171801 | + |
| 171802 | + /* Append "UPDATE tbl SET " */ |
| 171803 | + sessionAppendStr(&buf, "UPDATE ", &rc); |
| 171804 | + sessionAppendIdent(&buf, zTab, &rc); |
| 171805 | + sessionAppendStr(&buf, " SET ", &rc); |
| 171806 | + |
| 171807 | + /* Append the assignments */ |
| 171808 | + for(i=0; i<p->nCol; i++){ |
| 171809 | + sessionAppendStr(&buf, zSep, &rc); |
| 171810 | + sessionAppendIdent(&buf, p->azCol[i], &rc); |
| 171811 | + sessionAppendStr(&buf, " = CASE WHEN ?", &rc); |
| 171812 | + sessionAppendInteger(&buf, i*3+2, &rc); |
| 171813 | + sessionAppendStr(&buf, " THEN ?", &rc); |
| 171814 | + sessionAppendInteger(&buf, i*3+3, &rc); |
| 171815 | + sessionAppendStr(&buf, " ELSE ", &rc); |
| 171816 | + sessionAppendIdent(&buf, p->azCol[i], &rc); |
| 171817 | + sessionAppendStr(&buf, " END", &rc); |
| 171818 | + zSep = ", "; |
| 171819 | + } |
| 171820 | + |
| 171821 | + /* Append the PK part of the WHERE clause */ |
| 171822 | + sessionAppendStr(&buf, " WHERE ", &rc); |
| 171823 | + for(i=0; i<p->nCol; i++){ |
| 171824 | + if( p->abPK[i] ){ |
| 171825 | + sessionAppendIdent(&buf, p->azCol[i], &rc); |
| 171826 | + sessionAppendStr(&buf, " = ?", &rc); |
| 171827 | + sessionAppendInteger(&buf, i*3+1, &rc); |
| 171828 | + sessionAppendStr(&buf, " AND ", &rc); |
| 171829 | + } |
| 171830 | + } |
| 171831 | + |
| 171832 | + /* Append the non-PK part of the WHERE clause */ |
| 171833 | + sessionAppendStr(&buf, " (?", &rc); |
| 171834 | + sessionAppendInteger(&buf, p->nCol*3+1, &rc); |
| 171835 | + sessionAppendStr(&buf, " OR 1", &rc); |
| 171836 | + for(i=0; i<p->nCol; i++){ |
| 171837 | + if( !p->abPK[i] ){ |
| 171838 | + sessionAppendStr(&buf, " AND (?", &rc); |
| 171839 | + sessionAppendInteger(&buf, i*3+2, &rc); |
| 171840 | + sessionAppendStr(&buf, "=0 OR ", &rc); |
| 171841 | + sessionAppendIdent(&buf, p->azCol[i], &rc); |
| 171842 | + sessionAppendStr(&buf, " IS ?", &rc); |
| 171843 | + sessionAppendInteger(&buf, i*3+1, &rc); |
| 171844 | + sessionAppendStr(&buf, ")", &rc); |
| 171845 | + } |
| 171846 | + } |
| 171847 | + sessionAppendStr(&buf, ")", &rc); |
| 171848 | + |
| 171849 | + if( rc==SQLITE_OK ){ |
| 171850 | + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0); |
| 171851 | + } |
| 171852 | + sqlite3_free(buf.aBuf); |
| 171853 | + |
| 171854 | + return rc; |
| 171855 | +} |
| 171856 | + |
| 171857 | +/* |
| 171858 | +** Formulate and prepare an SQL statement to query table zTab by primary |
| 171859 | +** key. Assuming the following table structure: |
| 171860 | +** |
| 171861 | +** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); |
| 171862 | +** |
| 171863 | +** The SELECT statement looks like this: |
| 171864 | +** |
| 171865 | +** SELECT * FROM x WHERE a = ?1 AND c = ?3 |
| 171866 | +** |
| 171867 | +** If successful, SQLITE_OK is returned and SessionApplyCtx.pSelect is left |
| 171868 | +** pointing to the prepared version of the SQL statement. |
| 171869 | +*/ |
| 171870 | +static int sessionSelectRow( |
| 171871 | + sqlite3 *db, /* Database handle */ |
| 171872 | + const char *zTab, /* Table name */ |
| 171873 | + SessionApplyCtx *p /* Session changeset-apply context */ |
| 171874 | +){ |
| 171875 | + return sessionSelectStmt( |
| 171876 | + db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); |
| 171877 | +} |
| 171878 | + |
| 171879 | +/* |
| 171880 | +** Formulate and prepare an INSERT statement to add a record to table zTab. |
| 171881 | +** For example: |
| 171882 | +** |
| 171883 | +** INSERT INTO main."zTab" VALUES(?1, ?2, ?3 ...); |
| 171884 | +** |
| 171885 | +** If successful, SQLITE_OK is returned and SessionApplyCtx.pInsert is left |
| 171886 | +** pointing to the prepared version of the SQL statement. |
| 171887 | +*/ |
| 171888 | +static int sessionInsertRow( |
| 171889 | + sqlite3 *db, /* Database handle */ |
| 171890 | + const char *zTab, /* Table name */ |
| 171891 | + SessionApplyCtx *p /* Session changeset-apply context */ |
| 171892 | +){ |
| 171893 | + int rc = SQLITE_OK; |
| 171894 | + int i; |
| 171895 | + SessionBuffer buf = {0, 0, 0}; |
| 171896 | + |
| 171897 | + sessionAppendStr(&buf, "INSERT INTO main.", &rc); |
| 171898 | + sessionAppendIdent(&buf, zTab, &rc); |
| 171899 | + sessionAppendStr(&buf, " VALUES(?", &rc); |
| 171900 | + for(i=1; i<p->nCol; i++){ |
| 171901 | + sessionAppendStr(&buf, ", ?", &rc); |
| 171902 | + } |
| 171903 | + sessionAppendStr(&buf, ")", &rc); |
| 171904 | + |
| 171905 | + if( rc==SQLITE_OK ){ |
| 171906 | + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0); |
| 171907 | + } |
| 171908 | + sqlite3_free(buf.aBuf); |
| 171909 | + return rc; |
| 171910 | +} |
| 171911 | + |
| 171912 | +/* |
| 171913 | +** A wrapper around sqlite3_bind_value() that detects an extra problem. |
| 171914 | +** See comments in the body of this function for details. |
| 171915 | +*/ |
| 171916 | +static int sessionBindValue( |
| 171917 | + sqlite3_stmt *pStmt, /* Statement to bind value to */ |
| 171918 | + int i, /* Parameter number to bind to */ |
| 171919 | + sqlite3_value *pVal /* Value to bind */ |
| 171920 | +){ |
| 171921 | + int eType = sqlite3_value_type(pVal); |
| 171922 | + /* COVERAGE: The (pVal->z==0) branch is never true using current versions |
| 171923 | + ** of SQLite. If a malloc fails in an sqlite3_value_xxx() function, either |
| 171924 | + ** the (pVal->z) variable remains as it was or the type of the value is |
| 171925 | + ** set to SQLITE_NULL. */ |
| 171926 | + if( (eType==SQLITE_TEXT || eType==SQLITE_BLOB) && pVal->z==0 ){ |
| 171927 | + /* This condition occurs when an earlier OOM in a call to |
| 171928 | + ** sqlite3_value_text() or sqlite3_value_blob() (perhaps from within |
| 171929 | + ** a conflict-handler) has zeroed the pVal->z pointer. Return NOMEM. */ |
| 171930 | + return SQLITE_NOMEM; |
| 171931 | + } |
| 171932 | + return sqlite3_bind_value(pStmt, i, pVal); |
| 171933 | +} |
| 171934 | + |
| 171935 | +/* |
| 171936 | +** Iterator pIter must point to an SQLITE_INSERT entry. This function |
| 171937 | +** transfers new.* values from the current iterator entry to statement |
| 171938 | +** pStmt. The table being inserted into has nCol columns. |
| 171939 | +** |
| 171940 | +** New.* value $i from the iterator is bound to variable ($i+1) of |
| 171941 | +** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1) |
| 171942 | +** are transfered to the statement. Otherwise, if abPK is not NULL, it points |
| 171943 | +** to an array nCol elements in size. In this case only those values for |
| 171944 | +** which abPK[$i] is true are read from the iterator and bound to the |
| 171945 | +** statement. |
| 171946 | +** |
| 171947 | +** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK. |
| 171948 | +*/ |
| 171949 | +static int sessionBindRow( |
| 171950 | + sqlite3_changeset_iter *pIter, /* Iterator to read values from */ |
| 171951 | + int(*xValue)(sqlite3_changeset_iter *, int, sqlite3_value **), |
| 171952 | + int nCol, /* Number of columns */ |
| 171953 | + u8 *abPK, /* If not NULL, bind only if true */ |
| 171954 | + sqlite3_stmt *pStmt /* Bind values to this statement */ |
| 171955 | +){ |
| 171956 | + int i; |
| 171957 | + int rc = SQLITE_OK; |
| 171958 | + |
| 171959 | + /* Neither sqlite3changeset_old or sqlite3changeset_new can fail if the |
| 171960 | + ** argument iterator points to a suitable entry. Make sure that xValue |
| 171961 | + ** is one of these to guarantee that it is safe to ignore the return |
| 171962 | + ** in the code below. */ |
| 171963 | + assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new ); |
| 171964 | + |
| 171965 | + for(i=0; rc==SQLITE_OK && i<nCol; i++){ |
| 171966 | + if( !abPK || abPK[i] ){ |
| 171967 | + sqlite3_value *pVal; |
| 171968 | + (void)xValue(pIter, i, &pVal); |
| 171969 | + rc = sessionBindValue(pStmt, i+1, pVal); |
| 171970 | + } |
| 171971 | + } |
| 171972 | + return rc; |
| 171973 | +} |
| 171974 | + |
| 171975 | +/* |
| 171976 | +** SQL statement pSelect is as generated by the sessionSelectRow() function. |
| 171977 | +** This function binds the primary key values from the change that changeset |
| 171978 | +** iterator pIter points to to the SELECT and attempts to seek to the table |
| 171979 | +** entry. If a row is found, the SELECT statement left pointing at the row |
| 171980 | +** and SQLITE_ROW is returned. Otherwise, if no row is found and no error |
| 171981 | +** has occured, the statement is reset and SQLITE_OK is returned. If an |
| 171982 | +** error occurs, the statement is reset and an SQLite error code is returned. |
| 171983 | +** |
| 171984 | +** If this function returns SQLITE_ROW, the caller must eventually reset() |
| 171985 | +** statement pSelect. If any other value is returned, the statement does |
| 171986 | +** not require a reset(). |
| 171987 | +** |
| 171988 | +** If the iterator currently points to an INSERT record, bind values from the |
| 171989 | +** new.* record to the SELECT statement. Or, if it points to a DELETE or |
| 171990 | +** UPDATE, bind values from the old.* record. |
| 171991 | +*/ |
| 171992 | +static int sessionSeekToRow( |
| 171993 | + sqlite3 *db, /* Database handle */ |
| 171994 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 171995 | + u8 *abPK, /* Primary key flags array */ |
| 171996 | + sqlite3_stmt *pSelect /* SELECT statement from sessionSelectRow() */ |
| 171997 | +){ |
| 171998 | + int rc; /* Return code */ |
| 171999 | + int nCol; /* Number of columns in table */ |
| 172000 | + int op; /* Changset operation (SQLITE_UPDATE etc.) */ |
| 172001 | + const char *zDummy; /* Unused */ |
| 172002 | + |
| 172003 | + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); |
| 172004 | + rc = sessionBindRow(pIter, |
| 172005 | + op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old, |
| 172006 | + nCol, abPK, pSelect |
| 172007 | + ); |
| 172008 | + |
| 172009 | + if( rc==SQLITE_OK ){ |
| 172010 | + rc = sqlite3_step(pSelect); |
| 172011 | + if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect); |
| 172012 | + } |
| 172013 | + |
| 172014 | + return rc; |
| 172015 | +} |
| 172016 | + |
| 172017 | +/* |
| 172018 | +** Invoke the conflict handler for the change that the changeset iterator |
| 172019 | +** currently points to. |
| 172020 | +** |
| 172021 | +** Argument eType must be either CHANGESET_DATA or CHANGESET_CONFLICT. |
| 172022 | +** If argument pbReplace is NULL, then the type of conflict handler invoked |
| 172023 | +** depends solely on eType, as follows: |
| 172024 | +** |
| 172025 | +** eType value Value passed to xConflict |
| 172026 | +** ------------------------------------------------- |
| 172027 | +** CHANGESET_DATA CHANGESET_NOTFOUND |
| 172028 | +** CHANGESET_CONFLICT CHANGESET_CONSTRAINT |
| 172029 | +** |
| 172030 | +** Or, if pbReplace is not NULL, then an attempt is made to find an existing |
| 172031 | +** record with the same primary key as the record about to be deleted, updated |
| 172032 | +** or inserted. If such a record can be found, it is available to the conflict |
| 172033 | +** handler as the "conflicting" record. In this case the type of conflict |
| 172034 | +** handler invoked is as follows: |
| 172035 | +** |
| 172036 | +** eType value PK Record found? Value passed to xConflict |
| 172037 | +** ---------------------------------------------------------------- |
| 172038 | +** CHANGESET_DATA Yes CHANGESET_DATA |
| 172039 | +** CHANGESET_DATA No CHANGESET_NOTFOUND |
| 172040 | +** CHANGESET_CONFLICT Yes CHANGESET_CONFLICT |
| 172041 | +** CHANGESET_CONFLICT No CHANGESET_CONSTRAINT |
| 172042 | +** |
| 172043 | +** If pbReplace is not NULL, and a record with a matching PK is found, and |
| 172044 | +** the conflict handler function returns SQLITE_CHANGESET_REPLACE, *pbReplace |
| 172045 | +** is set to non-zero before returning SQLITE_OK. |
| 172046 | +** |
| 172047 | +** If the conflict handler returns SQLITE_CHANGESET_ABORT, SQLITE_ABORT is |
| 172048 | +** returned. Or, if the conflict handler returns an invalid value, |
| 172049 | +** SQLITE_MISUSE. If the conflict handler returns SQLITE_CHANGESET_OMIT, |
| 172050 | +** this function returns SQLITE_OK. |
| 172051 | +*/ |
| 172052 | +static int sessionConflictHandler( |
| 172053 | + int eType, /* Either CHANGESET_DATA or CONFLICT */ |
| 172054 | + SessionApplyCtx *p, /* changeset_apply() context */ |
| 172055 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 172056 | + int(*xConflict)(void *, int, sqlite3_changeset_iter*), |
| 172057 | + void *pCtx, /* First argument for conflict handler */ |
| 172058 | + int *pbReplace /* OUT: Set to true if PK row is found */ |
| 172059 | +){ |
| 172060 | + int res; /* Value returned by conflict handler */ |
| 172061 | + int rc; |
| 172062 | + int nCol; |
| 172063 | + int op; |
| 172064 | + const char *zDummy; |
| 172065 | + |
| 172066 | + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); |
| 172067 | + |
| 172068 | + assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA ); |
| 172069 | + assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT ); |
| 172070 | + assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND ); |
| 172071 | + |
| 172072 | + /* Bind the new.* PRIMARY KEY values to the SELECT statement. */ |
| 172073 | + if( pbReplace ){ |
| 172074 | + rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect); |
| 172075 | + }else{ |
| 172076 | + rc = SQLITE_OK; |
| 172077 | + } |
| 172078 | + |
| 172079 | + if( rc==SQLITE_ROW ){ |
| 172080 | + /* There exists another row with the new.* primary key. */ |
| 172081 | + pIter->pConflict = p->pSelect; |
| 172082 | + res = xConflict(pCtx, eType, pIter); |
| 172083 | + pIter->pConflict = 0; |
| 172084 | + rc = sqlite3_reset(p->pSelect); |
| 172085 | + }else if( rc==SQLITE_OK ){ |
| 172086 | + if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ |
| 172087 | + /* Instead of invoking the conflict handler, append the change blob |
| 172088 | + ** to the SessionApplyCtx.constraints buffer. */ |
| 172089 | + u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; |
| 172090 | + int nBlob = pIter->in.iNext - pIter->in.iCurrent; |
| 172091 | + sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); |
| 172092 | + res = SQLITE_CHANGESET_OMIT; |
| 172093 | + }else{ |
| 172094 | + /* No other row with the new.* primary key. */ |
| 172095 | + res = xConflict(pCtx, eType+1, pIter); |
| 172096 | + if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; |
| 172097 | + } |
| 172098 | + } |
| 172099 | + |
| 172100 | + if( rc==SQLITE_OK ){ |
| 172101 | + switch( res ){ |
| 172102 | + case SQLITE_CHANGESET_REPLACE: |
| 172103 | + assert( pbReplace ); |
| 172104 | + *pbReplace = 1; |
| 172105 | + break; |
| 172106 | + |
| 172107 | + case SQLITE_CHANGESET_OMIT: |
| 172108 | + break; |
| 172109 | + |
| 172110 | + case SQLITE_CHANGESET_ABORT: |
| 172111 | + rc = SQLITE_ABORT; |
| 172112 | + break; |
| 172113 | + |
| 172114 | + default: |
| 172115 | + rc = SQLITE_MISUSE; |
| 172116 | + break; |
| 172117 | + } |
| 172118 | + } |
| 172119 | + |
| 172120 | + return rc; |
| 172121 | +} |
| 172122 | + |
| 172123 | +/* |
| 172124 | +** Attempt to apply the change that the iterator passed as the first argument |
| 172125 | +** currently points to to the database. If a conflict is encountered, invoke |
| 172126 | +** the conflict handler callback. |
| 172127 | +** |
| 172128 | +** If argument pbRetry is NULL, then ignore any CHANGESET_DATA conflict. If |
| 172129 | +** one is encountered, update or delete the row with the matching primary key |
| 172130 | +** instead. Or, if pbRetry is not NULL and a CHANGESET_DATA conflict occurs, |
| 172131 | +** invoke the conflict handler. If it returns CHANGESET_REPLACE, set *pbRetry |
| 172132 | +** to true before returning. In this case the caller will invoke this function |
| 172133 | +** again, this time with pbRetry set to NULL. |
| 172134 | +** |
| 172135 | +** If argument pbReplace is NULL and a CHANGESET_CONFLICT conflict is |
| 172136 | +** encountered invoke the conflict handler with CHANGESET_CONSTRAINT instead. |
| 172137 | +** Or, if pbReplace is not NULL, invoke it with CHANGESET_CONFLICT. If such |
| 172138 | +** an invocation returns SQLITE_CHANGESET_REPLACE, set *pbReplace to true |
| 172139 | +** before retrying. In this case the caller attempts to remove the conflicting |
| 172140 | +** row before invoking this function again, this time with pbReplace set |
| 172141 | +** to NULL. |
| 172142 | +** |
| 172143 | +** If any conflict handler returns SQLITE_CHANGESET_ABORT, this function |
| 172144 | +** returns SQLITE_ABORT. Otherwise, if no error occurs, SQLITE_OK is |
| 172145 | +** returned. |
| 172146 | +*/ |
| 172147 | +static int sessionApplyOneOp( |
| 172148 | + sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 172149 | + SessionApplyCtx *p, /* changeset_apply() context */ |
| 172150 | + int(*xConflict)(void *, int, sqlite3_changeset_iter *), |
| 172151 | + void *pCtx, /* First argument for the conflict handler */ |
| 172152 | + int *pbReplace, /* OUT: True to remove PK row and retry */ |
| 172153 | + int *pbRetry /* OUT: True to retry. */ |
| 172154 | +){ |
| 172155 | + const char *zDummy; |
| 172156 | + int op; |
| 172157 | + int nCol; |
| 172158 | + int rc = SQLITE_OK; |
| 172159 | + |
| 172160 | + assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect ); |
| 172161 | + assert( p->azCol && p->abPK ); |
| 172162 | + assert( !pbReplace || *pbReplace==0 ); |
| 172163 | + |
| 172164 | + sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); |
| 172165 | + |
| 172166 | + if( op==SQLITE_DELETE ){ |
| 172167 | + |
| 172168 | + /* Bind values to the DELETE statement. If conflict handling is required, |
| 172169 | + ** bind values for all columns and set bound variable (nCol+1) to true. |
| 172170 | + ** Or, if conflict handling is not required, bind just the PK column |
| 172171 | + ** values and, if it exists, set (nCol+1) to false. Conflict handling |
| 172172 | + ** is not required if: |
| 172173 | + ** |
| 172174 | + ** * this is a patchset, or |
| 172175 | + ** * (pbRetry==0), or |
| 172176 | + ** * all columns of the table are PK columns (in this case there is |
| 172177 | + ** no (nCol+1) variable to bind to). |
| 172178 | + */ |
| 172179 | + u8 *abPK = (pIter->bPatchset ? p->abPK : 0); |
| 172180 | + rc = sessionBindRow(pIter, sqlite3changeset_old, nCol, abPK, p->pDelete); |
| 172181 | + if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ |
| 172182 | + rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK)); |
| 172183 | + } |
| 172184 | + if( rc!=SQLITE_OK ) return rc; |
| 172185 | + |
| 172186 | + sqlite3_step(p->pDelete); |
| 172187 | + rc = sqlite3_reset(p->pDelete); |
| 172188 | + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ |
| 172189 | + rc = sessionConflictHandler( |
| 172190 | + SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry |
| 172191 | + ); |
| 172192 | + }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ |
| 172193 | + rc = sessionConflictHandler( |
| 172194 | + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 |
| 172195 | + ); |
| 172196 | + } |
| 172197 | + |
| 172198 | + }else if( op==SQLITE_UPDATE ){ |
| 172199 | + int i; |
| 172200 | + |
| 172201 | + /* Bind values to the UPDATE statement. */ |
| 172202 | + for(i=0; rc==SQLITE_OK && i<nCol; i++){ |
| 172203 | + sqlite3_value *pOld = sessionChangesetOld(pIter, i); |
| 172204 | + sqlite3_value *pNew = sessionChangesetNew(pIter, i); |
| 172205 | + |
| 172206 | + sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew); |
| 172207 | + if( pOld ){ |
| 172208 | + rc = sessionBindValue(p->pUpdate, i*3+1, pOld); |
| 172209 | + } |
| 172210 | + if( rc==SQLITE_OK && pNew ){ |
| 172211 | + rc = sessionBindValue(p->pUpdate, i*3+3, pNew); |
| 172212 | + } |
| 172213 | + } |
| 172214 | + if( rc==SQLITE_OK ){ |
| 172215 | + sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset); |
| 172216 | + } |
| 172217 | + if( rc!=SQLITE_OK ) return rc; |
| 172218 | + |
| 172219 | + /* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict, |
| 172220 | + ** the result will be SQLITE_OK with 0 rows modified. */ |
| 172221 | + sqlite3_step(p->pUpdate); |
| 172222 | + rc = sqlite3_reset(p->pUpdate); |
| 172223 | + |
| 172224 | + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ |
| 172225 | + /* A NOTFOUND or DATA error. Search the table to see if it contains |
| 172226 | + ** a row with a matching primary key. If so, this is a DATA conflict. |
| 172227 | + ** Otherwise, if there is no primary key match, it is a NOTFOUND. */ |
| 172228 | + |
| 172229 | + rc = sessionConflictHandler( |
| 172230 | + SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry |
| 172231 | + ); |
| 172232 | + |
| 172233 | + }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ |
| 172234 | + /* This is always a CONSTRAINT conflict. */ |
| 172235 | + rc = sessionConflictHandler( |
| 172236 | + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 |
| 172237 | + ); |
| 172238 | + } |
| 172239 | + |
| 172240 | + }else{ |
| 172241 | + assert( op==SQLITE_INSERT ); |
| 172242 | + rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); |
| 172243 | + if( rc!=SQLITE_OK ) return rc; |
| 172244 | + |
| 172245 | + sqlite3_step(p->pInsert); |
| 172246 | + rc = sqlite3_reset(p->pInsert); |
| 172247 | + if( (rc&0xff)==SQLITE_CONSTRAINT ){ |
| 172248 | + rc = sessionConflictHandler( |
| 172249 | + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace |
| 172250 | + ); |
| 172251 | + } |
| 172252 | + } |
| 172253 | + |
| 172254 | + return rc; |
| 172255 | +} |
| 172256 | + |
| 172257 | +/* |
| 172258 | +** Attempt to apply the change that the iterator passed as the first argument |
| 172259 | +** currently points to to the database. If a conflict is encountered, invoke |
| 172260 | +** the conflict handler callback. |
| 172261 | +** |
| 172262 | +** The difference between this function and sessionApplyOne() is that this |
| 172263 | +** function handles the case where the conflict-handler is invoked and |
| 172264 | +** returns SQLITE_CHANGESET_REPLACE - indicating that the change should be |
| 172265 | +** retried in some manner. |
| 172266 | +*/ |
| 172267 | +static int sessionApplyOneWithRetry( |
| 172268 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 172269 | + sqlite3_changeset_iter *pIter, /* Changeset iterator to read change from */ |
| 172270 | + SessionApplyCtx *pApply, /* Apply context */ |
| 172271 | + int(*xConflict)(void*, int, sqlite3_changeset_iter*), |
| 172272 | + void *pCtx /* First argument passed to xConflict */ |
| 172273 | +){ |
| 172274 | + int bReplace = 0; |
| 172275 | + int bRetry = 0; |
| 172276 | + int rc; |
| 172277 | + |
| 172278 | + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); |
| 172279 | + assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); |
| 172280 | + |
| 172281 | + /* If the bRetry flag is set, the change has not been applied due to an |
| 172282 | + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and |
| 172283 | + ** a row with the correct PK is present in the db, but one or more other |
| 172284 | + ** fields do not contain the expected values) and the conflict handler |
| 172285 | + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, |
| 172286 | + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores |
| 172287 | + ** the SQLITE_CHANGESET_DATA problem. */ |
| 172288 | + if( bRetry ){ |
| 172289 | + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); |
| 172290 | + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); |
| 172291 | + } |
| 172292 | + |
| 172293 | + /* If the bReplace flag is set, the change is an INSERT that has not |
| 172294 | + ** been performed because the database already contains a row with the |
| 172295 | + ** specified primary key and the conflict handler returned |
| 172296 | + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row |
| 172297 | + ** before reattempting the INSERT. */ |
| 172298 | + else if( bReplace ){ |
| 172299 | + assert( pIter->op==SQLITE_INSERT ); |
| 172300 | + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); |
| 172301 | + if( rc==SQLITE_OK ){ |
| 172302 | + rc = sessionBindRow(pIter, |
| 172303 | + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); |
| 172304 | + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); |
| 172305 | + } |
| 172306 | + if( rc==SQLITE_OK ){ |
| 172307 | + sqlite3_step(pApply->pDelete); |
| 172308 | + rc = sqlite3_reset(pApply->pDelete); |
| 172309 | + } |
| 172310 | + if( rc==SQLITE_OK ){ |
| 172311 | + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); |
| 172312 | + } |
| 172313 | + if( rc==SQLITE_OK ){ |
| 172314 | + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); |
| 172315 | + } |
| 172316 | + } |
| 172317 | + |
| 172318 | + return rc; |
| 172319 | +} |
| 172320 | + |
| 172321 | +/* |
| 172322 | +** Retry the changes accumulated in the pApply->constraints buffer. |
| 172323 | +*/ |
| 172324 | +static int sessionRetryConstraints( |
| 172325 | + sqlite3 *db, |
| 172326 | + int bPatchset, |
| 172327 | + const char *zTab, |
| 172328 | + SessionApplyCtx *pApply, |
| 172329 | + int(*xConflict)(void*, int, sqlite3_changeset_iter*), |
| 172330 | + void *pCtx /* First argument passed to xConflict */ |
| 172331 | +){ |
| 172332 | + int rc = SQLITE_OK; |
| 172333 | + |
| 172334 | + while( pApply->constraints.nBuf ){ |
| 172335 | + sqlite3_changeset_iter *pIter2 = 0; |
| 172336 | + SessionBuffer cons = pApply->constraints; |
| 172337 | + memset(&pApply->constraints, 0, sizeof(SessionBuffer)); |
| 172338 | + |
| 172339 | + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); |
| 172340 | + if( rc==SQLITE_OK ){ |
| 172341 | + int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); |
| 172342 | + int rc2; |
| 172343 | + pIter2->bPatchset = bPatchset; |
| 172344 | + pIter2->zTab = (char*)zTab; |
| 172345 | + pIter2->nCol = pApply->nCol; |
| 172346 | + pIter2->abPK = pApply->abPK; |
| 172347 | + sessionBufferGrow(&pIter2->tblhdr, nByte, &rc); |
| 172348 | + pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf; |
| 172349 | + if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte); |
| 172350 | + |
| 172351 | + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){ |
| 172352 | + rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx); |
| 172353 | + } |
| 172354 | + |
| 172355 | + rc2 = sqlite3changeset_finalize(pIter2); |
| 172356 | + if( rc==SQLITE_OK ) rc = rc2; |
| 172357 | + } |
| 172358 | + assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 ); |
| 172359 | + |
| 172360 | + sqlite3_free(cons.aBuf); |
| 172361 | + if( rc!=SQLITE_OK ) break; |
| 172362 | + if( pApply->constraints.nBuf>=cons.nBuf ){ |
| 172363 | + /* No progress was made on the last round. */ |
| 172364 | + pApply->bDeferConstraints = 0; |
| 172365 | + } |
| 172366 | + } |
| 172367 | + |
| 172368 | + return rc; |
| 172369 | +} |
| 172370 | + |
| 172371 | +/* |
| 172372 | +** Argument pIter is a changeset iterator that has been initialized, but |
| 172373 | +** not yet passed to sqlite3changeset_next(). This function applies the |
| 172374 | +** changeset to the main database attached to handle "db". The supplied |
| 172375 | +** conflict handler callback is invoked to resolve any conflicts encountered |
| 172376 | +** while applying the change. |
| 172377 | +*/ |
| 172378 | +static int sessionChangesetApply( |
| 172379 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 172380 | + sqlite3_changeset_iter *pIter, /* Changeset to apply */ |
| 172381 | + int(*xFilter)( |
| 172382 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 172383 | + const char *zTab /* Table name */ |
| 172384 | + ), |
| 172385 | + int(*xConflict)( |
| 172386 | + void *pCtx, /* Copy of fifth arg to _apply() */ |
| 172387 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 172388 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 172389 | + ), |
| 172390 | + void *pCtx /* First argument passed to xConflict */ |
| 172391 | +){ |
| 172392 | + int schemaMismatch = 0; |
| 172393 | + int rc; /* Return code */ |
| 172394 | + const char *zTab = 0; /* Name of current table */ |
| 172395 | + int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ |
| 172396 | + SessionApplyCtx sApply; /* changeset_apply() context object */ |
| 172397 | + int bPatchset; |
| 172398 | + |
| 172399 | + assert( xConflict!=0 ); |
| 172400 | + |
| 172401 | + pIter->in.bNoDiscard = 1; |
| 172402 | + memset(&sApply, 0, sizeof(sApply)); |
| 172403 | + sqlite3_mutex_enter(sqlite3_db_mutex(db)); |
| 172404 | + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); |
| 172405 | + if( rc==SQLITE_OK ){ |
| 172406 | + rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); |
| 172407 | + } |
| 172408 | + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ |
| 172409 | + int nCol; |
| 172410 | + int op; |
| 172411 | + const char *zNew; |
| 172412 | + |
| 172413 | + sqlite3changeset_op(pIter, &zNew, &nCol, &op, 0); |
| 172414 | + |
| 172415 | + if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){ |
| 172416 | + u8 *abPK; |
| 172417 | + |
| 172418 | + rc = sessionRetryConstraints( |
| 172419 | + db, pIter->bPatchset, zTab, &sApply, xConflict, pCtx |
| 172420 | + ); |
| 172421 | + if( rc!=SQLITE_OK ) break; |
| 172422 | + |
| 172423 | + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ |
| 172424 | + sqlite3_finalize(sApply.pDelete); |
| 172425 | + sqlite3_finalize(sApply.pUpdate); |
| 172426 | + sqlite3_finalize(sApply.pInsert); |
| 172427 | + sqlite3_finalize(sApply.pSelect); |
| 172428 | + memset(&sApply, 0, sizeof(sApply)); |
| 172429 | + sApply.db = db; |
| 172430 | + sApply.bDeferConstraints = 1; |
| 172431 | + |
| 172432 | + /* If an xFilter() callback was specified, invoke it now. If the |
| 172433 | + ** xFilter callback returns zero, skip this table. If it returns |
| 172434 | + ** non-zero, proceed. */ |
| 172435 | + schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); |
| 172436 | + if( schemaMismatch ){ |
| 172437 | + zTab = sqlite3_mprintf("%s", zNew); |
| 172438 | + if( zTab==0 ){ |
| 172439 | + rc = SQLITE_NOMEM; |
| 172440 | + break; |
| 172441 | + } |
| 172442 | + nTab = (int)strlen(zTab); |
| 172443 | + sApply.azCol = (const char **)zTab; |
| 172444 | + }else{ |
| 172445 | + sqlite3changeset_pk(pIter, &abPK, 0); |
| 172446 | + rc = sessionTableInfo( |
| 172447 | + db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK |
| 172448 | + ); |
| 172449 | + if( rc!=SQLITE_OK ) break; |
| 172450 | + |
| 172451 | + if( sApply.nCol==0 ){ |
| 172452 | + schemaMismatch = 1; |
| 172453 | + sqlite3_log(SQLITE_SCHEMA, |
| 172454 | + "sqlite3changeset_apply(): no such table: %s", zTab |
| 172455 | + ); |
| 172456 | + } |
| 172457 | + else if( sApply.nCol!=nCol ){ |
| 172458 | + schemaMismatch = 1; |
| 172459 | + sqlite3_log(SQLITE_SCHEMA, |
| 172460 | + "sqlite3changeset_apply(): table %s has %d columns, expected %d", |
| 172461 | + zTab, sApply.nCol, nCol |
| 172462 | + ); |
| 172463 | + } |
| 172464 | + else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){ |
| 172465 | + schemaMismatch = 1; |
| 172466 | + sqlite3_log(SQLITE_SCHEMA, "sqlite3changeset_apply(): " |
| 172467 | + "primary key mismatch for table %s", zTab |
| 172468 | + ); |
| 172469 | + } |
| 172470 | + else if( |
| 172471 | + (rc = sessionSelectRow(db, zTab, &sApply)) |
| 172472 | + || (rc = sessionUpdateRow(db, zTab, &sApply)) |
| 172473 | + || (rc = sessionDeleteRow(db, zTab, &sApply)) |
| 172474 | + || (rc = sessionInsertRow(db, zTab, &sApply)) |
| 172475 | + ){ |
| 172476 | + break; |
| 172477 | + } |
| 172478 | + nTab = sqlite3Strlen30(zTab); |
| 172479 | + } |
| 172480 | + } |
| 172481 | + |
| 172482 | + /* If there is a schema mismatch on the current table, proceed to the |
| 172483 | + ** next change. A log message has already been issued. */ |
| 172484 | + if( schemaMismatch ) continue; |
| 172485 | + |
| 172486 | + rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx); |
| 172487 | + } |
| 172488 | + |
| 172489 | + bPatchset = pIter->bPatchset; |
| 172490 | + if( rc==SQLITE_OK ){ |
| 172491 | + rc = sqlite3changeset_finalize(pIter); |
| 172492 | + }else{ |
| 172493 | + sqlite3changeset_finalize(pIter); |
| 172494 | + } |
| 172495 | + |
| 172496 | + if( rc==SQLITE_OK ){ |
| 172497 | + rc = sessionRetryConstraints(db, bPatchset, zTab, &sApply, xConflict, pCtx); |
| 172498 | + } |
| 172499 | + |
| 172500 | + if( rc==SQLITE_OK ){ |
| 172501 | + int nFk, notUsed; |
| 172502 | + sqlite3_db_status(db, SQLITE_DBSTATUS_DEFERRED_FKS, &nFk, ¬Used, 0); |
| 172503 | + if( nFk!=0 ){ |
| 172504 | + int res = SQLITE_CHANGESET_ABORT; |
| 172505 | + sqlite3_changeset_iter sIter; |
| 172506 | + memset(&sIter, 0, sizeof(sIter)); |
| 172507 | + sIter.nCol = nFk; |
| 172508 | + res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter); |
| 172509 | + if( res!=SQLITE_CHANGESET_OMIT ){ |
| 172510 | + rc = SQLITE_CONSTRAINT; |
| 172511 | + } |
| 172512 | + } |
| 172513 | + } |
| 172514 | + sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); |
| 172515 | + |
| 172516 | + if( rc==SQLITE_OK ){ |
| 172517 | + rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); |
| 172518 | + }else{ |
| 172519 | + sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); |
| 172520 | + sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); |
| 172521 | + } |
| 172522 | + |
| 172523 | + sqlite3_finalize(sApply.pInsert); |
| 172524 | + sqlite3_finalize(sApply.pDelete); |
| 172525 | + sqlite3_finalize(sApply.pUpdate); |
| 172526 | + sqlite3_finalize(sApply.pSelect); |
| 172527 | + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ |
| 172528 | + sqlite3_free((char*)sApply.constraints.aBuf); |
| 172529 | + sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 172530 | + return rc; |
| 172531 | +} |
| 172532 | + |
| 172533 | +/* |
| 172534 | +** Apply the changeset passed via pChangeset/nChangeset to the main database |
| 172535 | +** attached to handle "db". Invoke the supplied conflict handler callback |
| 172536 | +** to resolve any conflicts encountered while applying the change. |
| 172537 | +*/ |
| 172538 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_apply( |
| 172539 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 172540 | + int nChangeset, /* Size of changeset in bytes */ |
| 172541 | + void *pChangeset, /* Changeset blob */ |
| 172542 | + int(*xFilter)( |
| 172543 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 172544 | + const char *zTab /* Table name */ |
| 172545 | + ), |
| 172546 | + int(*xConflict)( |
| 172547 | + void *pCtx, /* Copy of fifth arg to _apply() */ |
| 172548 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 172549 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 172550 | + ), |
| 172551 | + void *pCtx /* First argument passed to xConflict */ |
| 172552 | +){ |
| 172553 | + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ |
| 172554 | + int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); |
| 172555 | + if( rc==SQLITE_OK ){ |
| 172556 | + rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); |
| 172557 | + } |
| 172558 | + return rc; |
| 172559 | +} |
| 172560 | + |
| 172561 | +/* |
| 172562 | +** Apply the changeset passed via xInput/pIn to the main database |
| 172563 | +** attached to handle "db". Invoke the supplied conflict handler callback |
| 172564 | +** to resolve any conflicts encountered while applying the change. |
| 172565 | +*/ |
| 172566 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_apply_strm( |
| 172567 | + sqlite3 *db, /* Apply change to "main" db of this handle */ |
| 172568 | + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ |
| 172569 | + void *pIn, /* First arg for xInput */ |
| 172570 | + int(*xFilter)( |
| 172571 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 172572 | + const char *zTab /* Table name */ |
| 172573 | + ), |
| 172574 | + int(*xConflict)( |
| 172575 | + void *pCtx, /* Copy of sixth arg to _apply() */ |
| 172576 | + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ |
| 172577 | + sqlite3_changeset_iter *p /* Handle describing change and conflict */ |
| 172578 | + ), |
| 172579 | + void *pCtx /* First argument passed to xConflict */ |
| 172580 | +){ |
| 172581 | + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ |
| 172582 | + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); |
| 172583 | + if( rc==SQLITE_OK ){ |
| 172584 | + rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); |
| 172585 | + } |
| 172586 | + return rc; |
| 172587 | +} |
| 172588 | + |
| 172589 | +/* |
| 172590 | +** sqlite3_changegroup handle. |
| 172591 | +*/ |
| 172592 | +struct sqlite3_changegroup { |
| 172593 | + int rc; /* Error code */ |
| 172594 | + int bPatch; /* True to accumulate patchsets */ |
| 172595 | + SessionTable *pList; /* List of tables in current patch */ |
| 172596 | +}; |
| 172597 | + |
| 172598 | +/* |
| 172599 | +** This function is called to merge two changes to the same row together as |
| 172600 | +** part of an sqlite3changeset_concat() operation. A new change object is |
| 172601 | +** allocated and a pointer to it stored in *ppNew. |
| 172602 | +*/ |
| 172603 | +static int sessionChangeMerge( |
| 172604 | + SessionTable *pTab, /* Table structure */ |
| 172605 | + int bPatchset, /* True for patchsets */ |
| 172606 | + SessionChange *pExist, /* Existing change */ |
| 172607 | + int op2, /* Second change operation */ |
| 172608 | + int bIndirect, /* True if second change is indirect */ |
| 172609 | + u8 *aRec, /* Second change record */ |
| 172610 | + int nRec, /* Number of bytes in aRec */ |
| 172611 | + SessionChange **ppNew /* OUT: Merged change */ |
| 172612 | +){ |
| 172613 | + SessionChange *pNew = 0; |
| 172614 | + |
| 172615 | + if( !pExist ){ |
| 172616 | + pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); |
| 172617 | + if( !pNew ){ |
| 172618 | + return SQLITE_NOMEM; |
| 172619 | + } |
| 172620 | + memset(pNew, 0, sizeof(SessionChange)); |
| 172621 | + pNew->op = op2; |
| 172622 | + pNew->bIndirect = bIndirect; |
| 172623 | + pNew->nRecord = nRec; |
| 172624 | + pNew->aRecord = (u8*)&pNew[1]; |
| 172625 | + memcpy(pNew->aRecord, aRec, nRec); |
| 172626 | + }else{ |
| 172627 | + int op1 = pExist->op; |
| 172628 | + |
| 172629 | + /* |
| 172630 | + ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. |
| 172631 | + ** op1=INSERT, op2=UPDATE -> INSERT. |
| 172632 | + ** op1=INSERT, op2=DELETE -> (none) |
| 172633 | + ** |
| 172634 | + ** op1=UPDATE, op2=INSERT -> Unsupported. Discard op2. |
| 172635 | + ** op1=UPDATE, op2=UPDATE -> UPDATE. |
| 172636 | + ** op1=UPDATE, op2=DELETE -> DELETE. |
| 172637 | + ** |
| 172638 | + ** op1=DELETE, op2=INSERT -> UPDATE. |
| 172639 | + ** op1=DELETE, op2=UPDATE -> Unsupported. Discard op2. |
| 172640 | + ** op1=DELETE, op2=DELETE -> Unsupported. Discard op2. |
| 172641 | + */ |
| 172642 | + if( (op1==SQLITE_INSERT && op2==SQLITE_INSERT) |
| 172643 | + || (op1==SQLITE_UPDATE && op2==SQLITE_INSERT) |
| 172644 | + || (op1==SQLITE_DELETE && op2==SQLITE_UPDATE) |
| 172645 | + || (op1==SQLITE_DELETE && op2==SQLITE_DELETE) |
| 172646 | + ){ |
| 172647 | + pNew = pExist; |
| 172648 | + }else if( op1==SQLITE_INSERT && op2==SQLITE_DELETE ){ |
| 172649 | + sqlite3_free(pExist); |
| 172650 | + assert( pNew==0 ); |
| 172651 | + }else{ |
| 172652 | + u8 *aExist = pExist->aRecord; |
| 172653 | + int nByte; |
| 172654 | + u8 *aCsr; |
| 172655 | + |
| 172656 | + /* Allocate a new SessionChange object. Ensure that the aRecord[] |
| 172657 | + ** buffer of the new object is large enough to hold any record that |
| 172658 | + ** may be generated by combining the input records. */ |
| 172659 | + nByte = sizeof(SessionChange) + pExist->nRecord + nRec; |
| 172660 | + pNew = (SessionChange *)sqlite3_malloc(nByte); |
| 172661 | + if( !pNew ){ |
| 172662 | + sqlite3_free(pExist); |
| 172663 | + return SQLITE_NOMEM; |
| 172664 | + } |
| 172665 | + memset(pNew, 0, sizeof(SessionChange)); |
| 172666 | + pNew->bIndirect = (bIndirect && pExist->bIndirect); |
| 172667 | + aCsr = pNew->aRecord = (u8 *)&pNew[1]; |
| 172668 | + |
| 172669 | + if( op1==SQLITE_INSERT ){ /* INSERT + UPDATE */ |
| 172670 | + u8 *a1 = aRec; |
| 172671 | + assert( op2==SQLITE_UPDATE ); |
| 172672 | + pNew->op = SQLITE_INSERT; |
| 172673 | + if( bPatchset==0 ) sessionSkipRecord(&a1, pTab->nCol); |
| 172674 | + sessionMergeRecord(&aCsr, pTab->nCol, aExist, a1); |
| 172675 | + }else if( op1==SQLITE_DELETE ){ /* DELETE + INSERT */ |
| 172676 | + assert( op2==SQLITE_INSERT ); |
| 172677 | + pNew->op = SQLITE_UPDATE; |
| 172678 | + if( bPatchset ){ |
| 172679 | + memcpy(aCsr, aRec, nRec); |
| 172680 | + aCsr += nRec; |
| 172681 | + }else{ |
| 172682 | + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aExist, 0,aRec,0) ){ |
| 172683 | + sqlite3_free(pNew); |
| 172684 | + pNew = 0; |
| 172685 | + } |
| 172686 | + } |
| 172687 | + }else if( op2==SQLITE_UPDATE ){ /* UPDATE + UPDATE */ |
| 172688 | + u8 *a1 = aExist; |
| 172689 | + u8 *a2 = aRec; |
| 172690 | + assert( op1==SQLITE_UPDATE ); |
| 172691 | + if( bPatchset==0 ){ |
| 172692 | + sessionSkipRecord(&a1, pTab->nCol); |
| 172693 | + sessionSkipRecord(&a2, pTab->nCol); |
| 172694 | + } |
| 172695 | + pNew->op = SQLITE_UPDATE; |
| 172696 | + if( 0==sessionMergeUpdate(&aCsr, pTab, bPatchset, aRec, aExist,a1,a2) ){ |
| 172697 | + sqlite3_free(pNew); |
| 172698 | + pNew = 0; |
| 172699 | + } |
| 172700 | + }else{ /* UPDATE + DELETE */ |
| 172701 | + assert( op1==SQLITE_UPDATE && op2==SQLITE_DELETE ); |
| 172702 | + pNew->op = SQLITE_DELETE; |
| 172703 | + if( bPatchset ){ |
| 172704 | + memcpy(aCsr, aRec, nRec); |
| 172705 | + aCsr += nRec; |
| 172706 | + }else{ |
| 172707 | + sessionMergeRecord(&aCsr, pTab->nCol, aRec, aExist); |
| 172708 | + } |
| 172709 | + } |
| 172710 | + |
| 172711 | + if( pNew ){ |
| 172712 | + pNew->nRecord = (int)(aCsr - pNew->aRecord); |
| 172713 | + } |
| 172714 | + sqlite3_free(pExist); |
| 172715 | + } |
| 172716 | + } |
| 172717 | + |
| 172718 | + *ppNew = pNew; |
| 172719 | + return SQLITE_OK; |
| 172720 | +} |
| 172721 | + |
| 172722 | +/* |
| 172723 | +** Add all changes in the changeset traversed by the iterator passed as |
| 172724 | +** the first argument to the changegroup hash tables. |
| 172725 | +*/ |
| 172726 | +static int sessionChangesetToHash( |
| 172727 | + sqlite3_changeset_iter *pIter, /* Iterator to read from */ |
| 172728 | + sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ |
| 172729 | +){ |
| 172730 | + u8 *aRec; |
| 172731 | + int nRec; |
| 172732 | + int rc = SQLITE_OK; |
| 172733 | + SessionTable *pTab = 0; |
| 172734 | + |
| 172735 | + |
| 172736 | + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ |
| 172737 | + const char *zNew; |
| 172738 | + int nCol; |
| 172739 | + int op; |
| 172740 | + int iHash; |
| 172741 | + int bIndirect; |
| 172742 | + SessionChange *pChange; |
| 172743 | + SessionChange *pExist = 0; |
| 172744 | + SessionChange **pp; |
| 172745 | + |
| 172746 | + if( pGrp->pList==0 ){ |
| 172747 | + pGrp->bPatch = pIter->bPatchset; |
| 172748 | + }else if( pIter->bPatchset!=pGrp->bPatch ){ |
| 172749 | + rc = SQLITE_ERROR; |
| 172750 | + break; |
| 172751 | + } |
| 172752 | + |
| 172753 | + sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); |
| 172754 | + if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ |
| 172755 | + /* Search the list for a matching table */ |
| 172756 | + int nNew = (int)strlen(zNew); |
| 172757 | + u8 *abPK; |
| 172758 | + |
| 172759 | + sqlite3changeset_pk(pIter, &abPK, 0); |
| 172760 | + for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ |
| 172761 | + if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; |
| 172762 | + } |
| 172763 | + if( !pTab ){ |
| 172764 | + SessionTable **ppTab; |
| 172765 | + |
| 172766 | + pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1); |
| 172767 | + if( !pTab ){ |
| 172768 | + rc = SQLITE_NOMEM; |
| 172769 | + break; |
| 172770 | + } |
| 172771 | + memset(pTab, 0, sizeof(SessionTable)); |
| 172772 | + pTab->nCol = nCol; |
| 172773 | + pTab->abPK = (u8*)&pTab[1]; |
| 172774 | + memcpy(pTab->abPK, abPK, nCol); |
| 172775 | + pTab->zName = (char*)&pTab->abPK[nCol]; |
| 172776 | + memcpy(pTab->zName, zNew, nNew+1); |
| 172777 | + |
| 172778 | + /* The new object must be linked on to the end of the list, not |
| 172779 | + ** simply added to the start of it. This is to ensure that the |
| 172780 | + ** tables within the output of sqlite3changegroup_output() are in |
| 172781 | + ** the right order. */ |
| 172782 | + for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext); |
| 172783 | + *ppTab = pTab; |
| 172784 | + }else if( pTab->nCol!=nCol || memcmp(pTab->abPK, abPK, nCol) ){ |
| 172785 | + rc = SQLITE_SCHEMA; |
| 172786 | + break; |
| 172787 | + } |
| 172788 | + } |
| 172789 | + |
| 172790 | + if( sessionGrowHash(pIter->bPatchset, pTab) ){ |
| 172791 | + rc = SQLITE_NOMEM; |
| 172792 | + break; |
| 172793 | + } |
| 172794 | + iHash = sessionChangeHash( |
| 172795 | + pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange |
| 172796 | + ); |
| 172797 | + |
| 172798 | + /* Search for existing entry. If found, remove it from the hash table. |
| 172799 | + ** Code below may link it back in. |
| 172800 | + */ |
| 172801 | + for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ |
| 172802 | + int bPkOnly1 = 0; |
| 172803 | + int bPkOnly2 = 0; |
| 172804 | + if( pIter->bPatchset ){ |
| 172805 | + bPkOnly1 = (*pp)->op==SQLITE_DELETE; |
| 172806 | + bPkOnly2 = op==SQLITE_DELETE; |
| 172807 | + } |
| 172808 | + if( sessionChangeEqual(pTab, bPkOnly1, (*pp)->aRecord, bPkOnly2, aRec) ){ |
| 172809 | + pExist = *pp; |
| 172810 | + *pp = (*pp)->pNext; |
| 172811 | + pTab->nEntry--; |
| 172812 | + break; |
| 172813 | + } |
| 172814 | + } |
| 172815 | + |
| 172816 | + rc = sessionChangeMerge(pTab, |
| 172817 | + pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange |
| 172818 | + ); |
| 172819 | + if( rc ) break; |
| 172820 | + if( pChange ){ |
| 172821 | + pChange->pNext = pTab->apChange[iHash]; |
| 172822 | + pTab->apChange[iHash] = pChange; |
| 172823 | + pTab->nEntry++; |
| 172824 | + } |
| 172825 | + } |
| 172826 | + |
| 172827 | + if( rc==SQLITE_OK ) rc = pIter->rc; |
| 172828 | + return rc; |
| 172829 | +} |
| 172830 | + |
| 172831 | +/* |
| 172832 | +** Serialize a changeset (or patchset) based on all changesets (or patchsets) |
| 172833 | +** added to the changegroup object passed as the first argument. |
| 172834 | +** |
| 172835 | +** If xOutput is not NULL, then the changeset/patchset is returned to the |
| 172836 | +** user via one or more calls to xOutput, as with the other streaming |
| 172837 | +** interfaces. |
| 172838 | +** |
| 172839 | +** Or, if xOutput is NULL, then (*ppOut) is populated with a pointer to a |
| 172840 | +** buffer containing the output changeset before this function returns. In |
| 172841 | +** this case (*pnOut) is set to the size of the output buffer in bytes. It |
| 172842 | +** is the responsibility of the caller to free the output buffer using |
| 172843 | +** sqlite3_free() when it is no longer required. |
| 172844 | +** |
| 172845 | +** If successful, SQLITE_OK is returned. Or, if an error occurs, an SQLite |
| 172846 | +** error code. If an error occurs and xOutput is NULL, (*ppOut) and (*pnOut) |
| 172847 | +** are both set to 0 before returning. |
| 172848 | +*/ |
| 172849 | +static int sessionChangegroupOutput( |
| 172850 | + sqlite3_changegroup *pGrp, |
| 172851 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 172852 | + void *pOut, |
| 172853 | + int *pnOut, |
| 172854 | + void **ppOut |
| 172855 | +){ |
| 172856 | + int rc = SQLITE_OK; |
| 172857 | + SessionBuffer buf = {0, 0, 0}; |
| 172858 | + SessionTable *pTab; |
| 172859 | + assert( xOutput==0 || (ppOut==0 && pnOut==0) ); |
| 172860 | + |
| 172861 | + /* Create the serialized output changeset based on the contents of the |
| 172862 | + ** hash tables attached to the SessionTable objects in list p->pList. |
| 172863 | + */ |
| 172864 | + for(pTab=pGrp->pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ |
| 172865 | + int i; |
| 172866 | + if( pTab->nEntry==0 ) continue; |
| 172867 | + |
| 172868 | + sessionAppendTableHdr(&buf, pGrp->bPatch, pTab, &rc); |
| 172869 | + for(i=0; i<pTab->nChange; i++){ |
| 172870 | + SessionChange *p; |
| 172871 | + for(p=pTab->apChange[i]; p; p=p->pNext){ |
| 172872 | + sessionAppendByte(&buf, p->op, &rc); |
| 172873 | + sessionAppendByte(&buf, p->bIndirect, &rc); |
| 172874 | + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); |
| 172875 | + } |
| 172876 | + } |
| 172877 | + |
| 172878 | + if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ |
| 172879 | + rc = xOutput(pOut, buf.aBuf, buf.nBuf); |
| 172880 | + buf.nBuf = 0; |
| 172881 | + } |
| 172882 | + } |
| 172883 | + |
| 172884 | + if( rc==SQLITE_OK ){ |
| 172885 | + if( xOutput ){ |
| 172886 | + if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf); |
| 172887 | + }else{ |
| 172888 | + *ppOut = buf.aBuf; |
| 172889 | + *pnOut = buf.nBuf; |
| 172890 | + buf.aBuf = 0; |
| 172891 | + } |
| 172892 | + } |
| 172893 | + sqlite3_free(buf.aBuf); |
| 172894 | + |
| 172895 | + return rc; |
| 172896 | +} |
| 172897 | + |
| 172898 | +/* |
| 172899 | +** Allocate a new, empty, sqlite3_changegroup. |
| 172900 | +*/ |
| 172901 | +SQLITE_API int SQLITE_STDCALL sqlite3changegroup_new(sqlite3_changegroup **pp){ |
| 172902 | + int rc = SQLITE_OK; /* Return code */ |
| 172903 | + sqlite3_changegroup *p; /* New object */ |
| 172904 | + p = (sqlite3_changegroup*)sqlite3_malloc(sizeof(sqlite3_changegroup)); |
| 172905 | + if( p==0 ){ |
| 172906 | + rc = SQLITE_NOMEM; |
| 172907 | + }else{ |
| 172908 | + memset(p, 0, sizeof(sqlite3_changegroup)); |
| 172909 | + } |
| 172910 | + *pp = p; |
| 172911 | + return rc; |
| 172912 | +} |
| 172913 | + |
| 172914 | +/* |
| 172915 | +** Add the changeset currently stored in buffer pData, size nData bytes, |
| 172916 | +** to changeset-group p. |
| 172917 | +*/ |
| 172918 | +SQLITE_API int SQLITE_STDCALL sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ |
| 172919 | + sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ |
| 172920 | + int rc; /* Return code */ |
| 172921 | + |
| 172922 | + rc = sqlite3changeset_start(&pIter, nData, pData); |
| 172923 | + if( rc==SQLITE_OK ){ |
| 172924 | + rc = sessionChangesetToHash(pIter, pGrp); |
| 172925 | + } |
| 172926 | + sqlite3changeset_finalize(pIter); |
| 172927 | + return rc; |
| 172928 | +} |
| 172929 | + |
| 172930 | +/* |
| 172931 | +** Obtain a buffer containing a changeset representing the concatenation |
| 172932 | +** of all changesets added to the group so far. |
| 172933 | +*/ |
| 172934 | +SQLITE_API int SQLITE_STDCALL sqlite3changegroup_output( |
| 172935 | + sqlite3_changegroup *pGrp, |
| 172936 | + int *pnData, |
| 172937 | + void **ppData |
| 172938 | +){ |
| 172939 | + return sessionChangegroupOutput(pGrp, 0, 0, pnData, ppData); |
| 172940 | +} |
| 172941 | + |
| 172942 | +/* |
| 172943 | +** Streaming versions of changegroup_add(). |
| 172944 | +*/ |
| 172945 | +SQLITE_API int SQLITE_STDCALL sqlite3changegroup_add_strm( |
| 172946 | + sqlite3_changegroup *pGrp, |
| 172947 | + int (*xInput)(void *pIn, void *pData, int *pnData), |
| 172948 | + void *pIn |
| 172949 | +){ |
| 172950 | + sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ |
| 172951 | + int rc; /* Return code */ |
| 172952 | + |
| 172953 | + rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); |
| 172954 | + if( rc==SQLITE_OK ){ |
| 172955 | + rc = sessionChangesetToHash(pIter, pGrp); |
| 172956 | + } |
| 172957 | + sqlite3changeset_finalize(pIter); |
| 172958 | + return rc; |
| 172959 | +} |
| 172960 | + |
| 172961 | +/* |
| 172962 | +** Streaming versions of changegroup_output(). |
| 172963 | +*/ |
| 172964 | +SQLITE_API int SQLITE_STDCALL sqlite3changegroup_output_strm( |
| 172965 | + sqlite3_changegroup *pGrp, |
| 172966 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 172967 | + void *pOut |
| 172968 | +){ |
| 172969 | + return sessionChangegroupOutput(pGrp, xOutput, pOut, 0, 0); |
| 172970 | +} |
| 172971 | + |
| 172972 | +/* |
| 172973 | +** Delete a changegroup object. |
| 172974 | +*/ |
| 172975 | +SQLITE_API void SQLITE_STDCALL sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ |
| 172976 | + if( pGrp ){ |
| 172977 | + sessionDeleteTable(pGrp->pList); |
| 172978 | + sqlite3_free(pGrp); |
| 172979 | + } |
| 172980 | +} |
| 172981 | + |
| 172982 | +/* |
| 172983 | +** Combine two changesets together. |
| 172984 | +*/ |
| 172985 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_concat( |
| 172986 | + int nLeft, /* Number of bytes in lhs input */ |
| 172987 | + void *pLeft, /* Lhs input changeset */ |
| 172988 | + int nRight /* Number of bytes in rhs input */, |
| 172989 | + void *pRight, /* Rhs input changeset */ |
| 172990 | + int *pnOut, /* OUT: Number of bytes in output changeset */ |
| 172991 | + void **ppOut /* OUT: changeset (left <concat> right) */ |
| 172992 | +){ |
| 172993 | + sqlite3_changegroup *pGrp; |
| 172994 | + int rc; |
| 172995 | + |
| 172996 | + rc = sqlite3changegroup_new(&pGrp); |
| 172997 | + if( rc==SQLITE_OK ){ |
| 172998 | + rc = sqlite3changegroup_add(pGrp, nLeft, pLeft); |
| 172999 | + } |
| 173000 | + if( rc==SQLITE_OK ){ |
| 173001 | + rc = sqlite3changegroup_add(pGrp, nRight, pRight); |
| 173002 | + } |
| 173003 | + if( rc==SQLITE_OK ){ |
| 173004 | + rc = sqlite3changegroup_output(pGrp, pnOut, ppOut); |
| 173005 | + } |
| 173006 | + sqlite3changegroup_delete(pGrp); |
| 173007 | + |
| 173008 | + return rc; |
| 173009 | +} |
| 173010 | + |
| 173011 | +/* |
| 173012 | +** Streaming version of sqlite3changeset_concat(). |
| 173013 | +*/ |
| 173014 | +SQLITE_API int SQLITE_STDCALL sqlite3changeset_concat_strm( |
| 173015 | + int (*xInputA)(void *pIn, void *pData, int *pnData), |
| 173016 | + void *pInA, |
| 173017 | + int (*xInputB)(void *pIn, void *pData, int *pnData), |
| 173018 | + void *pInB, |
| 173019 | + int (*xOutput)(void *pOut, const void *pData, int nData), |
| 173020 | + void *pOut |
| 173021 | +){ |
| 173022 | + sqlite3_changegroup *pGrp; |
| 173023 | + int rc; |
| 173024 | + |
| 173025 | + rc = sqlite3changegroup_new(&pGrp); |
| 173026 | + if( rc==SQLITE_OK ){ |
| 173027 | + rc = sqlite3changegroup_add_strm(pGrp, xInputA, pInA); |
| 173028 | + } |
| 173029 | + if( rc==SQLITE_OK ){ |
| 173030 | + rc = sqlite3changegroup_add_strm(pGrp, xInputB, pInB); |
| 173031 | + } |
| 173032 | + if( rc==SQLITE_OK ){ |
| 173033 | + rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); |
| 173034 | + } |
| 173035 | + sqlite3changegroup_delete(pGrp); |
| 173036 | + |
| 173037 | + return rc; |
| 173038 | +} |
| 173039 | + |
| 173040 | +#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ |
| 173041 | + |
| 173042 | +/************** End of sqlite3session.c **************************************/ |
| 166428 | 173043 | /************** Begin file json1.c *******************************************/ |
| 166429 | 173044 | /* |
| 166430 | 173045 | ** 2015-08-12 |
| 166431 | 173046 | ** |
| 166432 | 173047 | ** The author disclaims copyright to this source code. In place of |
| | @@ -185422,11 +192037,11 @@ |
| 185422 | 192037 | int nArg, /* Number of args */ |
| 185423 | 192038 | sqlite3_value **apUnused /* Function arguments */ |
| 185424 | 192039 | ){ |
| 185425 | 192040 | assert( nArg==0 ); |
| 185426 | 192041 | UNUSED_PARAM2(nArg, apUnused); |
| 185427 | | - sqlite3_result_text(pCtx, "fts5: 2016-03-29 10:14:15 e9bb4cf40f4971974a74468ef922bdee481c988b", -1, SQLITE_TRANSIENT); |
| 192042 | + sqlite3_result_text(pCtx, "fts5: 2016-03-30 16:23:06 7cf0cab730e2d570c82dd789279ad6501ac598c8", -1, SQLITE_TRANSIENT); |
| 185428 | 192043 | } |
| 185429 | 192044 | |
| 185430 | 192045 | static int fts5Init(sqlite3 *db){ |
| 185431 | 192046 | static const sqlite3_module fts5Mod = { |
| 185432 | 192047 | /* iVersion */ 2, |
| 185433 | 192048 | |