Documentation Source Text

Check-in [326066ebea]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change the name of OTA to RBU.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 326066ebeac4148aa306b3281eeb7b7931572599
User & Date: drh 2015-07-23 20:49:21
Context
2015-07-23
20:50
More OTA to RBU changes that were missed by the previous check-in. check-in: 97e489408d user: drh tags: trunk
20:49
Change the name of OTA to RBU. check-in: 326066ebea user: drh tags: trunk
2015-07-16
03:22
Add Sibsankar's second book to the books.html page. check-in: cf7fe0f52c user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to pages/changes.in.

15
16
17
18
19
20
21
22

23
24

25
26
27
28
29
30
31
proc chng {date desc {options {}}} {
  global nChng aChng
  set aChng($nChng) [list $date $desc $options]
  incr nChng
}

chng {2015-07-31 (3.8.11)} {
<li>Added the [OTA] extension.

<li>Added the experimental [FTS5] extension.  Note that this extension is experimental
    and so the file format may yet change.

<li>Added the [sqlite3_value_dup()] and [sqlite3_value_free()] interfaces.
<li>Enhance the [spellfix1] extension to support [ON CONFLICT] clauses.
<li>The [IS operator] is now able to drive indexes.
<li>Enhance the query planner to permit [automatic indexing] on FROM-clause
    subqueries that are implemented by co-routine.
<li>Disallow the use of "rowid" in [common table expressions].
<li>Added the [PRAGMA cell_size_check] command for better and earlier







|
>

<
>







15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
proc chng {date desc {options {}}} {
  global nChng aChng
  set aChng($nChng) [list $date $desc $options]
  incr nChng
}

chng {2015-07-31 (3.8.11)} {
<li>Added the experimental [RBU] extension.  Note that this extension is experimental
    and subject to change in incompatible ways.
<li>Added the experimental [FTS5] extension.  Note that this extension is experimental

    and subject to change in incompatible ways.
<li>Added the [sqlite3_value_dup()] and [sqlite3_value_free()] interfaces.
<li>Enhance the [spellfix1] extension to support [ON CONFLICT] clauses.
<li>The [IS operator] is now able to drive indexes.
<li>Enhance the query planner to permit [automatic indexing] on FROM-clause
    subqueries that are implemented by co-routine.
<li>Disallow the use of "rowid" in [common table expressions].
<li>Added the [PRAGMA cell_size_check] command for better and earlier

Name change from pages/ota.in to pages/rbu.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
<title>The OTA Extension</title>
<tcl>
hd_keywords {OTA} {OTA extension}
proc CODE {text} {
  hd_puts "<blockquote><pre>"
  hd_puts $text
  hd_puts "</pre></blockquote>"
}
</tcl>
<h1 align='center'>The OTA Extension</h1>

<p>The OTA extension is an add-on for SQLite that facilitates 
rapid bulk updates of large SQLite database files on low-power
devices at the edge of a network.

<p>The OTA name stands for "Over-the-Air" since its original use-case
was updating maps in low-power navigation devices via
wireless.  However, the name is overly specific, since the changes
can be sent to the edge device by any available channel.

<p>Updating an SQLite database file on a remote device can normally
be accomplished simply by sending the text of various [INSERT], [DELETE],
and [UPDATE] commands to the device and evaluating them all inside of
a transaction.  OTA provides some advantages over this simple approach:

<ol>
<li><b>OTA runs faster</b>

<p>The most efficient way to apply changes to a B-Tree is to make
the changes in row order.  But if an SQL table has indexes, the row
order for the indexes will all be different from each other and from
the row order of the original table.  OTA works around this by applying
all changes to the table in one pass, then
applying changes to each index in separate passes, thus updating each
B-Trees in its optimal sequence.  For a large database file (one that
does not fit in the OS disk cache) this procedure can result in
two orders of magnitude faster updates.

<li><b>OTA runs in the background</b>

<p>The changes can be applied to the database file by a background
process that does not interfere with read access to the database
file.

<li><b>OTA runs incrementally</b>

<p>The changes can be applied to the database incrementally, with
intervening power outages and/or system resets.  And yet the original
unmodified data remains visible to the device until the moment that
entire change set commits.  
</ol>

<h2>Limitations</h2>

<p>The following limitations apply to OTA updates:

<ul>
<li><p>The changes must consist of [INSERT], [UPDATE], and [DELETE]
    operations only.  CREATE and DROP operations are not
    supported.</p></li>
<li><p>[INSERT] statements may not use default values.</p></li>
<li><p>[UPDATE] and [DELETE] statements must identify the target rows
    by rowid or by non-NULL PRIMARY KEY values.</p></li>
<li><p>[UPDATE] statements may not modify PRIMARY KEY or rowid values.
    </p></li>
<li><p>OTA updates cannot be applied to any tables that contain a column
       named "ota_control".</p></li>
<li><p>The OTA update will not fire any triggers.</p></li>
<li><p>The OTA update will not detect or prevent foreign key or
       CHECK constraint violations.</p></li>
<li><p>All OTA updates us the "OR ROLLBACK" constraint handling mechanism.
    </p></li>
<li><p>The target database may not be in [WAL mode].</p></li>
<li><p>No other writes may occur on the target database while the
       OTA update is being applied.  A read-lock is held on the target
       database to prevent this.</p></li>
</ul>


<h2>Preparing An OTA Update File</h2>

<p>All changes to be applied by OTA are stored in a separate SQLite database
called the "OTA database".  The database that is to be modified is called
the "target database".

<p>
For each table in the target database, the OTA database should contain a table
named "data_&lt;<i>target-table-name</i>&gt;" with 
the all the same columns as the
target table, plus one additional column named "ota_control".
The data_% table should have no PRIMARY KEY or UNIQUE constraints, but
each column should have the same type as the corresponding column in
the target database.
The ota_control column should have no type at all. For example, if
the target database contains:

<tcl>CODE {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
}</tcl>

<p>Then the OTA database should contain:

<tcl>CODE {
CREATE TABLE data_t1(a INTEGER, b TEXT, c, ota_control);
}</tcl>

<p>The order of the columns in the data_% table does not matter.

<p>If the target database table is a virtual table or a table that has no
PRIMARY KEY declaration, the data_% table must also contain a column 
named "ota_rowid". The ota_rowid column is mapped to the tables [ROWID].
For example, if the target database contains either of the following:

<tcl>CODE {
CREATE VIRTUAL TABLE x1 USING fts3(a, b);
CREATE TABLE x1(a, b);
}</tcl>

<p>then the OTA database should contain:

<tcl>CODE {
CREATE TABLE data_x1(a, b, ota_rowid, ota_control);
}</tcl>

<p>Virtual tables for which the "rowid" column does 
not function like a primary key value cannot be updated using OTA.

<p>
All non-hidden columns (i.e. all columns matched by "SELECT *") of the
target table must be present in the input table. For virtual tables,
hidden columns are optional - they are updated by OTA if present in
the input table, or not otherwise. For example, to write to an fts4
table with a hidden languageid column such as:

<tcl>CODE {
CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid');
}</tcl>

<p>Either of the following input table schemas may be used:

<tcl>CODE {
CREATE TABLE data_ft1(a, b, langid, ota_rowid, ota_control);
CREATE TABLE data_ft1(a, b, ota_rowid, ota_control);
}</tcl>

<p>For each row to INSERT into the target database as part of the OTA 
update, the corresponding data_% table should contain a single record
with the "ota_control" column set to contain integer value 0. The
other columns should be set to the values that make up the new record 
to insert. 

<p>If the target database table has an INTEGER PRIMARY KEY, it is not 
possible to insert a NULL value into the IPK column. Attempting to 
do so results in an SQLITE_MISMATCH error.

<p>For each row to DELETE from the target database as part of the OTA 
update, the corresponding data_% table should contain a single record
with the "ota_control" column set to contain integer value 1. The
real primary key values of the row to delete should be stored in the
corresponding columns of the data_% table. The values stored in the
other columns are not used.

<p>For each row to UPDATE from the target database as part of the OTA 
update, the corresponding data_% table should contain a single record
with the "ota_control" column set to contain a value of type text.
The real primary key values identifying the row to update should be 
stored in the corresponding columns of the data_% table row, as should
the new values of all columns being update. The text value in the 
"ota_control" column must contain the same number of characters as
there are columns in the target database table, and must consist entirely
of 'x' and '.' characters (or in some special cases 'd' - see below). For 
each column that is being updated, the corresponding character is set to
'x'. For those that remain as they are, the corresponding character of the
ota_control value should be set to '.'. For example, given the tables 
above, the update statement:

<tcl>CODE {
UPDATE t1 SET c = 'usa' WHERE a = 4;
}</tcl>

<p>is represented by the data_t1 row created by:

<tcl>CODE {
INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..x');
}</tcl>

<p>Instead of an 'x' character, characters of the ota_control value specified
for UPDATEs may also be set to 'd'. In this case, instead of updating the
target table with the value stored in the corresponding data_% column, the
user-defined SQL function "ota_delta()" is invoked and the result stored in
the target table column. ota_delta() is invoked with two arguments - the
original value currently stored in the target table column and the 
value specified in the data_xxx table.

<p>For example, this row:

<tcl>CODE {
INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..d');
}</tcl>


<p>is similar to an UPDATE statement such as: 

<tcl>CODE {
UPDATE t1 SET c = ota_delta(c, 'usa') WHERE a = 4;
}</tcl>

<p>If the target database table is a virtual table or a table with no PRIMARY
KEY, the ota_control value should not include a character corresponding 
to the ota_rowid value. For example, this:

<tcl>CODE {
INSERT INTO data_ft1(a, b, ota_rowid, ota_control) 
  VALUES(NULL, 'usa', 12, '.x');
}</tcl>


<p>causes a result similar to:

<tcl>CODE {
UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
}</tcl>

<p>The data_xxx tables themselves should have no PRIMARY KEY declarations.
However, OTA is more efficient if reading the rows in from each data_xxx
table in "rowid" order is roughly the same as reading them sorted by
the PRIMARY KEY of the corresponding target database table. In other 
words, rows should be sorted using the destination table PRIMARY KEY 
fields before they are inserted into the data_xxx tables.

<h2>C/C++ Interface</h2>

<p>Enable the OTA extension by compiling the [amalgamation] with the
[SQLITE_ENABLE_OTA] compile-time option.

<p>The OTA extension interface allows an application to apply an OTA update 
stored in an OTA database to an existing target database.
The procedures is as follows:

<ol>
<li><p>
Open an OTA handle using the sqlite3ota_open(T,A,S) function.

<p>The T argument is the name of the target database file.
The A argument is the name of the OTA database file.
The S argument is the name of a "state database" used to store
state information needed to resume the update after an interruption.
The S argument can be NULL in which case the state information
is stored in the OTA database in various tables whose names all
begin with "ota_".

<p>The sqlite3ota_open(T,A,S) function returns a pointer to
an "sqlite3ota" object, which is then passed into the subsequent
interfaces.


<li><p>
Register any required virtual table modules with the database
handle returned by sqlite3ota_db(X) (where argument X is the sqlite3ota
pointer returned from sqlite3ota_open()).  Also, if required, register
the ota_delta() SQL function using 
[sqlite3_create_function_v2()].

<li><p>
Invoke the sqlite3ota_step(X) function one or more times on
the sqlite3ota object pointer X. Each call to sqlite3ota_step() 
performs a single b-tree operation, so thousands of calls may be 
required to apply a complete update.  The sqlite3ota_step() 
interface will return SQLITE_DONE when the update has been
completely applied.

<li><p>
Call sqlite3ota_close(X) to destroy the sqlite3ota object pointer.
If sqlite3ota_step(X) has been called enough times to completely
apply the update to the target database, then the OTA database
is marked as fully applied. Otherwise, the state of the OTA 
update application is saved in the state database (or in the OTA
database if the name of the state database file in sqlite3ota_open()
is NULL) for later resumption of the update.
</ol>

<p>If an update is only partially applied to the target database by the
time sqlite3ota_close() is called, state information is saved 
within the state database if it exists, or otherwise in the OTA database. 
This allows subsequent processes to automatically
resume the OTA update from where it left off.
If state information is stored in the OTA database, it can be removed
by dropping all tables whose names begin with "ota_".
|

|






|

|
|
|

|
<
<
<




|


|




|






|





|









|










|
|
|
|

|



|




|

|
|



|


|



|






|


|






|







|


|



|




|










|
|


|

|







|

|




|

|



|




|









|


|


|
|






|






|



|
|


|











|







|
|

|
|




|


|



|
|

|
|





|
|
|



|
|

|




|
|
|
|
|
|




|
|

|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
<title>The RBU Extension</title>
<tcl>
hd_keywords {RBU} {RBU extension}
proc CODE {text} {
  hd_puts "<blockquote><pre>"
  hd_puts $text
  hd_puts "</pre></blockquote>"
}
</tcl>
<h1 align='center'>The RBU Extension</h1>

<p>The RBU extension is an add-on for SQLite that facilitates 
rapid incremental updates of large SQLite database files 
on low-power devices at the edge of a network.

<p>The RBU name stands for "Resumable Bulk Update".




<p>Updating an SQLite database file on a remote device can normally
be accomplished simply by sending the text of various [INSERT], [DELETE],
and [UPDATE] commands to the device and evaluating them all inside of
a transaction.  RBU provides some advantages over this simple approach:

<ol>
<li><b>RBU runs faster</b>

<p>The most efficient way to apply changes to a B-Tree is to make
the changes in row order.  But if an SQL table has indexes, the row
order for the indexes will all be different from each other and from
the row order of the original table.  RBU works around this by applying
all changes to the table in one pass, then
applying changes to each index in separate passes, thus updating each
B-Trees in its optimal sequence.  For a large database file (one that
does not fit in the OS disk cache) this procedure can result in
two orders of magnitude faster updates.

<li><b>RBU runs in the background</b>

<p>The changes can be applied to the database file by a background
process that does not interfere with read access to the database
file.

<li><b>RBU runs incrementally</b>

<p>The changes can be applied to the database incrementally, with
intervening power outages and/or system resets.  And yet the original
unmodified data remains visible to the device until the moment that
entire change set commits.  
</ol>

<h2>Limitations</h2>

<p>The following limitations apply to RBU updates:

<ul>
<li><p>The changes must consist of [INSERT], [UPDATE], and [DELETE]
    operations only.  CREATE and DROP operations are not
    supported.</p></li>
<li><p>[INSERT] statements may not use default values.</p></li>
<li><p>[UPDATE] and [DELETE] statements must identify the target rows
    by rowid or by non-NULL PRIMARY KEY values.</p></li>
<li><p>[UPDATE] statements may not modify PRIMARY KEY or rowid values.
    </p></li>
<li><p>RBU updates cannot be applied to any tables that contain a column
       named "rbu_control".</p></li>
<li><p>The RBU update will not fire any triggers.</p></li>
<li><p>The RBU update will not detect or prevent foreign key or
       CHECK constraint violations.</p></li>
<li><p>All RBU updates us the "OR ROLLBACK" constraint handling mechanism.
    </p></li>
<li><p>The target database may not be in [WAL mode].</p></li>
<li><p>No other writes may occur on the target database while the
       RBU update is being applied.  A read-lock is held on the target
       database to prevent this.</p></li>
</ul>


<h2>Preparing An RBU Update File</h2>

<p>All changes to be applied by RBU are stored in a separate SQLite database
called the "RBU database".  The database that is to be modified is called
the "target database".

<p>
For each table in the target database, the RBU database should contain a table
named "data_&lt;<i>target-table-name</i>&gt;" with 
the all the same columns as the
target table, plus one additional column named "rbu_control".
The data_% table should have no PRIMARY KEY or UNIQUE constraints, but
each column should have the same type as the corresponding column in
the target database.
The rbu_control column should have no type at all. For example, if
the target database contains:

<tcl>CODE {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE);
}</tcl>

<p>Then the RBU database should contain:

<tcl>CODE {
CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control);
}</tcl>

