OLD | NEW |
1 /* | 1 /* |
2 ** 2014 August 30 | 2 ** 2014 August 30 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 ** middle of an incremental checkpoint (an incremental checkpoint cannot | 140 ** middle of an incremental checkpoint (an incremental checkpoint cannot |
141 ** be continued if this happens). | 141 ** be continued if this happens). |
142 ** | 142 ** |
143 ** RBU_STATE_COOKIE: | 143 ** RBU_STATE_COOKIE: |
144 ** Valid if STAGE==1. The current change-counter cookie value in the | 144 ** Valid if STAGE==1. The current change-counter cookie value in the |
145 ** target db file. | 145 ** target db file. |
146 ** | 146 ** |
147 ** RBU_STATE_OALSZ: | 147 ** RBU_STATE_OALSZ: |
148 ** Valid if STAGE==1. The size in bytes of the *-oal file. | 148 ** Valid if STAGE==1. The size in bytes of the *-oal file. |
149 */ | 149 */ |
150 #define RBU_STATE_STAGE 1 | 150 #define RBU_STATE_STAGE 1 |
151 #define RBU_STATE_TBL 2 | 151 #define RBU_STATE_TBL 2 |
152 #define RBU_STATE_IDX 3 | 152 #define RBU_STATE_IDX 3 |
153 #define RBU_STATE_ROW 4 | 153 #define RBU_STATE_ROW 4 |
154 #define RBU_STATE_PROGRESS 5 | 154 #define RBU_STATE_PROGRESS 5 |
155 #define RBU_STATE_CKPT 6 | 155 #define RBU_STATE_CKPT 6 |
156 #define RBU_STATE_COOKIE 7 | 156 #define RBU_STATE_COOKIE 7 |
157 #define RBU_STATE_OALSZ 8 | 157 #define RBU_STATE_OALSZ 8 |
| 158 #define RBU_STATE_PHASEONESTEP 9 |
158 | 159 |
159 #define RBU_STAGE_OAL 1 | 160 #define RBU_STAGE_OAL 1 |
160 #define RBU_STAGE_MOVE 2 | 161 #define RBU_STAGE_MOVE 2 |
161 #define RBU_STAGE_CAPTURE 3 | 162 #define RBU_STAGE_CAPTURE 3 |
162 #define RBU_STAGE_CKPT 4 | 163 #define RBU_STAGE_CKPT 4 |
163 #define RBU_STAGE_DONE 5 | 164 #define RBU_STAGE_DONE 5 |
164 | 165 |
165 | 166 |
166 #define RBU_CREATE_STATE \ | 167 #define RBU_CREATE_STATE \ |
167 "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" | 168 "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" |
168 | 169 |
169 typedef struct RbuFrame RbuFrame; | 170 typedef struct RbuFrame RbuFrame; |
170 typedef struct RbuObjIter RbuObjIter; | 171 typedef struct RbuObjIter RbuObjIter; |
171 typedef struct RbuState RbuState; | 172 typedef struct RbuState RbuState; |
172 typedef struct rbu_vfs rbu_vfs; | 173 typedef struct rbu_vfs rbu_vfs; |
173 typedef struct rbu_file rbu_file; | 174 typedef struct rbu_file rbu_file; |
174 typedef struct RbuUpdateStmt RbuUpdateStmt; | 175 typedef struct RbuUpdateStmt RbuUpdateStmt; |
175 | 176 |
176 #if !defined(SQLITE_AMALGAMATION) | 177 #if !defined(SQLITE_AMALGAMATION) |
177 typedef unsigned int u32; | 178 typedef unsigned int u32; |
| 179 typedef unsigned short u16; |
178 typedef unsigned char u8; | 180 typedef unsigned char u8; |
179 typedef sqlite3_int64 i64; | 181 typedef sqlite3_int64 i64; |
180 #endif | 182 #endif |
181 | 183 |
182 /* | 184 /* |
183 ** These values must match the values defined in wal.c for the equivalent | 185 ** These values must match the values defined in wal.c for the equivalent |
184 ** locks. These are not magic numbers as they are part of the SQLite file | 186 ** locks. These are not magic numbers as they are part of the SQLite file |
185 ** format. | 187 ** format. |
186 */ | 188 */ |
187 #define WAL_LOCK_WRITE 0 | 189 #define WAL_LOCK_WRITE 0 |
188 #define WAL_LOCK_CKPT 1 | 190 #define WAL_LOCK_CKPT 1 |
189 #define WAL_LOCK_READ0 3 | 191 #define WAL_LOCK_READ0 3 |
190 | 192 |
| 193 #define SQLITE_FCNTL_RBUCNT 5149216 |
| 194 |
191 /* | 195 /* |
192 ** A structure to store values read from the rbu_state table in memory. | 196 ** A structure to store values read from the rbu_state table in memory. |
193 */ | 197 */ |
194 struct RbuState { | 198 struct RbuState { |
195 int eStage; | 199 int eStage; |
196 char *zTbl; | 200 char *zTbl; |
197 char *zIdx; | 201 char *zIdx; |
198 i64 iWalCksum; | 202 i64 iWalCksum; |
199 int nRow; | 203 int nRow; |
200 i64 nProgress; | 204 i64 nProgress; |
201 u32 iCookie; | 205 u32 iCookie; |
202 i64 iOalSz; | 206 i64 iOalSz; |
| 207 i64 nPhaseOneStep; |
203 }; | 208 }; |
204 | 209 |
205 struct RbuUpdateStmt { | 210 struct RbuUpdateStmt { |
206 char *zMask; /* Copy of update mask used with pUpdate */ | 211 char *zMask; /* Copy of update mask used with pUpdate */ |
207 sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ | 212 sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ |
208 RbuUpdateStmt *pNext; | 213 RbuUpdateStmt *pNext; |
209 }; | 214 }; |
210 | 215 |
211 /* | 216 /* |
212 ** An iterator of this type is used to iterate through all objects in | 217 ** An iterator of this type is used to iterate through all objects in |
(...skipping 24 matching lines...) Expand all Loading... |
237 int eType; /* Table type - an RBU_PK_XXX value */ | 242 int eType; /* Table type - an RBU_PK_XXX value */ |
238 | 243 |
239 /* Output variables. zTbl==0 implies EOF. */ | 244 /* Output variables. zTbl==0 implies EOF. */ |
240 int bCleanup; /* True in "cleanup" state */ | 245 int bCleanup; /* True in "cleanup" state */ |
241 const char *zTbl; /* Name of target db table */ | 246 const char *zTbl; /* Name of target db table */ |
242 const char *zDataTbl; /* Name of rbu db table (or null) */ | 247 const char *zDataTbl; /* Name of rbu db table (or null) */ |
243 const char *zIdx; /* Name of target db index (or null) */ | 248 const char *zIdx; /* Name of target db index (or null) */ |
244 int iTnum; /* Root page of current object */ | 249 int iTnum; /* Root page of current object */ |
245 int iPkTnum; /* If eType==EXTERNAL, root of PK index */ | 250 int iPkTnum; /* If eType==EXTERNAL, root of PK index */ |
246 int bUnique; /* Current index is unique */ | 251 int bUnique; /* Current index is unique */ |
| 252 int nIndex; /* Number of aux. indexes on table zTbl */ |
247 | 253 |
248 /* Statements created by rbuObjIterPrepareAll() */ | 254 /* Statements created by rbuObjIterPrepareAll() */ |
249 int nCol; /* Number of columns in current object */ | 255 int nCol; /* Number of columns in current object */ |
250 sqlite3_stmt *pSelect; /* Source data */ | 256 sqlite3_stmt *pSelect; /* Source data */ |
251 sqlite3_stmt *pInsert; /* Statement for INSERT operations */ | 257 sqlite3_stmt *pInsert; /* Statement for INSERT operations */ |
252 sqlite3_stmt *pDelete; /* Statement for DELETE ops */ | 258 sqlite3_stmt *pDelete; /* Statement for DELETE ops */ |
253 sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ | 259 sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */ |
254 | 260 |
255 /* Last UPDATE used (for PK b-tree updates only), or NULL. */ | 261 /* Last UPDATE used (for PK b-tree updates only), or NULL. */ |
256 RbuUpdateStmt *pRbuUpdate; | 262 RbuUpdateStmt *pRbuUpdate; |
(...skipping 16 matching lines...) Expand all Loading... |
273 #define RBU_PK_WITHOUT_ROWID 4 | 279 #define RBU_PK_WITHOUT_ROWID 4 |
274 #define RBU_PK_VTAB 5 | 280 #define RBU_PK_VTAB 5 |
275 | 281 |
276 | 282 |
277 /* | 283 /* |
278 ** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs | 284 ** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs |
279 ** one of the following operations. | 285 ** one of the following operations. |
280 */ | 286 */ |
281 #define RBU_INSERT 1 /* Insert on a main table b-tree */ | 287 #define RBU_INSERT 1 /* Insert on a main table b-tree */ |
282 #define RBU_DELETE 2 /* Delete a row from a main table b-tree */ | 288 #define RBU_DELETE 2 /* Delete a row from a main table b-tree */ |
283 #define RBU_IDX_DELETE 3 /* Delete a row from an aux. index b-tree */ | 289 #define RBU_REPLACE 3 /* Delete and then insert a row */ |
284 #define RBU_IDX_INSERT 4 /* Insert on an aux. index b-tree */ | 290 #define RBU_IDX_DELETE 4 /* Delete a row from an aux. index b-tree */ |
285 #define RBU_UPDATE 5 /* Update a row in a main table b-tree */ | 291 #define RBU_IDX_INSERT 5 /* Insert on an aux. index b-tree */ |
286 | 292 |
| 293 #define RBU_UPDATE 6 /* Update a row in a main table b-tree */ |
287 | 294 |
288 /* | 295 /* |
289 ** A single step of an incremental checkpoint - frame iWalFrame of the wal | 296 ** A single step of an incremental checkpoint - frame iWalFrame of the wal |
290 ** file should be copied to page iDbPage of the database file. | 297 ** file should be copied to page iDbPage of the database file. |
291 */ | 298 */ |
292 struct RbuFrame { | 299 struct RbuFrame { |
293 u32 iDbPage; | 300 u32 iDbPage; |
294 u32 iWalFrame; | 301 u32 iWalFrame; |
295 }; | 302 }; |
296 | 303 |
297 /* | 304 /* |
298 ** RBU handle. | 305 ** RBU handle. |
| 306 ** |
| 307 ** nPhaseOneStep: |
| 308 ** If the RBU database contains an rbu_count table, this value is set to |
| 309 ** a running estimate of the number of b-tree operations required to |
| 310 ** finish populating the *-oal file. This allows the sqlite3_bp_progress() |
| 311 ** API to calculate the permyriadage progress of populating the *-oal file |
| 312 ** using the formula: |
| 313 ** |
| 314 ** permyriadage = (10000 * nProgress) / nPhaseOneStep |
| 315 ** |
| 316 ** nPhaseOneStep is initialized to the sum of: |
| 317 ** |
| 318 ** nRow * (nIndex + 1) |
| 319 ** |
| 320 ** for all source tables in the RBU database, where nRow is the number |
| 321 ** of rows in the source table and nIndex the number of indexes on the |
| 322 ** corresponding target database table. |
| 323 ** |
| 324 ** This estimate is accurate if the RBU update consists entirely of |
| 325 ** INSERT operations. However, it is inaccurate if: |
| 326 ** |
| 327 ** * the RBU update contains any UPDATE operations. If the PK specified |
| 328 ** for an UPDATE operation does not exist in the target table, then |
| 329 ** no b-tree operations are required on index b-trees. Or if the |
| 330 ** specified PK does exist, then (nIndex*2) such operations are |
| 331 ** required (one delete and one insert on each index b-tree). |
| 332 ** |
| 333 ** * the RBU update contains any DELETE operations for which the specified |
| 334 ** PK does not exist. In this case no operations are required on index |
| 335 ** b-trees. |
| 336 ** |
| 337 ** * the RBU update contains REPLACE operations. These are similar to |
| 338 ** UPDATE operations. |
| 339 ** |
| 340 ** nPhaseOneStep is updated to account for the conditions above during the |
| 341 ** first pass of each source table. The updated nPhaseOneStep value is |
| 342 ** stored in the rbu_state table if the RBU update is suspended. |
299 */ | 343 */ |
300 struct sqlite3rbu { | 344 struct sqlite3rbu { |
301 int eStage; /* Value of RBU_STATE_STAGE field */ | 345 int eStage; /* Value of RBU_STATE_STAGE field */ |
302 sqlite3 *dbMain; /* target database handle */ | 346 sqlite3 *dbMain; /* target database handle */ |
303 sqlite3 *dbRbu; /* rbu database handle */ | 347 sqlite3 *dbRbu; /* rbu database handle */ |
304 char *zTarget; /* Path to target db */ | 348 char *zTarget; /* Path to target db */ |
305 char *zRbu; /* Path to rbu db */ | 349 char *zRbu; /* Path to rbu db */ |
306 char *zState; /* Path to state db (or NULL if zRbu) */ | 350 char *zState; /* Path to state db (or NULL if zRbu) */ |
307 char zStateDb[5]; /* Db name for state ("stat" or "main") */ | 351 char zStateDb[5]; /* Db name for state ("stat" or "main") */ |
308 int rc; /* Value returned by last rbu_step() call */ | 352 int rc; /* Value returned by last rbu_step() call */ |
309 char *zErrmsg; /* Error message if rc!=SQLITE_OK */ | 353 char *zErrmsg; /* Error message if rc!=SQLITE_OK */ |
310 int nStep; /* Rows processed for current object */ | 354 int nStep; /* Rows processed for current object */ |
311 int nProgress; /* Rows processed for all objects */ | 355 int nProgress; /* Rows processed for all objects */ |
312 RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ | 356 RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ |
313 const char *zVfsName; /* Name of automatically created rbu vfs */ | 357 const char *zVfsName; /* Name of automatically created rbu vfs */ |
314 rbu_file *pTargetFd; /* File handle open on target db */ | 358 rbu_file *pTargetFd; /* File handle open on target db */ |
315 i64 iOalSz; | 359 i64 iOalSz; |
| 360 i64 nPhaseOneStep; |
316 | 361 |
317 /* The following state variables are used as part of the incremental | 362 /* The following state variables are used as part of the incremental |
318 ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding | 363 ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding |
319 ** function rbuSetupCheckpoint() for details. */ | 364 ** function rbuSetupCheckpoint() for details. */ |
320 u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ | 365 u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ |
321 u32 mLock; | 366 u32 mLock; |
322 int nFrame; /* Entries in aFrame[] array */ | 367 int nFrame; /* Entries in aFrame[] array */ |
323 int nFrameAlloc; /* Allocated size of aFrame[] array */ | 368 int nFrameAlloc; /* Allocated size of aFrame[] array */ |
324 RbuFrame *aFrame; | 369 RbuFrame *aFrame; |
325 int pgsz; | 370 int pgsz; |
326 u8 *aBuf; | 371 u8 *aBuf; |
327 i64 iWalCksum; | 372 i64 iWalCksum; |
| 373 |
| 374 /* Used in RBU vacuum mode only */ |
| 375 int nRbu; /* Number of RBU VFS in the stack */ |
| 376 rbu_file *pRbuFd; /* Fd for main db of dbRbu */ |
328 }; | 377 }; |
329 | 378 |
330 /* | 379 /* |
331 ** An rbu VFS is implemented using an instance of this structure. | 380 ** An rbu VFS is implemented using an instance of this structure. |
332 */ | 381 */ |
333 struct rbu_vfs { | 382 struct rbu_vfs { |
334 sqlite3_vfs base; /* rbu VFS shim methods */ | 383 sqlite3_vfs base; /* rbu VFS shim methods */ |
335 sqlite3_vfs *pRealVfs; /* Underlying VFS */ | 384 sqlite3_vfs *pRealVfs; /* Underlying VFS */ |
336 sqlite3_mutex *mutex; /* Mutex to protect pMain */ | 385 sqlite3_mutex *mutex; /* Mutex to protect pMain */ |
337 rbu_file *pMain; /* Linked list of main db files */ | 386 rbu_file *pMain; /* Linked list of main db files */ |
338 }; | 387 }; |
339 | 388 |
340 /* | 389 /* |
341 ** Each file opened by an rbu VFS is represented by an instance of | 390 ** Each file opened by an rbu VFS is represented by an instance of |
342 ** the following structure. | 391 ** the following structure. |
343 */ | 392 */ |
344 struct rbu_file { | 393 struct rbu_file { |
345 sqlite3_file base; /* sqlite3_file methods */ | 394 sqlite3_file base; /* sqlite3_file methods */ |
346 sqlite3_file *pReal; /* Underlying file handle */ | 395 sqlite3_file *pReal; /* Underlying file handle */ |
347 rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ | 396 rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ |
348 sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ | 397 sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ |
349 | 398 |
350 int openFlags; /* Flags this file was opened with */ | 399 int openFlags; /* Flags this file was opened with */ |
351 u32 iCookie; /* Cookie value for main db files */ | 400 u32 iCookie; /* Cookie value for main db files */ |
352 u8 iWriteVer; /* "write-version" value for main db files */ | 401 u8 iWriteVer; /* "write-version" value for main db files */ |
| 402 u8 bNolock; /* True to fail EXCLUSIVE locks */ |
353 | 403 |
354 int nShm; /* Number of entries in apShm[] array */ | 404 int nShm; /* Number of entries in apShm[] array */ |
355 char **apShm; /* Array of mmap'd *-shm regions */ | 405 char **apShm; /* Array of mmap'd *-shm regions */ |
356 char *zDel; /* Delete this when closing file */ | 406 char *zDel; /* Delete this when closing file */ |
357 | 407 |
358 const char *zWal; /* Wal filename for this main db file */ | 408 const char *zWal; /* Wal filename for this main db file */ |
359 rbu_file *pWalFd; /* Wal file descriptor for this main db */ | 409 rbu_file *pWalFd; /* Wal file descriptor for this main db */ |
360 rbu_file *pMainNext; /* Next MAIN_DB file */ | 410 rbu_file *pMainNext; /* Next MAIN_DB file */ |
361 }; | 411 }; |
362 | 412 |
| 413 /* |
| 414 ** True for an RBU vacuum handle, or false otherwise. |
| 415 */ |
| 416 #define rbuIsVacuum(p) ((p)->zTarget==0) |
| 417 |
363 | 418 |
364 /************************************************************************* | 419 /************************************************************************* |
365 ** The following three functions, found below: | 420 ** The following three functions, found below: |
366 ** | 421 ** |
367 ** rbuDeltaGetInt() | 422 ** rbuDeltaGetInt() |
368 ** rbuDeltaChecksum() | 423 ** rbuDeltaChecksum() |
369 ** rbuDeltaApply() | 424 ** rbuDeltaApply() |
370 ** | 425 ** |
371 ** are lifted from the fossil source code (http://fossil-scm.org). They | 426 ** are lifted from the fossil source code (http://fossil-scm.org). They |
372 ** are used to implement the scalar SQL function rbu_fossil_delta(). | 427 ** are used to implement the scalar SQL function rbu_fossil_delta(). |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 if( rc!=SQLITE_OK ){ | 856 if( rc!=SQLITE_OK ){ |
802 rbuObjIterFinalize(pIter); | 857 rbuObjIterFinalize(pIter); |
803 p->rc = rc; | 858 p->rc = rc; |
804 } | 859 } |
805 return rc; | 860 return rc; |
806 } | 861 } |
807 | 862 |
808 | 863 |
809 /* | 864 /* |
810 ** The implementation of the rbu_target_name() SQL function. This function | 865 ** The implementation of the rbu_target_name() SQL function. This function |
811 ** accepts one argument - the name of a table in the RBU database. If the | 866 ** accepts one or two arguments. The first argument is the name of a table - |
812 ** table name matches the pattern: | 867 ** the name of a table in the RBU database. The second, if it is present, is 1 |
| 868 ** for a view or 0 for a table. |
| 869 ** |
| 870 ** For a non-vacuum RBU handle, if the table name matches the pattern: |
813 ** | 871 ** |
814 ** data[0-9]_<name> | 872 ** data[0-9]_<name> |
815 ** | 873 ** |
816 ** where <name> is any sequence of 1 or more characters, <name> is returned. | 874 ** where <name> is any sequence of 1 or more characters, <name> is returned. |
817 ** Otherwise, if the only argument does not match the above pattern, an SQL | 875 ** Otherwise, if the only argument does not match the above pattern, an SQL |
818 ** NULL is returned. | 876 ** NULL is returned. |
819 ** | 877 ** |
820 ** "data_t1" -> "t1" | 878 ** "data_t1" -> "t1" |
821 ** "data0123_t2" -> "t2" | 879 ** "data0123_t2" -> "t2" |
822 ** "dataAB_t3" -> NULL | 880 ** "dataAB_t3" -> NULL |
| 881 ** |
| 882 ** For an rbu vacuum handle, a copy of the first argument is returned if |
| 883 ** the second argument is either missing or 0 (not a view). |
823 */ | 884 */ |
824 static void rbuTargetNameFunc( | 885 static void rbuTargetNameFunc( |
825 sqlite3_context *context, | 886 sqlite3_context *pCtx, |
826 int argc, | 887 int argc, |
827 sqlite3_value **argv | 888 sqlite3_value **argv |
828 ){ | 889 ){ |
| 890 sqlite3rbu *p = sqlite3_user_data(pCtx); |
829 const char *zIn; | 891 const char *zIn; |
830 assert( argc==1 ); | 892 assert( argc==1 || argc==2 ); |
831 | 893 |
832 zIn = (const char*)sqlite3_value_text(argv[0]); | 894 zIn = (const char*)sqlite3_value_text(argv[0]); |
833 if( zIn && strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ | 895 if( zIn ){ |
834 int i; | 896 if( rbuIsVacuum(p) ){ |
835 for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); | 897 if( argc==1 || 0==sqlite3_value_int(argv[1]) ){ |
836 if( zIn[i]=='_' && zIn[i+1] ){ | 898 sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC); |
837 sqlite3_result_text(context, &zIn[i+1], -1, SQLITE_STATIC); | 899 } |
| 900 }else{ |
| 901 if( strlen(zIn)>4 && memcmp("data", zIn, 4)==0 ){ |
| 902 int i; |
| 903 for(i=4; zIn[i]>='0' && zIn[i]<='9'; i++); |
| 904 if( zIn[i]=='_' && zIn[i+1] ){ |
| 905 sqlite3_result_text(pCtx, &zIn[i+1], -1, SQLITE_STATIC); |
| 906 } |
| 907 } |
838 } | 908 } |
839 } | 909 } |
840 } | 910 } |
841 | 911 |
842 /* | 912 /* |
843 ** Initialize the iterator structure passed as the second argument. | 913 ** Initialize the iterator structure passed as the second argument. |
844 ** | 914 ** |
845 ** If no error occurs, SQLITE_OK is returned and the iterator is left | 915 ** If no error occurs, SQLITE_OK is returned and the iterator is left |
846 ** pointing to the first entry. Otherwise, an error code and message is | 916 ** pointing to the first entry. Otherwise, an error code and message is |
847 ** left in the RBU handle passed as the first argument. A copy of the | 917 ** left in the RBU handle passed as the first argument. A copy of the |
848 ** error code is returned. | 918 ** error code is returned. |
849 */ | 919 */ |
850 static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ | 920 static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ |
851 int rc; | 921 int rc; |
852 memset(pIter, 0, sizeof(RbuObjIter)); | 922 memset(pIter, 0, sizeof(RbuObjIter)); |
853 | 923 |
854 rc = prepareAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, | 924 rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, |
855 "SELECT rbu_target_name(name) AS target, name FROM sqlite_master " | 925 sqlite3_mprintf( |
| 926 "SELECT rbu_target_name(name, type='view') AS target, name " |
| 927 "FROM sqlite_master " |
856 "WHERE type IN ('table', 'view') AND target IS NOT NULL " | 928 "WHERE type IN ('table', 'view') AND target IS NOT NULL " |
| 929 " %s " |
857 "ORDER BY name" | 930 "ORDER BY name" |
858 ); | 931 , rbuIsVacuum(p) ? "AND rootpage!=0 AND rootpage IS NOT NULL" : "")); |
859 | 932 |
860 if( rc==SQLITE_OK ){ | 933 if( rc==SQLITE_OK ){ |
861 rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, | 934 rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, |
862 "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " | 935 "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " |
863 " FROM main.sqlite_master " | 936 " FROM main.sqlite_master " |
864 " WHERE type='index' AND tbl_name = ?" | 937 " WHERE type='index' AND tbl_name = ?" |
865 ); | 938 ); |
866 } | 939 } |
867 | 940 |
868 pIter->bCleanup = 1; | 941 pIter->bCleanup = 1; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 ** If an error (i.e. an OOM condition) occurs, return NULL and leave an | 1001 ** If an error (i.e. an OOM condition) occurs, return NULL and leave an |
929 ** error code in the rbu handle passed as the first argument. Or, if an | 1002 ** error code in the rbu handle passed as the first argument. Or, if an |
930 ** error has already occurred when this function is called, return NULL | 1003 ** error has already occurred when this function is called, return NULL |
931 ** immediately without attempting the allocation or modifying the stored | 1004 ** immediately without attempting the allocation or modifying the stored |
932 ** error code. | 1005 ** error code. |
933 */ | 1006 */ |
934 static void *rbuMalloc(sqlite3rbu *p, int nByte){ | 1007 static void *rbuMalloc(sqlite3rbu *p, int nByte){ |
935 void *pRet = 0; | 1008 void *pRet = 0; |
936 if( p->rc==SQLITE_OK ){ | 1009 if( p->rc==SQLITE_OK ){ |
937 assert( nByte>0 ); | 1010 assert( nByte>0 ); |
938 pRet = sqlite3_malloc(nByte); | 1011 pRet = sqlite3_malloc64(nByte); |
939 if( pRet==0 ){ | 1012 if( pRet==0 ){ |
940 p->rc = SQLITE_NOMEM; | 1013 p->rc = SQLITE_NOMEM; |
941 }else{ | 1014 }else{ |
942 memset(pRet, 0, nByte); | 1015 memset(pRet, 0, nByte); |
943 } | 1016 } |
944 } | 1017 } |
945 return pRet; | 1018 return pRet; |
946 } | 1019 } |
947 | 1020 |
948 | 1021 |
(...skipping 25 matching lines...) Expand all Loading... |
974 ** | 1047 ** |
975 ** If an OOM condition is encountered when attempting to allocate memory, | 1048 ** If an OOM condition is encountered when attempting to allocate memory, |
976 ** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, | 1049 ** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, |
977 ** if the allocation succeeds, (*pRc) is left unchanged. | 1050 ** if the allocation succeeds, (*pRc) is left unchanged. |
978 */ | 1051 */ |
979 static char *rbuStrndup(const char *zStr, int *pRc){ | 1052 static char *rbuStrndup(const char *zStr, int *pRc){ |
980 char *zRet = 0; | 1053 char *zRet = 0; |
981 | 1054 |
982 assert( *pRc==SQLITE_OK ); | 1055 assert( *pRc==SQLITE_OK ); |
983 if( zStr ){ | 1056 if( zStr ){ |
984 int nCopy = strlen(zStr) + 1; | 1057 size_t nCopy = strlen(zStr) + 1; |
985 zRet = (char*)sqlite3_malloc(nCopy); | 1058 zRet = (char*)sqlite3_malloc64(nCopy); |
986 if( zRet ){ | 1059 if( zRet ){ |
987 memcpy(zRet, zStr, nCopy); | 1060 memcpy(zRet, zStr, nCopy); |
988 }else{ | 1061 }else{ |
989 *pRc = SQLITE_NOMEM; | 1062 *pRc = SQLITE_NOMEM; |
990 } | 1063 } |
991 } | 1064 } |
992 | 1065 |
993 return zRet; | 1066 return zRet; |
994 } | 1067 } |
995 | 1068 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 sqlite3_stmt *pList = 0; | 1209 sqlite3_stmt *pList = 0; |
1137 int bIndex = 0; | 1210 int bIndex = 0; |
1138 | 1211 |
1139 if( p->rc==SQLITE_OK ){ | 1212 if( p->rc==SQLITE_OK ){ |
1140 memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); | 1213 memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); |
1141 p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, | 1214 p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, |
1142 sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) | 1215 sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) |
1143 ); | 1216 ); |
1144 } | 1217 } |
1145 | 1218 |
| 1219 pIter->nIndex = 0; |
1146 while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ | 1220 while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ |
1147 const char *zIdx = (const char*)sqlite3_column_text(pList, 1); | 1221 const char *zIdx = (const char*)sqlite3_column_text(pList, 1); |
1148 sqlite3_stmt *pXInfo = 0; | 1222 sqlite3_stmt *pXInfo = 0; |
1149 if( zIdx==0 ) break; | 1223 if( zIdx==0 ) break; |
1150 p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, | 1224 p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, |
1151 sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) | 1225 sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) |
1152 ); | 1226 ); |
1153 while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ | 1227 while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ |
1154 int iCid = sqlite3_column_int(pXInfo, 1); | 1228 int iCid = sqlite3_column_int(pXInfo, 1); |
1155 if( iCid>=0 ) pIter->abIndexed[iCid] = 1; | 1229 if( iCid>=0 ) pIter->abIndexed[iCid] = 1; |
1156 } | 1230 } |
1157 rbuFinalize(p, pXInfo); | 1231 rbuFinalize(p, pXInfo); |
1158 bIndex = 1; | 1232 bIndex = 1; |
| 1233 pIter->nIndex++; |
| 1234 } |
| 1235 |
| 1236 if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ |
| 1237 /* "PRAGMA index_list" includes the main PK b-tree */ |
| 1238 pIter->nIndex--; |
1159 } | 1239 } |
1160 | 1240 |
1161 rbuFinalize(p, pList); | 1241 rbuFinalize(p, pList); |
1162 if( bIndex==0 ) pIter->abIndexed = 0; | 1242 if( bIndex==0 ) pIter->abIndexed = 0; |
1163 } | 1243 } |
1164 | 1244 |
1165 | 1245 |
1166 /* | 1246 /* |
1167 ** If they are not already populated, populate the pIter->azTblCol[], | 1247 ** If they are not already populated, populate the pIter->azTblCol[], |
1168 ** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to | 1248 ** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 pIter->azTblCol[pIter->nTblCol++] = zCopy; | 1294 pIter->azTblCol[pIter->nTblCol++] = zCopy; |
1215 } | 1295 } |
1216 else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){ | 1296 else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){ |
1217 bRbuRowid = 1; | 1297 bRbuRowid = 1; |
1218 } | 1298 } |
1219 } | 1299 } |
1220 sqlite3_finalize(pStmt); | 1300 sqlite3_finalize(pStmt); |
1221 pStmt = 0; | 1301 pStmt = 0; |
1222 | 1302 |
1223 if( p->rc==SQLITE_OK | 1303 if( p->rc==SQLITE_OK |
| 1304 && rbuIsVacuum(p)==0 |
1224 && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) | 1305 && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) |
1225 ){ | 1306 ){ |
1226 p->rc = SQLITE_ERROR; | 1307 p->rc = SQLITE_ERROR; |
1227 p->zErrmsg = sqlite3_mprintf( | 1308 p->zErrmsg = sqlite3_mprintf( |
1228 "table %q %s rbu_rowid column", pIter->zDataTbl, | 1309 "table %q %s rbu_rowid column", pIter->zDataTbl, |
1229 (bRbuRowid ? "may not have" : "requires") | 1310 (bRbuRowid ? "may not have" : "requires") |
1230 ); | 1311 ); |
1231 } | 1312 } |
1232 | 1313 |
1233 /* Check that all non-HIDDEN columns in the destination table are also | 1314 /* Check that all non-HIDDEN columns in the destination table are also |
(...skipping 28 matching lines...) Expand all Loading... |
1262 pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); | 1343 pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); |
1263 pIter->abTblPk[iOrder] = (iPk!=0); | 1344 pIter->abTblPk[iOrder] = (iPk!=0); |
1264 pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); | 1345 pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); |
1265 iOrder++; | 1346 iOrder++; |
1266 } | 1347 } |
1267 } | 1348 } |
1268 | 1349 |
1269 rbuFinalize(p, pStmt); | 1350 rbuFinalize(p, pStmt); |
1270 rbuObjIterCacheIndexedCols(p, pIter); | 1351 rbuObjIterCacheIndexedCols(p, pIter); |
1271 assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); | 1352 assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); |
| 1353 assert( pIter->eType!=RBU_PK_VTAB || pIter->nIndex==0 ); |
1272 } | 1354 } |
1273 | 1355 |
1274 return p->rc; | 1356 return p->rc; |
1275 } | 1357 } |
1276 | 1358 |
1277 /* | 1359 /* |
1278 ** This function constructs and returns a pointer to a nul-terminated | 1360 ** This function constructs and returns a pointer to a nul-terminated |
1279 ** string containing some SQL clause or list based on one or more of the | 1361 ** string containing some SQL clause or list based on one or more of the |
1280 ** column names currently stored in the pIter->azTblCol[] array. | 1362 ** column names currently stored in the pIter->azTblCol[] array. |
1281 */ | 1363 */ |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 const char *zType; | 1434 const char *zType; |
1353 | 1435 |
1354 if( iCid<0 ){ | 1436 if( iCid<0 ){ |
1355 /* An integer primary key. If the table has an explicit IPK, use | 1437 /* An integer primary key. If the table has an explicit IPK, use |
1356 ** its name. Otherwise, use "rbu_rowid". */ | 1438 ** its name. Otherwise, use "rbu_rowid". */ |
1357 if( pIter->eType==RBU_PK_IPK ){ | 1439 if( pIter->eType==RBU_PK_IPK ){ |
1358 int i; | 1440 int i; |
1359 for(i=0; pIter->abTblPk[i]==0; i++); | 1441 for(i=0; pIter->abTblPk[i]==0; i++); |
1360 assert( i<pIter->nTblCol ); | 1442 assert( i<pIter->nTblCol ); |
1361 zCol = pIter->azTblCol[i]; | 1443 zCol = pIter->azTblCol[i]; |
| 1444 }else if( rbuIsVacuum(p) ){ |
| 1445 zCol = "_rowid_"; |
1362 }else{ | 1446 }else{ |
1363 zCol = "rbu_rowid"; | 1447 zCol = "rbu_rowid"; |
1364 } | 1448 } |
1365 zType = "INTEGER"; | 1449 zType = "INTEGER"; |
1366 }else{ | 1450 }else{ |
1367 zCol = pIter->azTblCol[iCid]; | 1451 zCol = pIter->azTblCol[iCid]; |
1368 zType = pIter->azTblType[iCid]; | 1452 zType = pIter->azTblType[iCid]; |
1369 } | 1453 } |
1370 | 1454 |
1371 zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); | 1455 zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 | 1899 |
1816 static void rbuTmpInsertFunc( | 1900 static void rbuTmpInsertFunc( |
1817 sqlite3_context *pCtx, | 1901 sqlite3_context *pCtx, |
1818 int nVal, | 1902 int nVal, |
1819 sqlite3_value **apVal | 1903 sqlite3_value **apVal |
1820 ){ | 1904 ){ |
1821 sqlite3rbu *p = sqlite3_user_data(pCtx); | 1905 sqlite3rbu *p = sqlite3_user_data(pCtx); |
1822 int rc = SQLITE_OK; | 1906 int rc = SQLITE_OK; |
1823 int i; | 1907 int i; |
1824 | 1908 |
| 1909 assert( sqlite3_value_int(apVal[0])!=0 |
| 1910 || p->objiter.eType==RBU_PK_EXTERNAL |
| 1911 || p->objiter.eType==RBU_PK_NONE |
| 1912 ); |
| 1913 if( sqlite3_value_int(apVal[0])!=0 ){ |
| 1914 p->nPhaseOneStep += p->objiter.nIndex; |
| 1915 } |
| 1916 |
1825 for(i=0; rc==SQLITE_OK && i<nVal; i++){ | 1917 for(i=0; rc==SQLITE_OK && i<nVal; i++){ |
1826 rc = sqlite3_bind_value(p->objiter.pTmpInsert, i+1, apVal[i]); | 1918 rc = sqlite3_bind_value(p->objiter.pTmpInsert, i+1, apVal[i]); |
1827 } | 1919 } |
1828 if( rc==SQLITE_OK ){ | 1920 if( rc==SQLITE_OK ){ |
1829 sqlite3_step(p->objiter.pTmpInsert); | 1921 sqlite3_step(p->objiter.pTmpInsert); |
1830 rc = sqlite3_reset(p->objiter.pTmpInsert); | 1922 rc = sqlite3_reset(p->objiter.pTmpInsert); |
1831 } | 1923 } |
1832 | 1924 |
1833 if( rc!=SQLITE_OK ){ | 1925 if( rc!=SQLITE_OK ){ |
1834 sqlite3_result_error_code(pCtx, rc); | 1926 sqlite3_result_error_code(pCtx, rc); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1884 /* Create the statement to insert index entries */ | 1976 /* Create the statement to insert index entries */ |
1885 pIter->nCol = nBind; | 1977 pIter->nCol = nBind; |
1886 if( p->rc==SQLITE_OK ){ | 1978 if( p->rc==SQLITE_OK ){ |
1887 p->rc = prepareFreeAndCollectError( | 1979 p->rc = prepareFreeAndCollectError( |
1888 p->dbMain, &pIter->pInsert, &p->zErrmsg, | 1980 p->dbMain, &pIter->pInsert, &p->zErrmsg, |
1889 sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind) | 1981 sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind) |
1890 ); | 1982 ); |
1891 } | 1983 } |
1892 | 1984 |
1893 /* And to delete index entries */ | 1985 /* And to delete index entries */ |
1894 if( p->rc==SQLITE_OK ){ | 1986 if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ |
1895 p->rc = prepareFreeAndCollectError( | 1987 p->rc = prepareFreeAndCollectError( |
1896 p->dbMain, &pIter->pDelete, &p->zErrmsg, | 1988 p->dbMain, &pIter->pDelete, &p->zErrmsg, |
1897 sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) | 1989 sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) |
1898 ); | 1990 ); |
1899 } | 1991 } |
1900 | 1992 |
1901 /* Create the SELECT statement to read keys in sorted order */ | 1993 /* Create the SELECT statement to read keys in sorted order */ |
1902 if( p->rc==SQLITE_OK ){ | 1994 if( p->rc==SQLITE_OK ){ |
1903 char *zSql; | 1995 char *zSql; |
| 1996 if( rbuIsVacuum(p) ){ |
| 1997 zSql = sqlite3_mprintf( |
| 1998 "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s", |
| 1999 zCollist, |
| 2000 pIter->zDataTbl, |
| 2001 zCollist, zLimit |
| 2002 ); |
| 2003 }else |
| 2004 |
1904 if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ | 2005 if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ |
1905 zSql = sqlite3_mprintf( | 2006 zSql = sqlite3_mprintf( |
1906 "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", | 2007 "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", |
1907 zCollist, p->zStateDb, pIter->zDataTbl, | 2008 zCollist, p->zStateDb, pIter->zDataTbl, |
1908 zCollist, zLimit | 2009 zCollist, zLimit |
1909 ); | 2010 ); |
1910 }else{ | 2011 }else{ |
1911 zSql = sqlite3_mprintf( | 2012 zSql = sqlite3_mprintf( |
| 2013 "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " |
| 2014 "UNION ALL " |
1912 "SELECT %s, rbu_control FROM '%q' " | 2015 "SELECT %s, rbu_control FROM '%q' " |
1913 "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " | 2016 "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " |
1914 "UNION ALL " | |
1915 "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " | |
1916 "ORDER BY %s%s", | 2017 "ORDER BY %s%s", |
| 2018 zCollist, p->zStateDb, pIter->zDataTbl, |
1917 zCollist, pIter->zDataTbl, | 2019 zCollist, pIter->zDataTbl, |
1918 zCollist, p->zStateDb, pIter->zDataTbl, | |
1919 zCollist, zLimit | 2020 zCollist, zLimit |
1920 ); | 2021 ); |
1921 } | 2022 } |
1922 p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); | 2023 p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); |
1923 } | 2024 } |
1924 | 2025 |
1925 sqlite3_free(zImposterCols); | 2026 sqlite3_free(zImposterCols); |
1926 sqlite3_free(zImposterPK); | 2027 sqlite3_free(zImposterPK); |
1927 sqlite3_free(zWhere); | 2028 sqlite3_free(zWhere); |
1928 sqlite3_free(zBind); | 2029 sqlite3_free(zBind); |
1929 }else{ | 2030 }else{ |
1930 int bRbuRowid = (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE); | 2031 int bRbuRowid = (pIter->eType==RBU_PK_VTAB) |
| 2032 ||(pIter->eType==RBU_PK_NONE) |
| 2033 ||(pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)); |
1931 const char *zTbl = pIter->zTbl; /* Table this step applies to */ | 2034 const char *zTbl = pIter->zTbl; /* Table this step applies to */ |
1932 const char *zWrite; /* Imposter table name */ | 2035 const char *zWrite; /* Imposter table name */ |
1933 | 2036 |
1934 char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid); | 2037 char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid); |
1935 char *zWhere = rbuObjIterGetWhere(p, pIter); | 2038 char *zWhere = rbuObjIterGetWhere(p, pIter); |
1936 char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old"); | 2039 char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old"); |
1937 char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new"); | 2040 char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new"); |
1938 | 2041 |
1939 zCollist = rbuObjIterGetCollist(p, pIter); | 2042 zCollist = rbuObjIterGetCollist(p, pIter); |
1940 pIter->nCol = pIter->nTblCol; | 2043 pIter->nCol = pIter->nTblCol; |
1941 | 2044 |
1942 /* Create the imposter table or tables (if required). */ | 2045 /* Create the imposter table or tables (if required). */ |
1943 rbuCreateImposterTable(p, pIter); | 2046 rbuCreateImposterTable(p, pIter); |
1944 rbuCreateImposterTable2(p, pIter); | 2047 rbuCreateImposterTable2(p, pIter); |
1945 zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_"); | 2048 zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_"); |
1946 | 2049 |
1947 /* Create the INSERT statement to write to the target PK b-tree */ | 2050 /* Create the INSERT statement to write to the target PK b-tree */ |
1948 if( p->rc==SQLITE_OK ){ | 2051 if( p->rc==SQLITE_OK ){ |
1949 p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, | 2052 p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, |
1950 sqlite3_mprintf( | 2053 sqlite3_mprintf( |
1951 "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", | 2054 "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", |
1952 zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings | 2055 zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings |
1953 ) | 2056 ) |
1954 ); | 2057 ); |
1955 } | 2058 } |
1956 | 2059 |
1957 /* Create the DELETE statement to write to the target PK b-tree */ | 2060 /* Create the DELETE statement to write to the target PK b-tree. |
1958 if( p->rc==SQLITE_OK ){ | 2061 ** Because it only performs INSERT operations, this is not required for |
| 2062 ** an rbu vacuum handle. */ |
| 2063 if( rbuIsVacuum(p)==0 && p->rc==SQLITE_OK ){ |
1959 p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, | 2064 p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, |
1960 sqlite3_mprintf( | 2065 sqlite3_mprintf( |
1961 "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere | 2066 "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere |
1962 ) | 2067 ) |
1963 ); | 2068 ); |
1964 } | 2069 } |
1965 | 2070 |
1966 if( pIter->abIndexed ){ | 2071 if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ |
1967 const char *zRbuRowid = ""; | 2072 const char *zRbuRowid = ""; |
1968 if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ | 2073 if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ |
1969 zRbuRowid = ", rbu_rowid"; | 2074 zRbuRowid = ", rbu_rowid"; |
1970 } | 2075 } |
1971 | 2076 |
1972 /* Create the rbu_tmp_xxx table and the triggers to populate it. */ | 2077 /* Create the rbu_tmp_xxx table and the triggers to populate it. */ |
1973 rbuMPrintfExec(p, p->dbRbu, | 2078 rbuMPrintfExec(p, p->dbRbu, |
1974 "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS " | 2079 "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS " |
1975 "SELECT *%s FROM '%q' WHERE 0;" | 2080 "SELECT *%s FROM '%q' WHERE 0;" |
1976 , p->zStateDb, pIter->zDataTbl | 2081 , p->zStateDb, pIter->zDataTbl |
1977 , (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "") | 2082 , (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "") |
1978 , pIter->zDataTbl | 2083 , pIter->zDataTbl |
1979 ); | 2084 ); |
1980 | 2085 |
1981 rbuMPrintfExec(p, p->dbMain, | 2086 rbuMPrintfExec(p, p->dbMain, |
1982 "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " | 2087 "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " |
1983 "BEGIN " | 2088 "BEGIN " |
1984 " SELECT rbu_tmp_insert(2, %s);" | 2089 " SELECT rbu_tmp_insert(3, %s);" |
1985 "END;" | 2090 "END;" |
1986 | 2091 |
1987 "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " | 2092 "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " |
1988 "BEGIN " | 2093 "BEGIN " |
1989 " SELECT rbu_tmp_insert(2, %s);" | 2094 " SELECT rbu_tmp_insert(3, %s);" |
1990 "END;" | 2095 "END;" |
1991 | 2096 |
1992 "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " | 2097 "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " |
1993 "BEGIN " | 2098 "BEGIN " |
1994 " SELECT rbu_tmp_insert(3, %s);" | 2099 " SELECT rbu_tmp_insert(4, %s);" |
1995 "END;", | 2100 "END;", |
1996 zWrite, zTbl, zOldlist, | 2101 zWrite, zTbl, zOldlist, |
1997 zWrite, zTbl, zOldlist, | 2102 zWrite, zTbl, zOldlist, |
1998 zWrite, zTbl, zNewlist | 2103 zWrite, zTbl, zNewlist |
1999 ); | 2104 ); |
2000 | 2105 |
2001 if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ | 2106 if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ |
2002 rbuMPrintfExec(p, p->dbMain, | 2107 rbuMPrintfExec(p, p->dbMain, |
2003 "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" " | 2108 "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" " |
2004 "BEGIN " | 2109 "BEGIN " |
2005 " SELECT rbu_tmp_insert(0, %s);" | 2110 " SELECT rbu_tmp_insert(0, %s);" |
2006 "END;", | 2111 "END;", |
2007 zWrite, zTbl, zNewlist | 2112 zWrite, zTbl, zNewlist |
2008 ); | 2113 ); |
2009 } | 2114 } |
2010 | 2115 |
2011 rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid); | 2116 rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid); |
2012 } | 2117 } |
2013 | 2118 |
2014 /* Create the SELECT statement to read keys from data_xxx */ | 2119 /* Create the SELECT statement to read keys from data_xxx */ |
2015 if( p->rc==SQLITE_OK ){ | 2120 if( p->rc==SQLITE_OK ){ |
| 2121 const char *zRbuRowid = ""; |
| 2122 if( bRbuRowid ){ |
| 2123 zRbuRowid = rbuIsVacuum(p) ? ",_rowid_ " : ",rbu_rowid"; |
| 2124 } |
2016 p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, | 2125 p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, |
2017 sqlite3_mprintf( | 2126 sqlite3_mprintf( |
2018 "SELECT %s, rbu_control%s FROM '%q'%s", | 2127 "SELECT %s,%s rbu_control%s FROM '%q'%s", |
2019 zCollist, (bRbuRowid ? ", rbu_rowid" : ""), | 2128 zCollist, |
| 2129 (rbuIsVacuum(p) ? "0 AS " : ""), |
| 2130 zRbuRowid, |
2020 pIter->zDataTbl, zLimit | 2131 pIter->zDataTbl, zLimit |
2021 ) | 2132 ) |
2022 ); | 2133 ); |
2023 } | 2134 } |
2024 | 2135 |
2025 sqlite3_free(zWhere); | 2136 sqlite3_free(zWhere); |
2026 sqlite3_free(zOldlist); | 2137 sqlite3_free(zOldlist); |
2027 sqlite3_free(zNewlist); | 2138 sqlite3_free(zNewlist); |
2028 sqlite3_free(zBindings); | 2139 sqlite3_free(zBindings); |
2029 } | 2140 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2104 ); | 2215 ); |
2105 *ppStmt = pUp->pUpdate; | 2216 *ppStmt = pUp->pUpdate; |
2106 } | 2217 } |
2107 sqlite3_free(zWhere); | 2218 sqlite3_free(zWhere); |
2108 sqlite3_free(zSet); | 2219 sqlite3_free(zSet); |
2109 } | 2220 } |
2110 | 2221 |
2111 return p->rc; | 2222 return p->rc; |
2112 } | 2223 } |
2113 | 2224 |
2114 static sqlite3 *rbuOpenDbhandle(sqlite3rbu *p, const char *zName){ | 2225 static sqlite3 *rbuOpenDbhandle( |
| 2226 sqlite3rbu *p, |
| 2227 const char *zName, |
| 2228 int bUseVfs |
| 2229 ){ |
2115 sqlite3 *db = 0; | 2230 sqlite3 *db = 0; |
2116 if( p->rc==SQLITE_OK ){ | 2231 if( p->rc==SQLITE_OK ){ |
2117 const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; | 2232 const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; |
2118 p->rc = sqlite3_open_v2(zName, &db, flags, p->zVfsName); | 2233 p->rc = sqlite3_open_v2(zName, &db, flags, bUseVfs ? p->zVfsName : 0); |
2119 if( p->rc ){ | 2234 if( p->rc ){ |
2120 p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); | 2235 p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
2121 sqlite3_close(db); | 2236 sqlite3_close(db); |
2122 db = 0; | 2237 db = 0; |
2123 } | 2238 } |
2124 } | 2239 } |
2125 return db; | 2240 return db; |
2126 } | 2241 } |
2127 | 2242 |
2128 /* | 2243 /* |
| 2244 ** Free an RbuState object allocated by rbuLoadState(). |
| 2245 */ |
| 2246 static void rbuFreeState(RbuState *p){ |
| 2247 if( p ){ |
| 2248 sqlite3_free(p->zTbl); |
| 2249 sqlite3_free(p->zIdx); |
| 2250 sqlite3_free(p); |
| 2251 } |
| 2252 } |
| 2253 |
| 2254 /* |
| 2255 ** Allocate an RbuState object and load the contents of the rbu_state |
| 2256 ** table into it. Return a pointer to the new object. It is the |
| 2257 ** responsibility of the caller to eventually free the object using |
| 2258 ** sqlite3_free(). |
| 2259 ** |
| 2260 ** If an error occurs, leave an error code and message in the rbu handle |
| 2261 ** and return NULL. |
| 2262 */ |
| 2263 static RbuState *rbuLoadState(sqlite3rbu *p){ |
| 2264 RbuState *pRet = 0; |
| 2265 sqlite3_stmt *pStmt = 0; |
| 2266 int rc; |
| 2267 int rc2; |
| 2268 |
| 2269 pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); |
| 2270 if( pRet==0 ) return 0; |
| 2271 |
| 2272 rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, |
| 2273 sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) |
| 2274 ); |
| 2275 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 2276 switch( sqlite3_column_int(pStmt, 0) ){ |
| 2277 case RBU_STATE_STAGE: |
| 2278 pRet->eStage = sqlite3_column_int(pStmt, 1); |
| 2279 if( pRet->eStage!=RBU_STAGE_OAL |
| 2280 && pRet->eStage!=RBU_STAGE_MOVE |
| 2281 && pRet->eStage!=RBU_STAGE_CKPT |
| 2282 ){ |
| 2283 p->rc = SQLITE_CORRUPT; |
| 2284 } |
| 2285 break; |
| 2286 |
| 2287 case RBU_STATE_TBL: |
| 2288 pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); |
| 2289 break; |
| 2290 |
| 2291 case RBU_STATE_IDX: |
| 2292 pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); |
| 2293 break; |
| 2294 |
| 2295 case RBU_STATE_ROW: |
| 2296 pRet->nRow = sqlite3_column_int(pStmt, 1); |
| 2297 break; |
| 2298 |
| 2299 case RBU_STATE_PROGRESS: |
| 2300 pRet->nProgress = sqlite3_column_int64(pStmt, 1); |
| 2301 break; |
| 2302 |
| 2303 case RBU_STATE_CKPT: |
| 2304 pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); |
| 2305 break; |
| 2306 |
| 2307 case RBU_STATE_COOKIE: |
| 2308 pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); |
| 2309 break; |
| 2310 |
| 2311 case RBU_STATE_OALSZ: |
| 2312 pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); |
| 2313 break; |
| 2314 |
| 2315 case RBU_STATE_PHASEONESTEP: |
| 2316 pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); |
| 2317 break; |
| 2318 |
| 2319 default: |
| 2320 rc = SQLITE_CORRUPT; |
| 2321 break; |
| 2322 } |
| 2323 } |
| 2324 rc2 = sqlite3_finalize(pStmt); |
| 2325 if( rc==SQLITE_OK ) rc = rc2; |
| 2326 |
| 2327 p->rc = rc; |
| 2328 return pRet; |
| 2329 } |
| 2330 |
| 2331 |
| 2332 /* |
2129 ** Open the database handle and attach the RBU database as "rbu". If an | 2333 ** Open the database handle and attach the RBU database as "rbu". If an |
2130 ** error occurs, leave an error code and message in the RBU handle. | 2334 ** error occurs, leave an error code and message in the RBU handle. |
2131 */ | 2335 */ |
2132 static void rbuOpenDatabase(sqlite3rbu *p){ | 2336 static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){ |
2133 assert( p->rc==SQLITE_OK ); | 2337 assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); |
2134 assert( p->dbMain==0 && p->dbRbu==0 ); | 2338 assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); |
2135 | 2339 |
2136 p->eStage = 0; | 2340 /* Open the RBU database */ |
2137 p->dbMain = rbuOpenDbhandle(p, p->zTarget); | 2341 p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); |
2138 p->dbRbu = rbuOpenDbhandle(p, p->zRbu); | 2342 |
| 2343 if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ |
| 2344 sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); |
| 2345 if( p->zState==0 ){ |
| 2346 const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); |
| 2347 p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile); |
| 2348 } |
| 2349 } |
2139 | 2350 |
2140 /* If using separate RBU and state databases, attach the state database to | 2351 /* If using separate RBU and state databases, attach the state database to |
2141 ** the RBU db handle now. */ | 2352 ** the RBU db handle now. */ |
2142 if( p->zState ){ | 2353 if( p->zState ){ |
2143 rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState); | 2354 rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState); |
2144 memcpy(p->zStateDb, "stat", 4); | 2355 memcpy(p->zStateDb, "stat", 4); |
2145 }else{ | 2356 }else{ |
2146 memcpy(p->zStateDb, "main", 4); | 2357 memcpy(p->zStateDb, "main", 4); |
2147 } | 2358 } |
2148 | 2359 |
| 2360 #if 0 |
| 2361 if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ |
| 2362 p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, 0); |
| 2363 } |
| 2364 #endif |
| 2365 |
| 2366 /* If it has not already been created, create the rbu_state table */ |
| 2367 rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); |
| 2368 |
| 2369 #if 0 |
| 2370 if( rbuIsVacuum(p) ){ |
| 2371 if( p->rc==SQLITE_OK ){ |
| 2372 int rc2; |
| 2373 int bOk = 0; |
| 2374 sqlite3_stmt *pCnt = 0; |
| 2375 p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg, |
| 2376 "SELECT count(*) FROM stat.sqlite_master" |
| 2377 ); |
| 2378 if( p->rc==SQLITE_OK |
| 2379 && sqlite3_step(pCnt)==SQLITE_ROW |
| 2380 && 1==sqlite3_column_int(pCnt, 0) |
| 2381 ){ |
| 2382 bOk = 1; |
| 2383 } |
| 2384 rc2 = sqlite3_finalize(pCnt); |
| 2385 if( p->rc==SQLITE_OK ) p->rc = rc2; |
| 2386 |
| 2387 if( p->rc==SQLITE_OK && bOk==0 ){ |
| 2388 p->rc = SQLITE_ERROR; |
| 2389 p->zErrmsg = sqlite3_mprintf("invalid state database"); |
| 2390 } |
| 2391 |
| 2392 if( p->rc==SQLITE_OK ){ |
| 2393 p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0); |
| 2394 } |
| 2395 } |
| 2396 } |
| 2397 #endif |
| 2398 |
| 2399 if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ |
| 2400 int bOpen = 0; |
| 2401 int rc; |
| 2402 p->nRbu = 0; |
| 2403 p->pRbuFd = 0; |
| 2404 rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); |
| 2405 if( rc!=SQLITE_NOTFOUND ) p->rc = rc; |
| 2406 if( p->eStage>=RBU_STAGE_MOVE ){ |
| 2407 bOpen = 1; |
| 2408 }else{ |
| 2409 RbuState *pState = rbuLoadState(p); |
| 2410 if( pState ){ |
| 2411 bOpen = (pState->eStage>=RBU_STAGE_MOVE); |
| 2412 rbuFreeState(pState); |
| 2413 } |
| 2414 } |
| 2415 if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1); |
| 2416 } |
| 2417 |
| 2418 p->eStage = 0; |
| 2419 if( p->rc==SQLITE_OK && p->dbMain==0 ){ |
| 2420 if( !rbuIsVacuum(p) ){ |
| 2421 p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1); |
| 2422 }else if( p->pRbuFd->pWalFd ){ |
| 2423 if( pbRetry ){ |
| 2424 p->pRbuFd->bNolock = 0; |
| 2425 sqlite3_close(p->dbRbu); |
| 2426 sqlite3_close(p->dbMain); |
| 2427 p->dbMain = 0; |
| 2428 p->dbRbu = 0; |
| 2429 *pbRetry = 1; |
| 2430 return; |
| 2431 } |
| 2432 p->rc = SQLITE_ERROR; |
| 2433 p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database"); |
| 2434 }else{ |
| 2435 char *zTarget; |
| 2436 char *zExtra = 0; |
| 2437 if( strlen(p->zRbu)>=5 && 0==memcmp("file:", p->zRbu, 5) ){ |
| 2438 zExtra = &p->zRbu[5]; |
| 2439 while( *zExtra ){ |
| 2440 if( *zExtra++=='?' ) break; |
| 2441 } |
| 2442 if( *zExtra=='\0' ) zExtra = 0; |
| 2443 } |
| 2444 |
| 2445 zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s", |
| 2446 sqlite3_db_filename(p->dbRbu, "main"), |
| 2447 (zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra) |
| 2448 ); |
| 2449 |
| 2450 if( zTarget==0 ){ |
| 2451 p->rc = SQLITE_NOMEM; |
| 2452 return; |
| 2453 } |
| 2454 p->dbMain = rbuOpenDbhandle(p, zTarget, p->nRbu<=1); |
| 2455 sqlite3_free(zTarget); |
| 2456 } |
| 2457 } |
| 2458 |
2149 if( p->rc==SQLITE_OK ){ | 2459 if( p->rc==SQLITE_OK ){ |
2150 p->rc = sqlite3_create_function(p->dbMain, | 2460 p->rc = sqlite3_create_function(p->dbMain, |
2151 "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 | 2461 "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 |
2152 ); | 2462 ); |
2153 } | 2463 } |
2154 | 2464 |
2155 if( p->rc==SQLITE_OK ){ | 2465 if( p->rc==SQLITE_OK ){ |
2156 p->rc = sqlite3_create_function(p->dbMain, | 2466 p->rc = sqlite3_create_function(p->dbMain, |
2157 "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0 | 2467 "rbu_fossil_delta", 2, SQLITE_UTF8, 0, rbuFossilDeltaFunc, 0, 0 |
2158 ); | 2468 ); |
2159 } | 2469 } |
2160 | 2470 |
2161 if( p->rc==SQLITE_OK ){ | 2471 if( p->rc==SQLITE_OK ){ |
2162 p->rc = sqlite3_create_function(p->dbRbu, | 2472 p->rc = sqlite3_create_function(p->dbRbu, |
2163 "rbu_target_name", 1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 | 2473 "rbu_target_name", -1, SQLITE_UTF8, (void*)p, rbuTargetNameFunc, 0, 0 |
2164 ); | 2474 ); |
2165 } | 2475 } |
2166 | 2476 |
2167 if( p->rc==SQLITE_OK ){ | 2477 if( p->rc==SQLITE_OK ){ |
2168 p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); | 2478 p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); |
2169 } | 2479 } |
2170 rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); | 2480 rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); |
2171 | 2481 |
2172 /* Mark the database file just opened as an RBU target database. If | 2482 /* Mark the database file just opened as an RBU target database. If |
2173 ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. | 2483 ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. |
(...skipping 28 matching lines...) Expand all Loading... |
2202 ** test.db-shm => test.shm | 2512 ** test.db-shm => test.shm |
2203 ** test.db-mj7f3319fa => test.9fa | 2513 ** test.db-mj7f3319fa => test.9fa |
2204 */ | 2514 */ |
2205 static void rbuFileSuffix3(const char *zBase, char *z){ | 2515 static void rbuFileSuffix3(const char *zBase, char *z){ |
2206 #ifdef SQLITE_ENABLE_8_3_NAMES | 2516 #ifdef SQLITE_ENABLE_8_3_NAMES |
2207 #if SQLITE_ENABLE_8_3_NAMES<2 | 2517 #if SQLITE_ENABLE_8_3_NAMES<2 |
2208 if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) | 2518 if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) |
2209 #endif | 2519 #endif |
2210 { | 2520 { |
2211 int i, sz; | 2521 int i, sz; |
2212 sz = sqlite3Strlen30(z); | 2522 sz = (int)strlen(z)&0xffffff; |
2213 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} | 2523 for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} |
2214 if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); | 2524 if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4); |
2215 } | 2525 } |
2216 #endif | 2526 #endif |
2217 } | 2527 } |
2218 | 2528 |
2219 /* | 2529 /* |
2220 ** Return the current wal-index header checksum for the target database | 2530 ** Return the current wal-index header checksum for the target database |
2221 ** as a 64-bit integer. | 2531 ** as a 64-bit integer. |
2222 ** | 2532 ** |
2223 ** The checksum is store in the first page of xShmMap memory as an 8-byte | 2533 ** The checksum is store in the first page of xShmMap memory as an 8-byte |
2224 ** blob starting at byte offset 40. | 2534 ** blob starting at byte offset 40. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2292 ** data from the wal file into the database file according to the | 2602 ** data from the wal file into the database file according to the |
2293 ** contents of aFrame[]. | 2603 ** contents of aFrame[]. |
2294 */ | 2604 */ |
2295 if( p->rc==SQLITE_OK ){ | 2605 if( p->rc==SQLITE_OK ){ |
2296 int rc2; | 2606 int rc2; |
2297 p->eStage = RBU_STAGE_CAPTURE; | 2607 p->eStage = RBU_STAGE_CAPTURE; |
2298 rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); | 2608 rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); |
2299 if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; | 2609 if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; |
2300 } | 2610 } |
2301 | 2611 |
2302 if( p->rc==SQLITE_OK ){ | 2612 if( p->rc==SQLITE_OK && p->nFrame>0 ){ |
2303 p->eStage = RBU_STAGE_CKPT; | 2613 p->eStage = RBU_STAGE_CKPT; |
2304 p->nStep = (pState ? pState->nRow : 0); | 2614 p->nStep = (pState ? pState->nRow : 0); |
2305 p->aBuf = rbuMalloc(p, p->pgsz); | 2615 p->aBuf = rbuMalloc(p, p->pgsz); |
2306 p->iWalCksum = rbuShmChecksum(p); | 2616 p->iWalCksum = rbuShmChecksum(p); |
2307 } | 2617 } |
2308 | 2618 |
2309 if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){ | 2619 if( p->rc==SQLITE_OK ){ |
2310 p->rc = SQLITE_DONE; | 2620 if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ |
2311 p->eStage = RBU_STAGE_DONE; | 2621 p->rc = SQLITE_DONE; |
| 2622 p->eStage = RBU_STAGE_DONE; |
| 2623 } |
2312 } | 2624 } |
2313 } | 2625 } |
2314 | 2626 |
2315 /* | 2627 /* |
2316 ** Called when iAmt bytes are read from offset iOff of the wal file while | 2628 ** Called when iAmt bytes are read from offset iOff of the wal file while |
2317 ** the rbu object is in capture mode. Record the frame number of the frame | 2629 ** the rbu object is in capture mode. Record the frame number of the frame |
2318 ** being read in the aFrame[] array. | 2630 ** being read in the aFrame[] array. |
2319 */ | 2631 */ |
2320 static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){ | 2632 static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){ |
2321 const u32 mReq = (1<<WAL_LOCK_WRITE)|(1<<WAL_LOCK_CKPT)|(1<<WAL_LOCK_READ0); | 2633 const u32 mReq = (1<<WAL_LOCK_WRITE)|(1<<WAL_LOCK_CKPT)|(1<<WAL_LOCK_READ0); |
2322 u32 iFrame; | 2634 u32 iFrame; |
2323 | 2635 |
2324 if( pRbu->mLock!=mReq ){ | 2636 if( pRbu->mLock!=mReq ){ |
2325 pRbu->rc = SQLITE_BUSY; | 2637 pRbu->rc = SQLITE_BUSY; |
2326 return SQLITE_INTERNAL; | 2638 return SQLITE_INTERNAL; |
2327 } | 2639 } |
2328 | 2640 |
2329 pRbu->pgsz = iAmt; | 2641 pRbu->pgsz = iAmt; |
2330 if( pRbu->nFrame==pRbu->nFrameAlloc ){ | 2642 if( pRbu->nFrame==pRbu->nFrameAlloc ){ |
2331 int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; | 2643 int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; |
2332 RbuFrame *aNew; | 2644 RbuFrame *aNew; |
2333 aNew = (RbuFrame*)sqlite3_realloc(pRbu->aFrame, nNew * sizeof(RbuFrame)); | 2645 aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame)); |
2334 if( aNew==0 ) return SQLITE_NOMEM; | 2646 if( aNew==0 ) return SQLITE_NOMEM; |
2335 pRbu->aFrame = aNew; | 2647 pRbu->aFrame = aNew; |
2336 pRbu->nFrameAlloc = nNew; | 2648 pRbu->nFrameAlloc = nNew; |
2337 } | 2649 } |
2338 | 2650 |
2339 iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; | 2651 iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; |
2340 if( pRbu->iMaxFrame<iFrame ) pRbu->iMaxFrame = iFrame; | 2652 if( pRbu->iMaxFrame<iFrame ) pRbu->iMaxFrame = iFrame; |
2341 pRbu->aFrame[pRbu->nFrame].iWalFrame = iFrame; | 2653 pRbu->aFrame[pRbu->nFrame].iWalFrame = iFrame; |
2342 pRbu->aFrame[pRbu->nFrame].iDbPage = 0; | 2654 pRbu->aFrame[pRbu->nFrame].iDbPage = 0; |
2343 pRbu->nFrame++; | 2655 pRbu->nFrame++; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2388 | 2700 |
2389 #if defined(_WIN32_WCE) | 2701 #if defined(_WIN32_WCE) |
2390 static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){ | 2702 static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){ |
2391 int nChar; | 2703 int nChar; |
2392 LPWSTR zWideFilename; | 2704 LPWSTR zWideFilename; |
2393 | 2705 |
2394 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); | 2706 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); |
2395 if( nChar==0 ){ | 2707 if( nChar==0 ){ |
2396 return 0; | 2708 return 0; |
2397 } | 2709 } |
2398 zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) ); | 2710 zWideFilename = sqlite3_malloc64( nChar*sizeof(zWideFilename[0]) ); |
2399 if( zWideFilename==0 ){ | 2711 if( zWideFilename==0 ){ |
2400 return 0; | 2712 return 0; |
2401 } | 2713 } |
2402 memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0])); | 2714 memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0])); |
2403 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, | 2715 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, |
2404 nChar); | 2716 nChar); |
2405 if( nChar==0 ){ | 2717 if( nChar==0 ){ |
2406 sqlite3_free(zWideFilename); | 2718 sqlite3_free(zWideFilename); |
2407 zWideFilename = 0; | 2719 zWideFilename = 0; |
2408 } | 2720 } |
2409 return zWideFilename; | 2721 return zWideFilename; |
2410 } | 2722 } |
2411 #endif | 2723 #endif |
2412 | 2724 |
2413 /* | 2725 /* |
2414 ** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock | 2726 ** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock |
2415 ** on the database file. This proc moves the *-oal file to the *-wal path, | 2727 ** on the database file. This proc moves the *-oal file to the *-wal path, |
2416 ** then reopens the database file (this time in vanilla, non-oal, WAL mode). | 2728 ** then reopens the database file (this time in vanilla, non-oal, WAL mode). |
2417 ** If an error occurs, leave an error code and error message in the rbu | 2729 ** If an error occurs, leave an error code and error message in the rbu |
2418 ** handle. | 2730 ** handle. |
2419 */ | 2731 */ |
2420 static void rbuMoveOalFile(sqlite3rbu *p){ | 2732 static void rbuMoveOalFile(sqlite3rbu *p){ |
2421 const char *zBase = sqlite3_db_filename(p->dbMain, "main"); | 2733 const char *zBase = sqlite3_db_filename(p->dbMain, "main"); |
| 2734 const char *zMove = zBase; |
| 2735 char *zOal; |
| 2736 char *zWal; |
2422 | 2737 |
2423 char *zWal = sqlite3_mprintf("%s-wal", zBase); | 2738 if( rbuIsVacuum(p) ){ |
2424 char *zOal = sqlite3_mprintf("%s-oal", zBase); | 2739 zMove = sqlite3_db_filename(p->dbRbu, "main"); |
| 2740 } |
| 2741 zOal = sqlite3_mprintf("%s-oal", zMove); |
| 2742 zWal = sqlite3_mprintf("%s-wal", zMove); |
2425 | 2743 |
2426 assert( p->eStage==RBU_STAGE_MOVE ); | 2744 assert( p->eStage==RBU_STAGE_MOVE ); |
2427 assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); | 2745 assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); |
2428 if( zWal==0 || zOal==0 ){ | 2746 if( zWal==0 || zOal==0 ){ |
2429 p->rc = SQLITE_NOMEM; | 2747 p->rc = SQLITE_NOMEM; |
2430 }else{ | 2748 }else{ |
2431 /* Move the *-oal file to *-wal. At this point connection p->db is | 2749 /* Move the *-oal file to *-wal. At this point connection p->db is |
2432 ** holding a SHARED lock on the target database file (because it is | 2750 ** holding a SHARED lock on the target database file (because it is |
2433 ** in WAL mode). So no other connection may be writing the db. | 2751 ** in WAL mode). So no other connection may be writing the db. |
2434 ** | 2752 ** |
2435 ** In order to ensure that there are no database readers, an EXCLUSIVE | 2753 ** In order to ensure that there are no database readers, an EXCLUSIVE |
2436 ** lock is obtained here before the *-oal is moved to *-wal. | 2754 ** lock is obtained here before the *-oal is moved to *-wal. |
2437 */ | 2755 */ |
2438 rbuLockDatabase(p); | 2756 rbuLockDatabase(p); |
2439 if( p->rc==SQLITE_OK ){ | 2757 if( p->rc==SQLITE_OK ){ |
2440 rbuFileSuffix3(zBase, zWal); | 2758 rbuFileSuffix3(zBase, zWal); |
2441 rbuFileSuffix3(zBase, zOal); | 2759 rbuFileSuffix3(zBase, zOal); |
2442 | 2760 |
2443 /* Re-open the databases. */ | 2761 /* Re-open the databases. */ |
2444 rbuObjIterFinalize(&p->objiter); | 2762 rbuObjIterFinalize(&p->objiter); |
| 2763 sqlite3_close(p->dbRbu); |
2445 sqlite3_close(p->dbMain); | 2764 sqlite3_close(p->dbMain); |
2446 sqlite3_close(p->dbRbu); | |
2447 p->dbMain = 0; | 2765 p->dbMain = 0; |
2448 p->dbRbu = 0; | 2766 p->dbRbu = 0; |
2449 | 2767 |
2450 #if defined(_WIN32_WCE) | 2768 #if defined(_WIN32_WCE) |
2451 { | 2769 { |
2452 LPWSTR zWideOal; | 2770 LPWSTR zWideOal; |
2453 LPWSTR zWideWal; | 2771 LPWSTR zWideWal; |
2454 | 2772 |
2455 zWideOal = rbuWinUtf8ToUnicode(zOal); | 2773 zWideOal = rbuWinUtf8ToUnicode(zOal); |
2456 if( zWideOal ){ | 2774 if( zWideOal ){ |
(...skipping 11 matching lines...) Expand all Loading... |
2468 sqlite3_free(zWideOal); | 2786 sqlite3_free(zWideOal); |
2469 }else{ | 2787 }else{ |
2470 p->rc = SQLITE_IOERR_NOMEM; | 2788 p->rc = SQLITE_IOERR_NOMEM; |
2471 } | 2789 } |
2472 } | 2790 } |
2473 #else | 2791 #else |
2474 p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK; | 2792 p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK; |
2475 #endif | 2793 #endif |
2476 | 2794 |
2477 if( p->rc==SQLITE_OK ){ | 2795 if( p->rc==SQLITE_OK ){ |
2478 rbuOpenDatabase(p); | 2796 rbuOpenDatabase(p, 0); |
2479 rbuSetupCheckpoint(p, 0); | 2797 rbuSetupCheckpoint(p, 0); |
2480 } | 2798 } |
2481 } | 2799 } |
2482 } | 2800 } |
2483 | 2801 |
2484 sqlite3_free(zWal); | 2802 sqlite3_free(zWal); |
2485 sqlite3_free(zOal); | 2803 sqlite3_free(zOal); |
2486 } | 2804 } |
2487 | 2805 |
2488 /* | 2806 /* |
(...skipping 13 matching lines...) Expand all Loading... |
2502 ** If the rbu_control field contains an invalid value, an error code and | 2820 ** If the rbu_control field contains an invalid value, an error code and |
2503 ** message are left in the RBU handle and zero returned. | 2821 ** message are left in the RBU handle and zero returned. |
2504 */ | 2822 */ |
2505 static int rbuStepType(sqlite3rbu *p, const char **pzMask){ | 2823 static int rbuStepType(sqlite3rbu *p, const char **pzMask){ |
2506 int iCol = p->objiter.nCol; /* Index of rbu_control column */ | 2824 int iCol = p->objiter.nCol; /* Index of rbu_control column */ |
2507 int res = 0; /* Return value */ | 2825 int res = 0; /* Return value */ |
2508 | 2826 |
2509 switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){ | 2827 switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){ |
2510 case SQLITE_INTEGER: { | 2828 case SQLITE_INTEGER: { |
2511 int iVal = sqlite3_column_int(p->objiter.pSelect, iCol); | 2829 int iVal = sqlite3_column_int(p->objiter.pSelect, iCol); |
2512 if( iVal==0 ){ | 2830 switch( iVal ){ |
2513 res = RBU_INSERT; | 2831 case 0: res = RBU_INSERT; break; |
2514 }else if( iVal==1 ){ | 2832 case 1: res = RBU_DELETE; break; |
2515 res = RBU_DELETE; | 2833 case 2: res = RBU_REPLACE; break; |
2516 }else if( iVal==2 ){ | 2834 case 3: res = RBU_IDX_DELETE; break; |
2517 res = RBU_IDX_DELETE; | 2835 case 4: res = RBU_IDX_INSERT; break; |
2518 }else if( iVal==3 ){ | |
2519 res = RBU_IDX_INSERT; | |
2520 } | 2836 } |
2521 break; | 2837 break; |
2522 } | 2838 } |
2523 | 2839 |
2524 case SQLITE_TEXT: { | 2840 case SQLITE_TEXT: { |
2525 const unsigned char *z = sqlite3_column_text(p->objiter.pSelect, iCol); | 2841 const unsigned char *z = sqlite3_column_text(p->objiter.pSelect, iCol); |
2526 if( z==0 ){ | 2842 if( z==0 ){ |
2527 p->rc = SQLITE_NOMEM; | 2843 p->rc = SQLITE_NOMEM; |
2528 }else{ | 2844 }else{ |
2529 *pzMask = (const char*)z; | 2845 *pzMask = (const char*)z; |
(...skipping 19 matching lines...) Expand all Loading... |
2549 */ | 2865 */ |
2550 static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){ | 2866 static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){ |
2551 const char *zCol = sqlite3_column_name(pStmt, iCol); | 2867 const char *zCol = sqlite3_column_name(pStmt, iCol); |
2552 assert( 0==sqlite3_stricmp(zName, zCol) ); | 2868 assert( 0==sqlite3_stricmp(zName, zCol) ); |
2553 } | 2869 } |
2554 #else | 2870 #else |
2555 # define assertColumnName(x,y,z) | 2871 # define assertColumnName(x,y,z) |
2556 #endif | 2872 #endif |
2557 | 2873 |
2558 /* | 2874 /* |
| 2875 ** Argument eType must be one of RBU_INSERT, RBU_DELETE, RBU_IDX_INSERT or |
| 2876 ** RBU_IDX_DELETE. This function performs the work of a single |
| 2877 ** sqlite3rbu_step() call for the type of operation specified by eType. |
| 2878 */ |
| 2879 static void rbuStepOneOp(sqlite3rbu *p, int eType){ |
| 2880 RbuObjIter *pIter = &p->objiter; |
| 2881 sqlite3_value *pVal; |
| 2882 sqlite3_stmt *pWriter; |
| 2883 int i; |
| 2884 |
| 2885 assert( p->rc==SQLITE_OK ); |
| 2886 assert( eType!=RBU_DELETE || pIter->zIdx==0 ); |
| 2887 assert( eType==RBU_DELETE || eType==RBU_IDX_DELETE |
| 2888 || eType==RBU_INSERT || eType==RBU_IDX_INSERT |
| 2889 ); |
| 2890 |
| 2891 /* If this is a delete, decrement nPhaseOneStep by nIndex. If the DELETE |
| 2892 ** statement below does actually delete a row, nPhaseOneStep will be |
| 2893 ** incremented by the same amount when SQL function rbu_tmp_insert() |
| 2894 ** is invoked by the trigger. */ |
| 2895 if( eType==RBU_DELETE ){ |
| 2896 p->nPhaseOneStep -= p->objiter.nIndex; |
| 2897 } |
| 2898 |
| 2899 if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){ |
| 2900 pWriter = pIter->pDelete; |
| 2901 }else{ |
| 2902 pWriter = pIter->pInsert; |
| 2903 } |
| 2904 |
| 2905 for(i=0; i<pIter->nCol; i++){ |
| 2906 /* If this is an INSERT into a table b-tree and the table has an |
| 2907 ** explicit INTEGER PRIMARY KEY, check that this is not an attempt |
| 2908 ** to write a NULL into the IPK column. That is not permitted. */ |
| 2909 if( eType==RBU_INSERT |
| 2910 && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] |
| 2911 && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL |
| 2912 ){ |
| 2913 p->rc = SQLITE_MISMATCH; |
| 2914 p->zErrmsg = sqlite3_mprintf("datatype mismatch"); |
| 2915 return; |
| 2916 } |
| 2917 |
| 2918 if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){ |
| 2919 continue; |
| 2920 } |
| 2921 |
| 2922 pVal = sqlite3_column_value(pIter->pSelect, i); |
| 2923 p->rc = sqlite3_bind_value(pWriter, i+1, pVal); |
| 2924 if( p->rc ) return; |
| 2925 } |
| 2926 if( pIter->zIdx==0 ){ |
| 2927 if( pIter->eType==RBU_PK_VTAB |
| 2928 || pIter->eType==RBU_PK_NONE |
| 2929 || (pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p)) |
| 2930 ){ |
| 2931 /* For a virtual table, or a table with no primary key, the |
| 2932 ** SELECT statement is: |
| 2933 ** |
| 2934 ** SELECT <cols>, rbu_control, rbu_rowid FROM .... |
| 2935 ** |
| 2936 ** Hence column_value(pIter->nCol+1). |
| 2937 */ |
| 2938 assertColumnName(pIter->pSelect, pIter->nCol+1, |
| 2939 rbuIsVacuum(p) ? "rowid" : "rbu_rowid" |
| 2940 ); |
| 2941 pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); |
| 2942 p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); |
| 2943 } |
| 2944 } |
| 2945 if( p->rc==SQLITE_OK ){ |
| 2946 sqlite3_step(pWriter); |
| 2947 p->rc = resetAndCollectError(pWriter, &p->zErrmsg); |
| 2948 } |
| 2949 } |
| 2950 |
| 2951 /* |
2559 ** This function does the work for an sqlite3rbu_step() call. | 2952 ** This function does the work for an sqlite3rbu_step() call. |
2560 ** | 2953 ** |
2561 ** The object-iterator (p->objiter) currently points to a valid object, | 2954 ** The object-iterator (p->objiter) currently points to a valid object, |
2562 ** and the input cursor (p->objiter.pSelect) currently points to a valid | 2955 ** and the input cursor (p->objiter.pSelect) currently points to a valid |
2563 ** input row. Perform whatever processing is required and return. | 2956 ** input row. Perform whatever processing is required and return. |
2564 ** | 2957 ** |
2565 ** If no error occurs, SQLITE_OK is returned. Otherwise, an error code | 2958 ** If no error occurs, SQLITE_OK is returned. Otherwise, an error code |
2566 ** and message is left in the RBU handle and a copy of the error code | 2959 ** and message is left in the RBU handle and a copy of the error code |
2567 ** returned. | 2960 ** returned. |
2568 */ | 2961 */ |
2569 static int rbuStep(sqlite3rbu *p){ | 2962 static int rbuStep(sqlite3rbu *p){ |
2570 RbuObjIter *pIter = &p->objiter; | 2963 RbuObjIter *pIter = &p->objiter; |
2571 const char *zMask = 0; | 2964 const char *zMask = 0; |
2572 int i; | |
2573 int eType = rbuStepType(p, &zMask); | 2965 int eType = rbuStepType(p, &zMask); |
2574 | 2966 |
2575 if( eType ){ | 2967 if( eType ){ |
| 2968 assert( eType==RBU_INSERT || eType==RBU_DELETE |
| 2969 || eType==RBU_REPLACE || eType==RBU_IDX_DELETE |
| 2970 || eType==RBU_IDX_INSERT || eType==RBU_UPDATE |
| 2971 ); |
2576 assert( eType!=RBU_UPDATE || pIter->zIdx==0 ); | 2972 assert( eType!=RBU_UPDATE || pIter->zIdx==0 ); |
2577 | 2973 |
2578 if( pIter->zIdx==0 && eType==RBU_IDX_DELETE ){ | 2974 if( pIter->zIdx==0 && (eType==RBU_IDX_DELETE || eType==RBU_IDX_INSERT) ){ |
2579 rbuBadControlError(p); | 2975 rbuBadControlError(p); |
2580 } | 2976 } |
2581 else if( | 2977 else if( eType==RBU_REPLACE ){ |
2582 eType==RBU_INSERT | 2978 if( pIter->zIdx==0 ){ |
2583 || eType==RBU_DELETE | 2979 p->nPhaseOneStep += p->objiter.nIndex; |
2584 || eType==RBU_IDX_DELETE | 2980 rbuStepOneOp(p, RBU_DELETE); |
2585 || eType==RBU_IDX_INSERT | |
2586 ){ | |
2587 sqlite3_value *pVal; | |
2588 sqlite3_stmt *pWriter; | |
2589 | |
2590 assert( eType!=RBU_UPDATE ); | |
2591 assert( eType!=RBU_DELETE || pIter->zIdx==0 ); | |
2592 | |
2593 if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){ | |
2594 pWriter = pIter->pDelete; | |
2595 }else{ | |
2596 pWriter = pIter->pInsert; | |
2597 } | 2981 } |
2598 | 2982 if( p->rc==SQLITE_OK ) rbuStepOneOp(p, RBU_INSERT); |
2599 for(i=0; i<pIter->nCol; i++){ | 2983 } |
2600 /* If this is an INSERT into a table b-tree and the table has an | 2984 else if( eType!=RBU_UPDATE ){ |
2601 ** explicit INTEGER PRIMARY KEY, check that this is not an attempt | 2985 rbuStepOneOp(p, eType); |
2602 ** to write a NULL into the IPK column. That is not permitted. */ | 2986 } |
2603 if( eType==RBU_INSERT | 2987 else{ |
2604 && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] | |
2605 && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL | |
2606 ){ | |
2607 p->rc = SQLITE_MISMATCH; | |
2608 p->zErrmsg = sqlite3_mprintf("datatype mismatch"); | |
2609 goto step_out; | |
2610 } | |
2611 | |
2612 if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){ | |
2613 continue; | |
2614 } | |
2615 | |
2616 pVal = sqlite3_column_value(pIter->pSelect, i); | |
2617 p->rc = sqlite3_bind_value(pWriter, i+1, pVal); | |
2618 if( p->rc ) goto step_out; | |
2619 } | |
2620 if( pIter->zIdx==0 | |
2621 && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) | |
2622 ){ | |
2623 /* For a virtual table, or a table with no primary key, the | |
2624 ** SELECT statement is: | |
2625 ** | |
2626 ** SELECT <cols>, rbu_control, rbu_rowid FROM .... | |
2627 ** | |
2628 ** Hence column_value(pIter->nCol+1). | |
2629 */ | |
2630 assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); | |
2631 pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); | |
2632 p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); | |
2633 } | |
2634 if( p->rc==SQLITE_OK ){ | |
2635 sqlite3_step(pWriter); | |
2636 p->rc = resetAndCollectError(pWriter, &p->zErrmsg); | |
2637 } | |
2638 }else{ | |
2639 sqlite3_value *pVal; | 2988 sqlite3_value *pVal; |
2640 sqlite3_stmt *pUpdate = 0; | 2989 sqlite3_stmt *pUpdate = 0; |
2641 assert( eType==RBU_UPDATE ); | 2990 assert( eType==RBU_UPDATE ); |
| 2991 p->nPhaseOneStep -= p->objiter.nIndex; |
2642 rbuGetUpdateStmt(p, pIter, zMask, &pUpdate); | 2992 rbuGetUpdateStmt(p, pIter, zMask, &pUpdate); |
2643 if( pUpdate ){ | 2993 if( pUpdate ){ |
| 2994 int i; |
2644 for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){ | 2995 for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){ |
2645 char c = zMask[pIter->aiSrcOrder[i]]; | 2996 char c = zMask[pIter->aiSrcOrder[i]]; |
2646 pVal = sqlite3_column_value(pIter->pSelect, i); | 2997 pVal = sqlite3_column_value(pIter->pSelect, i); |
2647 if( pIter->abTblPk[i] || c!='.' ){ | 2998 if( pIter->abTblPk[i] || c!='.' ){ |
2648 p->rc = sqlite3_bind_value(pUpdate, i+1, pVal); | 2999 p->rc = sqlite3_bind_value(pUpdate, i+1, pVal); |
2649 } | 3000 } |
2650 } | 3001 } |
2651 if( p->rc==SQLITE_OK | 3002 if( p->rc==SQLITE_OK |
2652 && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) | 3003 && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) |
2653 ){ | 3004 ){ |
2654 /* Bind the rbu_rowid value to column _rowid_ */ | 3005 /* Bind the rbu_rowid value to column _rowid_ */ |
2655 assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); | 3006 assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); |
2656 pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); | 3007 pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); |
2657 p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal); | 3008 p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal); |
2658 } | 3009 } |
2659 if( p->rc==SQLITE_OK ){ | 3010 if( p->rc==SQLITE_OK ){ |
2660 sqlite3_step(pUpdate); | 3011 sqlite3_step(pUpdate); |
2661 p->rc = resetAndCollectError(pUpdate, &p->zErrmsg); | 3012 p->rc = resetAndCollectError(pUpdate, &p->zErrmsg); |
2662 } | 3013 } |
2663 } | 3014 } |
2664 } | 3015 } |
2665 } | 3016 } |
2666 | |
2667 step_out: | |
2668 return p->rc; | 3017 return p->rc; |
2669 } | 3018 } |
2670 | 3019 |
2671 /* | 3020 /* |
2672 ** Increment the schema cookie of the main database opened by p->dbMain. | 3021 ** Increment the schema cookie of the main database opened by p->dbMain. |
| 3022 ** |
| 3023 ** Or, if this is an RBU vacuum, set the schema cookie of the main db |
| 3024 ** opened by p->dbMain to one more than the schema cookie of the main |
| 3025 ** db opened by p->dbRbu. |
2673 */ | 3026 */ |
2674 static void rbuIncrSchemaCookie(sqlite3rbu *p){ | 3027 static void rbuIncrSchemaCookie(sqlite3rbu *p){ |
2675 if( p->rc==SQLITE_OK ){ | 3028 if( p->rc==SQLITE_OK ){ |
| 3029 sqlite3 *dbread = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain); |
2676 int iCookie = 1000000; | 3030 int iCookie = 1000000; |
2677 sqlite3_stmt *pStmt; | 3031 sqlite3_stmt *pStmt; |
2678 | 3032 |
2679 p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, | 3033 p->rc = prepareAndCollectError(dbread, &pStmt, &p->zErrmsg, |
2680 "PRAGMA schema_version" | 3034 "PRAGMA schema_version" |
2681 ); | 3035 ); |
2682 if( p->rc==SQLITE_OK ){ | 3036 if( p->rc==SQLITE_OK ){ |
2683 /* Coverage: it may be that this sqlite3_step() cannot fail. There | 3037 /* Coverage: it may be that this sqlite3_step() cannot fail. There |
2684 ** is already a transaction open, so the prepared statement cannot | 3038 ** is already a transaction open, so the prepared statement cannot |
2685 ** throw an SQLITE_SCHEMA exception. The only database page the | 3039 ** throw an SQLITE_SCHEMA exception. The only database page the |
2686 ** statement reads is page 1, which is guaranteed to be in the cache. | 3040 ** statement reads is page 1, which is guaranteed to be in the cache. |
2687 ** And no memory allocations are required. */ | 3041 ** And no memory allocations are required. */ |
2688 if( SQLITE_ROW==sqlite3_step(pStmt) ){ | 3042 if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
2689 iCookie = sqlite3_column_int(pStmt, 0); | 3043 iCookie = sqlite3_column_int(pStmt, 0); |
2690 } | 3044 } |
2691 rbuFinalize(p, pStmt); | 3045 rbuFinalize(p, pStmt); |
2692 } | 3046 } |
2693 if( p->rc==SQLITE_OK ){ | 3047 if( p->rc==SQLITE_OK ){ |
2694 rbuMPrintfExec(p, p->dbMain, "PRAGMA schema_version = %d", iCookie+1); | 3048 rbuMPrintfExec(p, p->dbMain, "PRAGMA schema_version = %d", iCookie+1); |
2695 } | 3049 } |
2696 } | 3050 } |
2697 } | 3051 } |
2698 | 3052 |
2699 /* | 3053 /* |
2700 ** Update the contents of the rbu_state table within the rbu database. The | 3054 ** Update the contents of the rbu_state table within the rbu database. The |
2701 ** value stored in the RBU_STATE_STAGE column is eStage. All other values | 3055 ** value stored in the RBU_STATE_STAGE column is eStage. All other values |
2702 ** are determined by inspecting the rbu handle passed as the first argument. | 3056 ** are determined by inspecting the rbu handle passed as the first argument. |
2703 */ | 3057 */ |
2704 static void rbuSaveState(sqlite3rbu *p, int eStage){ | 3058 static void rbuSaveState(sqlite3rbu *p, int eStage){ |
2705 if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ | 3059 if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ |
2706 sqlite3_stmt *pInsert = 0; | 3060 sqlite3_stmt *pInsert = 0; |
| 3061 rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd); |
2707 int rc; | 3062 int rc; |
2708 | 3063 |
2709 assert( p->zErrmsg==0 ); | 3064 assert( p->zErrmsg==0 ); |
2710 rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg, | 3065 rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg, |
2711 sqlite3_mprintf( | 3066 sqlite3_mprintf( |
2712 "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES " | 3067 "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES " |
2713 "(%d, %d), " | 3068 "(%d, %d), " |
2714 "(%d, %Q), " | 3069 "(%d, %Q), " |
2715 "(%d, %Q), " | 3070 "(%d, %Q), " |
2716 "(%d, %d), " | 3071 "(%d, %d), " |
2717 "(%d, %d), " | 3072 "(%d, %d), " |
2718 "(%d, %lld), " | 3073 "(%d, %lld), " |
2719 "(%d, %lld), " | 3074 "(%d, %lld), " |
| 3075 "(%d, %lld), " |
2720 "(%d, %lld) ", | 3076 "(%d, %lld) ", |
2721 p->zStateDb, | 3077 p->zStateDb, |
2722 RBU_STATE_STAGE, eStage, | 3078 RBU_STATE_STAGE, eStage, |
2723 RBU_STATE_TBL, p->objiter.zTbl, | 3079 RBU_STATE_TBL, p->objiter.zTbl, |
2724 RBU_STATE_IDX, p->objiter.zIdx, | 3080 RBU_STATE_IDX, p->objiter.zIdx, |
2725 RBU_STATE_ROW, p->nStep, | 3081 RBU_STATE_ROW, p->nStep, |
2726 RBU_STATE_PROGRESS, p->nProgress, | 3082 RBU_STATE_PROGRESS, p->nProgress, |
2727 RBU_STATE_CKPT, p->iWalCksum, | 3083 RBU_STATE_CKPT, p->iWalCksum, |
2728 RBU_STATE_COOKIE, (i64)p->pTargetFd->iCookie, | 3084 RBU_STATE_COOKIE, (i64)pFd->iCookie, |
2729 RBU_STATE_OALSZ, p->iOalSz | 3085 RBU_STATE_OALSZ, p->iOalSz, |
| 3086 RBU_STATE_PHASEONESTEP, p->nPhaseOneStep |
2730 ) | 3087 ) |
2731 ); | 3088 ); |
2732 assert( pInsert==0 || rc==SQLITE_OK ); | 3089 assert( pInsert==0 || rc==SQLITE_OK ); |
2733 | 3090 |
2734 if( rc==SQLITE_OK ){ | 3091 if( rc==SQLITE_OK ){ |
2735 sqlite3_step(pInsert); | 3092 sqlite3_step(pInsert); |
2736 rc = sqlite3_finalize(pInsert); | 3093 rc = sqlite3_finalize(pInsert); |
2737 } | 3094 } |
2738 if( rc!=SQLITE_OK ) p->rc = rc; | 3095 if( rc!=SQLITE_OK ) p->rc = rc; |
2739 } | 3096 } |
2740 } | 3097 } |
2741 | 3098 |
2742 | 3099 |
2743 /* | 3100 /* |
| 3101 ** The second argument passed to this function is the name of a PRAGMA |
| 3102 ** setting - "page_size", "auto_vacuum", "user_version" or "application_id". |
| 3103 ** This function executes the following on sqlite3rbu.dbRbu: |
| 3104 ** |
| 3105 ** "PRAGMA main.$zPragma" |
| 3106 ** |
| 3107 ** where $zPragma is the string passed as the second argument, then |
| 3108 ** on sqlite3rbu.dbMain: |
| 3109 ** |
| 3110 ** "PRAGMA main.$zPragma = $val" |
| 3111 ** |
| 3112 ** where $val is the value returned by the first PRAGMA invocation. |
| 3113 ** |
| 3114 ** In short, it copies the value of the specified PRAGMA setting from |
| 3115 ** dbRbu to dbMain. |
| 3116 */ |
| 3117 static void rbuCopyPragma(sqlite3rbu *p, const char *zPragma){ |
| 3118 if( p->rc==SQLITE_OK ){ |
| 3119 sqlite3_stmt *pPragma = 0; |
| 3120 p->rc = prepareFreeAndCollectError(p->dbRbu, &pPragma, &p->zErrmsg, |
| 3121 sqlite3_mprintf("PRAGMA main.%s", zPragma) |
| 3122 ); |
| 3123 if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPragma) ){ |
| 3124 p->rc = rbuMPrintfExec(p, p->dbMain, "PRAGMA main.%s = %d", |
| 3125 zPragma, sqlite3_column_int(pPragma, 0) |
| 3126 ); |
| 3127 } |
| 3128 rbuFinalize(p, pPragma); |
| 3129 } |
| 3130 } |
| 3131 |
| 3132 /* |
| 3133 ** The RBU handle passed as the only argument has just been opened and |
| 3134 ** the state database is empty. If this RBU handle was opened for an |
| 3135 ** RBU vacuum operation, create the schema in the target db. |
| 3136 */ |
| 3137 static void rbuCreateTargetSchema(sqlite3rbu *p){ |
| 3138 sqlite3_stmt *pSql = 0; |
| 3139 sqlite3_stmt *pInsert = 0; |
| 3140 |
| 3141 assert( rbuIsVacuum(p) ); |
| 3142 p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=1", 0,0, &p->zErrmsg); |
| 3143 if( p->rc==SQLITE_OK ){ |
| 3144 p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, |
| 3145 "SELECT sql FROM sqlite_master WHERE sql!='' AND rootpage!=0" |
| 3146 " AND name!='sqlite_sequence' " |
| 3147 " ORDER BY type DESC" |
| 3148 ); |
| 3149 } |
| 3150 |
| 3151 while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){ |
| 3152 const char *zSql = (const char*)sqlite3_column_text(pSql, 0); |
| 3153 p->rc = sqlite3_exec(p->dbMain, zSql, 0, 0, &p->zErrmsg); |
| 3154 } |
| 3155 rbuFinalize(p, pSql); |
| 3156 if( p->rc!=SQLITE_OK ) return; |
| 3157 |
| 3158 if( p->rc==SQLITE_OK ){ |
| 3159 p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg, |
| 3160 "SELECT * FROM sqlite_master WHERE rootpage=0 OR rootpage IS NULL" |
| 3161 ); |
| 3162 } |
| 3163 |
| 3164 if( p->rc==SQLITE_OK ){ |
| 3165 p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg, |
| 3166 "INSERT INTO sqlite_master VALUES(?,?,?,?,?)" |
| 3167 ); |
| 3168 } |
| 3169 |
| 3170 while( p->rc==SQLITE_OK && sqlite3_step(pSql)==SQLITE_ROW ){ |
| 3171 int i; |
| 3172 for(i=0; i<5; i++){ |
| 3173 sqlite3_bind_value(pInsert, i+1, sqlite3_column_value(pSql, i)); |
| 3174 } |
| 3175 sqlite3_step(pInsert); |
| 3176 p->rc = sqlite3_reset(pInsert); |
| 3177 } |
| 3178 if( p->rc==SQLITE_OK ){ |
| 3179 p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=0",0,0,&p->zErrmsg); |
| 3180 } |
| 3181 |
| 3182 rbuFinalize(p, pSql); |
| 3183 rbuFinalize(p, pInsert); |
| 3184 } |
| 3185 |
| 3186 /* |
2744 ** Step the RBU object. | 3187 ** Step the RBU object. |
2745 */ | 3188 */ |
2746 int sqlite3rbu_step(sqlite3rbu *p){ | 3189 int sqlite3rbu_step(sqlite3rbu *p){ |
2747 if( p ){ | 3190 if( p ){ |
2748 switch( p->eStage ){ | 3191 switch( p->eStage ){ |
2749 case RBU_STAGE_OAL: { | 3192 case RBU_STAGE_OAL: { |
2750 RbuObjIter *pIter = &p->objiter; | 3193 RbuObjIter *pIter = &p->objiter; |
| 3194 |
| 3195 /* If this is an RBU vacuum operation and the state table was empty |
| 3196 ** when this handle was opened, create the target database schema. */ |
| 3197 if( rbuIsVacuum(p) && p->nProgress==0 && p->rc==SQLITE_OK ){ |
| 3198 rbuCreateTargetSchema(p); |
| 3199 rbuCopyPragma(p, "user_version"); |
| 3200 rbuCopyPragma(p, "application_id"); |
| 3201 } |
| 3202 |
2751 while( p->rc==SQLITE_OK && pIter->zTbl ){ | 3203 while( p->rc==SQLITE_OK && pIter->zTbl ){ |
2752 | 3204 |
2753 if( pIter->bCleanup ){ | 3205 if( pIter->bCleanup ){ |
2754 /* Clean up the rbu_tmp_xxx table for the previous table. It | 3206 /* Clean up the rbu_tmp_xxx table for the previous table. It |
2755 ** cannot be dropped as there are currently active SQL statements. | 3207 ** cannot be dropped as there are currently active SQL statements. |
2756 ** But the contents can be deleted. */ | 3208 ** But the contents can be deleted. */ |
2757 if( pIter->abIndexed ){ | 3209 if( rbuIsVacuum(p)==0 && pIter->abIndexed ){ |
2758 rbuMPrintfExec(p, p->dbRbu, | 3210 rbuMPrintfExec(p, p->dbRbu, |
2759 "DELETE FROM %s.'rbu_tmp_%q'", p->zStateDb, pIter->zDataTbl | 3211 "DELETE FROM %s.'rbu_tmp_%q'", p->zStateDb, pIter->zDataTbl |
2760 ); | 3212 ); |
2761 } | 3213 } |
2762 }else{ | 3214 }else{ |
2763 rbuObjIterPrepareAll(p, pIter, 0); | 3215 rbuObjIterPrepareAll(p, pIter, 0); |
2764 | 3216 |
2765 /* Advance to the next row to process. */ | 3217 /* Advance to the next row to process. */ |
2766 if( p->rc==SQLITE_OK ){ | 3218 if( p->rc==SQLITE_OK ){ |
2767 int rc = sqlite3_step(pIter->pSelect); | 3219 int rc = sqlite3_step(pIter->pSelect); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2835 default: | 3287 default: |
2836 break; | 3288 break; |
2837 } | 3289 } |
2838 return p->rc; | 3290 return p->rc; |
2839 }else{ | 3291 }else{ |
2840 return SQLITE_NOMEM; | 3292 return SQLITE_NOMEM; |
2841 } | 3293 } |
2842 } | 3294 } |
2843 | 3295 |
2844 /* | 3296 /* |
2845 ** Free an RbuState object allocated by rbuLoadState(). | |
2846 */ | |
2847 static void rbuFreeState(RbuState *p){ | |
2848 if( p ){ | |
2849 sqlite3_free(p->zTbl); | |
2850 sqlite3_free(p->zIdx); | |
2851 sqlite3_free(p); | |
2852 } | |
2853 } | |
2854 | |
2855 /* | |
2856 ** Allocate an RbuState object and load the contents of the rbu_state | |
2857 ** table into it. Return a pointer to the new object. It is the | |
2858 ** responsibility of the caller to eventually free the object using | |
2859 ** sqlite3_free(). | |
2860 ** | |
2861 ** If an error occurs, leave an error code and message in the rbu handle | |
2862 ** and return NULL. | |
2863 */ | |
2864 static RbuState *rbuLoadState(sqlite3rbu *p){ | |
2865 RbuState *pRet = 0; | |
2866 sqlite3_stmt *pStmt = 0; | |
2867 int rc; | |
2868 int rc2; | |
2869 | |
2870 pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); | |
2871 if( pRet==0 ) return 0; | |
2872 | |
2873 rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, | |
2874 sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) | |
2875 ); | |
2876 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ | |
2877 switch( sqlite3_column_int(pStmt, 0) ){ | |
2878 case RBU_STATE_STAGE: | |
2879 pRet->eStage = sqlite3_column_int(pStmt, 1); | |
2880 if( pRet->eStage!=RBU_STAGE_OAL | |
2881 && pRet->eStage!=RBU_STAGE_MOVE | |
2882 && pRet->eStage!=RBU_STAGE_CKPT | |
2883 ){ | |
2884 p->rc = SQLITE_CORRUPT; | |
2885 } | |
2886 break; | |
2887 | |
2888 case RBU_STATE_TBL: | |
2889 pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); | |
2890 break; | |
2891 | |
2892 case RBU_STATE_IDX: | |
2893 pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); | |
2894 break; | |
2895 | |
2896 case RBU_STATE_ROW: | |
2897 pRet->nRow = sqlite3_column_int(pStmt, 1); | |
2898 break; | |
2899 | |
2900 case RBU_STATE_PROGRESS: | |
2901 pRet->nProgress = sqlite3_column_int64(pStmt, 1); | |
2902 break; | |
2903 | |
2904 case RBU_STATE_CKPT: | |
2905 pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); | |
2906 break; | |
2907 | |
2908 case RBU_STATE_COOKIE: | |
2909 pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); | |
2910 break; | |
2911 | |
2912 case RBU_STATE_OALSZ: | |
2913 pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); | |
2914 break; | |
2915 | |
2916 default: | |
2917 rc = SQLITE_CORRUPT; | |
2918 break; | |
2919 } | |
2920 } | |
2921 rc2 = sqlite3_finalize(pStmt); | |
2922 if( rc==SQLITE_OK ) rc = rc2; | |
2923 | |
2924 p->rc = rc; | |
2925 return pRet; | |
2926 } | |
2927 | |
2928 /* | |
2929 ** Compare strings z1 and z2, returning 0 if they are identical, or non-zero | 3297 ** Compare strings z1 and z2, returning 0 if they are identical, or non-zero |
2930 ** otherwise. Either or both argument may be NULL. Two NULL values are | 3298 ** otherwise. Either or both argument may be NULL. Two NULL values are |
2931 ** considered equal, and NULL is considered distinct from all other values. | 3299 ** considered equal, and NULL is considered distinct from all other values. |
2932 */ | 3300 */ |
2933 static int rbuStrCompare(const char *z1, const char *z2){ | 3301 static int rbuStrCompare(const char *z1, const char *z2){ |
2934 if( z1==0 && z2==0 ) return 0; | 3302 if( z1==0 && z2==0 ) return 0; |
2935 if( z1==0 || z2==0 ) return 1; | 3303 if( z1==0 || z2==0 ) return 1; |
2936 return (sqlite3_stricmp(z1, z2)!=0); | 3304 return (sqlite3_stricmp(z1, z2)!=0); |
2937 } | 3305 } |
2938 | 3306 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3014 ** argument by an earlier call to rbuCreateVfs(). | 3382 ** argument by an earlier call to rbuCreateVfs(). |
3015 */ | 3383 */ |
3016 static void rbuDeleteVfs(sqlite3rbu *p){ | 3384 static void rbuDeleteVfs(sqlite3rbu *p){ |
3017 if( p->zVfsName ){ | 3385 if( p->zVfsName ){ |
3018 sqlite3rbu_destroy_vfs(p->zVfsName); | 3386 sqlite3rbu_destroy_vfs(p->zVfsName); |
3019 p->zVfsName = 0; | 3387 p->zVfsName = 0; |
3020 } | 3388 } |
3021 } | 3389 } |
3022 | 3390 |
3023 /* | 3391 /* |
3024 ** Open and return a new RBU handle. | 3392 ** This user-defined SQL function is invoked with a single argument - the |
| 3393 ** name of a table expected to appear in the target database. It returns |
| 3394 ** the number of auxilliary indexes on the table. |
3025 */ | 3395 */ |
3026 sqlite3rbu *sqlite3rbu_open( | 3396 static void rbuIndexCntFunc( |
| 3397 sqlite3_context *pCtx, |
| 3398 int nVal, |
| 3399 sqlite3_value **apVal |
| 3400 ){ |
| 3401 sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx); |
| 3402 sqlite3_stmt *pStmt = 0; |
| 3403 char *zErrmsg = 0; |
| 3404 int rc; |
| 3405 |
| 3406 assert( nVal==1 ); |
| 3407 |
| 3408 rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg, |
| 3409 sqlite3_mprintf("SELECT count(*) FROM sqlite_master " |
| 3410 "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0])) |
| 3411 ); |
| 3412 if( rc!=SQLITE_OK ){ |
| 3413 sqlite3_result_error(pCtx, zErrmsg, -1); |
| 3414 }else{ |
| 3415 int nIndex = 0; |
| 3416 if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 3417 nIndex = sqlite3_column_int(pStmt, 0); |
| 3418 } |
| 3419 rc = sqlite3_finalize(pStmt); |
| 3420 if( rc==SQLITE_OK ){ |
| 3421 sqlite3_result_int(pCtx, nIndex); |
| 3422 }else{ |
| 3423 sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1); |
| 3424 } |
| 3425 } |
| 3426 |
| 3427 sqlite3_free(zErrmsg); |
| 3428 } |
| 3429 |
| 3430 /* |
| 3431 ** If the RBU database contains the rbu_count table, use it to initialize |
| 3432 ** the sqlite3rbu.nPhaseOneStep variable. The schema of the rbu_count table |
| 3433 ** is assumed to contain the same columns as: |
| 3434 ** |
| 3435 ** CREATE TABLE rbu_count(tbl TEXT PRIMARY KEY, cnt INTEGER) WITHOUT ROWID; |
| 3436 ** |
| 3437 ** There should be one row in the table for each data_xxx table in the |
| 3438 ** database. The 'tbl' column should contain the name of a data_xxx table, |
| 3439 ** and the cnt column the number of rows it contains. |
| 3440 ** |
| 3441 ** sqlite3rbu.nPhaseOneStep is initialized to the sum of (1 + nIndex) * cnt |
| 3442 ** for all rows in the rbu_count table, where nIndex is the number of |
| 3443 ** indexes on the corresponding target database table. |
| 3444 */ |
| 3445 static void rbuInitPhaseOneSteps(sqlite3rbu *p){ |
| 3446 if( p->rc==SQLITE_OK ){ |
| 3447 sqlite3_stmt *pStmt = 0; |
| 3448 int bExists = 0; /* True if rbu_count exists */ |
| 3449 |
| 3450 p->nPhaseOneStep = -1; |
| 3451 |
| 3452 p->rc = sqlite3_create_function(p->dbRbu, |
| 3453 "rbu_index_cnt", 1, SQLITE_UTF8, (void*)p, rbuIndexCntFunc, 0, 0 |
| 3454 ); |
| 3455 |
| 3456 /* Check for the rbu_count table. If it does not exist, or if an error |
| 3457 ** occurs, nPhaseOneStep will be left set to -1. */ |
| 3458 if( p->rc==SQLITE_OK ){ |
| 3459 p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, |
| 3460 "SELECT 1 FROM sqlite_master WHERE tbl_name = 'rbu_count'" |
| 3461 ); |
| 3462 } |
| 3463 if( p->rc==SQLITE_OK ){ |
| 3464 if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 3465 bExists = 1; |
| 3466 } |
| 3467 p->rc = sqlite3_finalize(pStmt); |
| 3468 } |
| 3469 |
| 3470 if( p->rc==SQLITE_OK && bExists ){ |
| 3471 p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, |
| 3472 "SELECT sum(cnt * (1 + rbu_index_cnt(rbu_target_name(tbl))))" |
| 3473 "FROM rbu_count" |
| 3474 ); |
| 3475 if( p->rc==SQLITE_OK ){ |
| 3476 if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 3477 p->nPhaseOneStep = sqlite3_column_int64(pStmt, 0); |
| 3478 } |
| 3479 p->rc = sqlite3_finalize(pStmt); |
| 3480 } |
| 3481 } |
| 3482 } |
| 3483 } |
| 3484 |
| 3485 |
| 3486 static sqlite3rbu *openRbuHandle( |
3027 const char *zTarget, | 3487 const char *zTarget, |
3028 const char *zRbu, | 3488 const char *zRbu, |
3029 const char *zState | 3489 const char *zState |
3030 ){ | 3490 ){ |
3031 sqlite3rbu *p; | 3491 sqlite3rbu *p; |
3032 int nTarget = strlen(zTarget); | 3492 size_t nTarget = zTarget ? strlen(zTarget) : 0; |
3033 int nRbu = strlen(zRbu); | 3493 size_t nRbu = strlen(zRbu); |
3034 int nState = zState ? strlen(zState) : 0; | 3494 size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1; |
3035 | 3495 |
3036 p = (sqlite3rbu*)sqlite3_malloc(sizeof(sqlite3rbu)+nTarget+1+nRbu+1+nState+1); | 3496 p = (sqlite3rbu*)sqlite3_malloc64(nByte); |
3037 if( p ){ | 3497 if( p ){ |
3038 RbuState *pState = 0; | 3498 RbuState *pState = 0; |
3039 | 3499 |
3040 /* Create the custom VFS. */ | 3500 /* Create the custom VFS. */ |
3041 memset(p, 0, sizeof(sqlite3rbu)); | 3501 memset(p, 0, sizeof(sqlite3rbu)); |
3042 rbuCreateVfs(p); | 3502 rbuCreateVfs(p); |
3043 | 3503 |
3044 /* Open the target database */ | 3504 /* Open the target, RBU and state databases */ |
3045 if( p->rc==SQLITE_OK ){ | 3505 if( p->rc==SQLITE_OK ){ |
3046 p->zTarget = (char*)&p[1]; | 3506 char *pCsr = (char*)&p[1]; |
3047 memcpy(p->zTarget, zTarget, nTarget+1); | 3507 int bRetry = 0; |
3048 p->zRbu = &p->zTarget[nTarget+1]; | 3508 if( zTarget ){ |
| 3509 p->zTarget = pCsr; |
| 3510 memcpy(p->zTarget, zTarget, nTarget+1); |
| 3511 pCsr += nTarget+1; |
| 3512 } |
| 3513 p->zRbu = pCsr; |
3049 memcpy(p->zRbu, zRbu, nRbu+1); | 3514 memcpy(p->zRbu, zRbu, nRbu+1); |
| 3515 pCsr += nRbu+1; |
3050 if( zState ){ | 3516 if( zState ){ |
3051 p->zState = &p->zRbu[nRbu+1]; | 3517 p->zState = rbuMPrintf(p, "%s", zState); |
3052 memcpy(p->zState, zState, nState+1); | |
3053 } | 3518 } |
3054 rbuOpenDatabase(p); | 3519 |
| 3520 /* If the first attempt to open the database file fails and the bRetry |
| 3521 ** flag it set, this means that the db was not opened because it seemed |
| 3522 ** to be a wal-mode db. But, this may have happened due to an earlier |
| 3523 ** RBU vacuum operation leaving an old wal file in the directory. |
| 3524 ** If this is the case, it will have been checkpointed and deleted |
| 3525 ** when the handle was closed and a second attempt to open the |
| 3526 ** database may succeed. */ |
| 3527 rbuOpenDatabase(p, &bRetry); |
| 3528 if( bRetry ){ |
| 3529 rbuOpenDatabase(p, 0); |
| 3530 } |
3055 } | 3531 } |
3056 | 3532 |
3057 /* If it has not already been created, create the rbu_state table */ | |
3058 rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); | |
3059 | |
3060 if( p->rc==SQLITE_OK ){ | 3533 if( p->rc==SQLITE_OK ){ |
3061 pState = rbuLoadState(p); | 3534 pState = rbuLoadState(p); |
3062 assert( pState || p->rc!=SQLITE_OK ); | 3535 assert( pState || p->rc!=SQLITE_OK ); |
3063 if( p->rc==SQLITE_OK ){ | 3536 if( p->rc==SQLITE_OK ){ |
3064 | 3537 |
3065 if( pState->eStage==0 ){ | 3538 if( pState->eStage==0 ){ |
3066 rbuDeleteOalFile(p); | 3539 rbuDeleteOalFile(p); |
| 3540 rbuInitPhaseOneSteps(p); |
3067 p->eStage = RBU_STAGE_OAL; | 3541 p->eStage = RBU_STAGE_OAL; |
3068 }else{ | 3542 }else{ |
3069 p->eStage = pState->eStage; | 3543 p->eStage = pState->eStage; |
| 3544 p->nPhaseOneStep = pState->nPhaseOneStep; |
3070 } | 3545 } |
3071 p->nProgress = pState->nProgress; | 3546 p->nProgress = pState->nProgress; |
3072 p->iOalSz = pState->iOalSz; | 3547 p->iOalSz = pState->iOalSz; |
3073 } | 3548 } |
3074 } | 3549 } |
3075 assert( p->rc!=SQLITE_OK || p->eStage!=0 ); | 3550 assert( p->rc!=SQLITE_OK || p->eStage!=0 ); |
3076 | 3551 |
3077 if( p->rc==SQLITE_OK && p->pTargetFd->pWalFd ){ | 3552 if( p->rc==SQLITE_OK && p->pTargetFd->pWalFd ){ |
3078 if( p->eStage==RBU_STAGE_OAL ){ | 3553 if( p->eStage==RBU_STAGE_OAL ){ |
3079 p->rc = SQLITE_ERROR; | 3554 p->rc = SQLITE_ERROR; |
3080 p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); | 3555 p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); |
3081 }else if( p->eStage==RBU_STAGE_MOVE ){ | 3556 }else if( p->eStage==RBU_STAGE_MOVE ){ |
3082 p->eStage = RBU_STAGE_CKPT; | 3557 p->eStage = RBU_STAGE_CKPT; |
3083 p->nStep = 0; | 3558 p->nStep = 0; |
3084 } | 3559 } |
3085 } | 3560 } |
3086 | 3561 |
3087 if( p->rc==SQLITE_OK | 3562 if( p->rc==SQLITE_OK |
3088 && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE) | 3563 && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE) |
3089 && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie | 3564 && pState->eStage!=0 |
3090 ){ | 3565 ){ |
3091 /* At this point (pTargetFd->iCookie) contains the value of the | 3566 rbu_file *pFd = (rbuIsVacuum(p) ? p->pRbuFd : p->pTargetFd); |
3092 ** change-counter cookie (the thing that gets incremented when a | 3567 if( pFd->iCookie!=pState->iCookie ){ |
3093 ** transaction is committed in rollback mode) currently stored on | 3568 /* At this point (pTargetFd->iCookie) contains the value of the |
3094 ** page 1 of the database file. */ | 3569 ** change-counter cookie (the thing that gets incremented when a |
3095 p->rc = SQLITE_BUSY; | 3570 ** transaction is committed in rollback mode) currently stored on |
3096 p->zErrmsg = sqlite3_mprintf("database modified during rbu update"); | 3571 ** page 1 of the database file. */ |
| 3572 p->rc = SQLITE_BUSY; |
| 3573 p->zErrmsg = sqlite3_mprintf("database modified during rbu %s", |
| 3574 (rbuIsVacuum(p) ? "vacuum" : "update") |
| 3575 ); |
| 3576 } |
3097 } | 3577 } |
3098 | 3578 |
3099 if( p->rc==SQLITE_OK ){ | 3579 if( p->rc==SQLITE_OK ){ |
3100 if( p->eStage==RBU_STAGE_OAL ){ | 3580 if( p->eStage==RBU_STAGE_OAL ){ |
3101 sqlite3 *db = p->dbMain; | 3581 sqlite3 *db = p->dbMain; |
3102 | 3582 p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, &p->zErrmsg); |
3103 /* Open transactions both databases. The *-oal file is opened or | |
3104 ** created at this point. */ | |
3105 p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); | |
3106 if( p->rc==SQLITE_OK ){ | |
3107 p->rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); | |
3108 } | |
3109 | |
3110 /* Check if the main database is a zipvfs db. If it is, set the upper | |
3111 ** level pager to use "journal_mode=off". This prevents it from | |
3112 ** generating a large journal using a temp file. */ | |
3113 if( p->rc==SQLITE_OK ){ | |
3114 int frc = sqlite3_file_control(db, "main", SQLITE_FCNTL_ZIPVFS, 0); | |
3115 if( frc==SQLITE_OK ){ | |
3116 p->rc = sqlite3_exec(db, "PRAGMA journal_mode=off",0,0,&p->zErrmsg); | |
3117 } | |
3118 } | |
3119 | 3583 |
3120 /* Point the object iterator at the first object */ | 3584 /* Point the object iterator at the first object */ |
3121 if( p->rc==SQLITE_OK ){ | 3585 if( p->rc==SQLITE_OK ){ |
3122 p->rc = rbuObjIterFirst(p, &p->objiter); | 3586 p->rc = rbuObjIterFirst(p, &p->objiter); |
3123 } | 3587 } |
3124 | 3588 |
3125 /* If the RBU database contains no data_xxx tables, declare the RBU | 3589 /* If the RBU database contains no data_xxx tables, declare the RBU |
3126 ** update finished. */ | 3590 ** update finished. */ |
3127 if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){ | 3591 if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){ |
3128 p->rc = SQLITE_DONE; | 3592 p->rc = SQLITE_DONE; |
| 3593 p->eStage = RBU_STAGE_DONE; |
| 3594 }else{ |
| 3595 if( p->rc==SQLITE_OK && pState->eStage==0 && rbuIsVacuum(p) ){ |
| 3596 rbuCopyPragma(p, "page_size"); |
| 3597 rbuCopyPragma(p, "auto_vacuum"); |
| 3598 } |
| 3599 |
| 3600 /* Open transactions both databases. The *-oal file is opened or |
| 3601 ** created at this point. */ |
| 3602 if( p->rc==SQLITE_OK ){ |
| 3603 p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); |
| 3604 } |
| 3605 |
| 3606 /* Check if the main database is a zipvfs db. If it is, set the upper |
| 3607 ** level pager to use "journal_mode=off". This prevents it from |
| 3608 ** generating a large journal using a temp file. */ |
| 3609 if( p->rc==SQLITE_OK ){ |
| 3610 int frc = sqlite3_file_control(db, "main", SQLITE_FCNTL_ZIPVFS, 0); |
| 3611 if( frc==SQLITE_OK ){ |
| 3612 p->rc = sqlite3_exec( |
| 3613 db, "PRAGMA journal_mode=off",0,0,&p->zErrmsg); |
| 3614 } |
| 3615 } |
| 3616 |
| 3617 if( p->rc==SQLITE_OK ){ |
| 3618 rbuSetupOal(p, pState); |
| 3619 } |
3129 } | 3620 } |
3130 | |
3131 if( p->rc==SQLITE_OK ){ | |
3132 rbuSetupOal(p, pState); | |
3133 } | |
3134 | |
3135 }else if( p->eStage==RBU_STAGE_MOVE ){ | 3621 }else if( p->eStage==RBU_STAGE_MOVE ){ |
3136 /* no-op */ | 3622 /* no-op */ |
3137 }else if( p->eStage==RBU_STAGE_CKPT ){ | 3623 }else if( p->eStage==RBU_STAGE_CKPT ){ |
3138 rbuSetupCheckpoint(p, pState); | 3624 rbuSetupCheckpoint(p, pState); |
3139 }else if( p->eStage==RBU_STAGE_DONE ){ | 3625 }else if( p->eStage==RBU_STAGE_DONE ){ |
3140 p->rc = SQLITE_DONE; | 3626 p->rc = SQLITE_DONE; |
3141 }else{ | 3627 }else{ |
3142 p->rc = SQLITE_CORRUPT; | 3628 p->rc = SQLITE_CORRUPT; |
3143 } | 3629 } |
3144 } | 3630 } |
3145 | 3631 |
3146 rbuFreeState(pState); | 3632 rbuFreeState(pState); |
3147 } | 3633 } |
3148 | 3634 |
3149 return p; | 3635 return p; |
3150 } | 3636 } |
3151 | 3637 |
| 3638 /* |
| 3639 ** Allocate and return an RBU handle with all fields zeroed except for the |
| 3640 ** error code, which is set to SQLITE_MISUSE. |
| 3641 */ |
| 3642 static sqlite3rbu *rbuMisuseError(void){ |
| 3643 sqlite3rbu *pRet; |
| 3644 pRet = sqlite3_malloc64(sizeof(sqlite3rbu)); |
| 3645 if( pRet ){ |
| 3646 memset(pRet, 0, sizeof(sqlite3rbu)); |
| 3647 pRet->rc = SQLITE_MISUSE; |
| 3648 } |
| 3649 return pRet; |
| 3650 } |
| 3651 |
| 3652 /* |
| 3653 ** Open and return a new RBU handle. |
| 3654 */ |
| 3655 sqlite3rbu *sqlite3rbu_open( |
| 3656 const char *zTarget, |
| 3657 const char *zRbu, |
| 3658 const char *zState |
| 3659 ){ |
| 3660 if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); } |
| 3661 /* TODO: Check that zTarget and zRbu are non-NULL */ |
| 3662 return openRbuHandle(zTarget, zRbu, zState); |
| 3663 } |
| 3664 |
| 3665 /* |
| 3666 ** Open a handle to begin or resume an RBU VACUUM operation. |
| 3667 */ |
| 3668 sqlite3rbu *sqlite3rbu_vacuum( |
| 3669 const char *zTarget, |
| 3670 const char *zState |
| 3671 ){ |
| 3672 if( zTarget==0 ){ return rbuMisuseError(); } |
| 3673 /* TODO: Check that both arguments are non-NULL */ |
| 3674 return openRbuHandle(0, zTarget, zState); |
| 3675 } |
3152 | 3676 |
3153 /* | 3677 /* |
3154 ** Return the database handle used by pRbu. | 3678 ** Return the database handle used by pRbu. |
3155 */ | 3679 */ |
3156 sqlite3 *sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ | 3680 sqlite3 *sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ |
3157 sqlite3 *db = 0; | 3681 sqlite3 *db = 0; |
3158 if( pRbu ){ | 3682 if( pRbu ){ |
3159 db = (bRbu ? pRbu->dbRbu : pRbu->dbMain); | 3683 db = (bRbu ? pRbu->dbRbu : pRbu->dbMain); |
3160 } | 3684 } |
3161 return db; | 3685 return db; |
3162 } | 3686 } |
3163 | 3687 |
3164 | 3688 |
3165 /* | 3689 /* |
3166 ** If the error code currently stored in the RBU handle is SQLITE_CONSTRAINT, | 3690 ** If the error code currently stored in the RBU handle is SQLITE_CONSTRAINT, |
3167 ** then edit any error message string so as to remove all occurrences of | 3691 ** then edit any error message string so as to remove all occurrences of |
3168 ** the pattern "rbu_imp_[0-9]*". | 3692 ** the pattern "rbu_imp_[0-9]*". |
3169 */ | 3693 */ |
3170 static void rbuEditErrmsg(sqlite3rbu *p){ | 3694 static void rbuEditErrmsg(sqlite3rbu *p){ |
3171 if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){ | 3695 if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){ |
3172 int i; | 3696 unsigned int i; |
3173 int nErrmsg = strlen(p->zErrmsg); | 3697 size_t nErrmsg = strlen(p->zErrmsg); |
3174 for(i=0; i<(nErrmsg-8); i++){ | 3698 for(i=0; i<(nErrmsg-8); i++){ |
3175 if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){ | 3699 if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){ |
3176 int nDel = 8; | 3700 int nDel = 8; |
3177 while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++; | 3701 while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++; |
3178 memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel); | 3702 memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel); |
3179 nErrmsg -= nDel; | 3703 nErrmsg -= nDel; |
3180 } | 3704 } |
3181 } | 3705 } |
3182 } | 3706 } |
3183 } | 3707 } |
(...skipping 12 matching lines...) Expand all Loading... |
3196 | 3720 |
3197 rbuSaveState(p, p->eStage); | 3721 rbuSaveState(p, p->eStage); |
3198 | 3722 |
3199 if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ | 3723 if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ |
3200 p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); | 3724 p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); |
3201 } | 3725 } |
3202 | 3726 |
3203 /* Close any open statement handles. */ | 3727 /* Close any open statement handles. */ |
3204 rbuObjIterFinalize(&p->objiter); | 3728 rbuObjIterFinalize(&p->objiter); |
3205 | 3729 |
| 3730 /* If this is an RBU vacuum handle and the vacuum has either finished |
| 3731 ** successfully or encountered an error, delete the contents of the |
| 3732 ** state table. This causes the next call to sqlite3rbu_vacuum() |
| 3733 ** specifying the current target and state databases to start a new |
| 3734 ** vacuum from scratch. */ |
| 3735 if( rbuIsVacuum(p) && p->rc!=SQLITE_OK && p->dbRbu ){ |
| 3736 int rc2 = sqlite3_exec(p->dbRbu, "DELETE FROM stat.rbu_state", 0, 0, 0); |
| 3737 if( p->rc==SQLITE_DONE && rc2!=SQLITE_OK ) p->rc = rc2; |
| 3738 } |
| 3739 |
3206 /* Close the open database handle and VFS object. */ | 3740 /* Close the open database handle and VFS object. */ |
| 3741 sqlite3_close(p->dbRbu); |
3207 sqlite3_close(p->dbMain); | 3742 sqlite3_close(p->dbMain); |
3208 sqlite3_close(p->dbRbu); | |
3209 rbuDeleteVfs(p); | 3743 rbuDeleteVfs(p); |
3210 sqlite3_free(p->aBuf); | 3744 sqlite3_free(p->aBuf); |
3211 sqlite3_free(p->aFrame); | 3745 sqlite3_free(p->aFrame); |
3212 | 3746 |
3213 rbuEditErrmsg(p); | 3747 rbuEditErrmsg(p); |
3214 rc = p->rc; | 3748 rc = p->rc; |
3215 *pzErrmsg = p->zErrmsg; | 3749 *pzErrmsg = p->zErrmsg; |
| 3750 sqlite3_free(p->zState); |
3216 sqlite3_free(p); | 3751 sqlite3_free(p); |
3217 }else{ | 3752 }else{ |
3218 rc = SQLITE_NOMEM; | 3753 rc = SQLITE_NOMEM; |
3219 *pzErrmsg = 0; | 3754 *pzErrmsg = 0; |
3220 } | 3755 } |
3221 return rc; | 3756 return rc; |
3222 } | 3757 } |
3223 | 3758 |
3224 /* | 3759 /* |
3225 ** Return the total number of key-value operations (inserts, deletes or | 3760 ** Return the total number of key-value operations (inserts, deletes or |
3226 ** updates) that have been performed on the target database since the | 3761 ** updates) that have been performed on the target database since the |
3227 ** current RBU update was started. | 3762 ** current RBU update was started. |
3228 */ | 3763 */ |
3229 sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ | 3764 sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu){ |
3230 return pRbu->nProgress; | 3765 return pRbu->nProgress; |
3231 } | 3766 } |
3232 | 3767 |
| 3768 /* |
| 3769 ** Return permyriadage progress indications for the two main stages of |
| 3770 ** an RBU update. |
| 3771 */ |
| 3772 void sqlite3rbu_bp_progress(sqlite3rbu *p, int *pnOne, int *pnTwo){ |
| 3773 const int MAX_PROGRESS = 10000; |
| 3774 switch( p->eStage ){ |
| 3775 case RBU_STAGE_OAL: |
| 3776 if( p->nPhaseOneStep>0 ){ |
| 3777 *pnOne = (int)(MAX_PROGRESS * (i64)p->nProgress/(i64)p->nPhaseOneStep); |
| 3778 }else{ |
| 3779 *pnOne = -1; |
| 3780 } |
| 3781 *pnTwo = 0; |
| 3782 break; |
| 3783 |
| 3784 case RBU_STAGE_MOVE: |
| 3785 *pnOne = MAX_PROGRESS; |
| 3786 *pnTwo = 0; |
| 3787 break; |
| 3788 |
| 3789 case RBU_STAGE_CKPT: |
| 3790 *pnOne = MAX_PROGRESS; |
| 3791 *pnTwo = (int)(MAX_PROGRESS * (i64)p->nStep / (i64)p->nFrame); |
| 3792 break; |
| 3793 |
| 3794 case RBU_STAGE_DONE: |
| 3795 *pnOne = MAX_PROGRESS; |
| 3796 *pnTwo = MAX_PROGRESS; |
| 3797 break; |
| 3798 |
| 3799 default: |
| 3800 assert( 0 ); |
| 3801 } |
| 3802 } |
| 3803 |
| 3804 /* |
| 3805 ** Return the current state of the RBU vacuum or update operation. |
| 3806 */ |
| 3807 int sqlite3rbu_state(sqlite3rbu *p){ |
| 3808 int aRes[] = { |
| 3809 0, SQLITE_RBU_STATE_OAL, SQLITE_RBU_STATE_MOVE, |
| 3810 0, SQLITE_RBU_STATE_CHECKPOINT, SQLITE_RBU_STATE_DONE |
| 3811 }; |
| 3812 |
| 3813 assert( RBU_STAGE_OAL==1 ); |
| 3814 assert( RBU_STAGE_MOVE==2 ); |
| 3815 assert( RBU_STAGE_CKPT==4 ); |
| 3816 assert( RBU_STAGE_DONE==5 ); |
| 3817 assert( aRes[RBU_STAGE_OAL]==SQLITE_RBU_STATE_OAL ); |
| 3818 assert( aRes[RBU_STAGE_MOVE]==SQLITE_RBU_STATE_MOVE ); |
| 3819 assert( aRes[RBU_STAGE_CKPT]==SQLITE_RBU_STATE_CHECKPOINT ); |
| 3820 assert( aRes[RBU_STAGE_DONE]==SQLITE_RBU_STATE_DONE ); |
| 3821 |
| 3822 if( p->rc!=SQLITE_OK && p->rc!=SQLITE_DONE ){ |
| 3823 return SQLITE_RBU_STATE_ERROR; |
| 3824 }else{ |
| 3825 assert( p->rc!=SQLITE_DONE || p->eStage==RBU_STAGE_DONE ); |
| 3826 assert( p->eStage==RBU_STAGE_OAL |
| 3827 || p->eStage==RBU_STAGE_MOVE |
| 3828 || p->eStage==RBU_STAGE_CKPT |
| 3829 || p->eStage==RBU_STAGE_DONE |
| 3830 ); |
| 3831 return aRes[p->eStage]; |
| 3832 } |
| 3833 } |
| 3834 |
3233 int sqlite3rbu_savestate(sqlite3rbu *p){ | 3835 int sqlite3rbu_savestate(sqlite3rbu *p){ |
3234 int rc = p->rc; | 3836 int rc = p->rc; |
3235 | |
3236 if( rc==SQLITE_DONE ) return SQLITE_OK; | 3837 if( rc==SQLITE_DONE ) return SQLITE_OK; |
3237 | 3838 |
3238 assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE ); | 3839 assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE ); |
3239 if( p->eStage==RBU_STAGE_OAL ){ | 3840 if( p->eStage==RBU_STAGE_OAL ){ |
3240 assert( rc!=SQLITE_DONE ); | 3841 assert( rc!=SQLITE_DONE ); |
3241 if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0); | 3842 if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0); |
3242 } | 3843 } |
3243 | 3844 |
3244 p->rc = rc; | 3845 p->rc = rc; |
3245 rbuSaveState(p, p->eStage); | 3846 rbuSaveState(p, p->eStage); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3365 ** passed as the only argument. | 3966 ** passed as the only argument. |
3366 */ | 3967 */ |
3367 static u32 rbuGetU32(u8 *aBuf){ | 3968 static u32 rbuGetU32(u8 *aBuf){ |
3368 return ((u32)aBuf[0] << 24) | 3969 return ((u32)aBuf[0] << 24) |
3369 + ((u32)aBuf[1] << 16) | 3970 + ((u32)aBuf[1] << 16) |
3370 + ((u32)aBuf[2] << 8) | 3971 + ((u32)aBuf[2] << 8) |
3371 + ((u32)aBuf[3]); | 3972 + ((u32)aBuf[3]); |
3372 } | 3973 } |
3373 | 3974 |
3374 /* | 3975 /* |
| 3976 ** Write an unsigned 32-bit value in big-endian format to the supplied |
| 3977 ** buffer. |
| 3978 */ |
| 3979 static void rbuPutU32(u8 *aBuf, u32 iVal){ |
| 3980 aBuf[0] = (iVal >> 24) & 0xFF; |
| 3981 aBuf[1] = (iVal >> 16) & 0xFF; |
| 3982 aBuf[2] = (iVal >> 8) & 0xFF; |
| 3983 aBuf[3] = (iVal >> 0) & 0xFF; |
| 3984 } |
| 3985 |
| 3986 static void rbuPutU16(u8 *aBuf, u16 iVal){ |
| 3987 aBuf[0] = (iVal >> 8) & 0xFF; |
| 3988 aBuf[1] = (iVal >> 0) & 0xFF; |
| 3989 } |
| 3990 |
| 3991 /* |
3375 ** Read data from an rbuVfs-file. | 3992 ** Read data from an rbuVfs-file. |
3376 */ | 3993 */ |
3377 static int rbuVfsRead( | 3994 static int rbuVfsRead( |
3378 sqlite3_file *pFile, | 3995 sqlite3_file *pFile, |
3379 void *zBuf, | 3996 void *zBuf, |
3380 int iAmt, | 3997 int iAmt, |
3381 sqlite_int64 iOfst | 3998 sqlite_int64 iOfst |
3382 ){ | 3999 ){ |
3383 rbu_file *p = (rbu_file*)pFile; | 4000 rbu_file *p = (rbu_file*)pFile; |
3384 sqlite3rbu *pRbu = p->pRbu; | 4001 sqlite3rbu *pRbu = p->pRbu; |
3385 int rc; | 4002 int rc; |
3386 | 4003 |
3387 if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ | 4004 if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ |
3388 assert( p->openFlags & SQLITE_OPEN_WAL ); | 4005 assert( p->openFlags & SQLITE_OPEN_WAL ); |
3389 rc = rbuCaptureWalRead(p->pRbu, iOfst, iAmt); | 4006 rc = rbuCaptureWalRead(p->pRbu, iOfst, iAmt); |
3390 }else{ | 4007 }else{ |
3391 if( pRbu && pRbu->eStage==RBU_STAGE_OAL | 4008 if( pRbu && pRbu->eStage==RBU_STAGE_OAL |
3392 && (p->openFlags & SQLITE_OPEN_WAL) | 4009 && (p->openFlags & SQLITE_OPEN_WAL) |
3393 && iOfst>=pRbu->iOalSz | 4010 && iOfst>=pRbu->iOalSz |
3394 ){ | 4011 ){ |
3395 rc = SQLITE_OK; | 4012 rc = SQLITE_OK; |
3396 memset(zBuf, 0, iAmt); | 4013 memset(zBuf, 0, iAmt); |
3397 }else{ | 4014 }else{ |
3398 rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); | 4015 rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); |
| 4016 #if 1 |
| 4017 /* If this is being called to read the first page of the target |
| 4018 ** database as part of an rbu vacuum operation, synthesize the |
| 4019 ** contents of the first page if it does not yet exist. Otherwise, |
| 4020 ** SQLite will not check for a *-wal file. */ |
| 4021 if( pRbu && rbuIsVacuum(pRbu) |
| 4022 && rc==SQLITE_IOERR_SHORT_READ && iOfst==0 |
| 4023 && (p->openFlags & SQLITE_OPEN_MAIN_DB) |
| 4024 && pRbu->rc==SQLITE_OK |
| 4025 ){ |
| 4026 sqlite3_file *pFd = (sqlite3_file*)pRbu->pRbuFd; |
| 4027 rc = pFd->pMethods->xRead(pFd, zBuf, iAmt, iOfst); |
| 4028 if( rc==SQLITE_OK ){ |
| 4029 u8 *aBuf = (u8*)zBuf; |
| 4030 u32 iRoot = rbuGetU32(&aBuf[52]) ? 1 : 0; |
| 4031 rbuPutU32(&aBuf[52], iRoot); /* largest root page number */ |
| 4032 rbuPutU32(&aBuf[36], 0); /* number of free pages */ |
| 4033 rbuPutU32(&aBuf[32], 0); /* first page on free list trunk */ |
| 4034 rbuPutU32(&aBuf[28], 1); /* size of db file in pages */ |
| 4035 rbuPutU32(&aBuf[24], pRbu->pRbuFd->iCookie+1); /* Change counter */ |
| 4036 |
| 4037 if( iAmt>100 ){ |
| 4038 memset(&aBuf[100], 0, iAmt-100); |
| 4039 rbuPutU16(&aBuf[105], iAmt & 0xFFFF); |
| 4040 aBuf[100] = 0x0D; |
| 4041 } |
| 4042 } |
| 4043 } |
| 4044 #endif |
3399 } | 4045 } |
3400 if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ | 4046 if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ |
3401 /* These look like magic numbers. But they are stable, as they are part | 4047 /* These look like magic numbers. But they are stable, as they are part |
3402 ** of the definition of the SQLite file format, which may not change. */ | 4048 ** of the definition of the SQLite file format, which may not change. */ |
3403 u8 *pBuf = (u8*)zBuf; | 4049 u8 *pBuf = (u8*)zBuf; |
3404 p->iCookie = rbuGetU32(&pBuf[24]); | 4050 p->iCookie = rbuGetU32(&pBuf[24]); |
3405 p->iWriteVer = pBuf[19]; | 4051 p->iWriteVer = pBuf[19]; |
3406 } | 4052 } |
3407 } | 4053 } |
3408 return rc; | 4054 return rc; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3463 return SQLITE_OK; | 4109 return SQLITE_OK; |
3464 } | 4110 } |
3465 return p->pReal->pMethods->xSync(p->pReal, flags); | 4111 return p->pReal->pMethods->xSync(p->pReal, flags); |
3466 } | 4112 } |
3467 | 4113 |
3468 /* | 4114 /* |
3469 ** Return the current file-size of an rbuVfs-file. | 4115 ** Return the current file-size of an rbuVfs-file. |
3470 */ | 4116 */ |
3471 static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ | 4117 static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ |
3472 rbu_file *p = (rbu_file *)pFile; | 4118 rbu_file *p = (rbu_file *)pFile; |
3473 return p->pReal->pMethods->xFileSize(p->pReal, pSize); | 4119 int rc; |
| 4120 rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); |
| 4121 |
| 4122 /* If this is an RBU vacuum operation and this is the target database, |
| 4123 ** pretend that it has at least one page. Otherwise, SQLite will not |
| 4124 ** check for the existance of a *-wal file. rbuVfsRead() contains |
| 4125 ** similar logic. */ |
| 4126 if( rc==SQLITE_OK && *pSize==0 |
| 4127 && p->pRbu && rbuIsVacuum(p->pRbu) |
| 4128 && (p->openFlags & SQLITE_OPEN_MAIN_DB) |
| 4129 ){ |
| 4130 *pSize = 1024; |
| 4131 } |
| 4132 return rc; |
3474 } | 4133 } |
3475 | 4134 |
3476 /* | 4135 /* |
3477 ** Lock an rbuVfs-file. | 4136 ** Lock an rbuVfs-file. |
3478 */ | 4137 */ |
3479 static int rbuVfsLock(sqlite3_file *pFile, int eLock){ | 4138 static int rbuVfsLock(sqlite3_file *pFile, int eLock){ |
3480 rbu_file *p = (rbu_file*)pFile; | 4139 rbu_file *p = (rbu_file*)pFile; |
3481 sqlite3rbu *pRbu = p->pRbu; | 4140 sqlite3rbu *pRbu = p->pRbu; |
3482 int rc = SQLITE_OK; | 4141 int rc = SQLITE_OK; |
3483 | 4142 |
3484 assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); | 4143 assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); |
3485 if( pRbu && eLock==SQLITE_LOCK_EXCLUSIVE && pRbu->eStage!=RBU_STAGE_DONE ){ | 4144 if( eLock==SQLITE_LOCK_EXCLUSIVE |
| 4145 && (p->bNolock || (pRbu && pRbu->eStage!=RBU_STAGE_DONE)) |
| 4146 ){ |
3486 /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this | 4147 /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this |
3487 ** prevents it from checkpointing the database from sqlite3_close(). */ | 4148 ** prevents it from checkpointing the database from sqlite3_close(). */ |
3488 rc = SQLITE_BUSY; | 4149 rc = SQLITE_BUSY; |
3489 }else{ | 4150 }else{ |
3490 rc = p->pReal->pMethods->xLock(p->pReal, eLock); | 4151 rc = p->pReal->pMethods->xLock(p->pReal, eLock); |
3491 } | 4152 } |
3492 | 4153 |
3493 return rc; | 4154 return rc; |
3494 } | 4155 } |
3495 | 4156 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3538 pRbu->zErrmsg = sqlite3_mprintf("rbu/zipvfs setup error"); | 4199 pRbu->zErrmsg = sqlite3_mprintf("rbu/zipvfs setup error"); |
3539 }else if( rc==SQLITE_NOTFOUND ){ | 4200 }else if( rc==SQLITE_NOTFOUND ){ |
3540 pRbu->pTargetFd = p; | 4201 pRbu->pTargetFd = p; |
3541 p->pRbu = pRbu; | 4202 p->pRbu = pRbu; |
3542 if( p->pWalFd ) p->pWalFd->pRbu = pRbu; | 4203 if( p->pWalFd ) p->pWalFd->pRbu = pRbu; |
3543 rc = SQLITE_OK; | 4204 rc = SQLITE_OK; |
3544 } | 4205 } |
3545 } | 4206 } |
3546 return rc; | 4207 return rc; |
3547 } | 4208 } |
| 4209 else if( op==SQLITE_FCNTL_RBUCNT ){ |
| 4210 sqlite3rbu *pRbu = (sqlite3rbu*)pArg; |
| 4211 pRbu->nRbu++; |
| 4212 pRbu->pRbuFd = p; |
| 4213 p->bNolock = 1; |
| 4214 } |
3548 | 4215 |
3549 rc = xControl(p->pReal, op, pArg); | 4216 rc = xControl(p->pReal, op, pArg); |
3550 if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ | 4217 if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ |
3551 rbu_vfs *pRbuVfs = p->pRbuVfs; | 4218 rbu_vfs *pRbuVfs = p->pRbuVfs; |
3552 char *zIn = *(char**)pArg; | 4219 char *zIn = *(char**)pArg; |
3553 char *zOut = sqlite3_mprintf("rbu(%s)/%z", pRbuVfs->base.zName, zIn); | 4220 char *zOut = sqlite3_mprintf("rbu(%s)/%z", pRbuVfs->base.zName, zIn); |
3554 *(char**)pArg = zOut; | 4221 *(char**)pArg = zOut; |
3555 if( zOut==0 ) rc = SQLITE_NOMEM; | 4222 if( zOut==0 ) rc = SQLITE_NOMEM; |
3556 } | 4223 } |
3557 | 4224 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3627 int rc = SQLITE_OK; | 4294 int rc = SQLITE_OK; |
3628 int eStage = (p->pRbu ? p->pRbu->eStage : 0); | 4295 int eStage = (p->pRbu ? p->pRbu->eStage : 0); |
3629 | 4296 |
3630 /* If not in RBU_STAGE_OAL, allow this call to pass through. Or, if this | 4297 /* If not in RBU_STAGE_OAL, allow this call to pass through. Or, if this |
3631 ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space | 4298 ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space |
3632 ** instead of a file on disk. */ | 4299 ** instead of a file on disk. */ |
3633 assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); | 4300 assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); |
3634 if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ | 4301 if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ |
3635 if( iRegion<=p->nShm ){ | 4302 if( iRegion<=p->nShm ){ |
3636 int nByte = (iRegion+1) * sizeof(char*); | 4303 int nByte = (iRegion+1) * sizeof(char*); |
3637 char **apNew = (char**)sqlite3_realloc(p->apShm, nByte); | 4304 char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte); |
3638 if( apNew==0 ){ | 4305 if( apNew==0 ){ |
3639 rc = SQLITE_NOMEM; | 4306 rc = SQLITE_NOMEM; |
3640 }else{ | 4307 }else{ |
3641 memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); | 4308 memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); |
3642 p->apShm = apNew; | 4309 p->apShm = apNew; |
3643 p->nShm = iRegion+1; | 4310 p->nShm = iRegion+1; |
3644 } | 4311 } |
3645 } | 4312 } |
3646 | 4313 |
3647 if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ | 4314 if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ |
3648 char *pNew = (char*)sqlite3_malloc(szRegion); | 4315 char *pNew = (char*)sqlite3_malloc64(szRegion); |
3649 if( pNew==0 ){ | 4316 if( pNew==0 ){ |
3650 rc = SQLITE_NOMEM; | 4317 rc = SQLITE_NOMEM; |
3651 }else{ | 4318 }else{ |
3652 memset(pNew, 0, szRegion); | 4319 memset(pNew, 0, szRegion); |
3653 p->apShm[iRegion] = pNew; | 4320 p->apShm[iRegion] = pNew; |
3654 } | 4321 } |
3655 } | 4322 } |
3656 | 4323 |
3657 if( rc==SQLITE_OK ){ | 4324 if( rc==SQLITE_OK ){ |
3658 *pp = p->apShm[iRegion]; | 4325 *pp = p->apShm[iRegion]; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3696 | 4363 |
3697 /* | 4364 /* |
3698 ** Given that zWal points to a buffer containing a wal file name passed to | 4365 ** Given that zWal points to a buffer containing a wal file name passed to |
3699 ** either the xOpen() or xAccess() VFS method, return a pointer to the | 4366 ** either the xOpen() or xAccess() VFS method, return a pointer to the |
3700 ** file-handle opened by the same database connection on the corresponding | 4367 ** file-handle opened by the same database connection on the corresponding |
3701 ** database file. | 4368 ** database file. |
3702 */ | 4369 */ |
3703 static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ | 4370 static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ |
3704 rbu_file *pDb; | 4371 rbu_file *pDb; |
3705 sqlite3_mutex_enter(pRbuVfs->mutex); | 4372 sqlite3_mutex_enter(pRbuVfs->mutex); |
3706 for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext); | 4373 for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} |
3707 sqlite3_mutex_leave(pRbuVfs->mutex); | 4374 sqlite3_mutex_leave(pRbuVfs->mutex); |
3708 return pDb; | 4375 return pDb; |
3709 } | 4376 } |
3710 | 4377 |
| 4378 /* |
| 4379 ** A main database named zName has just been opened. The following |
| 4380 ** function returns a pointer to a buffer owned by SQLite that contains |
| 4381 ** the name of the *-wal file this db connection will use. SQLite |
| 4382 ** happens to pass a pointer to this buffer when using xAccess() |
| 4383 ** or xOpen() to operate on the *-wal file. |
| 4384 */ |
| 4385 static const char *rbuMainToWal(const char *zName, int flags){ |
| 4386 int n = (int)strlen(zName); |
| 4387 const char *z = &zName[n]; |
| 4388 if( flags & SQLITE_OPEN_URI ){ |
| 4389 int odd = 0; |
| 4390 while( 1 ){ |
| 4391 if( z[0]==0 ){ |
| 4392 odd = 1 - odd; |
| 4393 if( odd && z[1]==0 ) break; |
| 4394 } |
| 4395 z++; |
| 4396 } |
| 4397 z += 2; |
| 4398 }else{ |
| 4399 while( *z==0 ) z++; |
| 4400 } |
| 4401 z += (n + 8 + 1); |
| 4402 return z; |
| 4403 } |
| 4404 |
3711 /* | 4405 /* |
3712 ** Open an rbu file handle. | 4406 ** Open an rbu file handle. |
3713 */ | 4407 */ |
3714 static int rbuVfsOpen( | 4408 static int rbuVfsOpen( |
3715 sqlite3_vfs *pVfs, | 4409 sqlite3_vfs *pVfs, |
3716 const char *zName, | 4410 const char *zName, |
3717 sqlite3_file *pFile, | 4411 sqlite3_file *pFile, |
3718 int flags, | 4412 int flags, |
3719 int *pOutFlags | 4413 int *pOutFlags |
3720 ){ | 4414 ){ |
(...skipping 15 matching lines...) Expand all Loading... |
3736 rbuVfsShmLock, /* xShmLock */ | 4430 rbuVfsShmLock, /* xShmLock */ |
3737 rbuVfsShmBarrier, /* xShmBarrier */ | 4431 rbuVfsShmBarrier, /* xShmBarrier */ |
3738 rbuVfsShmUnmap, /* xShmUnmap */ | 4432 rbuVfsShmUnmap, /* xShmUnmap */ |
3739 0, 0 /* xFetch, xUnfetch */ | 4433 0, 0 /* xFetch, xUnfetch */ |
3740 }; | 4434 }; |
3741 rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; | 4435 rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; |
3742 sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; | 4436 sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; |
3743 rbu_file *pFd = (rbu_file *)pFile; | 4437 rbu_file *pFd = (rbu_file *)pFile; |
3744 int rc = SQLITE_OK; | 4438 int rc = SQLITE_OK; |
3745 const char *zOpen = zName; | 4439 const char *zOpen = zName; |
| 4440 int oflags = flags; |
3746 | 4441 |
3747 memset(pFd, 0, sizeof(rbu_file)); | 4442 memset(pFd, 0, sizeof(rbu_file)); |
3748 pFd->pReal = (sqlite3_file*)&pFd[1]; | 4443 pFd->pReal = (sqlite3_file*)&pFd[1]; |
3749 pFd->pRbuVfs = pRbuVfs; | 4444 pFd->pRbuVfs = pRbuVfs; |
3750 pFd->openFlags = flags; | 4445 pFd->openFlags = flags; |
3751 if( zName ){ | 4446 if( zName ){ |
3752 if( flags & SQLITE_OPEN_MAIN_DB ){ | 4447 if( flags & SQLITE_OPEN_MAIN_DB ){ |
3753 /* A main database has just been opened. The following block sets | 4448 /* A main database has just been opened. The following block sets |
3754 ** (pFd->zWal) to point to a buffer owned by SQLite that contains | 4449 ** (pFd->zWal) to point to a buffer owned by SQLite that contains |
3755 ** the name of the *-wal file this db connection will use. SQLite | 4450 ** the name of the *-wal file this db connection will use. SQLite |
3756 ** happens to pass a pointer to this buffer when using xAccess() | 4451 ** happens to pass a pointer to this buffer when using xAccess() |
3757 ** or xOpen() to operate on the *-wal file. */ | 4452 ** or xOpen() to operate on the *-wal file. */ |
3758 int n = strlen(zName); | 4453 pFd->zWal = rbuMainToWal(zName, flags); |
3759 const char *z = &zName[n]; | |
3760 if( flags & SQLITE_OPEN_URI ){ | |
3761 int odd = 0; | |
3762 while( 1 ){ | |
3763 if( z[0]==0 ){ | |
3764 odd = 1 - odd; | |
3765 if( odd && z[1]==0 ) break; | |
3766 } | |
3767 z++; | |
3768 } | |
3769 z += 2; | |
3770 }else{ | |
3771 while( *z==0 ) z++; | |
3772 } | |
3773 z += (n + 8 + 1); | |
3774 pFd->zWal = z; | |
3775 } | 4454 } |
3776 else if( flags & SQLITE_OPEN_WAL ){ | 4455 else if( flags & SQLITE_OPEN_WAL ){ |
3777 rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); | 4456 rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); |
3778 if( pDb ){ | 4457 if( pDb ){ |
3779 if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ | 4458 if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ |
3780 /* This call is to open a *-wal file. Intead, open the *-oal. This | 4459 /* This call is to open a *-wal file. Intead, open the *-oal. This |
3781 ** code ensures that the string passed to xOpen() is terminated by a | 4460 ** code ensures that the string passed to xOpen() is terminated by a |
3782 ** pair of '\0' bytes in case the VFS attempts to extract a URI | 4461 ** pair of '\0' bytes in case the VFS attempts to extract a URI |
3783 ** parameter from it. */ | 4462 ** parameter from it. */ |
3784 int nCopy = strlen(zName); | 4463 const char *zBase = zName; |
3785 char *zCopy = sqlite3_malloc(nCopy+2); | 4464 size_t nCopy; |
| 4465 char *zCopy; |
| 4466 if( rbuIsVacuum(pDb->pRbu) ){ |
| 4467 zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main"); |
| 4468 zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI); |
| 4469 } |
| 4470 nCopy = strlen(zBase); |
| 4471 zCopy = sqlite3_malloc64(nCopy+2); |
3786 if( zCopy ){ | 4472 if( zCopy ){ |
3787 memcpy(zCopy, zName, nCopy); | 4473 memcpy(zCopy, zBase, nCopy); |
3788 zCopy[nCopy-3] = 'o'; | 4474 zCopy[nCopy-3] = 'o'; |
3789 zCopy[nCopy] = '\0'; | 4475 zCopy[nCopy] = '\0'; |
3790 zCopy[nCopy+1] = '\0'; | 4476 zCopy[nCopy+1] = '\0'; |
3791 zOpen = (const char*)(pFd->zDel = zCopy); | 4477 zOpen = (const char*)(pFd->zDel = zCopy); |
3792 }else{ | 4478 }else{ |
3793 rc = SQLITE_NOMEM; | 4479 rc = SQLITE_NOMEM; |
3794 } | 4480 } |
3795 pFd->pRbu = pDb->pRbu; | 4481 pFd->pRbu = pDb->pRbu; |
3796 } | 4482 } |
3797 pDb->pWalFd = pFd; | 4483 pDb->pWalFd = pFd; |
3798 } | 4484 } |
3799 } | 4485 } |
3800 } | 4486 } |
3801 | 4487 |
| 4488 if( oflags & SQLITE_OPEN_MAIN_DB |
| 4489 && sqlite3_uri_boolean(zName, "rbu_memory", 0) |
| 4490 ){ |
| 4491 assert( oflags & SQLITE_OPEN_MAIN_DB ); |
| 4492 oflags = SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | |
| 4493 SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; |
| 4494 zOpen = 0; |
| 4495 } |
| 4496 |
3802 if( rc==SQLITE_OK ){ | 4497 if( rc==SQLITE_OK ){ |
3803 rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, flags, pOutFlags); | 4498 rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, oflags, pOutFlags); |
3804 } | 4499 } |
3805 if( pFd->pReal->pMethods ){ | 4500 if( pFd->pReal->pMethods ){ |
3806 /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods | 4501 /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods |
3807 ** pointer and, if the file is a main database file, link it into the | 4502 ** pointer and, if the file is a main database file, link it into the |
3808 ** mutex protected linked list of all such files. */ | 4503 ** mutex protected linked list of all such files. */ |
3809 pFile->pMethods = &rbuvfs_io_methods; | 4504 pFile->pMethods = &rbuvfs_io_methods; |
3810 if( flags & SQLITE_OPEN_MAIN_DB ){ | 4505 if( flags & SQLITE_OPEN_MAIN_DB ){ |
3811 sqlite3_mutex_enter(pRbuVfs->mutex); | 4506 sqlite3_mutex_enter(pRbuVfs->mutex); |
3812 pFd->pMainNext = pRbuVfs->pMain; | 4507 pFd->pMainNext = pRbuVfs->pMain; |
3813 pRbuVfs->pMain = pFd; | 4508 pRbuVfs->pMain = pFd; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4004 | 4699 |
4005 rbuVfsRandomness, /* xRandomness */ | 4700 rbuVfsRandomness, /* xRandomness */ |
4006 rbuVfsSleep, /* xSleep */ | 4701 rbuVfsSleep, /* xSleep */ |
4007 rbuVfsCurrentTime, /* xCurrentTime */ | 4702 rbuVfsCurrentTime, /* xCurrentTime */ |
4008 rbuVfsGetLastError, /* xGetLastError */ | 4703 rbuVfsGetLastError, /* xGetLastError */ |
4009 0, /* xCurrentTimeInt64 (version 2) */ | 4704 0, /* xCurrentTimeInt64 (version 2) */ |
4010 0, 0, 0 /* Unimplemented version 3 methods */ | 4705 0, 0, 0 /* Unimplemented version 3 methods */ |
4011 }; | 4706 }; |
4012 | 4707 |
4013 rbu_vfs *pNew = 0; /* Newly allocated VFS */ | 4708 rbu_vfs *pNew = 0; /* Newly allocated VFS */ |
4014 int nName; | |
4015 int rc = SQLITE_OK; | 4709 int rc = SQLITE_OK; |
| 4710 size_t nName; |
| 4711 size_t nByte; |
4016 | 4712 |
4017 int nByte; | |
4018 nName = strlen(zName); | 4713 nName = strlen(zName); |
4019 nByte = sizeof(rbu_vfs) + nName + 1; | 4714 nByte = sizeof(rbu_vfs) + nName + 1; |
4020 pNew = (rbu_vfs*)sqlite3_malloc(nByte); | 4715 pNew = (rbu_vfs*)sqlite3_malloc64(nByte); |
4021 if( pNew==0 ){ | 4716 if( pNew==0 ){ |
4022 rc = SQLITE_NOMEM; | 4717 rc = SQLITE_NOMEM; |
4023 }else{ | 4718 }else{ |
4024 sqlite3_vfs *pParent; /* Parent VFS */ | 4719 sqlite3_vfs *pParent; /* Parent VFS */ |
4025 memset(pNew, 0, nByte); | 4720 memset(pNew, 0, nByte); |
4026 pParent = sqlite3_vfs_find(zParent); | 4721 pParent = sqlite3_vfs_find(zParent); |
4027 if( pParent==0 ){ | 4722 if( pParent==0 ){ |
4028 rc = SQLITE_NOTFOUND; | 4723 rc = SQLITE_NOTFOUND; |
4029 }else{ | 4724 }else{ |
4030 char *zSpace; | 4725 char *zSpace; |
(...skipping 19 matching lines...) Expand all Loading... |
4050 } | 4745 } |
4051 } | 4746 } |
4052 | 4747 |
4053 return rc; | 4748 return rc; |
4054 } | 4749 } |
4055 | 4750 |
4056 | 4751 |
4057 /**************************************************************************/ | 4752 /**************************************************************************/ |
4058 | 4753 |
4059 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ | 4754 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ |
OLD | NEW |