diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:28:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:28:19 +0000 |
commit | 18657a960e125336f704ea058e25c27bd3900dcb (patch) | |
tree | 17b438b680ed45a996d7b59951e6aa34023783f2 /www/session/sqlite3changeset_apply.html | |
parent | Initial commit. (diff) | |
download | sqlite3-18657a960e125336f704ea058e25c27bd3900dcb.tar.xz sqlite3-18657a960e125336f704ea058e25c27bd3900dcb.zip |
Adding upstream version 3.40.1.upstream/3.40.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'www/session/sqlite3changeset_apply.html')
-rw-r--r-- | www/session/sqlite3changeset_apply.html | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/www/session/sqlite3changeset_apply.html b/www/session/sqlite3changeset_apply.html new file mode 100644 index 0000000..ca95e9d --- /dev/null +++ b/www/session/sqlite3changeset_apply.html @@ -0,0 +1,309 @@ +<!DOCTYPE html> +<html><head> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<link href="../sqlite.css" rel="stylesheet"> +<title>Apply A Changeset To A Database</title> +<!-- path=../ --> +</head> +<body> +<div class=nosearch> +<a href="../index.html"> +<img class="logo" src="../images/sqlite370_banner.gif" alt="SQLite" border="0"> +</a> +<div><!-- IE hack to prevent disappearing logo --></div> +<div class="tagline desktoponly"> +Small. Fast. Reliable.<br>Choose any three. +</div> +<div class="menu mainmenu"> +<ul> +<li><a href="../index.html">Home</a> +<li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a> +<li class='wideonly'><a href='../about.html'>About</a> +<li class='desktoponly'><a href="../docs.html">Documentation</a> +<li class='desktoponly'><a href="../download.html">Download</a> +<li class='wideonly'><a href='../copyright.html'>License</a> +<li class='desktoponly'><a href="../support.html">Support</a> +<li class='desktoponly'><a href="../prosupport.html">Purchase</a> +<li class='search' id='search_menubutton'> +<a href="javascript:void(0)" onclick='toggle_search()'>Search</a> +</ul> +</div> +<div class="menu submenu" id="submenu"> +<ul> +<li><a href='../about.html'>About</a> +<li><a href='../docs.html'>Documentation</a> +<li><a href='../download.html'>Download</a> +<li><a href='../support.html'>Support</a> +<li><a href='../prosupport.html'>Purchase</a> +</ul> +</div> +<div class="searchmenu" id="searchmenu"> +<form method="GET" action="../search"> +<select name="s" id="searchtype"> +<option value="d">Search Documentation</option> +<option value="c">Search Changelog</option> +</select> +<input type="text" name="q" id="searchbox" value=""> +<input type="submit" value="Go"> +</form> +</div> +</div> +<script> +function toggle_div(nm) { +var w = document.getElementById(nm); +if( w.style.display=="block" ){ +w.style.display = "none"; +}else{ +w.style.display = "block"; +} +} +function toggle_search() { +var w = document.getElementById("searchmenu"); +if( w.style.display=="block" ){ +w.style.display = "none"; +} else { +w.style.display = "block"; +setTimeout(function(){ +document.getElementById("searchbox").focus() +}, 30); +} +} +function div_off(nm){document.getElementById(nm).style.display="none";} +window.onbeforeunload = function(e){div_off("submenu");} +/* Disable the Search feature if we are not operating from CGI, since */ +/* Search is accomplished using CGI and will not work without it. */ +if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){ +document.getElementById("search_menubutton").style.display = "none"; +} +/* Used by the Hide/Show button beside syntax diagrams, to toggle the */ +function hideorshow(btn,obj){ +var x = document.getElementById(obj); +var b = document.getElementById(btn); +if( x.style.display!='none' ){ +x.style.display = 'none'; +b.innerHTML='show'; +}else{ +x.style.display = ''; +b.innerHTML='hide'; +} +return false; +} +var antiRobot = 0; +function antiRobotGo(){ +if( antiRobot!=3 ) return; +antiRobot = 7; +var j = document.getElementById("mtimelink"); +if(j && j.hasAttribute("data-href")) j.href=j.getAttribute("data-href"); +} +function antiRobotDefense(){ +document.body.onmousedown=function(){ +antiRobot |= 2; +antiRobotGo(); +document.body.onmousedown=null; +} +document.body.onmousemove=function(){ +antiRobot |= 2; +antiRobotGo(); +document.body.onmousemove=null; +} +setTimeout(function(){ +antiRobot |= 1; +antiRobotGo(); +}, 100) +antiRobotGo(); +} +antiRobotDefense(); +</script> +<a href="intro.html"><h2>Session Module C Interface</h2></a><h2>Apply A Changeset To A Database</h2><blockquote><pre>int sqlite3changeset_apply( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); +int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ +); +</pre></blockquote><p> +Apply a changeset or patchset to a database. These functions attempt to +update the "main" database attached to handle db with the changes found in +the changeset passed via the second and third arguments. </p> + +<p>The fourth argument (xFilter) passed to these functions is the "filter +callback". If it is not NULL, then for each table affected by at least one +change in the changeset, the filter callback is invoked with +the table name as the second argument, and a copy of the context pointer +passed as the sixth argument as the first. If the "filter callback" +returns zero, then no attempt is made to apply any changes to the table. +Otherwise, if the return value is non-zero or the xFilter argument to +is NULL, all changes related to the table are attempted.</p> + +<p>For each table that is not excluded by the filter callback, this function +tests that the target database contains a compatible table. A table is +considered compatible if all of the following are true:</p> + +<p><ul> + <li> The table has the same name as the name recorded in the + changeset, and + <li> The table has at least as many columns as recorded in the + changeset, and + <li> The table has primary key columns in the same position as + recorded in the changeset. +</ul></p> + +<p>If there is no compatible table, it is not an error, but none of the +changes associated with the table are applied. A warning message is issued +via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most +one such warning is issued for each table in the changeset.</p> + +<p>For each change for which there is a compatible table, an attempt is made +to modify the table contents according to the UPDATE, INSERT or DELETE +change. If a change cannot be applied cleanly, the conflict handler +function passed as the fifth argument to sqlite3changeset_apply() may be +invoked. A description of exactly when the conflict handler is invoked for +each type of change is below.</p> + +<p>Unlike the xFilter argument, xConflict may not be passed NULL. The results +of passing anything other than a valid function pointer as the xConflict +argument are undefined.</p> + +<p>Each time the conflict handler function is invoked, it must return one +of <a href="../session/c_changeset_abort.html">SQLITE_CHANGESET_OMIT</a>, <a href="../session/c_changeset_abort.html">SQLITE_CHANGESET_ABORT</a> or +<a href="../session/c_changeset_abort.html">SQLITE_CHANGESET_REPLACE</a>. SQLITE_CHANGESET_REPLACE may only be returned +if the second argument passed to the conflict handler is either +SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler +returns an illegal value, any changes already made are rolled back and +the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +actions are taken by sqlite3changeset_apply() depending on the value +returned by each invocation of the conflict-handler function. Refer to +the documentation for the three +<a href="../session/c_changeset_abort.html">available return values</a> for details.</p> + +<p><dl> +<dt>DELETE Changes<dd> + For each DELETE change, the function checks if the target database + contains a row with the same primary key value (or values) as the + original row values stored in the changeset. If it does, and the values + stored in all non-primary key columns also match the values stored in + the changeset the row is deleted from the target database.</p> + +<p> If a row with matching primary key values is found, but one or more of + the non-primary key fields contains a value different from the original + row value stored in the changeset, the conflict-handler function is + invoked with <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_DATA</a> as the second argument. If the + database table has more columns than are recorded in the changeset, + only the values of those non-primary key fields are compared against + the current database contents - any trailing database table columns + are ignored.</p> + +<p> If no row with matching primary key values is found in the database, + the conflict-handler function is invoked with <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_NOTFOUND</a> + passed as the second argument.</p> + +<p> If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT + (which can only happen if a foreign key constraint is violated), the + conflict-handler function is invoked with <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_CONSTRAINT</a> + passed as the second argument. This includes the case where the DELETE + operation is attempted because an earlier call to the conflict handler + function returned <a href="../session/c_changeset_abort.html">SQLITE_CHANGESET_REPLACE</a>.</p> + +<p><dt>INSERT Changes<dd> + For each INSERT change, an attempt is made to insert the new row into + the database. If the changeset row contains fewer fields than the + database table, the trailing fields are populated with their default + values.</p> + +<p> If the attempt to insert the row fails because the database already + contains a row with the same primary key values, the conflict handler + function is invoked with the second argument set to + <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_CONFLICT</a>.</p> + +<p> If the attempt to insert the row fails because of some other constraint + violation (e.g. NOT NULL or UNIQUE), the conflict handler function is + invoked with the second argument set to <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_CONSTRAINT</a>. + This includes the case where the INSERT operation is re-attempted because + an earlier call to the conflict handler function returned + <a href="../session/c_changeset_abort.html">SQLITE_CHANGESET_REPLACE</a>.</p> + +<p><dt>UPDATE Changes<dd> + For each UPDATE change, the function checks if the target database + contains a row with the same primary key value (or values) as the + original row values stored in the changeset. If it does, and the values + stored in all modified non-primary key columns also match the values + stored in the changeset the row is updated within the target database.</p> + +<p> If a row with matching primary key values is found, but one or more of + the modified non-primary key fields contains a value different from an + original row value stored in the changeset, the conflict-handler function + is invoked with <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_DATA</a> as the second argument. Since + UPDATE changes only contain values for non-primary key fields that are + to be modified, only those fields need to match the original values to + avoid the SQLITE_CHANGESET_DATA conflict-handler callback.</p> + +<p> If no row with matching primary key values is found in the database, + the conflict-handler function is invoked with <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_NOTFOUND</a> + passed as the second argument.</p> + +<p> If the UPDATE operation is attempted, but SQLite returns + SQLITE_CONSTRAINT, the conflict-handler function is invoked with + <a href="../session/c_changeset_conflict.html">SQLITE_CHANGESET_CONSTRAINT</a> passed as the second argument. + This includes the case where the UPDATE operation is attempted after + an earlier call to the conflict handler function returned + <a href="../session/c_changeset_abort.html">SQLITE_CHANGESET_REPLACE</a>. +</dl></p> + +<p>It is safe to execute SQL statements, including those that write to the +table that the callback related to, from within the xConflict callback. +This can be used to further customize the application's conflict +resolution strategy.</p> + +<p>All changes made by these functions are enclosed in a savepoint transaction. +If any other error (aside from a constraint failure when attempting to +write to the target database) occurs, then the savepoint transaction is +rolled back, restoring the target database to its original state, and an +SQLite error code returned.</p> + +<p>If the output parameters (ppRebase) and (pnRebase) are non-NULL and +the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() +may set (*ppRebase) to point to a "rebase" that may be used with the +sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) +is set to the size of the buffer in bytes. It is the responsibility of the +caller to eventually free any such buffer using sqlite3_free(). The buffer +is only allocated and populated if one or more conflicts were encountered +while applying the patchset. See comments surrounding the sqlite3_rebaser +APIs for further details.</p> + +<p>The behavior of sqlite3changeset_apply_v2() and its streaming equivalent +may be modified by passing a combination of +<a href="../session/c_changesetapply_invert.html">supported flags</a> as the 9th parameter.</p> + +<p>Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b> +and therefore subject to change. +</p><p>See also lists of + <a href="objlist.html">Objects</a>, + <a href="constlist.html">Constants</a>, and + <a href="funclist.html">Functions</a>.</p> + |