<p>The order of the columns in the data_% table does not matter.

<p>If the target database table is a virtual table or a table that has no
PRIMARY KEY declaration, the data_% table must also contain a column 
named "rbu_rowid". The rbu_rowid column is mapped to the tables [ROWID].
For example, if the target database contains either of the following:

<tcl>CODE {
CREATE VIRTUAL TABLE x1 USING fts3(a, b);
CREATE TABLE x1(a, b);
}</tcl>

<p>then the RBU database should contain:

<tcl>CODE {
CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control);
}</tcl>

<p>Virtual tables for which the "rowid" column does 
not function like a primary key value cannot be updated using RBU.

<p>
All non-hidden columns (i.e. all columns matched by "SELECT *") of the
target table must be present in the input table. For virtual tables,
hidden columns are optional - they are updated by RBU if present in
the input table, or not otherwise. For example, to write to an fts4
table with a hidden languageid column such as:

<tcl>CODE {
CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid');
}</tcl>

<p>Either of the following input table schemas may be used:

<tcl>CODE {
CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control);
CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control);
}</tcl>

<p>For each row to INSERT into the target database as part of the RBU 
update, the corresponding data_% table should contain a single record
with the "rbu_control" column set to contain integer value 0. The
other columns should be set to the values that make up the new record 
to insert. 

<p>If the target database table has an INTEGER PRIMARY KEY, it is not 
possible to insert a NULL value into the IPK column. Attempting to 
do so results in an SQLITE_MISMATCH error.

<p>For each row to DELETE from the target database as part of the RBU 
update, the corresponding data_% table should contain a single record
with the "rbu_control" column set to contain integer value 1. The
real primary key values of the row to delete should be stored in the
corresponding columns of the data_% table. The values stored in the
other columns are not used.

<p>For each row to UPDATE from the target database as part of the RBU 
update, the corresponding data_% table should contain a single record
with the "rbu_control" column set to contain a value of type text.
The real primary key values identifying the row to update should be 
stored in the corresponding columns of the data_% table row, as should
the new values of all columns being update. The text value in the 
"rbu_control" column must contain the same number of characters as
there are columns in the target database table, and must consist entirely
of 'x' and '.' characters (or in some special cases 'd' - see below). For 
each column that is being updated, the corresponding character is set to
'x'. For those that remain as they are, the corresponding character of the
rbu_control value should be set to '.'. For example, given the tables 
above, the update statement:

<tcl>CODE {
UPDATE t1 SET c = 'usa' WHERE a = 4;
}</tcl>

<p>is represented by the data_t1 row created by:

<tcl>CODE {
INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x');
}</tcl>

<p>Instead of an 'x' character, characters of the rbu_control value specified
for UPDATEs may also be set to 'd'. In this case, instead of updating the
target table with the value stored in the corresponding data_% column, the
user-defined SQL function "rbu_delta()" is invoked and the result stored in
the target table column. rbu_delta() is invoked with two arguments - the
original value currently stored in the target table column and the 
value specified in the data_xxx table.

<p>For example, this row:

<tcl>CODE {
INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d');
}</tcl>


<p>is similar to an UPDATE statement such as: 

<tcl>CODE {
UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4;
}</tcl>

<p>If the target database table is a virtual table or a table with no PRIMARY
KEY, the rbu_control value should not include a character corresponding 
to the rbu_rowid value. For example, this:

<tcl>CODE {
INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) 
  VALUES(NULL, 'usa', 12, '.x');
}</tcl>


<p>causes a result similar to:

<tcl>CODE {
UPDATE ft1 SET b = 'usa' WHERE rowid = 12;
}</tcl>

<p>The data_xxx tables themselves should have no PRIMARY KEY declarations.
However, RBU is more efficient if reading the rows in from each data_xxx
table in "rowid" order is roughly the same as reading them sorted by
the PRIMARY KEY of the corresponding target database table. In other 
words, rows should be sorted using the destination table PRIMARY KEY 
fields before they are inserted into the data_xxx tables.

<h2>C/C++ Interface</h2>

<p>Enable the RBU extension by compiling the [amalgamation] with the
[SQLITE_ENABLE_RBU] compile-time option.

<p>The RBU extension interface allows an application to apply an RBU update 
stored in an RBU database to an existing target database.
The procedures is as follows:

<ol>
<li><p>
Open an RBU handle using the sqlite3rbu_open(T,A,S) function.

<p>The T argument is the name of the target database file.
The A argument is the name of the RBU database file.
The S argument is the name of a "state database" used to store
state information needed to resume the update after an interruption.
The S argument can be NULL in which case the state information
is stored in the RBU database in various tables whose names all
begin with "rbu_".

<p>The sqlite3rbu_open(T,A,S) function returns a pointer to
an "sqlite3rbu" object, which is then passed into the subsequent
interfaces.


<li><p>
Register any required virtual table modules with the database
handle returned by sqlite3rbu_db(X) (where argument X is the sqlite3rbu
pointer returned from sqlite3rbu_open()).  Also, if required, register
the rbu_delta() SQL function using 
[sqlite3_create_function_v2()].

<li><p>
Invoke the sqlite3rbu_step(X) function one or more times on
the sqlite3rbu object pointer X. Each call to sqlite3rbu_step() 
performs a single b-tree operation, so thousands of calls may be 
required to apply a complete update.  The sqlite3rbu_step() 
interface will return SQLITE_DONE when the update has been
completely applied.

<li><p>
Call sqlite3rbu_close(X) to destroy the sqlite3rbu object pointer.
If sqlite3rbu_step(X) has been called enough times to completely
apply the update to the target database, then the RBU database
is marked as fully applied. Otherwise, the state of the RBU 
update application is saved in the state database (or in the RBU
database if the name of the state database file in sqlite3rbu_open()
is NULL) for later resumption of the update.
</ol>

<p>If an update is only partially applied to the target database by the
time sqlite3rbu_close() is called, state information is saved 
within the state database if it exists, or otherwise in the RBU database. 
This allows subsequent processes to automatically
resume the RBU update from where it left off.
If state information is stored in the RBU database, it can be removed
by dropping all tables whose names begin with "rbu_".