Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch apple-osx Excluding Merge-Ins
This is equivalent to a diff from 85d3dc8c to d6fda470
2020-04-16
| ||
11:35 | Improve corruption detection in fts3 shadow tables earlier in order to prevent an assert() from failing. (check-in: a9ec8c8f user: dan tags: trunk) | |
2020-04-14
| ||
15:48 | Add the UINT collating sequence extension. The implementation is copied out of the "natsort" branch. (check-in: 6f46c6e3 user: drh tags: trunk) | |
15:24 | Merge trunk enhancements. (check-in: f1c284dd user: drh tags: natsort) | |
2020-04-09
| ||
18:51 | Merge recent trunk changes into the apple-osx branch. (Leaf check-in: d6fda470 user: drh tags: apple-osx) | |
18:46 | Merge recent trunk enhancements into the wal2 branch. (check-in: 6fb87062 user: drh tags: wal2) | |
18:44 | Merge recent trunk enhancements into the begin-concurrent-pnu branch. (check-in: cedd138c user: drh tags: begin-concurrent-pnu) | |
18:29 | Merge recent trunk enhancements into the begin-concurrent branch. (check-in: 92f71a88 user: drh tags: begin-concurrent) | |
15:31 | When compiling the shell for WinRT, avoid using Win32 APIs that are unavailable. (check-in: 85d3dc8c user: mistachkin tags: trunk) | |
2020-04-07
| ||
15:07 | Limit LIKE/GLOB pattern length to 100 bytes (default is 50K) when running dbsql cases in the fuzzcheck utility. (check-in: 10306118 user: drh tags: trunk) | |
2020-02-01
| ||
14:29 | Fix a problem in sqlite3CodecQueryParameters() that was introduced by the query parameter encoding changes for the 3.31.1 release. (check-in: 1240ee4f user: drh tags: apple-osx) | |
Changes to Makefile.in.
︙ | ︙ | |||
60 61 62 63 64 65 66 | # The library that programs using readline() must link against. # LIBREADLINE = @TARGET_READLINE_LIBS@ # Should the database engine be compiled threadsafe # | | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | # The library that programs using readline() must link against. # LIBREADLINE = @TARGET_READLINE_LIBS@ # Should the database engine be compiled threadsafe # #TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@ # Any target libraries which libsqlite must be linked against # TLIBS = @LIBS@ $(LIBS) # Flags controlling use of the in memory btree implementation # |
︙ | ︙ | |||
114 115 116 117 118 119 120 | # This is the command to use for tclsh - normally just "tclsh", but we may # know the specific version we want to use # TCLSH_CMD = @TCLSH_CMD@ # Where do we want to install the tcl plugin # | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | # This is the command to use for tclsh - normally just "tclsh", but we may # know the specific version we want to use # TCLSH_CMD = @TCLSH_CMD@ # Where do we want to install the tcl plugin # TCLLIBDIR = /System/Library/Tcl # The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib" # SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@ # If gcov support was enabled by the configure script, add the appropriate # flags here. It's not always as easy as just having the user add the right |
︙ | ︙ | |||
349 350 351 352 353 354 355 356 357 358 359 360 361 362 | SRC += \ $(TOP)/ext/icu/sqliteicu.h \ $(TOP)/ext/icu/icu.c SRC += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c \ $(TOP)/ext/rtree/geopoly.c SRC += \ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h SRC += \ $(TOP)/ext/userauth/userauth.c \ $(TOP)/ext/userauth/sqlite3userauth.h SRC += \ | > > > | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | SRC += \ $(TOP)/ext/icu/sqliteicu.h \ $(TOP)/ext/icu/icu.c SRC += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c \ $(TOP)/ext/rtree/geopoly.c SRC += \ $(TOP)/ext/sqlrr/sqlrr.h \ $(TOP)/ext/sqlrr/sqlrr.c SRC += \ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h SRC += \ $(TOP)/ext/userauth/userauth.c \ $(TOP)/ext/userauth/sqlite3userauth.h SRC += \ |
︙ | ︙ | |||
566 567 568 569 570 571 572 573 574 575 576 577 578 579 | $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/rtree/sqlite3rtree.h EXTHDR += \ $(TOP)/ext/userauth/sqlite3userauth.h # executables needed for testing # TESTPROGS = \ testfixture$(TEXE) \ sqlite3$(TEXE) \ sqlite3_analyzer$(TEXE) \ | > > > > > > > > > > > | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 | $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/rtree/sqlite3rtree.h EXTHDR += \ $(TOP)/ext/userauth/sqlite3userauth.h EXTHDR += \ $(TOP)/ext/sqlrr/sqlrr.h # If using the amalgamation, use sqlite3.c directly to build the test # fixture. Otherwise link against libsqlite3.la. (This distinction is # necessary because the test fixture requires non-API symbols which are # hidden when the library is built via the amalgamation). # TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la TESTFIXTURE_SRC1 = sqlite3.c TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) # executables needed for testing # TESTPROGS = \ testfixture$(TEXE) \ sqlite3$(TEXE) \ sqlite3_analyzer$(TEXE) \ |
︙ | ︙ | |||
636 637 638 639 640 641 642 | libsqlite3.la: $(LIBOBJ) $(LTLINK) -no-undefined -o $@ $(LIBOBJ) $(TLIBS) \ ${ALLOWRELEASE} -rpath "$(libdir)" -version-info "8:6:8" libtclsqlite3.la: tclsqlite.lo libsqlite3.la $(LTLINK) -no-undefined -o $@ tclsqlite.lo \ libsqlite3.la @TCL_STUB_LIB_SPEC@ $(TLIBS) \ | | | < | 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 | libsqlite3.la: $(LIBOBJ) $(LTLINK) -no-undefined -o $@ $(LIBOBJ) $(TLIBS) \ ${ALLOWRELEASE} -rpath "$(libdir)" -version-info "8:6:8" libtclsqlite3.la: tclsqlite.lo libsqlite3.la $(LTLINK) -no-undefined -o $@ tclsqlite.lo \ libsqlite3.la @TCL_STUB_LIB_SPEC@ $(TLIBS) \ -rpath "$(TCLLIBDIR)/sqlite3" \ -version-info "8:6:8" sqlite3$(TEXE): shell.c sqlite3.c $(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \ shell.c sqlite3.c \ $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)" sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h |
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 | $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir) $(INSTALL) -d $(DESTDIR)$(pkgconfigdir) $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir) pkgIndex.tcl: echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@ tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl | | | | | | 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 | $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir) $(INSTALL) -d $(DESTDIR)$(pkgconfigdir) $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir) pkgIndex.tcl: echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@ tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl $(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)/sqlite3 $(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/sqlite3 rm -f $(DESTDIR)$(TCLLIBDIR)/sqlite3/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/sqlite3/libtclsqlite3.a $(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)/sqlite3 clean: rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la rm -f sqlite3.h opcodes.* rm -rf .libs .deps rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz rm -f mkkeywordhash$(BEXE) keywordhash.h |
︙ | ︙ |
Changes to ext/fts5/test/fts5misc.test.
︙ | ︙ | |||
320 321 322 323 324 325 326 | SELECT * FROM ft NATURAL JOIN t1 WHERE ft MATCH('b') } {b world {}} do_execsql_test 12.3 { SELECT * FROM t2 JOIN ft USING (ft) } {3 4 b b} finish_test | < | 320 321 322 323 324 325 326 | SELECT * FROM ft NATURAL JOIN t1 WHERE ft MATCH('b') } {b world {}} do_execsql_test 12.3 { SELECT * FROM t2 JOIN ft USING (ft) } {3 4 b b} finish_test |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 | # undef NDEBUG #endif #endif #include <string.h> #include <stdio.h> #include <assert.h> /* The following macro is used to suppress compiler warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(x) (void)(x) #endif | > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | # undef NDEBUG #endif #endif #include <string.h> #include <stdio.h> #include <assert.h> #include <stdint.h> /* The following macro is used to suppress compiler warnings. */ #ifndef UNUSED_PARAMETER # define UNUSED_PARAMETER(x) (void)(x) #endif |
︙ | ︙ |
Added ext/sqlrr/README.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | sqlrr - 10/19/2009 SQL Replay Recording SUMMARY ------------------------------------------------------- This extension enables recording sqlite API calls that access the database so that they can be replayed or examined. USAGE ------------------------------------------------------ Recording is enabled by compiling sqlite with symbolic constant SQLITE_ENABLE_SQLRR defined. By default logs are written to /tmp/<databasename>_<pid>_<connection_number>.sqlrr, to choose another directory, set the environment variable SQLITE_REPLAY_RECORD_DIR to that path. FILE FORMAT ----------------------------------------------------- file: <header>[<sql-command>]* header: <signature><format-version> signature: SQLRR (5 bytes) format-version: n (1 byte) sql-command: <timestamp><type><arg-data> timestamp: n (16 bytes) type: n (1 byte) open 0 close 1 exec 8 bind-text 16 bind-double 17 bind-int 18 bind-null 19 bind-value 20 bind-clear 21 prep 32 step 33 reset 34 finalize 35 open-arg-data: <connection><path><flags> close-arg-data: <connection> exec-arg-data: <connection><len><statement-text> bind-text-arg-data: <statement-ref><index><len><data> bind-double-arg-data: <statement-ref><index><data> bind-int-arg-data: <statement-ref><index><data> bind-null-arg-data: <statement-ref><index> bind-value-arg-data: <statement-ref><index><len><data> ??? bind-clear-arg-data: <statement-ref> prep-arg-data: <connection><len><statement-text> step-arg-data: <statement-ref> reset-arg-data: <statement-ref> finalize-arg-data: <statement-ref> NOTES |
Added ext/sqlrr/sqlrr.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 | /* * sqlrr.c */ #include "sqlrr.h" #if defined(SQLITE_ENABLE_SQLRR) #include <unistd.h> #include <string.h> #include <stdio.h> #include <sys/param.h> #include <errno.h> #include <pthread.h> #include <libkern/OSAtomic.h> #include "sqliteInt.h" #include "vdbeInt.h" #define LOGSUFFIXLEN 48 /* * Data types */ typedef struct SRRLogRef SRRLogRef; struct SRRLogRef { int fd; sqlite3 *db; const char *dbPath; char *logPath; int connection; int depth; SRRLogRef *nextRef; }; /* * Globals */ SRRLogRef *logRefHead = NULL; int dbLogCount = 0; static int srr_enabled = 1; pthread_mutex_t srr_log_mutex; static volatile int32_t srr_initialized = 0; /* * Log management */ extern void SRRecInitialize() { int go = OSAtomicCompareAndSwap32Barrier(0, 1, &srr_initialized); if( go ){ pthread_mutex_init(&srr_log_mutex, NULL); } } static SRRLogRef *createLog(sqlite3 *db, const char *dbPath) { SRRLogRef *ref = NULL; char *baseDir = getenv("SQLITE_REPLAY_RECORD_DIR"); char logPath[MAXPATHLEN] = ""; char suffix[LOGSUFFIXLEN] = ""; const char *dbName = dbPath; int len = 0; int index = 0; int fd = -1; size_t out; unsigned char version = SRR_FILE_VERSION; SRRecInitialize(); /* construct the path for the log file * ${SQLITE_REPLAY_DIR}/<dbname>_<pid>_<connection_number>.sqlrr */ if (baseDir == NULL) { baseDir = "/tmp"; /* getenv(TMPDIR) */ } len = strlen(baseDir); strlcat(logPath, baseDir, MAXPATHLEN); if ((len>0) && (baseDir[len-1] != '/')) { strlcat(logPath, "/", MAXPATHLEN); } len = strlen(dbPath); for (index = len-2; index >= 0; index --){ if (dbPath[index] == '/') { dbName = &dbPath[index+1]; break; } } strlcat(logPath, dbName, MAXPATHLEN); int cNum = ++dbLogCount; snprintf(suffix, sizeof(suffix), "_%d_%d_XXXX.sqlrr", getpid(), cNum); len = strlcat(logPath, suffix, MAXPATHLEN); /* make it unique if we have the space */ if ((len + 1) < MAXPATHLEN) { fd = mkstemps(logPath, 6); } else { fprintf(stderr, "Failed to create sqlite replay log path for %s [%s]\n", dbPath, logPath); return NULL; } if (fd == -1) { fprintf(stderr, "Failed to create sqlite replay log file for %s with path %s [%s]\n", dbPath, logPath, strerror(errno)); return NULL; } fprintf(stdout, "Writing sqlite replay log file %s\n", logPath); out = write(fd, SRR_FILE_SIGNATURE, SRR_FILE_SIGNATURE_LEN); if (out!=-1) { out = write(fd, &version, 1); } if (out == -1){ fprintf(stderr, "Write failure on log [%s]: %s\n", logPath, strerror(errno)); close(fd); return NULL; } len = strlen(logPath) + 1; ref = (SRRLogRef *)malloc(sizeof(SRRLogRef)); ref->db = db; ref->dbPath = dbPath; ref->logPath = (char *)malloc(len * sizeof(char)); strlcpy(ref->logPath, logPath, len); ref->fd = fd; ref->connection = cNum; ref->depth = 0; pthread_mutex_lock(&srr_log_mutex); ref->nextRef = logRefHead; logRefHead = ref; pthread_mutex_unlock(&srr_log_mutex); return ref; } static void closeLog(sqlite3 *db) { SRRLogRef *ref = NULL; SRRLogRef *lastRef = NULL; pthread_mutex_lock(&srr_log_mutex); for (ref = logRefHead; ref != NULL; ref = ref->nextRef) { if (ref->db == db) { if (lastRef == NULL) { logRefHead = ref->nextRef; } else { lastRef->nextRef = ref->nextRef; } } } pthread_mutex_unlock(&srr_log_mutex); if (ref != NULL) { fprintf(stdout, "Closing sqlite replay log file %s\n", ref->logPath); close(ref->fd); free(ref->logPath); free(ref); } } static SRRLogRef *getLog(sqlite3 *db) { pthread_mutex_lock(&srr_log_mutex); SRRLogRef *ref = logRefHead; for (ref = logRefHead; ref != NULL; ref = ref->nextRef) { if (ref->db == db) { pthread_mutex_unlock(&srr_log_mutex); return ref; } } pthread_mutex_unlock(&srr_log_mutex); return NULL; } /* * SQLite recording API */ void SQLiteReplayRecorder(int flag) { srr_enabled = flag; } // open-arg-data: <connection><len><path><flags> void _SRRecOpen(sqlite3 *db, const char *path, int flags) { if (!srr_enabled) return; if (db) { SRRLogRef *ref = createLog(db, path); if (ref) { SRRCommand code = SRROpen; int len = strlen(path); struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out=write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { out=write(ref->fd, &(ref->connection), sizeof(ref->connection)); } if (out!=-1) { out=write(ref->fd, &len, sizeof(len)); } if (out!=-1) { out=write(ref->fd, path, len); } if (out!=-1) { out=write(ref->fd, &flags, sizeof(flags)); } if (out==-1) { fprintf(stderr, "Error writing open to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(db); } } } } //close-arg-data: <connection> void SRRecClose(sqlite3 *db) { if (!srr_enabled) return; if (db) { SRRLogRef *ref = getLog(db); if (ref) { SRRCommand code = SRRClose; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); } if (out==-1) { fprintf(stderr, "Error writing close to log file [%s]: %s\n", ref->logPath, strerror(errno)); } closeLog(db); } } } // exec-arg-data: <connection><len><statement-text> void SRRecExec(sqlite3 *db, const char *sql) { if (!srr_enabled) return; if (db) { SRRLogRef *ref = getLog(db); if (ref) { if (ref->depth == 0) { SRRCommand code = SRRExec; int len = strlen(sql); struct timeval tv; size_t out; ref->depth = 1; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); } if (out!=-1) { out = write(ref->fd, &len, sizeof(len)); } if (out!=-1) { out = write(ref->fd, sql, len); } if (out==-1) { fprintf(stderr, "Error writing exec to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(db); } } else { ref->depth ++; } } } } void SRRecExecEnd(sqlite3 *db) { if (!srr_enabled) return; if (db) { SRRLogRef *ref = getLog(db); if (ref) { ref->depth --; } } } // prep-arg-data: <connection><len><statement-text><savesql><statement-ref> void _SRRecPrepare(sqlite3 *db, const char *sql, int nBytes, int saveSql, sqlite3_stmt *pStmt) { if (!srr_enabled) return; if ((db!=NULL)&&(pStmt!=NULL)) { SRRLogRef *ref = getLog(db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRPrepare; struct timeval tv; size_t out; int sqlLen = nBytes; if (sqlLen == -1) { sqlLen = strlen(sql); } gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { out = write(ref->fd, &(ref->connection), sizeof(ref->connection)); } if (out!=-1) { out = write(ref->fd, &sqlLen, sizeof(sqlLen)); } if (out!=-1) { out = write(ref->fd, sql, sqlLen); } if (out!=-1) { out = write(ref->fd, &saveSql, sizeof(saveSql)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out==-1) { fprintf(stderr, "Error writing prepare to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(db); } } } } //step-arg-data: <statement-ref> void SRRecStep(sqlite3_stmt *pStmt) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref) { if (ref->depth == 0) { SRRCommand code = SRRStep; struct timeval tv; size_t out; ref->depth = 1; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out==-1) { fprintf(stderr, "Error writing step to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } else { ref->depth ++; } } } } void SRRecStepEnd(sqlite3_stmt *pStmt) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref) { ref->depth --; } } } // reset-arg-data: <statement-ref> void SRRecReset(sqlite3_stmt *pStmt) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRReset; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out==-1) { fprintf(stderr, "Error writing reset to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // finalize-arg-data: <statement-ref> void SRRecFinalize(sqlite3_stmt *pStmt) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRFinalize; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out==-1) { fprintf(stderr, "Error writing finalize to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // bind-text-arg-data: <statement-ref><index><len><data> void SRRecBindText(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRBindText; struct timeval tv; size_t out; int64_t textLen = nData; if (textLen == -1) { textLen = strlen(zData); } gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); } if (out!=-1) { out = write(ref->fd, &textLen, sizeof(textLen)); } if (out!=-1) { out = write(ref->fd, zData, textLen); } if (out==-1) { fprintf(stderr, "Error writing bind text to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // bind-blob-arg-data: <statement-ref><index><len>[<data>] void SRRecBindBlob(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRBindBlob; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); } if (zData == NULL) { int64_t negNData = -nData; if (out!=-1) { out = write(ref->fd, &negNData, sizeof(negNData)); } } else { if (out!=-1) { out = write(ref->fd, &nData, sizeof(nData)); } if (out!=-1) { out = write(ref->fd, zData, nData); } } if (out==-1) { fprintf(stderr, "Error writing bind blob to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // bind-double-arg-data: <statement-ref><index><data> void SRRecBindDouble(sqlite3_stmt *pStmt, int i, double value) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRBindDouble; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); } if (out!=-1) { out = write(ref->fd, &value, sizeof(value)); } if (out==-1) { fprintf(stderr, "Error writing bind double to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // bind-int-arg-data: <statement-ref><index><data> void SRRecBindInt64(sqlite3_stmt *pStmt, int i, int64_t value) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRBindInt; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); } if (out!=-1) { out = write(ref->fd, &value, sizeof(value)); } if (out==-1) { fprintf(stderr, "Error writing bind int to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // bind-null-arg-data: <statement-ref><index> void SRRecBindNull(sqlite3_stmt *pStmt, int i) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRBindNull; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out!=-1) { out = write(ref->fd, &i, sizeof(i)); } if (out==-1) { fprintf(stderr, "Error writing bind null to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } // bind-value-arg-data: <statement-ref><index><len><data> ??? void SRRecBindValue(sqlite3_stmt *pStmt, int i, const sqlite3_value *value) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { fprintf(stderr, "SRRecBindValue(sqlite3_bind_value) is not yet supported, closing [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } // bind-clear-arg-data: <statement-ref> void SRRecClearBindings(sqlite3_stmt *pStmt) { if (!srr_enabled) return; if(pStmt!=NULL) { Vdbe *v = (Vdbe *)pStmt; SRRLogRef *ref = getLog(v->db); if (ref && (ref->depth == 0)) { SRRCommand code = SRRBindClear; struct timeval tv; size_t out; gettimeofday(&tv, NULL); out = write(ref->fd, &tv, sizeof(tv)); if (out!=-1) { out = write(ref->fd, &code, sizeof(SRRCommand)); } if (out!=-1) { int64_t stmtInt = (int64_t)((intptr_t)(pStmt)); out = write(ref->fd, &stmtInt, sizeof(int64_t)); } if (out==-1) { fprintf(stderr, "Error writing clear bindings to log file [%s]: %s\n", ref->logPath, strerror(errno)); closeLog(ref->db); } } } } #endif /* SQLITE_ENABLE_SQLRR */ |
Added ext/sqlrr/sqlrr.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | /* * sqlrr.h */ #ifndef _SQLRR_H_ #define _SQLRR_H_ /* ** Header constants */ #define SRR_FILE_SIGNATURE "SQLRR" #define SRR_FILE_SIGNATURE_LEN 5 #define SRR_FILE_VERSION 0x1 #define SRR_FILE_VERSION_LEN 1 #if defined(SQLITE_ENABLE_SQLRR) #include "sqlite3.h" #include <sys/types.h> #define SRRecOpen(A,B,C) if(!rc){_SRRecOpen(A,B,C);} #define SRRecPrepare(A,B,C,D,E) if(!rc){_SRRecPrepare(A,B,C,D,E);} typedef enum { SRROpen = 0, SRRClose = 1, SRRExec = 8, SRRBindText = 16, SRRBindBlob = 17, SRRBindDouble = 18, SRRBindInt = 19, SRRBindNull = 20, SRRBindValue = 21, SRRBindClear = 22, SRRPrepare = 32, SRRStep = 33, SRRReset = 34, SRRFinalize = 35 } SRRCommand; extern void SQLiteReplayRecorder(int flag); extern void _SRRecOpen(sqlite3 *db, const char *path, int flags); extern void SRRecClose(sqlite3 *db); extern void SRRecExec(sqlite3 *db, const char *sql); extern void SRRecExecEnd(sqlite3 *db); extern void _SRRecPrepare(sqlite3 *db, const char *sql, int nBytes, int saveSql, sqlite3_stmt *stmt); extern void SRRecStep(sqlite3_stmt *pStmt); extern void SRRecStepEnd(sqlite3_stmt *pStmt); extern void SRRecReset(sqlite3_stmt *pStmt); extern void SRRecFinalize(sqlite3_stmt *pStmt); extern void SRRecBindText(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData); extern void SRRecBindBlob(sqlite3_stmt *pStmt, int i, const char *zData, int64_t nData); extern void SRRecBindDouble(sqlite3_stmt *pStmt, int i, double value); extern void SRRecBindInt64(sqlite3_stmt *pStmt, int i, int64_t value); extern void SRRecBindNull(sqlite3_stmt *pStmt, int i); extern void SRRecBindValue(sqlite3_stmt *pStmt, int i, const sqlite3_value *value); extern void SRRecClearBindings(sqlite3_stmt *pStmt); #endif /* defined(SQLITE_ENABLE_SQLRR) */ #endif /* _SQLRR_H_ */ |
Changes to main.mk.
︙ | ︙ | |||
227 228 229 230 231 232 233 234 235 236 237 238 239 240 | $(TOP)/ext/icu/sqliteicu.h \ $(TOP)/ext/icu/icu.c SRC += \ $(TOP)/ext/rtree/sqlite3rtree.h \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c \ $(TOP)/ext/rtree/geopoly.c SRC += \ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h SRC += \ $(TOP)/ext/userauth/userauth.c \ $(TOP)/ext/userauth/sqlite3userauth.h SRC += \ | > > > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | $(TOP)/ext/icu/sqliteicu.h \ $(TOP)/ext/icu/icu.c SRC += \ $(TOP)/ext/rtree/sqlite3rtree.h \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c \ $(TOP)/ext/rtree/geopoly.c SRC += \ $(TOP)/ext/sqlrr/sqlrr.h \ $(TOP)/ext/sqlrr/sqlrr.c SRC += \ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h SRC += \ $(TOP)/ext/userauth/userauth.c \ $(TOP)/ext/userauth/sqlite3userauth.h SRC += \ |
︙ | ︙ | |||
474 475 476 477 478 479 480 481 482 483 484 485 486 487 | $(TOP)/ext/fts2/fts2_hash.h \ $(TOP)/ext/fts2/fts2_tokenizer.h EXTHDR += \ $(TOP)/ext/fts3/fts3.h \ $(TOP)/ext/fts3/fts3Int.h \ $(TOP)/ext/fts3/fts3_hash.h \ $(TOP)/ext/fts3/fts3_tokenizer.h EXTHDR += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/fts5/fts5Int.h \ | > > | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | $(TOP)/ext/fts2/fts2_hash.h \ $(TOP)/ext/fts2/fts2_tokenizer.h EXTHDR += \ $(TOP)/ext/fts3/fts3.h \ $(TOP)/ext/fts3/fts3Int.h \ $(TOP)/ext/fts3/fts3_hash.h \ $(TOP)/ext/fts3/fts3_tokenizer.h EXTHDR += \ $(TOP)/ext/sqlrr/sqlrr.h EXTHDR += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/fts5/fts5Int.h \ |
︙ | ︙ | |||
628 629 630 631 632 633 634 | # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to # build on the target system. Some of the C source code and header # files are automatically generated. This target takes care of # all that automatic generation. # | | | | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to # build on the target system. Some of the C source code and header # files are automatically generated. This target takes care of # all that automatic generation. # target_source: $(SRC) $(EXTHDR) $(TOP)/tool/vdbe-compress.tcl fts5.c rm -rf tsrc mkdir tsrc cp -f $(SRC) $(EXTHDR) tsrc rm tsrc/sqlite.h.in tsrc/parse.y tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new mv vdbe.new tsrc/vdbe.c cp fts5.c fts5.h tsrc touch target_source sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | ** Enable or disable the shared pager and schema features. ** ** This routine has no effect on existing database connections. ** The shared cache setting effects only future calls to ** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). */ int sqlite3_enable_shared_cache(int enable){ sqlite3GlobalConfig.sharedCacheEnabled = enable; return SQLITE_OK; } #endif #ifdef SQLITE_OMIT_SHARED_CACHE /* | > > > > > > | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | ** Enable or disable the shared pager and schema features. ** ** This routine has no effect on existing database connections. ** The shared cache setting effects only future calls to ** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). */ int sqlite3_enable_shared_cache(int enable){ #if defined(__APPLE__) && !defined(SQLITE_TEST) && !defined(TH3_COMPATIBILITY) /* Enable global shared cache function for debugging and unit tests, ** but not for release */ return SQLITE_MISUSE; #else sqlite3GlobalConfig.sharedCacheEnabled = enable; return SQLITE_OK; #endif } #endif #ifdef SQLITE_OMIT_SHARED_CACHE /* |
︙ | ︙ |
Changes to src/btreeInt.h.
︙ | ︙ | |||
229 230 231 232 233 234 235 | #define MX_CELL(pBt) ((pBt->pageSize-8)/6) /* Forward declarations */ typedef struct MemPage MemPage; typedef struct BtLock BtLock; typedef struct CellInfo CellInfo; | < < < < < < < < < < < < < < < < | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | #define MX_CELL(pBt) ((pBt->pageSize-8)/6) /* Forward declarations */ typedef struct MemPage MemPage; typedef struct BtLock BtLock; typedef struct CellInfo CellInfo; /* ** Page type flags. An ORed combination of these flags appear as the ** first byte of on-disk image of every BTree page. */ #define PTF_INTKEY 0x01 #define PTF_ZERODATA 0x02 #define PTF_LEAFDATA 0x04 |
︙ | ︙ |
Changes to src/legacy.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. */ #include "sqliteInt.h" /* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result | > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_SQLRR # include "sqlrr.h" #endif /* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result |
︙ | ︙ | |||
38 39 40 41 42 43 44 | const char *zLeftover; /* Tail of unprocessed SQL */ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ char **azCols = 0; /* Names of result columns */ int callbackIsInit; /* True if callback data is initialized */ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; if( zSql==0 ) zSql = ""; | | > > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | const char *zLeftover; /* Tail of unprocessed SQL */ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ char **azCols = 0; /* Names of result columns */ int callbackIsInit; /* True if callback data is initialized */ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; if( zSql==0 ) zSql = ""; #ifdef SQLITE_ENABLE_SQLRR SRRecExec(db, zSql); #endif sqlite3_mutex_enter(db->mutex); sqlite3Error(db, SQLITE_OK); while( rc==SQLITE_OK && zSql[0] ){ int nCol = 0; char **azVals = 0; pStmt = 0; |
︙ | ︙ | |||
119 120 121 122 123 124 125 126 127 128 129 130 131 132 | sqlite3DbFree(db, azCols); azCols = 0; } exec_out: if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt); sqlite3DbFree(db, azCols); rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && pzErrMsg ){ *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db)); if( *pzErrMsg==0 ){ rc = SQLITE_NOMEM_BKPT; sqlite3Error(db, SQLITE_NOMEM); | > > > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | sqlite3DbFree(db, azCols); azCols = 0; } exec_out: if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt); sqlite3DbFree(db, azCols); #ifdef SQLITE_ENABLE_SQLRR SRRecExecEnd(db); #endif rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && pzErrMsg ){ *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db)); if( *pzErrMsg==0 ){ rc = SQLITE_NOMEM_BKPT; sqlite3Error(db, SQLITE_NOMEM); |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" #endif #ifdef SQLITE_ENABLE_RTREE # include "rtree.h" #endif #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) | > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_SQLRR # include "sqlrr.h" #endif #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" #endif #ifdef SQLITE_ENABLE_RTREE # include "rtree.h" #endif #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) |
︙ | ︙ | |||
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 | sqlite3_mutex_leave(db->mutex); db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); assert( sqlite3LookasideUsed(db,0)==0 ); if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } sqlite3_free(db); } /* ** Rollback all database files. If tripCode is not SQLITE_OK, then ** any write cursors are invalidated ("tripped" - as in "tripping a circuit ** breaker") and made to return tripCode if there are any further | > > > > | 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | sqlite3_mutex_leave(db->mutex); db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); assert( sqlite3LookasideUsed(db,0)==0 ); if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } #ifdef SQLITE_ENABLE_SQLRR SRRecClose(db); #endif sqlite3_free(db); } /* ** Rollback all database files. If tripCode is not SQLITE_OK, then ** any write cursors are invalidated ("tripped" - as in "tripping a circuit ** breaker") and made to return tripCode if there are any further |
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 | case SQLITE_IOERR_SHMLOCK: zName = "SQLITE_IOERR_SHMLOCK"; break; case SQLITE_IOERR_SHMMAP: zName = "SQLITE_IOERR_SHMMAP"; break; case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break; case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break; case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break; case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break; case SQLITE_IOERR_CONVPATH: zName = "SQLITE_IOERR_CONVPATH"; break; case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break; case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; case SQLITE_FULL: zName = "SQLITE_FULL"; break; case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break; case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break; | > | 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 | case SQLITE_IOERR_SHMLOCK: zName = "SQLITE_IOERR_SHMLOCK"; break; case SQLITE_IOERR_SHMMAP: zName = "SQLITE_IOERR_SHMMAP"; break; case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break; case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break; case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break; case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break; case SQLITE_IOERR_CONVPATH: zName = "SQLITE_IOERR_CONVPATH"; break; case SQLITE_IOERR_VNODE: zName = "SQLITE_IOERR_VNODE"; break; case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break; case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; case SQLITE_FULL: zName = "SQLITE_FULL"; break; case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break; case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break; |
︙ | ︙ | |||
2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 | if( newLimit>aHardLimit[limitId] ){ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ } db->aLimit[limitId] = newLimit; } return oldLimit; /* IMP: R-53341-35419 */ } /* ** This function is used to parse both URIs and non-URI filenames passed by the ** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database ** URIs specified as part of ATTACH statements. ** ** The first argument to this function is the name of the VFS to use (or | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 | if( newLimit>aHardLimit[limitId] ){ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ } db->aLimit[limitId] = newLimit; } return oldLimit; /* IMP: R-53341-35419 */ } #if defined(SQLITE_ENABLE_AUTO_PROFILE) /* stderr logging */ void _sqlite_auto_profile(void *aux, const char *sql, u64 ns); void _sqlite_auto_trace(void *aux, const char *sql); void _sqlite_auto_profile(void *aux, const char *sql, u64 ns) { #pragma unused(aux) fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000); } void _sqlite_auto_trace(void *aux, const char *sql) { fprintf(stderr, "TraceSQL(%p): %s\n", aux, sql); } /* syslog logging */ #include <asl.h> static aslclient autolog_client = NULL; static void _close_asl_log() { if( NULL!=autolog_client ){ asl_close(autolog_client); autolog_client = NULL; } } static void _open_asl_log() { if( NULL==autolog_client ){ autolog_client = asl_open("SQLite", NULL, 0); atexit(_close_asl_log); } } void _sqlite_auto_profile_syslog(void *aux, const char *sql, u64 ns); void _sqlite_auto_trace_syslog(void *aux, const char *sql); void _sqlite_auto_profile_syslog(void *aux, const char *sql, u64 ns) { #pragma unused(aux) asl_log(autolog_client, NULL, ASL_LEVEL_NOTICE, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000); } void _sqlite_auto_trace_syslog(void *aux, const char *sql) { asl_log(autolog_client, NULL, ASL_LEVEL_NOTICE, "TraceSQL(%p): %s\n", aux, sql); } #endif /* ** This function is used to parse both URIs and non-URI filenames passed by the ** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database ** URIs specified as part of ATTACH statements. ** ** The first argument to this function is the name of the VFS to use (or |
︙ | ︙ | |||
3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 | zFile = 0; } *pFlags = flags; *pzFile = zFile; return rc; } /* ** This routine does the core work of extracting URI parameters from a ** database filename for the sqlite3_uri_parameter() interface. */ static const char *uriParameter(const char *zFilename, const char *zParam){ zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ int x = strcmp(zFilename, zParam); zFilename += sqlite3Strlen30(zFilename) + 1; if( x==0 ) return zFilename; zFilename += sqlite3Strlen30(zFilename) + 1; } return 0; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 | zFile = 0; } *pFlags = flags; *pzFile = zFile; return rc; } #if defined(SQLITE_ENABLE_AUTO_PROFILE) #define SQLITE_AUTOLOGGING_STDERR 1 #define SQLITE_AUTOLOGGING_SYSLOG 2 static void enableAutoLogging( sqlite3 *db ){ char *envprofile = getenv("SQLITE_AUTO_PROFILE"); if( envprofile!=NULL ){ int where = 0; if( !strncasecmp("1", envprofile, 1) ){ if( isatty(2) ){ where = SQLITE_AUTOLOGGING_STDERR; }else{ where = SQLITE_AUTOLOGGING_SYSLOG; } } else if( !strncasecmp("stderr", envprofile, 6) ){ where = SQLITE_AUTOLOGGING_STDERR; } else if( !strncasecmp("syslog", envprofile, 6) ){ where = SQLITE_AUTOLOGGING_SYSLOG; } if( where==SQLITE_AUTOLOGGING_STDERR ){ sqlite3_profile(db, _sqlite_auto_profile, db); }else if( where==SQLITE_AUTOLOGGING_SYSLOG ){ _open_asl_log(); sqlite3_profile(db, _sqlite_auto_profile_syslog, db); } } char *envtrace = getenv("SQLITE_AUTO_TRACE"); if( envtrace!=NULL ){ int where = 0; if( !strncasecmp("1", envtrace, 1) ){ if( isatty(2) ){ where = SQLITE_AUTOLOGGING_STDERR; }else{ where = SQLITE_AUTOLOGGING_SYSLOG; } } else if( !strncasecmp("stderr", envtrace, 6) ){ where = SQLITE_AUTOLOGGING_STDERR; } else if( !strncasecmp("syslog", envtrace, 6) ){ where = SQLITE_AUTOLOGGING_SYSLOG; } if( where==SQLITE_AUTOLOGGING_STDERR ){ sqlite3_trace(db, _sqlite_auto_trace, db); }else if( where==SQLITE_AUTOLOGGING_SYSLOG ){ _open_asl_log(); sqlite3_trace(db, _sqlite_auto_trace_syslog, db); } } } #endif /* ** This routine does the core work of extracting URI parameters from a ** database filename for the sqlite3_uri_parameter() interface. */ static const char *uriParameter(const char *zFilename, const char *zParam){ zFilename += sqlite3Strlen30(zFilename) + 1; while( zFilename[0] ){ int x = strcmp(zFilename, zParam); zFilename += sqlite3Strlen30(zFilename) + 1; if( x==0 ) return zFilename; zFilename += sqlite3Strlen30(zFilename) + 1; } return 0; } /* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" ** is UTF-8 encoded. */ static int openDatabase( |
︙ | ︙ | |||
3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 | assert( db!=0 || rc==SQLITE_NOMEM ); if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ /* Opening a db handle. Fourth parameter is passed 0. */ void *pArg = sqlite3GlobalConfig.pSqllogArg; sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif | > > > > > > > > > > > > > > > > > > > > > > > | 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 | assert( db!=0 || rc==SQLITE_NOMEM ); if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } #if defined(__APPLE__) && ENABLE_FORCE_WAL if( db && !rc ){ if ((0 == access("/var/db/enableForceWAL", R_OK))) { #ifdef SQLITE_DEBUG fprintf(stderr, "SQLite WAL journal_mode ENABLED by default.\n"); #endif sqlite3_exec(db, "pragma journal_mode=wal", NULL, NULL, NULL); #ifdef SQLITE_DEBUG // } else { // fprintf(stderr, "SQLite WAL journal_mode NOT ENABLED by default.\n"); #endif } } #endif #if defined(SQLITE_ENABLE_AUTO_PROFILE) if( db && !rc ){ enableAutoLogging(db); } #endif *ppDb = db; #ifdef SQLITE_ENABLE_SQLRR SRRecOpen(db, zFilename, flags); #endif #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ /* Opening a db handle. Fourth parameter is passed 0. */ void *pArg = sqlite3GlobalConfig.pSqllogArg; sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif |
︙ | ︙ | |||
3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 | rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_VFS_POINTER ){ *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_DATA_VERSION ){ *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); rc = SQLITE_OK; }else{ rc = sqlite3OsFileControl(fd, op, pArg); } sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); return rc; } /* ** Interface to the testing logic. */ | > > > > > > > > > | 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 | rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_VFS_POINTER ){ *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; #ifndef SQLITE_OMIT_WAL if( (rc==SQLITE_OK)&&(op==SQLITE_FCNTL_LAST_ERRNO)&&(*(int *)pArg==0) ){ sqlite3_file *pWalFd = sqlite3PagerWalFile(pPager); if( pWalFd&&(pWalFd->pMethods) ){ rc = sqlite3OsFileControl(pWalFd, op, pArg); } } #endif }else if( op==SQLITE_FCNTL_DATA_VERSION ){ *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); rc = SQLITE_OK; }else{ rc = sqlite3OsFileControl(fd, op, pArg); } sqlite3BtreeLeave(pBtree); } sqlite3Error(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Interface to the testing logic. */ |
︙ | ︙ | |||
4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 | (void)SQLITE_MISUSE_BKPT; return -1; } #endif pBt = sqlite3DbNameToBtree(db, zDbName); return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; } #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Obtain a snapshot handle for the snapshot of database zDb currently ** being read by handle db. */ int sqlite3_snapshot_get( | > > > > > > > > > > > > > > > > > > > > > > > > > > | 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 | (void)SQLITE_MISUSE_BKPT; return -1; } #endif pBt = sqlite3DbNameToBtree(db, zDbName); return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; } #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) #include "sqlite3_private.h" /* ** Testing a file path for sqlite locks held by a process ID. ** Returns SQLITE_LOCKSTATE_ON if locks are present on path ** that would prevent writing to the database. */ int _sqlite3_lockstate(const char *path, pid_t pid){ sqlite3 *db = NULL; if( sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK ){ LockstatePID lockstate = {pid, -1}; sqlite3_file_control(db, NULL, SQLITE_FCNTL_LOCKSTATE_PID, &lockstate); sqlite3_close(db); int state = lockstate.state; return state; } if( NULL!=db ){ sqlite3_close(db); /* need to close even if open returns an error */ } return SQLITE_LOCKSTATE_ERROR; } #endif /* SQLITE_ENABLE_APPLE_SPI */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Obtain a snapshot handle for the snapshot of database zDb currently ** being read by handle db. */ int sqlite3_snapshot_get( |
︙ | ︙ |
Changes to src/os.c.
︙ | ︙ | |||
206 207 208 209 210 211 212 213 214 215 216 217 | sqlite3_vfs *pVfs, const char *zPath, sqlite3_file *pFile, int flags, int *pFlagsOut ){ int rc; DO_OS_MALLOC_TEST(0); /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before ** reaching the VFS. */ | > > > > > > | | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | sqlite3_vfs *pVfs, const char *zPath, sqlite3_file *pFile, int flags, int *pFlagsOut ){ int rc; int openFlags; DO_OS_MALLOC_TEST(0); /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before ** reaching the VFS. */ #if SQLITE_ENABLE_DATA_PROTECTION openFlags = flags & (0x1087f7f | SQLITE_OPEN_FILEPROTECTION_MASK); #else openFlags = flags & 0x1087f7f; #endif rc = pVfs->xOpen(pVfs, zPath, pFile, openFlags, pFlagsOut); assert( rc==SQLITE_OK || pFile->pMethods==0 ); return rc; } int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ DO_OS_MALLOC_TEST(0); assert( dirSync==0 || dirSync==1 ); return pVfs->xDelete(pVfs, zPath, dirSync); |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #include <errno.h> #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 # include <sys/mman.h> #endif #if SQLITE_ENABLE_LOCKING_STYLE # include <sys/ioctl.h> # include <sys/file.h> # include <sys/param.h> #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* ** Try to determine if gethostuuid() is available based on standard ** macros. This might sometimes compute the wrong value for some | > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #include <errno.h> #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 # include <sys/mman.h> #endif #if SQLITE_ENABLE_LOCKING_STYLE # include <sys/ioctl.h> # include <uuid/uuid.h> # include <sys/file.h> # include <sys/param.h> #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* ** Try to determine if gethostuuid() is available based on standard ** macros. This might sometimes compute the wrong value for some |
︙ | ︙ | |||
233 234 235 236 237 238 239 | sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ void *pMapRegion; /* Memory mapped region */ #endif int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ | | > > > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ void *pMapRegion; /* Memory mapped region */ #endif int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_DATA_PROTECTION int protFlags; /* Data protection flags from unixOpen */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #ifdef SQLITE_ENABLE_SETLK_TIMEOUT unsigned iBusyTimeout; /* Wait this many millisec on locks */ #endif #if OS_VXWORKS |
︙ | ︙ | |||
320 321 322 323 324 325 326 327 328 329 330 331 332 333 | ** testing and debugging only. */ #if SQLITE_THREADSAFE #define threadid pthread_self() #else #define threadid 0 #endif /* ** HAVE_MREMAP defaults to true on Linux and false everywhere else. */ #if !defined(HAVE_MREMAP) # if defined(__linux__) && defined(_GNU_SOURCE) # define HAVE_MREMAP 1 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 | ** testing and debugging only. */ #if SQLITE_THREADSAFE #define threadid pthread_self() #else #define threadid 0 #endif #ifdef __APPLE__ #define SQLITE_ENABLE_SUPERLOCK 1 #endif #if SQLITE_ENABLE_SUPERLOCK #include "sqlite3.h" #include <string.h> #include <assert.h> /* ** A structure to collect a busy-handler callback and argument and a count ** of the number of times it has been invoked. */ struct SuperlockBusy { int (*xBusy)(void*,int); /* Pointer to busy-handler function */ void *pBusyArg; /* First arg to pass to xBusy */ int nBusy; /* Number of times xBusy has been invoked */ }; typedef struct SuperlockBusy SuperlockBusy; /* ** An instance of the following structure is allocated for each active ** superlock. The opaque handle returned by sqlite3demo_superlock() is ** actually a pointer to an instance of this structure. */ struct Superlock { sqlite3 *db; /* Database handle used to lock db */ int bWal; /* True if db is a WAL database */ }; typedef struct Superlock Superlock; /* ** The pCtx pointer passed to this function is actually a pointer to a ** SuperlockBusy structure. Invoke the busy-handler function encapsulated ** by the structure and return the result. */ static int superlockBusyHandler(void *pCtx, int UNUSED){ SuperlockBusy *pBusy = (SuperlockBusy *)pCtx; if( pBusy->xBusy==0 ) return 0; return pBusy->xBusy(pBusy->pBusyArg, pBusy->nBusy++); } /* ** This function is used to determine if the main database file for ** connection db is open in WAL mode or not. If no error occurs and the ** database file is in WAL mode, set *pbWal to true and return SQLITE_OK. ** If it is not in WAL mode, set *pbWal to false. ** ** If an error occurs, return an SQLite error code. The value of *pbWal ** is undefined in this case. */ static int superlockIsWal(Superlock *pLock){ int rc; /* Return Code */ sqlite3_stmt *pStmt; /* Compiled PRAGMA journal_mode statement */ rc = sqlite3_prepare(pLock->db, "PRAGMA main.journal_mode", -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; pLock->bWal = 0; if( SQLITE_ROW==sqlite3_step(pStmt) ){ const char *zMode = (const char *)sqlite3_column_text(pStmt, 0); if( zMode && strlen(zMode)==3 && sqlite3_strnicmp("wal", zMode, 3)==0 ){ pLock->bWal = 1; } } return sqlite3_finalize(pStmt); } /* ** Obtain an exclusive shm-lock on nByte bytes starting at offset idx ** of the file fd. If the lock cannot be obtained immediately, invoke ** the busy-handler until either it is obtained or the busy-handler ** callback returns 0. */ static int superlockShmLock( sqlite3_file *fd, /* Database file handle */ int idx, /* Offset of shm-lock to obtain */ int nByte, /* Number of consective bytes to lock */ SuperlockBusy *pBusy /* Busy-handler wrapper object */ ){ int rc; int (*xShmLock)(sqlite3_file*, int, int, int) = fd->pMethods->xShmLock; do { rc = xShmLock(fd, idx, nByte, SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE); }while( rc==SQLITE_BUSY && superlockBusyHandler((void *)pBusy, 0) ); return rc; } /* ** Obtain the extra locks on the database file required for WAL databases. ** Invoke the supplied busy-handler as required. */ static int superlockWalLock( sqlite3 *db, /* Database handle open on WAL database */ SuperlockBusy *pBusy /* Busy handler wrapper object */ ){ int rc; /* Return code */ sqlite3_file *fd = 0; /* Main database file handle */ void volatile *p = 0; /* Pointer to first page of shared memory */ /* Obtain a pointer to the sqlite3_file object open on the main db file. */ rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd); if( rc!=SQLITE_OK ) return rc; /* Obtain the "recovery" lock. Normally, this lock is only obtained by ** clients running database recovery. */ rc = superlockShmLock(fd, 2, 1, pBusy); if( rc!=SQLITE_OK ) return rc; /* Zero the start of the first shared-memory page. This means that any ** clients that open read or write transactions from this point on will ** have to run recovery before proceeding. Since they need the "recovery" ** lock that this process is holding to do that, no new read or write ** transactions may now be opened. Nor can a checkpoint be run, for the ** same reason. */ rc = fd->pMethods->xShmMap(fd, 0, 32*1024, 1, &p); if( rc!=SQLITE_OK ) return rc; memset((void *)p, 0, 32); /* Obtain exclusive locks on all the "read-lock" slots. Once these locks ** are held, it is guaranteed that there are no active reader, writer or ** checkpointer clients. */ rc = superlockShmLock(fd, 3, SQLITE_SHM_NLOCK-3, pBusy); return rc; } /* ** Release a superlock held on a database file. The argument passed to ** this function must have been obtained from a successful call to ** sqlite3demo_superlock(). */ static void sqlite3demo_superunlock(void *pLock){ Superlock *p = (Superlock *)pLock; if( p->bWal ){ int rc; /* Return code */ int flags = SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE; sqlite3_file *fd = 0; rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd); if( rc==SQLITE_OK ){ fd->pMethods->xShmLock(fd, 2, 1, flags); fd->pMethods->xShmLock(fd, 3, SQLITE_SHM_NLOCK-3, flags); } } sqlite3_close(p->db); sqlite3_free(p); } /* ** Obtain a superlock on the database file identified by zPath, using the ** locking primitives provided by VFS zVfs. If successful, SQLITE_OK is ** returned and output variable *ppLock is populated with an opaque handle ** that may be used with sqlite3demo_superunlock() to release the lock. ** ** If an error occurs, *ppLock is set to 0 and an SQLite error code ** (e.g. SQLITE_BUSY) is returned. ** ** If a required lock cannot be obtained immediately and the xBusy parameter ** to this function is not NULL, then xBusy is invoked in the same way ** as a busy-handler registered with SQLite (using sqlite3_busy_handler()) ** until either the lock can be obtained or the busy-handler function returns ** 0 (indicating "give up"). */ static int sqlite3demo_superlock( const char *zPath, /* Path to database file to lock */ const char *zVfs, /* VFS to use to access database file */ int flags, /* Additional flags to pass to sqlite3_open_v2 */ int (*xBusy)(void*,int), /* Busy handler callback */ void *pBusyArg, /* Context arg for busy handler */ void **ppLock /* OUT: Context to pass to superunlock() */ ){ SuperlockBusy busy = {0, 0, 0}; /* Busy handler wrapper object */ int rc; /* Return code */ Superlock *pLock; pLock = sqlite3_malloc(sizeof(Superlock)); if( !pLock ) return SQLITE_NOMEM; memset(pLock, 0, sizeof(Superlock)); /* Open a database handle on the file to superlock. */ rc = sqlite3_open_v2( zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|flags, zVfs ); /* Install a busy-handler and execute a BEGIN EXCLUSIVE. If this is not ** a WAL database, this is all we need to do. ** ** A wrapper function is used to invoke the busy-handler instead of ** registering the busy-handler function supplied by the user directly ** with SQLite. This is because the same busy-handler function may be ** invoked directly later on when attempting to obtain the extra locks ** required in WAL mode. By using the wrapper, we are able to guarantee ** that the "nBusy" integer parameter passed to the users busy-handler ** represents the total number of busy-handler invocations made within ** this call to sqlite3demo_superlock(), including any made during the ** "BEGIN EXCLUSIVE". */ if( rc==SQLITE_OK ){ busy.xBusy = xBusy; busy.pBusyArg = pBusyArg; sqlite3_busy_handler(pLock->db, superlockBusyHandler, (void *)&busy); rc = sqlite3_exec(pLock->db, "BEGIN EXCLUSIVE", 0, 0, 0); } /* If the BEGIN EXCLUSIVE was executed successfully and this is a WAL ** database, call superlockWalLock() to obtain the extra locks required ** to prevent readers, writers and/or checkpointers from accessing the ** db while this process is holding the superlock. ** ** Before attempting any WAL locks, commit the transaction started above ** to drop the WAL read and write locks currently held. Otherwise, the ** new WAL locks may conflict with the old. */ if( rc==SQLITE_OK ){ if( SQLITE_OK==(rc = superlockIsWal(pLock)) && pLock->bWal ){ rc = sqlite3_exec(pLock->db, "COMMIT", 0, 0, 0); if( rc==SQLITE_OK ){ rc = superlockWalLock(pLock->db, &busy); } } } if( rc!=SQLITE_OK ){ sqlite3demo_superunlock(pLock); *ppLock = 0; }else{ *ppLock = pLock; } return rc; } /* A corrupt DB won't work with the sql-based locking attempt, grab an ** exclusive lock and return SQLITE_OK or SQLITE_BUSY if the lock fails ** returns the current lock level held on sqlite3_file */ static int sqlite3demo_superlock_corrupt( sqlite3_file *id, int eTargetFileLock, int *pFileLock ){ unixFile *pFile = (unixFile*)id; int eFileLock = pFile->eFileLock; int rc = SQLITE_OK; if( eFileLock<eTargetFileLock ){ rc = pFile->pMethod->xLock(id, SQLITE_LOCK_SHARED); } if( !rc && SQLITE_LOCK_SHARED<eTargetFileLock ){ rc = pFile->pMethod->xLock(id, SQLITE_LOCK_EXCLUSIVE); } if( rc ){ if( pFile->eFileLock > eFileLock ){ pFile->pMethod->xUnlock(id, eFileLock); } return rc; } if (pFileLock) { *pFileLock = eFileLock; } return SQLITE_OK; } static int sqlite3demo_superunlock_corrupt(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; int rc = SQLITE_OK; if( pFile->eFileLock > eFileLock ){ rc = pFile->pMethod->xUnlock(id, SQLITE_LOCK_SHARED); } if( pFile->eFileLock > eFileLock ){ int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_NONE); if (!rc) rc = unlockRC; } return rc; } #endif /* SQLITE_ENABLE_SUPERLOCK */ /* ** HAVE_MREMAP defaults to true on Linux and false everywhere else. */ #if !defined(HAVE_MREMAP) # if defined(__linux__) && defined(_GNU_SOURCE) # define HAVE_MREMAP 1 |
︙ | ︙ | |||
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 | static void closePendingFds(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; UnixUnusedFd *p; UnixUnusedFd *pNext; assert( unixFileMutexHeld(pFile) ); for(p=pInode->pUnused; p; p=pNext){ pNext = p->pNext; robust_close(pFile, p->fd, __LINE__); sqlite3_free(p); } pInode->pUnused = 0; } /* ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). ** | > > > > > > > > > > > | 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 | static void closePendingFds(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; UnixUnusedFd *p; UnixUnusedFd *pNext; assert( unixFileMutexHeld(pFile) ); for(p=pInode->pUnused; p; p=pNext){ pNext = p->pNext; #if OSCLOSE_CHECK_CLOSE_IOERR if( close(p->fd) ){ storeLastErrno(pFile, errno); rc = SQLITE_IOERR_CLOSE; p->pNext = pError; pError = p; }else{ sqlite3_free(p); } #else robust_close(pFile, p->fd, __LINE__); sqlite3_free(p); #endif } pInode->pUnused = 0; } /* ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). ** |
︙ | ︙ | |||
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 | if( !reserved && !pFile->pInode->bProcessLock ){ struct flock lock; lock.l_whence = SEEK_SET; lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; if( osFcntl(pFile->h, F_GETLK, &lock) ){ rc = SQLITE_IOERR_CHECKRESERVEDLOCK; storeLastErrno(pFile, errno); } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } } #endif sqlite3_mutex_leave(pFile->pInode->pLockMutex); | > > > > > > | 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 | if( !reserved && !pFile->pInode->bProcessLock ){ struct flock lock; lock.l_whence = SEEK_SET; lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; if( osFcntl(pFile->h, F_GETLK, &lock) ){ #if OSLOCKING_CHECK_BUSY_IOERR int tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); storeLastErrno(pFile, tErrno); #else rc = SQLITE_IOERR_CHECKRESERVEDLOCK; storeLastErrno(pFile, errno); #endif } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } } #endif sqlite3_mutex_leave(pFile->pInode->pLockMutex); |
︙ | ︙ | |||
1596 1597 1598 1599 1600 1601 1602 | ** This function is a pass-through to fcntl(F_SETLK) if pFile is using ** any VFS other than "unix-excl" or if pFile is opened on "unix-excl" ** and is read-only. ** ** Zero is returned if the call completes successfully, or -1 if a call ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()). */ | | | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 | ** This function is a pass-through to fcntl(F_SETLK) if pFile is using ** any VFS other than "unix-excl" or if pFile is opened on "unix-excl" ** and is read-only. ** ** Zero is returned if the call completes successfully, or -1 if a call ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()). */ static int unixFileLock(unixFile *pFile, struct flock *pLock, int nRetry){ int rc; unixInodeInfo *pInode = pFile->pInode; assert( pInode!=0 ); assert( sqlite3_mutex_held(pInode->pLockMutex) ); if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ if( pInode->bProcessLock==0 ){ struct flock lock; |
︙ | ︙ | |||
1759 1760 1761 1762 1763 1764 1765 | lock.l_len = 1L; lock.l_whence = SEEK_SET; if( eFileLock==SHARED_LOCK || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK) ){ lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_start = PENDING_BYTE; | | | | | > > > > | | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 | lock.l_len = 1L; lock.l_whence = SEEK_SET; if( eFileLock==SHARED_LOCK || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK) ){ lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_start = PENDING_BYTE; if( unixFileLock(pFile, &lock, 0) ){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } goto end_lock; } } /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( eFileLock==SHARED_LOCK ){ assert( pInode->nShared==0 ); assert( pInode->eFileLock==0 ); assert( rc==SQLITE_OK ); /* Now get the read-lock */ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; if( unixFileLock(pFile, &lock, 0) ){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); } /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; if( unixFileLock(pFile, &lock, 10) && rc==SQLITE_OK ){ /* This could happen with a network mount */ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); #else rc = SQLITE_IOERR_UNLOCK; #endif } if( rc ){ if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } goto end_lock; }else{ pFile->eFileLock = SHARED_LOCK; pInode->nLock++; pInode->nShared = 1; |
︙ | ︙ | |||
1827 1828 1829 1830 1831 1832 1833 | lock.l_start = RESERVED_BYTE; lock.l_len = 1L; }else{ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; } | | | 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | lock.l_start = RESERVED_BYTE; lock.l_len = 1L; }else{ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; } if( unixFileLock(pFile, &lock, 0) ){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ storeLastErrno(pFile, tErrno); } } } |
︙ | ︙ | |||
1952 1953 1954 1955 1956 1957 1958 | int tErrno; /* Error code from system call errors */ off_t divSize = SHARED_SIZE - 1; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; | | > > > > | > > > > | > > > > > > > | > > > > | > > > > | > > > > > > > > | > > > > > > > > | 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 | int tErrno; /* Error code from system call errors */ off_t divSize = SHARED_SIZE - 1; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; if( unixFileLock(pFile, &lock, 10)==(-1) ){ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); #else rc = SQLITE_IOERR_UNLOCK; #endif storeLastErrno(pFile, tErrno); goto end_unlock; } lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = divSize; if( unixFileLock(pFile, &lock, 10)==(-1) ){ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); #else rc = SQLITE_IOERR_UNLOCK; #endif if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } goto end_unlock; } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST+divSize; lock.l_len = SHARED_SIZE-divSize; if( unixFileLock(pFile, &lock, 10)==(-1) ){ tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); #else rc = SQLITE_IOERR_UNLOCK; #endif if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } storeLastErrno(pFile, tErrno); goto end_unlock; } }else #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ { lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; if( unixFileLock(pFile, &lock, 10) ){ int tErrno = errno; #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); #else /* In theory, the call to unixFileLock() cannot fail because another ** process is holding an incompatible lock. If it does, this ** indicates that the other process is not following the locking ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning ** SQLITE_BUSY would confuse the upper layer (in practice it causes ** an assert to fail). */ rc = SQLITE_IOERR_RDLOCK; storeLastErrno(pFile, tErrno); #endif if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } goto end_unlock; } } } lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); if( unixFileLock(pFile, &lock, 10)==0 ){ pInode->eFileLock = SHARED_LOCK; }else{ #if OSLOCKING_CHECK_BUSY_IOERR tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } #else rc = SQLITE_IOERR_UNLOCK; storeLastErrno(pFile, errno); #endif goto end_unlock; } } if( eFileLock==NO_LOCK ){ /* Decrement the shared lock counter. Release the lock using an ** OS call only when all threads in this same process have released ** the lock. */ pInode->nShared--; if( pInode->nShared==0 ){ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; if( unixFileLock(pFile, &lock, 10)==0 ){ pInode->eFileLock = NO_LOCK; }else{ #if OSLOCKING_CHECK_BUSY_IOERR tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ storeLastErrno(pFile, tErrno); } #else rc = SQLITE_IOERR_UNLOCK; storeLastErrno(pFile, errno); #endif pInode->eFileLock = NO_LOCK; pFile->eFileLock = NO_LOCK; } } /* Decrement the count of locks against this same file. When the ** count reaches zero, close any other file descriptors whose close |
︙ | ︙ | |||
2182 2183 2184 2185 2186 2187 2188 | return SQLITE_OK; } /* ** Close the file. */ static int nolockClose(sqlite3_file *id) { | > > > > > > > > > > > > > > > | > > | 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 | return SQLITE_OK; } /* ** Close the file. */ static int nolockClose(sqlite3_file *id) { int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; unixEnterMutex(); if( pFile->pInode ){ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); if( pFile->pInode->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pInode->pUnused list. It will be automatically closed ** when the last lock is cleared. */ setPendingFd(pFile); } releaseInodeInfo(pFile); } rc = closeUnixFile(id); unixLeaveMutex(); return rc; } /******************* End of the no-op lock implementation ********************* ******************************************************************************/ /****************************************************************************** ************************* Begin dot-file Locking ****************************** |
︙ | ︙ | |||
2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 | assert( eFileLock==NO_LOCK ); rc = osRmdir(zLockFile); if( rc<0 ){ int tErrno = errno; if( tErrno==ENOENT ){ rc = SQLITE_OK; }else{ rc = SQLITE_IOERR_UNLOCK; storeLastErrno(pFile, tErrno); } return rc; } pFile->eFileLock = NO_LOCK; return SQLITE_OK; } | > > > > | 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 | assert( eFileLock==NO_LOCK ); rc = osRmdir(zLockFile); if( rc<0 ){ int tErrno = errno; if( tErrno==ENOENT ){ rc = SQLITE_OK; }else{ #if OSLOCKING_CHECK_BUSY_IOERR rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); #else rc = SQLITE_IOERR_UNLOCK; #endif storeLastErrno(pFile, tErrno); } return rc; } pFile->eFileLock = NO_LOCK; return SQLITE_OK; } |
︙ | ︙ | |||
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 | int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB); if( !lrc ){ /* got the lock, unlock it */ lrc = robust_flock(pFile->h, LOCK_UN); if ( lrc ) { int tErrno = errno; /* unlock failed with an error */ lrc = SQLITE_IOERR_UNLOCK; storeLastErrno(pFile, tErrno); rc = lrc; } } else { int tErrno = errno; reserved = 1; /* someone else might have it reserved */ | > > > > > > > > | 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 | int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB); if( !lrc ){ /* got the lock, unlock it */ lrc = robust_flock(pFile->h, LOCK_UN); if ( lrc ) { int tErrno = errno; /* unlock failed with an error */ #if OSLOCKING_CHECK_BUSY_IOERR lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); #else lrc = SQLITE_IOERR_UNLOCK; #endif if( IS_LOCK_ERROR(lrc) ){ storeLastErrno(pFile, tErrno); rc = lrc; } storeLastErrno(pFile, tErrno); rc = lrc; } } else { int tErrno = errno; reserved = 1; /* someone else might have it reserved */ |
︙ | ︙ | |||
3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 | */ #ifdef F_FULLFSYNC # define HAVE_FULLFSYNC 1 #else # define HAVE_FULLFSYNC 0 #endif /* ** The fsync() system call does not work as advertised on many ** unix systems. The following procedure is an attempt to make ** it work better. ** ** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful | > > > > > > | 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 | */ #ifdef F_FULLFSYNC # define HAVE_FULLFSYNC 1 #else # define HAVE_FULLFSYNC 0 #endif #ifdef SQLITE_USE_REQUEST_FULLFSYNC #import <notify.h> #import <libkern/OSAtomic.h> static OSSpinLock notify_lock = 0; #define REQUEST_FULLSYNC_NOTIFICATION "com.apple.reqsync" #endif /* ** The fsync() system call does not work as advertised on many ** unix systems. The following procedure is an attempt to make ** it work better. ** ** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful |
︙ | ︙ | |||
3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 | #ifdef SQLITE_NO_SYNC { struct stat buf; rc = osFstat(fd, &buf); } #elif HAVE_FULLFSYNC if( fullSync ){ rc = osFcntl(fd, F_FULLFSYNC, 0); }else{ rc = 1; } /* If the FULLFSYNC failed, fall back to attempting an fsync(). ** It shouldn't be possible for fullfsync to fail on the local ** file system (on OSX), so failure indicates that FULLFSYNC ** isn't supported for this file system. So, attempt an fsync | > > > > > > > > > | 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 | #ifdef SQLITE_NO_SYNC { struct stat buf; rc = osFstat(fd, &buf); } #elif HAVE_FULLFSYNC if( fullSync ){ #ifdef SQLITE_USE_REQUEST_FULLFSYNC rc = osFsync(fd); if (!rc) { OSSpinLockLock(¬ify_lock); rc = notify_post(REQUEST_FULLSYNC_NOTIFICATION); OSSpinLockUnlock(¬ify_lock); } #else rc = osFcntl(fd, F_FULLFSYNC, 0); #endif }else{ rc = 1; } /* If the FULLFSYNC failed, fall back to attempting an fsync(). ** It shouldn't be possible for fullfsync to fail on the local ** file system (on OSX), so failure indicates that FULLFSYNC ** isn't supported for this file system. So, attempt an fsync |
︙ | ︙ | |||
3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 | if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){ int dirfd; OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath, HAVE_FULLFSYNC, isFullsync)); rc = osOpenDirectory(pFile->zPath, &dirfd); if( rc==SQLITE_OK ){ full_fsync(dirfd, 0, 0); robust_close(pFile, dirfd, __LINE__); }else{ assert( rc==SQLITE_CANTOPEN ); rc = SQLITE_OK; } pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } /* ** Truncate an open file to a specified size */ | > > > > > > > > | 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 | if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){ int dirfd; OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath, HAVE_FULLFSYNC, isFullsync)); rc = osOpenDirectory(pFile->zPath, &dirfd); if( rc==SQLITE_OK ){ full_fsync(dirfd, 0, 0); #if OSCLOSE_CHECK_CLOSE_IOERR if( close(pFile->dirfd) ){ storeLastErrno(pFile, errno); rc = SQLITE_IOERR_DIR_CLOSE; } #else robust_close(pFile, dirfd, __LINE__); #endif }else{ assert( rc==SQLITE_CANTOPEN ); rc = SQLITE_OK; } pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } /* ** Truncate an open file to a specified size */ |
︙ | ︙ | |||
3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 | */ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ if( pFile->szChunk>0 ){ i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ if( osFstat(pFile->h, &buf) ){ return SQLITE_IOERR_FSTAT; } nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; if( nSize>(i64)buf.st_size ){ #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE | > | 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 | */ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ if( pFile->szChunk>0 ){ i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ if( osFstat(pFile->h, &buf) ){ storeLastErrno(pFile, errno); return SQLITE_IOERR_FSTAT; } nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; if( nSize>(i64)buf.st_size ){ #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
︙ | ︙ | |||
3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 | rc = unixMapfile(pFile, nByte); return rc; } #endif return SQLITE_OK; } /* ** If *pArg is initially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. ** ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 | rc = unixMapfile(pFile, nByte); return rc; } #endif return SQLITE_OK; } #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) #include "sqlite3_private.h" #include <copyfile.h> static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath); #endif #if SQLITE_ENABLE_LOCKING_STYLE static int isProxyLockingMode(unixFile *); #endif #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) static int unixTruncateDatabase(unixFile *, int); static int unixInvalidateSupportFiles(unixFile *, int); static int findCreateFileMode(const char *, int, mode_t*, uid_t *,gid_t *); /* opens a read/write connection to a file zName inheriting the appropriate ** user/perms from the database file if running as root. Returns the file ** descriptor by reference */ static int unixOpenChildFile( const char *zName, int openFlags, int dbOpenFlags, int protFlags, int *pFd ){ int fd = -1; mode_t openMode; /* Permissions to create file with */ uid_t uid; /* Userid for the file */ gid_t gid; /* Groupid for the file */ int rc; assert(pFd!=NULL); rc = findCreateFileMode(zName, dbOpenFlags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ return rc; } fd = robust_open(zName, openFlags, openMode); OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); if( fd<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); return rc; } /* if we're opening the wal or journal and running as root, set ** the journal uid/gid */ if( dbOpenFlags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ uid_t euid = geteuid(); if( euid==0 && (euid!=uid || getegid()!=gid) ){ if( fchown(fd, uid, gid) ){ rc = SQLITE_CANTOPEN_BKPT; } } } if( rc==SQLITE_OK ){ *pFd = fd; } else { *pFd = -1; close(fd); } return rc; } static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) { sqlite3_file *id = (sqlite3_file *)pFile; Btree *pSrcBtree = NULL; sqlite3_file *src_file = NULL; unixFile *pSrcFile = NULL; char srcWalPath[MAXPATHLEN+5]; int srcWalFD = -1; int rc = SQLITE_OK; void *pLock = NULL; int flags = 0; sqlite3 *srcdb2 = NULL; copyfile_state_t s; int corruptSrcFileLock = 0; int corruptDstFileLock = 0; int isSrcCorrupt = 0; int isDstCorrupt = 0; if( !sqlite3SafetyCheckOk(srcdb) ){ return SQLITE_MISUSE; } #if SQLITE_ENABLE_DATA_PROTECTION flags |= pFile->protFlags; #endif #if SQLITE_ENABLE_LOCKING_STYLE if( isProxyLockingMode(pFile) ){ flags |= SQLITE_OPEN_AUTOPROXY; } #endif rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock); if( rc ){ if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ isDstCorrupt = 1; rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock); } if( rc ){ return rc; } } /* get the src file descriptor adhering to the db struct access rules ** this code is modeled after sqlite3_file_control() in main.c */ sqlite3_mutex_enter(srcdb->mutex); if( srcdb->nDb>0 ){ pSrcBtree = srcdb->aDb[0].pBt; } if( pSrcBtree ){ Pager *pSrcPager; sqlite3BtreeEnter(pSrcBtree); pSrcPager = sqlite3BtreePager(pSrcBtree); assert( pSrcPager!=0 ); src_file = sqlite3PagerFile(pSrcPager); assert( src_file!=0 ); if( src_file->pMethods ){ int srcFlags = 0; pSrcFile = (unixFile *)src_file; #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) { srcFlags = SQLITE_OPEN_READWRITE; } else { srcFlags = SQLITE_OPEN_READONLY; } #else srcFlags = SQLITE_OPEN_READWRITE; #endif #if SQLITE_ENABLE_DATA_PROTECTION srcFlags |= pSrcFile->protFlags; #endif #if SQLITE_ENABLE_LOCKING_STYLE if( isProxyLockingMode(pSrcFile) ){ srcFlags |= SQLITE_OPEN_AUTOPROXY; } #endif rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0); if( rc==SQLITE_OK ){ /* start a deferred transaction and read to establish a read lock */ rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0); if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ isSrcCorrupt = 1; rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock); } } } } if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){ rc = SQLITE_INTERNAL; } if( rc!=SQLITE_OK ){ goto end_replace_database; } /* both databases are locked appropriately, copy the src wal journal if ** one exists and then the actual database file */ strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5); strlcat(srcWalPath, "-wal", MAXPATHLEN+5); srcWalFD = open(srcWalPath, O_RDONLY); if( !(srcWalFD<0) ){ char dstWalPath[MAXPATHLEN+5]; int dstWalFD = -1; int protFlags = 0; strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5); strlcat(dstWalPath, "-wal", MAXPATHLEN+5); rc = unixOpenChildFile(dstWalPath, O_RDWR|O_CREAT, SQLITE_OPEN_WAL, protFlags, &dstWalFD); if( rc==SQLITE_OK ){ s = copyfile_state_alloc(); lseek(srcWalFD, 0, SEEK_SET); lseek(dstWalFD, 0, SEEK_SET); if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_DATA) ){ int err=errno; switch(err) { case ENOMEM: rc = SQLITE_NOMEM; break; default: storeLastErrno(pFile, err); rc = SQLITE_IOERR; } } copyfile_state_free(s); close(dstWalFD); } close(srcWalFD); } if( rc==SQLITE_OK ){ /* before we copy, ensure that the file change counter will be modified */ uint32_t srcChange = 0; uint32_t dstChange = 0; pread(pSrcFile->h, &srcChange, 4, 24); pread(pFile->h, &dstChange, 4, 24); /* copy the actual database */ s = copyfile_state_alloc(); lseek(pSrcFile->h, 0, SEEK_SET); lseek(pFile->h, 0, SEEK_SET); if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_DATA) ){ int err=errno; switch(err) { case ENOMEM: rc = SQLITE_NOMEM; break; default: storeLastErrno(pFile, err); rc = SQLITE_IOERR; } } copyfile_state_free(s); if (srcChange == dstChange) { /* modify the change counter to force page zero to be reloaded */ dstChange ++; pwrite(pFile->h, &dstChange, 4, 24); } } if( isSrcCorrupt ){ sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock); }else{ /* done with the source db so end the transaction */ sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0); } /* zero out any old journal clutter */ if( rc==SQLITE_OK ){ int skipWAL = (srcWalFD<0)?0:1; unixInvalidateSupportFiles(pFile, skipWAL); } end_replace_database: if( pSrcBtree ){ sqlite3_close(srcdb2); sqlite3BtreeLeave(pSrcBtree); } sqlite3_mutex_leave(srcdb->mutex); if( isDstCorrupt ){ sqlite3demo_superunlock_corrupt(id, corruptDstFileLock); }else{ sqlite3demo_superunlock(pLock); } return rc; } #define SQLITE_FILE_HEADER_LEN 16 /* Check for a conflicting lock. If one is found, print an this ** on standard output using the format string given and return 1. ** If there are no conflicting locks, return 0. */ static int unixIsLocked( pid_t pid, /* PID to test for lock owner */ int h, /* File descriptor to check */ int type, /* F_RDLCK or F_WRLCK */ unsigned int iOfst, /* First byte of the lock */ unsigned int iCnt, /* Number of bytes in the lock range */ const char *zType /* Type of lock */ ){ struct flock lk; int err; memset(&lk, 0, sizeof(lk)); lk.l_type = type; lk.l_whence = SEEK_SET; lk.l_start = iOfst; lk.l_len = iCnt; if( pid!=SQLITE_LOCKSTATE_ANYPID ){ #ifndef F_GETLKPID # warning F_GETLKPID undefined, _sqlite3_lockstate falling back to F_GETLK err = fcntl(h, F_GETLK, &lk); #else lk.l_pid = pid; err = fcntl(h, F_GETLKPID, &lk); #endif }else{ err = fcntl(h, F_GETLK, &lk); } if( err==(-1) ){ fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno); return -1; } if( lk.l_type!=F_UNLCK && (pid==SQLITE_LOCKSTATE_ANYPID || lk.l_pid==pid) ){ #ifdef SQLITE_DEBUG fprintf(stderr, "%s lock held by %d\n", zType, (int)lk.l_pid); #endif return 1; } return 0; } static int unixLockstatePid(unixFile *, pid_t, int *); #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ /* ** If *pArg is initially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. ** ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. */ |
︙ | ︙ | |||
4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 | #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) case SQLITE_FCNTL_SET_LOCKPROXYFILE: case SQLITE_FCNTL_GET_LOCKPROXYFILE: { return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ } return SQLITE_NOTFOUND; } /* ** If pFd->sectorSize is non-zero when this function is called, it is a ** no-op. Otherwise, the values of pFd->sectorSize and | > > > > > > > > > > > > > > > > > > > > | 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 | #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) case SQLITE_FCNTL_SET_LOCKPROXYFILE: case SQLITE_FCNTL_GET_LOCKPROXYFILE: { return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) case SQLITE_FCNTL_TRUNCATE_DATABASE: { return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0)); } case SQLITE_FCNTL_REPLACE_DATABASE: { return unixReplaceDatabase(pFile, (sqlite3 *)pArg); } case SQLITE_FCNTL_LOCKSTATE_PID: { LockstatePID *pLockstate; int rc; if( pArg==NULL ){ return SQLITE_MISUSE; } pLockstate = (LockstatePID *)pArg; rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state)); return rc; } #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ } return SQLITE_NOTFOUND; } /* ** If pFd->sectorSize is non-zero when this function is called, it is a ** no-op. Otherwise, the values of pFd->sectorSize and |
︙ | ︙ | |||
4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 | if( rc==SQLITE_OK ){ assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); } return rc; } /* ** Open a shared-memory area associated with open database file pDbFd. ** This particular implementation uses mmapped files. ** ** The file used to implement shared-memory is in the same directory ** as the open database file and has the same name as the open database ** file with the "-shm" suffix added. For example, if the database file | > > > > | 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 | if( rc==SQLITE_OK ){ assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); } return rc; } #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE static const char *proxySharedMemoryBasePath(unixFile *); #endif /* ** Open a shared-memory area associated with open database file pDbFd. ** This particular implementation uses mmapped files. ** ** The file used to implement shared-memory is in the same directory ** as the open database file and has the same name as the open database ** file with the "-shm" suffix added. For example, if the database file |
︙ | ︙ | |||
4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 | #endif /* Call fstat() to figure out the permissions on the database file. If ** a new *-shm file is created, an attempt will be made to create it ** with the same permissions. */ if( osFstat(pDbFd->h, &sStat) ){ rc = SQLITE_IOERR_FSTAT; goto shm_open_err; } #ifdef SQLITE_SHM_DIRECTORY nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; #else nShmFilename = 6 + (int)strlen(zBasePath); #endif pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ | > > > > > > > > > > > > > > > | 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 | #endif /* Call fstat() to figure out the permissions on the database file. If ** a new *-shm file is created, an attempt will be made to create it ** with the same permissions. */ if( osFstat(pDbFd->h, &sStat) ){ storeLastErrno(pDbFd, errno); rc = SQLITE_IOERR_FSTAT; goto shm_open_err; } #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE \ && !defined(SQLITE_SHM_DIRECTORY) /* If pDbFd is configured with proxy locking mode, use the local ** lock file path to determine the -shm file path */ if( isProxyLockingMode(pDbFd) ){ zBasePath = proxySharedMemoryBasePath(pDbFd); if( !zBasePath ){ rc = SQLITE_CANTOPEN_BKPT; goto shm_open_err; } } #endif #ifdef SQLITE_SHM_DIRECTORY nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; #else nShmFilename = 6 + (int)strlen(zBasePath); #endif pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ |
︙ | ︙ | |||
4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 | if( pShmNode->pShmMutex==0 ){ rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } } if( pInode->bProcessLock==0 ){ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW, (sStat.st_mode&0777)); } if( pShmNode->hShm<0 ){ pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW, (sStat.st_mode&0777)); | > > > > > > > | 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 | if( pShmNode->pShmMutex==0 ){ rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } } if( pInode->bProcessLock==0 ){ #ifdef __APPLE__ /* On MacOS and iOS, avoid even trying to open a read-only SHM file ** for writing, because doing so generates scary log messages */ if( osAccess(zShm, R_OK|W_OK)!=0 && (errno==EPERM || errno==EACCES) ){ pShmNode->hShm = -1; }else #endif if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW, (sStat.st_mode&0777)); } if( pShmNode->hShm<0 ){ pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW, (sStat.st_mode&0777)); |
︙ | ︙ | |||
4974 4975 4976 4977 4978 4979 4980 | /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ assert( unixFileMutexNotheld(pDbFd) ); unixEnterMutex(); assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 | /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ assert( unixFileMutexNotheld(pDbFd) ); unixEnterMutex(); assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ if( deleteFlag && pShmNode->hShm>=0 ) { if (deleteFlag == 1) { osUnlink(pShmNode->zFilename); } else if (deleteFlag == 2) { /* ftruncate(pShmNode->hShm, 32 * 1024); */ } } unixShmPurge(pDbFd); } unixLeaveMutex(); return SQLITE_OK; } #else # define unixShmMap 0 # define unixShmLock 0 # define unixShmBarrier 0 # define unixShmUnmap 0 #endif /* #ifndef SQLITE_OMIT_WAL */ #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) static const char *unixTempFileDir(void); static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) { char jPath[MAXPATHLEN+9]; int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9); if( zLen<MAXPATHLEN ){ size_t jLen; const char extensions[3][9] = { "-wal", "-journal", "-shm" }; int j = (skipWAL ? 1 : 0); for( ; j<3; j++ ){ /* Check to see if the shm file is already opened for this pFile */ if( j==2 ){ unixEnterMutex(); /* Because pFile->pInode is shared across threads */ unixShmNode *pShmNode = pFile->pInode->pShmNode; if( pShmNode && !pShmNode->isReadonly ){ struct stat sStat; sqlite3_mutex_enter(pShmNode->pShmMutex); if( pShmNode->hShm>=0 && !osFstat(pShmNode->hShm, &sStat) ){ unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4; if( size>0 ){ bzero(pShmNode->apRegion[0], size); sqlite3_mutex_leave(pShmNode->pShmMutex); unixLeaveMutex(); continue; } } sqlite3_mutex_leave(pShmNode->pShmMutex); } unixLeaveMutex(); } jLen = strlcpy(&jPath[zLen], extensions[j], 9); if( jLen < 9 ){ int jflags = (j<2) ? O_TRUNC : O_RDWR; int jfd = open(jPath, jflags); if( jfd==(-1) ){ if( errno!=ENOENT ){ perror(jPath); } } else { if( j==2 ){ struct stat sStat; if( !osFstat(jfd, &sStat) ){ unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4; if( size>0 ){ uint32_t zero = 0; pwrite(jfd, &zero, (size_t)size, 0); } } } fsync(jfd); close(jfd); } } } } return SQLITE_OK; } static int unixUnsafeTruncateDatabase(unixFile *pFile){ /* this is nasty & bad. destruction with prejudice. we'll lose all the ** file locks in this process, however. sqlite3_file_control works properly. ** But if it fails, this works approximately */ char journalPath[MAXPATHLEN]; char walPath[MAXPATHLEN]; int rc = SQLITE_OK; #ifdef DEBUG fprintf(stderr, "Force truncating database %s\n", pFile->zPath); #endif strlcpy(journalPath, pFile->zPath, MAXPATHLEN); strlcat(journalPath, "-journal", MAXPATHLEN); strlcpy(walPath, pFile->zPath, MAXPATHLEN); strlcat(walPath, "-wal", MAXPATHLEN); int fd1 = pFile->h; int result = 0; result = ftruncate(fd1, 0ll); if (result) { result = errno; } if (result) { rc = SQLITE_IOERR; storeLastErrno(pFile, result); } int fd2 = open(journalPath, O_RDWR); int result2 = 0; if (fd2 < 0) { if (errno != ENOENT) { result2 = errno; } else { result2 = 0; } } else { result2 = ftruncate(fd2, 0ll); if (result2) { result2 = errno; } } if (result2 && !result) { rc = SQLITE_IOERR; storeLastErrno(pFile, result2); } int fd3 = open(walPath, O_RDWR); int result3 = 0; if (fd3 < 0) { if (errno != ENOENT) { result3 = errno; } else { result3 = 0; } } else { result3 = ftruncate(fd3, 0ll); if (result3) { result3 = errno; } } if (result3 && !(result || result2)) { rc = SQLITE_IOERR; storeLastErrno(pFile, result2); } if (fd3 >= 0) { fsync(fd3); close(fd3); } if (fd2 >= 0) { fsync(fd2); close(fd2); } fsync(fd1); return rc; } static int unixTruncateDatabase(unixFile *pFile, int bFlags) { sqlite3_file *id = (sqlite3_file *)pFile; int rc = SQLITE_OK; void *pLock = NULL; int flags = 0; int corruptFileLock = 0; int isCorrupt = 0; int force = (bFlags & SQLITE_TRUNCATE_FORCE); int safeFailed = 0; #if SQLITE_ENABLE_DATA_PROTECTION flags |= pFile->protFlags; #endif #if SQLITE_ENABLE_LOCKING_STYLE if( isProxyLockingMode(pFile) ){ flags |= SQLITE_OPEN_AUTOPROXY; } #endif rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock); if( rc ){ if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){ isCorrupt = 1; rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock); } if( rc && !force ){ return rc; } rc = SQLITE_OK; /* Ignore the locking failure if force is true */ } if( (bFlags&SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK)!=0 ){ /* initialize a new database in TMPDIR and copy the contents over */ const char *tDir = unixTempFileDir(); int tDirLen = strlen(tDir); int tLen = sizeof(char) * (tDirLen + 12); char *tDbPath = (char *)malloc(tLen); int tFd = -1; strlcpy(tDbPath, tDir, tLen); if( tDbPath[(tDirLen-1)] != '/' ){ strlcat(tDbPath, "/tmpdbXXXXX", tLen); } else { strlcat(tDbPath, "tmpdbXXXXX", tLen); } tFd = mkstemp(tDbPath); if( tFd==-1 ){ storeLastErrno(pFile, errno); rc = SQLITE_IOERR; safeFailed = 1; }else{ sqlite3 *tDb = NULL; copyfile_state_t s; int trc = sqlite3_open_v2(tDbPath, &tDb, (SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_AUTOPROXY), NULL); char *errmsg = NULL; const char *sql = ""; if( !trc && (bFlags&SQLITE_TRUNCATE_PAGESIZE_MASK) ){ const char pagesize_sql[4][22] = { "pragma page_size=1024", "pragma page_size=2048", "pragma page_size=4096", "pragma page_size=8192" }; int iPagesize = (((bFlags&SQLITE_TRUNCATE_PAGESIZE_MASK) >> 4) - 1); assert( iPagesize>=0 && iPagesize<=4 ); sql = pagesize_sql[iPagesize]; trc = sqlite3_exec(tDb, sql, 0, 0, &errmsg); } if( !trc ){ const char autovacuum_sql[3][21] = { "pragma auto_vacuum=0", "pragma auto_vacuum=1", "pragma auto_vacuum=2" }; int iAutovacuum = 2; /* default to incremental */ if( (bFlags&SQLITE_TRUNCATE_AUTOVACUUM_MASK) ){ iAutovacuum = (((bFlags&SQLITE_TRUNCATE_AUTOVACUUM_MASK) >> 2) - 1); } assert( iAutovacuum>=0 && iAutovacuum<=2 ); sql = autovacuum_sql[iAutovacuum]; trc = sqlite3_exec(tDb, sql, 0, 0, &errmsg); } if( !trc && (bFlags&SQLITE_TRUNCATE_JOURNALMODE_WAL) ){ sql = "pragma journal_mode=wal"; trc = sqlite3_exec(tDb, sql, 0, 0, &errmsg); } if( trc ){ if( !tDb ){ fprintf(stderr, "failed to open temp database '%s' to reset " "truncated database %s with flags %x: %d\n", tDbPath, pFile->zPath, bFlags, trc); }else{ fprintf(stderr, "failed to set '%s' on truncated database %s, %d: " "%s\n", sql, pFile->zPath, trc, errmsg); } } if( tDb ){ int off = 0; /* merge the wal into the db */ sqlite3_file_control(tDb, NULL, SQLITE_FCNTL_PERSIST_WAL, &off); sqlite3_close(tDb); } s = copyfile_state_alloc(); lseek(tFd, 0, SEEK_SET); lseek(pFile->h, 0, SEEK_SET); if( fcopyfile(tFd, pFile->h, s, COPYFILE_DATA) ){ int err=errno; switch(err) { case ENOMEM: trc = SQLITE_NOMEM; break; default: storeLastErrno(pFile, err); trc = SQLITE_IOERR; } } copyfile_state_free(s); fsync(pFile->h); close(tFd); unlink(tDbPath); if( trc!=SQLITE_OK ){ safeFailed = 1; rc = trc; } } free(tDbPath); } else { rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L); if( rc ){ safeFailed = 1; } } if( rc==SQLITE_OK || force ){ rc = unixInvalidateSupportFiles(pFile, 0); if( rc ){ safeFailed = 1; } } pFile->pMethod->xSync(id, SQLITE_SYNC_FULL); if( isCorrupt ){ sqlite3demo_superunlock_corrupt(id, corruptFileLock); }else if( pLock ){ sqlite3demo_superunlock(pLock); }else{ assert(force); } if( force && safeFailed){ rc = unixUnsafeTruncateDatabase(pFile); } return rc; } /* ** Lock locations for shared-memory locks used by WAL mode. */ #ifndef SHM_BASE # define SHM_BASE 120 # define SHM_WRITE SHM_BASE # define SHM_CHECKPOINT (SHM_BASE+1) # define SHM_RECOVER (SHM_BASE+2) # define SHM_READ_FIRST (SHM_BASE+3) # define SHM_READ_SIZE 5 #endif /* SHM_BASE */ /* ** This test only works for lock testing on unix/posix VFS. ** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce */ static int unixLockstatePid(unixFile *pFile, pid_t pid, int *pLockstate){ int hDb; /* File descriptor for the open database file */ int hShm = -1; /* File descriptor for WAL shared-memory file */ ssize_t got; /* Bytes read from header */ int isWal = 0; /* True if in WAL mode */ int nLock = 0; /* Number of locks held */ int noHdr = 0; /* Zero byte DB has no header */ unsigned char aHdr[100]; /* Database header */ assert(pLockstate); /* make sure we are dealing with a database file */ hDb = pFile->h; if( hDb<0 ){ *pLockstate = SQLITE_LOCKSTATE_ERROR; return SQLITE_ERROR; } assert( (strlen(SQLITE_FILE_HEADER)+1)==SQLITE_FILE_HEADER_LEN ); got = pread(hDb, aHdr, 100, 0); if( got<0 ){ *pLockstate = SQLITE_LOCKSTATE_ERROR; return SQLITE_ERROR; } if( got==0 ){ noHdr = 1; }else if( got!=100 || memcmp(aHdr, SQLITE_FILE_HEADER, SQLITE_FILE_HEADER_LEN)!=0 ){ *pLockstate = SQLITE_LOCKSTATE_NOTADB; return SQLITE_NOTADB; } /* First check for an exclusive lock */ nLock += unixIsLocked(pid, hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE"); if (!noHdr) { isWal = aHdr[18]==2; } if( nLock==0 && isWal==0 ){ /* Rollback mode */ nLock += unixIsLocked(pid, hDb, F_WRLCK, PENDING_BYTE, SHARED_SIZE+2, "PENDING|RESERVED|SHARED"); } if( nLock==0 && isWal!=0 ){ /* lookup the file descriptor for the shared memory file if we have it open ** in this process */ unixEnterMutex(); /* Because pFile->pInode is shared across threads */ unixShmNode *pShmNode = pFile->pInode->pShmNode; if( pShmNode ){ sqlite3_mutex_enter(pShmNode->pShmMutex); hShm = pShmNode->hShm; if( hShm >= 0){ if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") || unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){ nLock = 1; } } sqlite3_mutex_leave(pShmNode->pShmMutex); } if( hShm<0 ){ /* the shared memory file isn't open in this process space, open our ** own FD */ char zShm[MAXPATHLEN]; /* WAL mode */ strlcpy(zShm, pFile->zPath, MAXPATHLEN); strlcat(zShm, "-shm", MAXPATHLEN); hShm = open(zShm, O_RDONLY, 0); if( hShm<0 ){ *pLockstate = SQLITE_LOCKSTATE_OFF; unixLeaveMutex(); return SQLITE_OK; } if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") || unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){ nLock = 1; } close(hShm); } unixLeaveMutex(); } if( nLock>0 ){ *pLockstate = SQLITE_LOCKSTATE_ON; } else { *pLockstate = SQLITE_LOCKSTATE_OFF; } return SQLITE_OK; } #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ #if SQLITE_MAX_MMAP_SIZE>0 /* ** If it is currently memory mapped, unmap file pFd. */ static void unixUnmapfile(unixFile *pFd){ assert( pFd->nFetchOut==0 ); if( pFd->pMapRegion ){ |
︙ | ︙ | |||
5370 5371 5372 5373 5374 5375 5376 | static int proxyClose(sqlite3_file*); static int proxyLock(sqlite3_file*, int); static int proxyUnlock(sqlite3_file*, int); static int proxyCheckReservedLock(sqlite3_file*, int*); IOMETHODS( proxyIoFinder, /* Finder function name */ proxyIoMethods, /* sqlite3_io_methods object name */ | | | 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 | static int proxyClose(sqlite3_file*); static int proxyLock(sqlite3_file*, int); static int proxyUnlock(sqlite3_file*, int); static int proxyCheckReservedLock(sqlite3_file*, int*); IOMETHODS( proxyIoFinder, /* Finder function name */ proxyIoMethods, /* sqlite3_io_methods object name */ 2, /* shared memory is enabled */ proxyClose, /* xClose method */ proxyLock, /* xLock method */ proxyUnlock, /* xUnlock method */ proxyCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif |
︙ | ︙ | |||
5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 | #endif } if( pLockingStyle == &posixIoMethods #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE || pLockingStyle == &nfsIoMethods #endif ){ unixEnterMutex(); rc = findInodeInfo(pNew, &pNew->pInode); if( rc!=SQLITE_OK ){ /* If an error occurred in findInodeInfo(), close the file descriptor ** immediately, before releasing the mutex. findInodeInfo() may fail ** in two scenarios: | > > | 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 | #endif } if( pLockingStyle == &posixIoMethods #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE || pLockingStyle == &nfsIoMethods #endif /* support WAL mode on read only mounted filesystem */ || (pLockingStyle == &nolockIoMethods && zFilename!=0) ){ unixEnterMutex(); rc = findInodeInfo(pNew, &pNew->pInode); if( rc!=SQLITE_OK ){ /* If an error occurred in findInodeInfo(), close the file descriptor ** immediately, before releasing the mutex. findInodeInfo() may fail ** in two scenarios: |
︙ | ︙ | |||
5947 5948 5949 5950 5951 5952 5953 | sqlite3_file *pFile, /* The file descriptor to be filled in */ int flags, /* Input flags to control the opening */ int *pOutFlags /* Output flags returned to SQLite core */ ){ unixFile *p = (unixFile *)pFile; int fd = -1; /* File descriptor returned by open() */ int openFlags = 0; /* Flags to pass to open() */ | > | > > > | 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 | sqlite3_file *pFile, /* The file descriptor to be filled in */ int flags, /* Input flags to control the opening */ int *pOutFlags /* Output flags returned to SQLite core */ ){ unixFile *p = (unixFile *)pFile; int fd = -1; /* File descriptor returned by open() */ int openFlags = 0; /* Flags to pass to open() */ #if SQLITE_ENABLE_DATA_PROTECTION int eType = flags&0xFE0FFF00; /* Type of file to open */ #else int eType = flags&0xFEFFFF00; /* Type of file to open */ #endif int noLock; /* True to omit locking primitives */ int rc = SQLITE_OK; /* Function Return Code */ int ctrlFlags = 0; /* UNIXFILE_* flags */ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); |
︙ | ︙ | |||
6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 | ** 'conch file' locking functions later on. */ if( isReadonly ) openFlags |= O_RDONLY; if( isReadWrite ) openFlags |= O_RDWR; if( isCreate ) openFlags |= O_CREAT; if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW); if( fd<0 ){ mode_t openMode; /* Permissions to create file with */ uid_t uid; /* Userid for the file */ gid_t gid; /* Groupid for the file */ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ assert( !p->pPreallocatedUnused ); | > > > > | 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 | ** 'conch file' locking functions later on. */ if( isReadonly ) openFlags |= O_RDONLY; if( isReadWrite ) openFlags |= O_RDWR; if( isCreate ) openFlags |= O_CREAT; if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW); openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW); #if SQLITE_ENABLE_DATA_PROTECTION p->protFlags = (flags & SQLITE_OPEN_FILEPROTECTION_MASK); #endif if( fd<0 ){ mode_t openMode; /* Permissions to create file with */ uid_t uid; /* Userid for the file */ gid_t gid; /* Groupid for the file */ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ assert( !p->pPreallocatedUnused ); |
︙ | ︙ | |||
6133 6134 6135 6136 6137 6138 6139 | robust_close(p, fd, __LINE__); return SQLITE_NOMEM_BKPT; } #else osUnlink(zName); #endif } | | | 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 | robust_close(p, fd, __LINE__); return SQLITE_NOMEM_BKPT; } #else osUnlink(zName); #endif } #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) else{ p->openFlags = openFlags; } #endif #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ |
︙ | ︙ | |||
6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 | /* Set up appropriate ctrlFlags */ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; noLock = eType!=SQLITE_OPEN_MAIN_DB; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; #if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_PREFER_PROXY_LOCKING isAutoProxy = 1; #endif if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); int useProxy = 0; /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means ** never use proxy, NULL means use proxy for non-local files only. */ if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); if( rc==SQLITE_OK ){ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); if( rc!=SQLITE_OK ){ /* Use unixClose to clean up the resources added in fillInUnixFile ** and clear all the structure's references. Specifically, ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op */ | > > > > > > > > > > | > | 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 | /* Set up appropriate ctrlFlags */ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE; if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; noLock = eType!=SQLITE_OPEN_MAIN_DB; if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC; if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; #if defined(SQLITE_ENABLE_PERSIST_WAL) if( eType==SQLITE_OPEN_MAIN_DB ) { ctrlFlags |= UNIXFILE_PERSIST_WAL; } #endif #if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_PREFER_PROXY_LOCKING isAutoProxy = 1; #endif if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); int useProxy = 0; /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means ** never use proxy, NULL means use proxy for non-local files only. */ if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); if( rc==SQLITE_OK ){ /* cache the pMethod in case the transform fails */ const struct sqlite3_io_methods *pMethod = pFile->pMethods; rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); if( rc!=SQLITE_OK ){ /* Use unixClose to clean up the resources added in fillInUnixFile ** and clear all the structure's references. Specifically, ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op */ if( pMethod!=NULL ){ pMethod->xClose(pFile); }else{ unixClose(pFile); } return rc; } } goto open_finished; } } #endif |
︙ | ︙ | |||
6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 | if( (dirSync & 1)!=0 ){ int fd; rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ if( full_fsync(fd,0,0) ){ rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); } robust_close(0, fd, __LINE__); }else{ assert( rc==SQLITE_CANTOPEN ); rc = SQLITE_OK; } } #endif return rc; | > > > > > > | 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 | if( (dirSync & 1)!=0 ){ int fd; rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ if( full_fsync(fd,0,0) ){ rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); } #if OSCLOSE_CHECK_CLOSE_IOERR if( close(fd)&&!rc ){ rc = SQLITE_IOERR_DIR_CLOSE; } #else robust_close(0, fd, __LINE__); #endif }else{ assert( rc==SQLITE_CANTOPEN ); rc = SQLITE_OK; } } #endif return rc; |
︙ | ︙ | |||
6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 | } buf[i] = lockPath[i]; } OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n",lockPath,osGetpid(0))); return 0; } /* ** Create a new VFS file descriptor (stored in memory obtained from ** sqlite3_malloc) and open the file named "path" in the file descriptor. ** ** The caller is responsible not only for closing the file descriptor ** but also for freeing the memory associated with the file descriptor. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > | 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 | } buf[i] = lockPath[i]; } OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n",lockPath,osGetpid(0))); return 0; } #if SQLITE_ENABLE_LOCKING_STYLE static int isProxyLockingMode(unixFile *pFile) { return (pFile->pMethod == &proxyIoMethods) ? 1 : 0; } #endif #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE /* ** Return the shared memory base path based on the lock proxy file if the ** lock proxy file is hosted on a shared memory compatible FS */ static const char *proxySharedMemoryBasePath(unixFile *pFile) { proxyLockingContext *pCtx; unixFile *pLockFile; assert(pFile!=NULL && pFile->lockingContext!=NULL); assert(pFile->pMethod == &proxyIoMethods); pCtx = ((proxyLockingContext *)(pFile->lockingContext)); pLockFile = pCtx->lockProxy; if( pLockFile->pMethod->iVersion>=2 && pLockFile->pMethod->xShmMap!=0 ){ return pCtx->lockProxyPath; } return NULL; } #endif /* ** Create a new VFS file descriptor (stored in memory obtained from ** sqlite3_malloc) and open the file named "path" in the file descriptor. ** ** The caller is responsible not only for closing the file descriptor ** but also for freeing the memory associated with the file descriptor. */ |
︙ | ︙ | |||
6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 | } if( fd<0 ){ openFlags = O_RDONLY | O_NOFOLLOW; fd = robust_open(path, openFlags, 0); terrno = errno; } if( fd<0 ){ if( islockfile ){ return SQLITE_BUSY; } switch (terrno) { case EACCES: return SQLITE_PERM; case EIO: | > | 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 | } if( fd<0 ){ openFlags = O_RDONLY | O_NOFOLLOW; fd = robust_open(path, openFlags, 0); terrno = errno; } if( fd<0 ){ sqlite3_free(pUnused); if( islockfile ){ return SQLITE_BUSY; } switch (terrno) { case EACCES: return SQLITE_PERM; case EIO: |
︙ | ︙ | |||
7078 7079 7080 7081 7082 7083 7084 | /* Take the requested lock on the conch file and break a stale lock if the ** host id matches. */ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *conchFile = pCtx->conchFile; int rc = SQLITE_OK; | < < > | | | | > > > > > > > > > > > > > > > > | | | | 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 | /* Take the requested lock on the conch file and break a stale lock if the ** host id matches. */ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *conchFile = pCtx->conchFile; int rc = SQLITE_OK; struct timespec conchModTime; memset(&conchModTime, 0, sizeof(conchModTime)); do { rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); if( rc==SQLITE_BUSY ){ pCtx->nFails ++; /* If the lock failed (busy): * 1st try: get the mod time of the conch, wait 0.5s and try again. * 2nd try: fail if the mod time changed or host id is different, wait * 10 sec and try again * 3rd try: break the lock unless the mod time has changed. */ struct stat buf; if( osFstat(conchFile->h, &buf) ){ storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } if( pCtx->nFails==1 ){ conchModTime = buf.st_mtimespec; usleep(500000); /* wait 0.5 sec and try the lock again*/ continue; } assert( pCtx->nFails>1 ); if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec || conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){ return SQLITE_BUSY; } if( pCtx->nFails==2 ){ char tBuf[PROXY_MAXCONCHLEN]; int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ /* don't break the lock if the host id doesn't match, but do log * an error to console so users can diagnose stale NFS locks more * easily */ if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){ uuid_t conchUUID; uuid_string_t conchUUIDString; uuid_string_t myUUIDString; assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); memcpy(conchUUID, &tBuf[PROXY_HEADERLEN], PROXY_HOSTIDLEN); uuid_unparse(conchUUID, conchUUIDString); uuid_unparse(myHostID, myUUIDString); fprintf(stderr, "ERROR: sqlite database is locked because it is in use " "by another host that holds a host-exclusive lock on %s; " "this host (UUID %s) cannot override the host-exclusive lock " "until the other host (UUID %s) releases its locks on %s\n", pFile->zPath, myUUIDString, conchUUIDString, conchFile->zPath); return SQLITE_BUSY; } }else{ /* don't break the lock on short read or a version mismatch */ return SQLITE_BUSY; } usleep(10000000); /* wait 10 sec and try the lock again */ continue; } assert( pCtx->nFails>=3 ); if( (pCtx->nFails==3)&&(0==proxyBreakConchLock(pFile, myHostID)) ){ rc = SQLITE_OK; if( lockType==EXCLUSIVE_LOCK ){ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); } if( !rc ){ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); } } } } while( rc==SQLITE_BUSY && pCtx->nFails<3 ); return rc; } /* Takes the conch by taking a shared lock and read the contents conch, if ** lockPath is non-NULL, the host ID and lock file path must match. A NULL ** lockPath means that the lockPath in the conch file will be used if the |
︙ | ︙ | |||
7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 | conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); end_takeconch: OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h)); if( rc==SQLITE_OK && pFile->openFlags ){ int fd; if( pFile->h>=0 ){ robust_close(pFile, pFile->h, __LINE__); } pFile->h = -1; fd = robust_open(pCtx->dbPath, pFile->openFlags, 0); OSTRACE(("TRANSPROXY: OPEN %d\n", fd)); if( fd>=0 ){ pFile->h = fd; }else{ | > > > > > > > | 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 | conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK); end_takeconch: OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h)); if( rc==SQLITE_OK && pFile->openFlags ){ int fd; if( pFile->h>=0 ){ #if defined(STRICT_CLOSE_ERROR) && OSCLOSE_CHECK_CLOSE_IOERR if( close(pFile->h) ){ storeLastErrno(pFile, errno); return SQLITE_IOERR_CLOSE; } #else robust_close(pFile, pFile->h, __LINE__); #endif } pFile->h = -1; fd = robust_open(pCtx->dbPath, pFile->openFlags, 0); OSTRACE(("TRANSPROXY: OPEN %d\n", fd)); if( fd>=0 ){ pFile->h = fd; }else{ |
︙ | ︙ | |||
7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 | pCtx->conchHeld = -1; /* read only FS/ lockless */ rc = SQLITE_OK; } } } if( rc==SQLITE_OK && lockPath ){ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); } if( rc==SQLITE_OK ){ pCtx->dbPath = sqlite3DbStrDup(0, dbPath); if( pCtx->dbPath==NULL ){ rc = SQLITE_NOMEM_BKPT; } | > > > | 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 | pCtx->conchHeld = -1; /* read only FS/ lockless */ rc = SQLITE_OK; } } } if( rc==SQLITE_OK && lockPath ){ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); if( pCtx->lockProxyPath==NULL ){ rc = SQLITE_NOMEM; } } if( rc==SQLITE_OK ){ pCtx->dbPath = sqlite3DbStrDup(0, dbPath); if( pCtx->dbPath==NULL ){ rc = SQLITE_NOMEM_BKPT; } |
︙ | ︙ | |||
7599 7600 7601 7602 7603 7604 7605 | ** This routine handles sqlite3_file_control() calls that are specific ** to proxy locking. */ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ case SQLITE_FCNTL_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; | | | | 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 | ** This routine handles sqlite3_file_control() calls that are specific ** to proxy locking. */ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ case SQLITE_FCNTL_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; if( isProxyLockingMode(pFile) ){ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; proxyTakeConch(pFile); if( pCtx->lockProxyPath ){ *(const char **)pArg = pCtx->lockProxyPath; }else{ *(const char **)pArg = ":auto: (not held)"; } } else { *(const char **)pArg = NULL; } return SQLITE_OK; } case SQLITE_FCNTL_SET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; int rc = SQLITE_OK; int isProxyStyle = isProxyLockingMode(pFile); if( pArg==NULL || (const char *)pArg==0 ){ if( isProxyStyle ){ /* turn off proxy locking - not supported. If support is added for ** switching proxy locking mode off then it will need to fail if ** the journal mode is WAL mode. */ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 | } } OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); return rc; } OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } case SQLITE_FCNTL_PERSIST_WAL: { winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { | > > > > > > > > > | 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 | } } OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); return rc; } OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } case SQLITE_FCNTL_PERSIST_WAL: { int bPersist = *(int*)pArg; if( bPersist<0 ){ *(int*)pArg = pFile->bPersistWal; }else{ pFile->bPersistWal = bPersist!=0; } return SQLITE_OK; } case SQLITE_FCNTL_PERSIST_WAL: { winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
2497 2498 2499 2500 2501 2502 2503 | ** If successful, open the master journal file for reading. */ pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2); pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); if( !pMaster ){ rc = SQLITE_NOMEM_BKPT; }else{ | > > > > | | 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 | ** If successful, open the master journal file for reading. */ pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2); pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); if( !pMaster ){ rc = SQLITE_NOMEM_BKPT; }else{ const int flags = #if SQLITE_ENABLE_DATA_PROTECTION (pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)| #endif (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); } if( rc!=SQLITE_OK ) goto delmaster_out; /* Load the entire master journal file into space obtained from ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain ** sufficient space (in zMasterPtr) to hold the names of master |
︙ | ︙ | |||
2534 2535 2536 2537 2538 2539 2540 | } if( exists ){ /* One of the journals pointed to by the master journal exists. ** Open it and check if it points at the master journal. If ** so, return without deleting the master journal file. */ int c; | > > > > | | 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 | } if( exists ){ /* One of the journals pointed to by the master journal exists. ** Open it and check if it points at the master journal. If ** so, return without deleting the master journal file. */ int c; int flags = #if SQLITE_ENABLE_DATA_PROTECTION (pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)| #endif (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL); rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0); if( rc!=SQLITE_OK ){ goto delmaster_out; } rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr); sqlite3OsClose(pJournal); |
︙ | ︙ | |||
3605 3606 3607 3608 3609 3610 3611 | ){ int rc; /* Return code */ #ifdef SQLITE_TEST sqlite3_opentemp_count++; /* Used for testing and analysis only */ #endif | > > > > | | 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 | ){ int rc; /* Return code */ #ifdef SQLITE_TEST sqlite3_opentemp_count++; /* Used for testing and analysis only */ #endif vfsFlags |= #if SQLITE_ENABLE_DATA_PROTECTION (pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)| #endif SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0); assert( rc!=SQLITE_OK || isOpen(pFile) ); return rc; } /* |
︙ | ︙ | |||
5089 5090 5091 5092 5093 5094 5095 | /* The journal file exists and no other connection has a reserved ** or greater lock on the database file. Now check that there is ** at least one non-zero bytes at the start of the journal file. ** If there is, then we consider this journal to be hot. If not, ** it can be ignored. */ if( !jrnlOpen ){ | > > > > | | 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 | /* The journal file exists and no other connection has a reserved ** or greater lock on the database file. Now check that there is ** at least one non-zero bytes at the start of the journal file. ** If there is, then we consider this journal to be hot. If not, ** it can be ignored. */ if( !jrnlOpen ){ int f = #if SQLITE_ENABLE_DATA_PROTECTION (pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)| #endif SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL; rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f); } if( rc==SQLITE_OK ){ u8 first = 0; rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; |
︙ | ︙ | |||
5229 5230 5231 5232 5233 5234 5235 | if( !isOpen(pPager->jfd) ){ sqlite3_vfs * const pVfs = pPager->pVfs; int bExists; /* True if journal file exists */ rc = sqlite3OsAccess( pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); if( rc==SQLITE_OK && bExists ){ int fout = 0; | > > > > | | 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 | if( !isOpen(pPager->jfd) ){ sqlite3_vfs * const pVfs = pPager->pVfs; int bExists; /* True if journal file exists */ rc = sqlite3OsAccess( pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); if( rc==SQLITE_OK && bExists ){ int fout = 0; int f = #if SQLITE_ENABLE_DATA_PROTECTION (pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK)| #endif SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; assert( !pPager->tempFile ); rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ rc = SQLITE_CANTOPEN_BKPT; sqlite3OsClose(pPager->jfd); } |
︙ | ︙ | |||
5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 | if( !isOpen(pPager->jfd) ){ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ sqlite3MemJournalOpen(pPager->jfd); }else{ int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; int nSpill; if( pPager->tempFile ){ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); nSpill = sqlite3Config.nStmtSpill; }else{ flags |= SQLITE_OPEN_MAIN_JOURNAL; nSpill = jrnlBufferSize(pPager); } | > > > | 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 | if( !isOpen(pPager->jfd) ){ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ sqlite3MemJournalOpen(pPager->jfd); }else{ int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; int nSpill; #if SQLITE_ENABLE_DATA_PROTECTION flags |= (pPager->vfsFlags&SQLITE_OPEN_FILEPROTECTION_MASK); #endif if( pPager->tempFile ){ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); nSpill = sqlite3Config.nStmtSpill; }else{ flags |= SQLITE_OPEN_MAIN_JOURNAL; nSpill = jrnlBufferSize(pPager); } |
︙ | ︙ | |||
6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 | ** Return the file handle for the database file associated ** with the pager. This might return NULL if the file has ** not yet been opened. */ sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* ** Reset the lock timeout for pager. */ void sqlite3PagerResetLockTimeout(Pager *pPager){ int x = 0; | > > > > > > > > > > > > | 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 | ** Return the file handle for the database file associated ** with the pager. This might return NULL if the file has ** not yet been opened. */ sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } #if !defined(SQLITE_OMIT_WAL) /* ** Return the file handle for the WAL journal file associated ** with the pager. This might return NULL if the file has ** not yet been opened. */ sqlite3_file *sqlite3PagerWalFile(Pager *pPager){ return ((pPager->pWal) ? sqlite3WalFile(pPager->pWal) : (NULL)); } #endif #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* ** Reset the lock timeout for pager. */ void sqlite3PagerResetLockTimeout(Pager *pPager){ int x = 0; |
︙ | ︙ | |||
7460 7461 7462 7463 7464 7465 7466 | rc = pagerExclusiveLock(pPager); } /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ | > | > > > | | < > | 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 | rc = pagerExclusiveLock(pPager); } /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ #if SQLITE_ENABLE_DATA_PROTECTION rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode, pPager->journalSizeLimit, (pPager->vfsFlags & (SQLITE_OPEN_FILEPROTECTION_MASK | SQLITE_OPEN_READONLY)), &pPager->pWal); #else rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode, pPager->journalSizeLimit, (pPager->vfsFlags & SQLITE_OPEN_READONLY), &pPager->pWal); #endif } pagerFixMaplimit(pPager); return rc; } |
︙ | ︙ | |||
7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 | if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } } return rc; } | > > > > > > > | 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 | if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); /* Ensure that the WAL file is deleted even if the PERSIST_WAL ** hint is enabled. */ if( rc==SQLITE_OK ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK; } if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } } return rc; } |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
199 200 201 202 203 204 205 206 207 208 209 210 211 212 | #ifdef SQLITE_DEBUG int sqlite3PagerRefcount(Pager*); #endif int sqlite3PagerMemUsed(Pager*); const char *sqlite3PagerFilename(const Pager*, int); sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); sqlite3_file *sqlite3PagerJrnlFile(Pager*); const char *sqlite3PagerJournalname(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); void sqlite3PagerClearCache(Pager*); int sqlite3SectorSize(sqlite3_file *); | > | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | #ifdef SQLITE_DEBUG int sqlite3PagerRefcount(Pager*); #endif int sqlite3PagerMemUsed(Pager*); const char *sqlite3PagerFilename(const Pager*, int); sqlite3_vfs *sqlite3PagerVfs(Pager*); sqlite3_file *sqlite3PagerFile(Pager*); sqlite3_file *sqlite3PagerWalFile(Pager *pPager); sqlite3_file *sqlite3PagerJrnlFile(Pager*); const char *sqlite3PagerJournalname(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); void sqlite3PagerClearCache(Pager*); int sqlite3SectorSize(sqlite3_file *); |
︙ | ︙ |
Changes to src/pcache1.c.
︙ | ︙ | |||
382 383 384 385 386 387 388 | assert( pcache1.nFreeSlot<=pcache1.nSlot ); sqlite3_mutex_leave(pcache1.mutex); }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS { | < | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | assert( pcache1.nFreeSlot<=pcache1.nSlot ); sqlite3_mutex_leave(pcache1.mutex); }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS { int nFreed = sqlite3MallocSize(p); sqlite3_mutex_enter(pcache1.mutex); sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); sqlite3_mutex_leave(pcache1.mutex); } #endif sqlite3_free(p); } |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
213 214 215 216 217 218 219 | Db *pDb = db->aDb; int n = db->nDb; assert( SQLITE_FullFSync==PAGER_FULLFSYNC ); assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC ); assert( SQLITE_CacheSpill==PAGER_CACHESPILL ); assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL) == PAGER_FLAGS_MASK ); | < > | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | Db *pDb = db->aDb; int n = db->nDb; assert( SQLITE_FullFSync==PAGER_FULLFSYNC ); assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC ); assert( SQLITE_CacheSpill==PAGER_CACHESPILL ); assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL) == PAGER_FLAGS_MASK ); while( (n--) > 0 ){ if( pDb->pBt ){ sqlite3BtreeSetPagerFlags(pDb->pBt, (pDb->safety_level & PAGER_SYNCHRONOUS_MASK) | (db->flags & PAGER_FLAGS_MASK) ); } pDb++; } } } #else # define setAllPagerFlags(X) /* no-op */ |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. */ #include "sqliteInt.h" /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ | > > > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_SQLRR # include "sqlrr.h" #endif /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ |
︙ | ︙ | |||
774 775 776 777 778 779 780 781 782 783 784 785 786 787 | const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc; rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail); assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ | > > > | 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ int rc; rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail); #ifdef SQLITE_ENABLE_SQLRR SRRecPrepare(db, zSql, nBytes, 0, *ppStmt); #endif assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } int sqlite3_prepare_v2( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ |
︙ | ︙ | |||
814 815 816 817 818 819 820 821 822 823 824 825 826 827 | ** SQLITE_PREPARE_* flags. ** ** Proof by comparison to the implementation of sqlite3_prepare_v2() ** directly above. */ rc = sqlite3LockAndPrepare(db,zSql,nBytes, SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), 0,ppStmt,pzTail); assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); return rc; } #ifndef SQLITE_OMIT_UTF16 /* | > > > | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 | ** SQLITE_PREPARE_* flags. ** ** Proof by comparison to the implementation of sqlite3_prepare_v2() ** directly above. */ rc = sqlite3LockAndPrepare(db,zSql,nBytes, SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), 0,ppStmt,pzTail); #ifdef SQLITE_ENABLE_SQLRR SRRecPrepare(db, zSql, nBytes, 1, *ppStmt); #endif assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); return rc; } #ifndef SQLITE_OMIT_UTF16 /* |
︙ | ︙ | |||
857 858 859 860 861 862 863 | nBytes = sz; } sqlite3_mutex_enter(db->mutex); zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); if( zSql8 ){ rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8); } | | > > | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | nBytes = sz; } sqlite3_mutex_enter(db->mutex); zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); if( zSql8 ){ rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8); } #ifdef SQLITE_ENABLE_SQLRR SRRecPrepare(db, zSql8, -1, 1, *ppStmt); #endif if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8)); |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
567 568 569 570 571 572 573 574 | #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ | > > < | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_FILEPROTECTION_MASK \ 0x00700000 #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ /* Reserved: 0x00F00000 */ /* ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods] ** object returns an integer which is a vector of these |
︙ | ︙ |
Added src/sqlite3_private.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | /* * sqlite3_private.h */ #ifndef _SQLITE3_PRIVATE_H #define _SQLITE3_PRIVATE_H #ifdef __cplusplus extern "C" { #endif #define SQLITE_LOCKSTATE_OFF 0 #define SQLITE_LOCKSTATE_ON 1 #define SQLITE_LOCKSTATE_NOTADB 2 #define SQLITE_LOCKSTATE_ERROR -1 #define SQLITE_LOCKSTATE_ANYPID -1 /* ** Test a file path for sqlite locks held by a process ID (-1 = any PID). ** Returns one of the following integer codes: ** ** SQLITE_LOCKSTATE_OFF no active sqlite file locks match the specified pid ** SQLITE_LOCKSTATE_ON active sqlite file locks match the specified pid ** SQLITE_LOCKSTATE_NOTADB path points to a file that is not an sqlite db file ** SQLITE_LOCKSTATE_ERROR path was not vaild or was unreadable ** ** There is no support for identifying db files encrypted via SEE encryption ** currently. Zero byte files are tested for sqlite locks, but if no sqlite ** locks are present then SQLITE_LOCKSTATE_NOTADB is returned. */ extern int _sqlite3_lockstate(const char *path, pid_t pid); /* ** Test an open database connection for sqlite locks held by a process ID, ** if a process has an open database connection this will avoid trashing file ** locks by re-using open file descriptors for the database file and support ** files (-shm) */ #define SQLITE_FCNTL_LOCKSTATE_PID 103 /* ** Pass the SQLITE_TRUNCATE_DATABASE operation code to sqlite3_file_control() ** to truncate a database and its associated journal file to zero length. The ** SQLITE_TRUNCATE_* flags represent optional flags to safely initialize an ** empty database in the place of the truncated database, the flags are passed ** into sqlite3_file_control via the fourth argument using a pointer to an integer ** configured with the ORed flags. If the fourth argument is NULL, the default ** behavior is applied and the database file is truncated to zero bytes, a rollback ** journal (if present) is unlinked, a WAL journal (if present) is truncated to zero ** bytes and the first few bytes of the -shm file is scrambled to trigger existing ** connections to rebuild the index from the database file contents. */ #define SQLITE_FCNTL_TRUNCATE_DATABASE 101 #define SQLITE_TRUNCATE_DATABASE SQLITE_FCNTL_TRUNCATE_DATABASE #define SQLITE_TRUNCATE_INITIALIZE_HEADER_MASK (0x7F<<0) #define SQLITE_TRUNCATE_JOURNALMODE_WAL (0x1<<0) #define SQLITE_TRUNCATE_AUTOVACUUM_MASK (0x3<<2) #define SQLITE_TRUNCATE_AUTOVACUUM_OFF (0x1<<2) #define SQLITE_TRUNCATE_AUTOVACUUM_FULL (0x2<<2) #define SQLITE_TRUNCATE_AUTOVACUUM_INCREMENTAL (0x3<<2) #define SQLITE_TRUNCATE_PAGESIZE_MASK (0x7<<4) #define SQLITE_TRUNCATE_PAGESIZE_1024 (0x1<<4) #define SQLITE_TRUNCATE_PAGESIZE_2048 (0x2<<4) #define SQLITE_TRUNCATE_PAGESIZE_4096 (0x3<<4) #define SQLITE_TRUNCATE_PAGESIZE_8192 (0x4<<4) #define SQLITE_TRUNCATE_FORCE (0x1<<7) /* ** Pass the SQLITE_REPLACE_DATABASE operation code to sqlite3_file_control() ** and a sqlite3 pointer to another open database file to safely copy the ** contents of that database file into the receiving database. */ #define SQLITE_FCNTL_REPLACE_DATABASE 102 #define SQLITE_REPLACE_DATABASE SQLITE_FCNTL_REPLACE_DATABASE #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
342 343 344 345 346 347 348 349 350 351 352 353 354 355 | #if defined(SQLITE_SYSTEM_MALLOC) \ + defined(SQLITE_WIN32_MALLOC) \ + defined(SQLITE_ZERO_MALLOC) \ + defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ #if !defined(SQLITE_MALLOC_SOFT_LIMIT) # define SQLITE_MALLOC_SOFT_LIMIT 1024 #endif | > > > > > > > > > > > > > > > > | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | #if defined(SQLITE_SYSTEM_MALLOC) \ + defined(SQLITE_WIN32_MALLOC) \ + defined(SQLITE_ZERO_MALLOC) \ + defined(SQLITE_MEMDEBUG)==0 # define SQLITE_SYSTEM_MALLOC 1 #endif /* ** This is a magic string that appears at the beginning of every ** SQLite database in order to identify the file as a real database. ** ** You can change this value at compile-time by specifying a ** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The ** header must be exactly 16 bytes including the zero-terminator so ** the string itself should be 15 characters long. If you change ** the header, then your custom library will not be able to read ** databases generated by the standard tools and the standard tools ** will not be able to read databases created by your custom library. */ #ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ # define SQLITE_FILE_HEADER "SQLite format 3" #endif /* ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the ** sizes of memory allocations below this value where possible. */ #if !defined(SQLITE_MALLOC_SOFT_LIMIT) # define SQLITE_MALLOC_SOFT_LIMIT 1024 #endif |
︙ | ︙ | |||
4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 | # define sqlite3MemdebugHasType(X,Y) 1 # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ #define MEMTYPE_PCACHE 0x04 /* Page cache allocations */ /* ** Threading interface */ #if SQLITE_MAX_WORKER_THREADS>0 int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); int sqlite3ThreadJoin(SQLiteThread*, void**); #endif | > > > > > > > > > > > > > > > > > > > > > > > > | 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 | # define sqlite3MemdebugHasType(X,Y) 1 # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ #define MEMTYPE_PCACHE 0x04 /* Page cache allocations */ #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) /* ** An instance of the following structure is used to hold the process ID ** and return-by-reference lockstate value. The SQLITE_FCNTL_LOCKSTATE_PID ** requires the 4th argument to sqlite3_file_control to be a pointer to an ** instance of LockstatePID initialized with a LockstatePID.pid value equal ** to a process ID to be tested, or the special value SQLITE_LOCKSTATE_ANYPID ** The Lockstate.state value is always set to one of the following values ** when sqlite3_file_control returns: ** ** SQLITE_LOCKSTATE_OFF no active sqlite file locks match the specified pid ** SQLITE_LOCKSTATE_ON active sqlite file locks match the specified pid ** SQLITE_LOCKSTATE_NOTADB path points to a file that is not an sqlite db file ** SQLITE_LOCKSTATE_ERROR path was not vaild or was unreadable */ typedef struct LockstatePID LockstatePID; struct LockstatePID { pid_t pid; /* Process ID to test */ int state; /* The state of the lock (return value) */ }; #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */ /* ** Threading interface */ #if SQLITE_MAX_WORKER_THREADS>0 int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); int sqlite3ThreadJoin(SQLiteThread*, void**); #endif |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 | Tcl_WrongNumArgs(interp, 1, objv, "STMT"); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); return TCL_OK; } /* ** Usage: sqlite3_sleep MILLISECONDS */ static int SQLITE_TCLAPI test_sleep( void * clientData, Tcl_Interp *interp, | > > > > > > > > > > > > > > > > > > | 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 | Tcl_WrongNumArgs(interp, 1, objv, "STMT"); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); return TCL_OK; } /* ** Usage: sqlite3_clear_bindings STMT ** */ static int test_clear_bindings_null( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ if( objc!=1 ){ return TCL_ERROR; } /* test for handling NULL <rdar://problem/6646331> */ Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(0))); return TCL_OK; } /* ** Usage: sqlite3_sleep MILLISECONDS */ static int SQLITE_TCLAPI test_sleep( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 | }else{ sqlite3_snprintf(sizeof(zBuf),zBuf,"%u",iVers); Tcl_SetResult(interp, (char *)zBuf, TCL_VOLATILE); return TCL_OK; } } /* ** tclcmd: file_control_chunksize_test DB DBNAME SIZE ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and ** SQLITE_SET_LOCKPROXYFILE verbs. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 | }else{ sqlite3_snprintf(sizeof(zBuf),zBuf,"%u",iVers); Tcl_SetResult(interp, (char *)zBuf, TCL_VOLATILE); return TCL_OK; } } #ifdef __APPLE__ /* From sqlite3_private.h */ # ifndef SQLITE_TRUNCATE_DATABASE # define SQLITE_TRUNCATE_DATABASE 101 # define SQLITE_TRUNCATE_JOURNALMODE_WAL (0x1<<0) # define SQLITE_TRUNCATE_AUTOVACUUM_MASK (0x3<<2) # define SQLITE_TRUNCATE_AUTOVACUUM_OFF (0x1<<2) # define SQLITE_TRUNCATE_AUTOVACUUM_FULL (0x2<<2) # define SQLITE_TRUNCATE_AUTOVACUUM_INCREMENTAL (0x3<<2) # define SQLITE_TRUNCATE_PAGESIZE_MASK (0x7<<4) # define SQLITE_TRUNCATE_PAGESIZE_1024 (0x1<<4) # define SQLITE_TRUNCATE_PAGESIZE_2048 (0x2<<4) # define SQLITE_TRUNCATE_PAGESIZE_4096 (0x3<<4) # define SQLITE_TRUNCATE_PAGESIZE_8192 (0x4<<4) # endif # ifndef SQLITE_REPLACE_DATABASE # define SQLITE_REPLACE_DATABASE 102 # endif /* ** tclcmd: file_control_truncate_test DB ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_TRUNCATE_DATABASE verb. */ static int file_control_truncate_test( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3 *db; int flags; int rc; if( objc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " DB FLAGS", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &flags) ){ return TCL_ERROR; } rc = sqlite3_file_control(db, NULL, SQLITE_TRUNCATE_DATABASE, &flags); if( rc ){ Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; } return TCL_OK; } /* ** tclcmd: file_control_replace_test DB ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_REPLACE_DATABASE verb. */ static int file_control_replace_test( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3 *src_db; sqlite3 *dst_db; int rc; if( objc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " DST_DB SRC_DB", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &dst_db) ){ return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[2]), &src_db) ){ return TCL_ERROR; } rc = sqlite3_file_control(dst_db, NULL, SQLITE_REPLACE_DATABASE, src_db); if( rc ){ Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; } return TCL_OK; } #endif /* __APPLE__ */ /* ** tclcmd: file_control_chunksize_test DB DBNAME SIZE ** ** This TCL command runs the sqlite3_file_control interface and ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and ** SQLITE_SET_LOCKPROXYFILE verbs. */ |
︙ | ︙ | |||
6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 | Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; } } #endif return TCL_OK; } #if SQLITE_OS_WIN /* ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY ** ** This TCL command runs the sqlite3_file_control interface with ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 | Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_ERROR; } } #endif return TCL_OK; } #ifdef __APPLE__ #include <sys/param.h> #include <sys/mount.h> #include <sys/errno.h> #endif /* ** tclcmd: path_is_local PWD */ static int path_is_local( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ #ifdef __APPLE__ const char *zPath; int nPath; struct statfs fsInfo; if( objc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " PATH", 0); return TCL_ERROR; } zPath = Tcl_GetStringFromObj(objv[1], &nPath); if( statfs(zPath, &fsInfo) == -1 ){ int err = errno; Tcl_AppendResult(interp, "Error calling statfs on path", Tcl_NewIntObj(err), 0); return TCL_ERROR; } if( fsInfo.f_flags&MNT_LOCAL ){ Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } #else Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); #endif return TCL_OK; } /* ** tclcmd: path_is_dos PWD */ static int path_is_dos( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ #ifdef __APPLE__ const char *zPath; int nPath; struct statfs fsInfo; if( objc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " PATH", 0); return TCL_ERROR; } zPath = Tcl_GetStringFromObj(objv[1], &nPath); if( statfs(zPath, &fsInfo) == -1 ){ int err = errno; Tcl_AppendResult(interp, "Error calling statfs on path", Tcl_NewIntObj(err), 0); return TCL_ERROR; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); } else if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } #else Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); #endif return TCL_OK; } #if SQLITE_OS_WIN /* ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY ** ** This TCL command runs the sqlite3_file_control interface with ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode. |
︙ | ︙ | |||
6169 6170 6171 6172 6173 6174 6175 | } if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR; rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist); sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist); Tcl_AppendResult(interp, z, (char*)0); return TCL_OK; } | < | 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 | } if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR; rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist); sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist); Tcl_AppendResult(interp, z, (char*)0); return TCL_OK; } /* ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG ** ** This TCL command runs the sqlite3_file_control interface with ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode. */ static int SQLITE_TCLAPI file_control_powersafe_overwrite( |
︙ | ︙ | |||
7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 | { "sqlite3_bind_text", test_bind_text ,0 }, { "sqlite3_bind_text16", test_bind_text16 ,0 }, { "sqlite3_bind_blob", test_bind_blob ,0 }, { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, { "sqlite3_clear_bindings", test_clear_bindings, 0}, { "sqlite3_sleep", test_sleep, 0}, { "sqlite3_errcode", test_errcode ,0 }, { "sqlite3_extended_errcode", test_ex_errcode ,0 }, { "sqlite3_errmsg", test_errmsg ,0 }, { "sqlite3_errmsg16", test_errmsg16 ,0 }, { "sqlite3_open", test_open ,0 }, { "sqlite3_open16", test_open16 ,0 }, | > | 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 | { "sqlite3_bind_text", test_bind_text ,0 }, { "sqlite3_bind_text16", test_bind_text16 ,0 }, { "sqlite3_bind_blob", test_bind_blob ,0 }, { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, { "sqlite3_clear_bindings", test_clear_bindings, 0}, { "sqlite3_clear_bindings_null", test_clear_bindings_null, 0}, { "sqlite3_sleep", test_sleep, 0}, { "sqlite3_errcode", test_errcode ,0 }, { "sqlite3_extended_errcode", test_ex_errcode ,0 }, { "sqlite3_errmsg", test_errmsg ,0 }, { "sqlite3_errmsg16", test_errmsg16 ,0 }, { "sqlite3_open", test_open ,0 }, { "sqlite3_open16", test_open16 ,0 }, |
︙ | ︙ | |||
8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 | { "vfs_unlink_test", vfs_unlink_test, 0 }, { "vfs_initfail_test", vfs_initfail_test, 0 }, { "vfs_unregister_all", vfs_unregister_all, 0 }, { "vfs_reregister_all", vfs_reregister_all, 0 }, { "file_control_test", file_control_test, 0 }, { "file_control_lasterrno_test", file_control_lasterrno_test, 0 }, { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, { "file_control_chunksize_test", file_control_chunksize_test, 0 }, { "file_control_sizehint_test", file_control_sizehint_test, 0 }, { "file_control_data_version", file_control_data_version, 0 }, #if SQLITE_OS_WIN { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_win32_get_handle", file_control_win32_get_handle, 0 }, { "file_control_win32_set_handle", file_control_win32_set_handle, 0 }, #endif { "file_control_persist_wal", file_control_persist_wal, 0 }, { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, { "file_control_vfsname", file_control_vfsname, 0 }, { "file_control_tempfilename", file_control_tempfilename, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 }, /* Functions from os.h */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, { "add_test_function", test_function, 0 }, { "add_test_utf16bin_collate", test_utf16bin_collate, 0 }, | > > > > > > | 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 | { "vfs_unlink_test", vfs_unlink_test, 0 }, { "vfs_initfail_test", vfs_initfail_test, 0 }, { "vfs_unregister_all", vfs_unregister_all, 0 }, { "vfs_reregister_all", vfs_reregister_all, 0 }, { "file_control_test", file_control_test, 0 }, { "file_control_lasterrno_test", file_control_lasterrno_test, 0 }, { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, #ifdef __APPLE__ { "file_control_truncate_test", file_control_truncate_test, 0 }, { "file_control_replace_test", file_control_replace_test, 0 }, #endif { "file_control_chunksize_test", file_control_chunksize_test, 0 }, { "file_control_sizehint_test", file_control_sizehint_test, 0 }, { "file_control_data_version", file_control_data_version, 0 }, #if SQLITE_OS_WIN { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_win32_get_handle", file_control_win32_get_handle, 0 }, { "file_control_win32_set_handle", file_control_win32_set_handle, 0 }, #endif { "file_control_persist_wal", file_control_persist_wal, 0 }, { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, { "file_control_vfsname", file_control_vfsname, 0 }, { "file_control_tempfilename", file_control_tempfilename, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 }, { "path_is_local", path_is_local, 0 }, { "path_is_dos", path_is_dos, 0 }, /* Functions from os.h */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, { "add_test_function", test_function, 0 }, { "add_test_utf16bin_collate", test_utf16bin_collate, 0 }, |
︙ | ︙ |
Changes to src/test_config.c.
︙ | ︙ | |||
606 607 608 609 610 611 612 | Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","0",TCL_GLOBAL_ONLY); #endif #if defined(SQLITE_PREFER_PROXY_LOCKING) && defined(__APPLE__) Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","0",TCL_GLOBAL_ONLY); #endif | | > > > > > > > > > > > > > > | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | Tcl_SetVar2(interp,"sqlite_options","lock_proxy_pragmas","0",TCL_GLOBAL_ONLY); #endif #if defined(SQLITE_PREFER_PROXY_LOCKING) && defined(__APPLE__) Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","prefer_proxy_locking","0",TCL_GLOBAL_ONLY); #endif #if defined(SQLITE_ENABLE_PURGEABLE_PCACHE) && defined(__APPLE__) Tcl_SetVar2(interp,"sqlite_options","enable_purgeable_pcache","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","enable_purgeable_pcache","0",TCL_GLOBAL_ONLY); #endif #if SQLITE_DEFAULT_CKPTFULLFSYNC Tcl_SetVar2(interp,"sqlite_options","default_ckptfullfsync","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","default_ckptfullfsync","0",TCL_GLOBAL_ONLY); #endif #if SQLITE_ENABLE_PERSIST_WAL Tcl_SetVar2(interp,"sqlite_options","enable_persist_wal","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp,"sqlite_options","enable_persist_wal","0",TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_OMIT_SHARED_CACHE Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY); #endif |
︙ | ︙ | |||
741 742 743 744 745 746 747 748 749 750 751 752 753 754 | #endif #ifdef SQLITE_ENABLE_SQLLOG Tcl_SetVar2(interp, "sqlite_options", "sqllog", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "sqllog", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_URI_00_ERROR Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY); #endif | > > > > > > > > > > > > > > > > | 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | #endif #ifdef SQLITE_ENABLE_SQLLOG Tcl_SetVar2(interp, "sqlite_options", "sqllog", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "sqllog", "0", TCL_GLOBAL_ONLY); #endif #ifdef __APPLE__ # if defined(__ppc__) Tcl_SetVar2(interp, "os_options", "arch", "ppc", TCL_GLOBAL_ONLY); # elif defined(__i386__) Tcl_SetVar2(interp, "os_options", "arch", "i386", TCL_GLOBAL_ONLY); # elif defined(__x86_64__) Tcl_SetVar2(interp, "os_options", "arch", "x86_64", TCL_GLOBAL_ONLY); # elif defined(__arm__) Tcl_SetVar2(interp, "os_options", "arch", "arm", TCL_GLOBAL_ONLY); # else # error Unrecognized architecture for exec_options # endif #else Tcl_SetVar2(interp, "os_options", "arch", "unknown", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_URI_00_ERROR Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY); #endif |
︙ | ︙ |
Changes to src/test_superlock.c.
︙ | ︙ | |||
144 145 146 147 148 149 150 | } /* ** Release a superlock held on a database file. The argument passed to ** this function must have been obtained from a successful call to ** sqlite3demo_superlock(). */ | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | } /* ** Release a superlock held on a database file. The argument passed to ** this function must have been obtained from a successful call to ** sqlite3demo_superlock(). */ static void sqlite3demo_superunlock(void *pLock){ Superlock *p = (Superlock *)pLock; if( p->bWal ){ int rc; /* Return code */ int flags = SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE; sqlite3_file *fd = 0; rc = sqlite3_file_control(p->db, "main", SQLITE_FCNTL_FILE_POINTER, (void *)&fd); if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
175 176 177 178 179 180 181 | ** ** If a required lock cannot be obtained immediately and the xBusy parameter ** to this function is not NULL, then xBusy is invoked in the same way ** as a busy-handler registered with SQLite (using sqlite3_busy_handler()) ** until either the lock can be obtained or the busy-handler function returns ** 0 (indicating "give up"). */ | | > | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | ** ** If a required lock cannot be obtained immediately and the xBusy parameter ** to this function is not NULL, then xBusy is invoked in the same way ** as a busy-handler registered with SQLite (using sqlite3_busy_handler()) ** until either the lock can be obtained or the busy-handler function returns ** 0 (indicating "give up"). */ static int sqlite3demo_superlock( const char *zPath, /* Path to database file to lock */ const char *zVfs, /* VFS to use to access database file */ int flags, /* Additional flags to pass to sqlite3_open_v2 */ int (*xBusy)(void*,int), /* Busy handler callback */ void *pBusyArg, /* Context arg for busy handler */ void **ppLock /* OUT: Context to pass to superunlock() */ ){ SuperlockBusy busy = {0, 0, 0}; /* Busy handler wrapper object */ int rc; /* Return code */ Superlock *pLock; pLock = sqlite3_malloc(sizeof(Superlock)); if( !pLock ) return SQLITE_NOMEM; memset(pLock, 0, sizeof(Superlock)); /* Open a database handle on the file to superlock. */ rc = sqlite3_open_v2( zPath, &pLock->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|flags, zVfs ); /* Install a busy-handler and execute a BEGIN EXCLUSIVE. If this is not ** a WAL database, this is all we need to do. ** ** A wrapper function is used to invoke the busy-handler instead of ** registering the busy-handler function supplied by the user directly |
︙ | ︙ | |||
334 335 336 337 338 339 340 | } if( objc>4 ){ busy.interp = interp; busy.pScript = objv[4]; xBusy = superlock_busy; } | | | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | } if( objc>4 ){ busy.interp = interp; busy.pScript = objv[4]; xBusy = superlock_busy; } rc = sqlite3demo_superlock(zPath, zVfs, 0, xBusy, &busy, &pLock); assert( rc==SQLITE_OK || pLock==0 ); assert( rc!=SQLITE_OK || pLock!=0 ); if( rc!=SQLITE_OK ){ extern const char *sqlite3ErrStr(int); Tcl_ResetResult(interp); Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
697 698 699 700 701 702 703 | } #endif if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } | | > | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | } #endif if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY || (p->rc&0xFF)==SQLITE_LOCKED ); assert( p->bIsReader || p->readOnly!=0 ); p->iCurrentTime = 0; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt; sqlite3VdbeIOTraceSql(p); |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. */ #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_DEPRECATED /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the ** execution environment changes in a way that would alter the program ** that sqlite3_prepare() generates. For example, if new functions or | > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. */ #include "sqliteInt.h" #include "vdbeInt.h" #ifdef SQLITE_ENABLE_SQLRR # include "sqlrr.h" #endif #ifndef SQLITE_OMIT_DEPRECATED /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the ** execution environment changes in a way that would alter the program ** that sqlite3_prepare() generates. For example, if new functions or |
︙ | ︙ | |||
100 101 102 103 104 105 106 107 108 109 110 111 112 113 | int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL ** pointer is a harmless no-op. */ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); | > > > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL ** pointer is a harmless no-op. */ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; #ifdef SQLITE_ENABLE_SQLRR SRRecFinalize(pStmt); #endif sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); |
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeReset(v); sqlite3VdbeRewind(v); assert( (rc & (db->errMask))==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); } return rc; } /* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; #if SQLITE_THREADSAFE | > > > > > > > > > > | | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; #ifdef SQLITE_ENABLE_SQLRR SRRecReset(pStmt); #endif sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeReset(v); sqlite3VdbeRewind(v); assert( (rc & (db->errMask))==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); } return rc; } /* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; #if SQLITE_THREADSAFE sqlite3_mutex *mutex=NULL; #endif if( NULL==pStmt ){ return SQLITE_OK; } /* <rdar://problem/6646331> */ #ifdef SQLITE_ENABLE_SQLRR SRRecClearBindings(pStmt); #endif #if SQLITE_THREADSAFE mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; i<p->nVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 ); |
︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 | int sqlite3_bind_blob( sqlite3_stmt *pStmt, int i, const void *zData, int nData, void (*xDel)(void*) ){ #ifdef SQLITE_ENABLE_API_ARMOR if( nData<0 ) return SQLITE_MISUSE_BKPT; #endif return bindText(pStmt, i, zData, nData, xDel, 0); } int sqlite3_bind_blob64( sqlite3_stmt *pStmt, | > > > | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | int sqlite3_bind_blob( sqlite3_stmt *pStmt, int i, const void *zData, int nData, void (*xDel)(void*) ){ #ifdef SQLITE_ENABLE_SQLRR SRRecBindBlob(pStmt, i, zData, nData); #endif #ifdef SQLITE_ENABLE_API_ARMOR if( nData<0 ) return SQLITE_MISUSE_BKPT; #endif return bindText(pStmt, i, zData, nData, xDel, 0); } int sqlite3_bind_blob64( sqlite3_stmt *pStmt, |
︙ | ︙ | |||
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 | }else{ return bindText(pStmt, i, zData, (int)nData, xDel, 0); } } int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); } int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_pointer( | > > > > > > > > > > > > | 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 | }else{ return bindText(pStmt, i, zData, (int)nData, xDel, 0); } } int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; #ifdef SQLITE_ENABLE_SQLRR SRRecBindDouble(pStmt, i, rValue); #endif rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ #ifdef SQLITE_ENABLE_SQLRR SRRecBindInt64(p, i, (i64)iValue); #endif return sqlite3_bind_int64(p, i, (i64)iValue); } int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; #ifdef SQLITE_ENABLE_SQLRR SRRecBindInt64(pStmt, i, iValue); #endif rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ int rc; Vdbe *p = (Vdbe*)pStmt; #ifdef SQLITE_ENABLE_SQLRR SRRecBindNull(pStmt, i); #endif rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_pointer( |
︙ | ︙ | |||
1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 | int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, const char *zData, int nData, void (*xDel)(void*) ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } int sqlite3_bind_text64( sqlite3_stmt *pStmt, int i, const char *zData, sqlite3_uint64 nData, | > > > | 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 | int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, const char *zData, int nData, void (*xDel)(void*) ){ #ifdef SQLITE_ENABLE_SQLRR SRRecBindText(pStmt, i, zData, nData); #endif return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); } int sqlite3_bind_text64( sqlite3_stmt *pStmt, int i, const char *zData, sqlite3_uint64 nData, |
︙ | ︙ | |||
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 | int sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, int nData, void (*xDel)(void*) ){ return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { | > > > | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 | int sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, int nData, void (*xDel)(void*) ){ #ifdef SQLITE_ENABLE_SQLRR SRRecBindText(pStmt, i, zData, nData); #endif return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); } #endif /* SQLITE_OMIT_UTF16 */ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; switch( sqlite3_value_type((sqlite3_value*)pValue) ){ case SQLITE_INTEGER: { |
︙ | ︙ | |||
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 | rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); }else{ rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT); } break; } case SQLITE_TEXT: { rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT, pValue->enc); break; } default: { rc = sqlite3_bind_null(pStmt, i); break; } } return rc; } int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); sqlite3_mutex_leave(p->db->mutex); } return rc; } | > > > > > > | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 | rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); }else{ rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT); } break; } case SQLITE_TEXT: { #ifdef SQLITE_ENABLE_SQLRR SRRecBindText(pStmt, i, pValue->z, pValue->n); #endif rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT, pValue->enc); break; } default: { rc = sqlite3_bind_null(pStmt, i); break; } } return rc; } int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; #ifdef SQLITE_ENABLE_SQLRR SRRecBindBlob(pStmt, i, NULL, n); #endif rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); sqlite3_mutex_leave(p->db->mutex); } return rc; } |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 | */ int sqlite3WalOpen( sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ sqlite3_file *pDbFd, /* The open database file */ const char *zWalName, /* Name of the WAL file */ int bNoShm, /* True to run in heap-memory mode */ i64 mxWalSize, /* Truncate WAL to this size on reset */ Wal **ppWal /* OUT: Allocated Wal handle */ ){ int rc; /* Return Code */ Wal *pRet; /* Object to allocate and return */ | > | | 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 | */ int sqlite3WalOpen( sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ sqlite3_file *pDbFd, /* The open database file */ const char *zWalName, /* Name of the WAL file */ int bNoShm, /* True to run in heap-memory mode */ i64 mxWalSize, /* Truncate WAL to this size on reset */ int flags, /* VFS file protection flags */ Wal **ppWal /* OUT: Allocated Wal handle */ ){ int rc; /* Return Code */ Wal *pRet; /* Object to allocate and return */ int vfsFlags; /* Flags passed to OsOpen() */ assert( zWalName && zWalName[0] ); assert( pDbFd ); /* In the amalgamation, the os_unix.c and os_win.c source files come before ** this source file. Verify that the #defines of the locking byte offsets ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. |
︙ | ︙ | |||
1373 1374 1375 1376 1377 1378 1379 | pRet->mxWalSize = mxWalSize; pRet->zWalName = zWalName; pRet->syncHeader = 1; pRet->padToSectorBoundary = 1; pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); /* Open file handle on the write-ahead log file. */ | > > > | > | | | 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 | pRet->mxWalSize = mxWalSize; pRet->zWalName = zWalName; pRet->syncHeader = 1; pRet->padToSectorBoundary = 1; pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); /* Open file handle on the write-ahead log file. */ if( flags&SQLITE_OPEN_READONLY ){ vfsFlags = flags | SQLITE_OPEN_WAL; } else { vfsFlags = flags | (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL); } rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, vfsFlags, &vfsFlags); if( rc==SQLITE_OK && vfsFlags&SQLITE_OPEN_READONLY ){ pRet->readOnly = WAL_RDONLY; } if( rc!=SQLITE_OK ){ walIndexClose(pRet, 0); sqlite3OsClose(pRet->pWalFd); sqlite3_free(pRet); |
︙ | ︙ | |||
2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 | ** ** There are two copies of the header at the beginning of the wal-index. ** When reading, read [0] first then [1]. Writes are in the reverse order. ** Memory barriers are used to prevent the compiler or the hardware from ** reordering the reads and writes. */ aHdr = walIndexHdr(pWal); memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); walShmBarrier(pWal); memcpy(&h2, (void *)&aHdr[1], sizeof(h2)); if( memcmp(&h1, &h2, sizeof(h1))!=0 ){ return 1; /* Dirty read */ } | > > > | 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 | ** ** There are two copies of the header at the beginning of the wal-index. ** When reading, read [0] first then [1]. Writes are in the reverse order. ** Memory barriers are used to prevent the compiler or the hardware from ** reordering the reads and writes. */ aHdr = walIndexHdr(pWal); if( aHdr==NULL ){ return 1; /* Shouldn't be getting NULL from walIndexHdr, but we are */ } memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); walShmBarrier(pWal); memcpy(&h2, (void *)&aHdr[1], sizeof(h2)); if( memcmp(&h1, &h2, sizeof(h1))!=0 ){ return 1; /* Dirty read */ } |
︙ | ︙ | |||
3000 3001 3002 3003 3004 3005 3006 | Pgno sqlite3WalDbsize(Wal *pWal){ if( pWal && ALWAYS(pWal->readLock>=0) ){ return pWal->hdr.nPage; } return 0; } | < | 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 | Pgno sqlite3WalDbsize(Wal *pWal){ if( pWal && ALWAYS(pWal->readLock>=0) ){ return pWal->hdr.nPage; } return 0; } /* ** This function starts a write transaction on the WAL. ** ** A read transaction must have already been started by a prior call ** to sqlite3WalBeginReadTransaction(). ** ** If another thread or process has written into the database since |
︙ | ︙ | |||
3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 | */ typedef struct WalWriter { Wal *pWal; /* The complete WAL information */ sqlite3_file *pFd; /* The WAL file to which we write */ sqlite3_int64 iSyncPoint; /* Fsync at this offset */ int syncFlags; /* Flags for the fsync */ int szPage; /* Size of one page */ } WalWriter; /* ** Write iAmt bytes of content into the WAL file beginning at iOffset. ** Do a sync when crossing the p->iSyncPoint boundary. ** ** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt, | > > > > | 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 | */ typedef struct WalWriter { Wal *pWal; /* The complete WAL information */ sqlite3_file *pFd; /* The WAL file to which we write */ sqlite3_int64 iSyncPoint; /* Fsync at this offset */ int syncFlags; /* Flags for the fsync */ int szPage; /* Size of one page */ #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) void *aFrameBuf; /* Frame buffer */ size_t szFrameBuf; /* Size of frame buffer */ #endif } WalWriter; /* ** Write iAmt bytes of content into the WAL file beginning at iOffset. ** Do a sync when crossing the p->iSyncPoint boundary. ** ** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt, |
︙ | ︙ | |||
3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 | WalWriter *p, /* Where to write the frame */ PgHdr *pPage, /* The page of the frame to be written */ int nTruncate, /* The commit flag. Usually 0. >0 for commit */ sqlite3_int64 iOffset /* Byte offset at which to write */ ){ int rc; /* Result code from subfunctions */ void *pData; /* Data actually written */ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ pData = pPage->pData; walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); if( rc ) return rc; /* Write the page data */ rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame)); return rc; } /* ** This function is called as part of committing a transaction within which ** one or more frames have been overwritten. It updates the checksums for ** all frames written to the wal file by the current transaction starting | > > > > > > > > > > > > | 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 | WalWriter *p, /* Where to write the frame */ PgHdr *pPage, /* The page of the frame to be written */ int nTruncate, /* The commit flag. Usually 0. >0 for commit */ sqlite3_int64 iOffset /* Byte offset at which to write */ ){ int rc; /* Result code from subfunctions */ void *pData; /* Data actually written */ #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) u8 *aFrame = p->aFrameBuf; #else u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ #endif pData = pPage->pData; walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) memcpy(&aFrame[WAL_FRAME_HDRSIZE], pData, p->szPage); rc = walWriteToLog(p, aFrame, (p->szPage + WAL_FRAME_HDRSIZE), iOffset); #else rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); if( rc ) return rc; /* Write the page data */ rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame)); #endif return rc; } /* ** This function is called as part of committing a transaction within which ** one or more frames have been overwritten. It updates the checksums for ** all frames written to the wal file by the current transaction starting |
︙ | ︙ | |||
3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 | w.pWal = pWal; w.pFd = pWal->pWalFd; w.iSyncPoint = 0; w.syncFlags = sync_flags; w.szPage = szPage; iOffset = walFrameOffset(iFrame+1, szPage); szFrame = szPage + WAL_FRAME_HDRSIZE; /* Write all frames into the log file exactly once */ for(p=pList; p; p=p->pDirty){ int nDbSize; /* 0 normally. Positive == commit flag */ /* Check if this page has already been written into the wal file by ** the current transaction. If so, overwrite the existing frame and | > > > > > > > | 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 | w.pWal = pWal; w.pFd = pWal->pWalFd; w.iSyncPoint = 0; w.syncFlags = sync_flags; w.szPage = szPage; iOffset = walFrameOffset(iFrame+1, szPage); szFrame = szPage + WAL_FRAME_HDRSIZE; #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) w.aFrameBuf = (void *)malloc(szFrame); if( NULL==w.aFrameBuf ){ return SQLITE_NOMEM; } #endif /* Write all frames into the log file exactly once */ for(p=pList; p; p=p->pDirty){ int nDbSize; /* 0 normally. Positive == commit flag */ /* Check if this page has already been written into the wal file by ** the current transaction. If so, overwrite the existing frame and |
︙ | ︙ | |||
3457 3458 3459 3460 3461 3462 3463 | } } iFrame++; assert( iOffset==walFrameOffset(iFrame, szPage) ); nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0; rc = walWriteOneFrame(&w, p, nDbSize, iOffset); | | > > > > > | 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 | } } iFrame++; assert( iOffset==walFrameOffset(iFrame, szPage) ); nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0; rc = walWriteOneFrame(&w, p, nDbSize, iOffset); if( rc ) { #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) free(w.aFrameBuf); #endif return rc; } pLast = p; iOffset += szFrame; p->flags |= PGHDR_WAL_APPEND; } /* Recalculate checksums within the wal file if required. */ if( isCommit && pWal->iReCksum ){ |
︙ | ︙ | |||
3492 3493 3494 3495 3496 3497 3498 | if( pWal->padToSectorBoundary ){ int sectorSize = sqlite3SectorSize(pWal->pWalFd); w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; bSync = (w.iSyncPoint==iOffset); testcase( bSync ); while( iOffset<w.iSyncPoint ){ rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset); | | > > > > > > > > | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 | if( pWal->padToSectorBoundary ){ int sectorSize = sqlite3SectorSize(pWal->pWalFd); w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; bSync = (w.iSyncPoint==iOffset); testcase( bSync ); while( iOffset<w.iSyncPoint ){ rc = walWriteOneFrame(&w, pLast, nTruncate, iOffset); if( rc ) { #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) free(w.aFrameBuf); #endif return rc; } iOffset += szFrame; nExtra++; assert( pLast!=0 ); } } if( bSync ){ assert( rc==SQLITE_OK ); rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags)); } } #if defined(SQLITE_WRITE_WALFRAME_PREBUFFERED) free(w.aFrameBuf); #endif /* If this frame set completes the first transaction in the WAL and ** if PRAGMA journal_size_limit is set, then truncate the WAL to the ** journal size limit, if possible. */ if( isCommit && pWal->truncateOnCommit && pWal->mxWalSize>=0 ){ i64 sz = pWal->mxWalSize; if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){ |
︙ | ︙ |
Changes to src/wal.h.
︙ | ︙ | |||
51 52 53 54 55 56 57 | /* Connection to a write-ahead log (WAL) file. ** There is one object of this type for each pager. */ typedef struct Wal Wal; /* Open and close a connection to a write-ahead log. */ | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | /* Connection to a write-ahead log (WAL) file. ** There is one object of this type for each pager. */ typedef struct Wal Wal; /* Open and close a connection to a write-ahead log. */ int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, int, Wal**); int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); /* Set the limiting size of a WAL file. */ void sqlite3WalLimit(Wal*, i64); /* Used by readers to open (lock) and close (unlock) a snapshot. A ** snapshot is like a read-transaction. It is the state of the database |
︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | /* Read a page from the write-ahead log, if it is present. */ int sqlite3WalFindFrame(Wal *, Pgno, u32 *); int sqlite3WalReadFrame(Wal *, u32, int, u8 *); /* If the WAL is not empty, return the size of the database. */ Pgno sqlite3WalDbsize(Wal *pWal); /* Obtain or release the WRITER lock. */ int sqlite3WalBeginWriteTransaction(Wal *pWal); int sqlite3WalEndWriteTransaction(Wal *pWal); /* Undo any frames written (but not committed) to the log */ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx); | > > > | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | /* Read a page from the write-ahead log, if it is present. */ int sqlite3WalFindFrame(Wal *, Pgno, u32 *); int sqlite3WalReadFrame(Wal *, u32, int, u8 *); /* If the WAL is not empty, return the size of the database. */ Pgno sqlite3WalDbsize(Wal *pWal); /* If a WAL journal file has been created, return it */ sqlite3_file *sqlite3WalFile(Wal *pWal); /* Obtain or release the WRITER lock. */ int sqlite3WalBeginWriteTransaction(Wal *pWal); int sqlite3WalEndWriteTransaction(Wal *pWal); /* Undo any frames written (but not committed) to the log */ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx); |
︙ | ︙ |
Changes to test/8_3_names.test.
︙ | ︙ | |||
142 143 144 145 146 147 148 149 150 151 152 153 154 155 | ########################################################################## # WAL mode. # ifcapable !wal { finish_test return } db close forcedelete test.db do_test 8_3_names-5.0 { sqlite3 db file:./test.db?8_3_names=1 load_static_extension db wholenumber db eval { PRAGMA journal_mode=WAL; | > > | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | ########################################################################## # WAL mode. # ifcapable !wal { finish_test return } if ![wal_is_ok] { finish_test; return } db close forcedelete test.db do_test 8_3_names-5.0 { sqlite3 db file:./test.db?8_3_names=1 load_static_extension db wholenumber db eval { PRAGMA journal_mode=WAL; |
︙ | ︙ |
Changes to test/altertab.test.
︙ | ︙ | |||
546 547 548 549 550 551 552 | INSERT INTO y1_segments VALUES(1, X'1234567890'); } {1 {table y1_segments may not be modified}} do_catchsql_test 16.20 { DROP TABLE y1_segments; } {1 {table y1_segments may not be dropped}} | | > > > > | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | INSERT INTO y1_segments VALUES(1, X'1234567890'); } {1 {table y1_segments may not be modified}} do_catchsql_test 16.20 { DROP TABLE y1_segments; } {1 {table y1_segments may not be dropped}} do_catchsql_test 16.21 { ALTER TABLE y1_segments RENAME TO abc; } {1 {table y1_segments may not be altered}} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 16.22 { ALTER TABLE y1_segments RENAME TO abc; } {0 {}} sqlite3_db_config db DEFENSIVE 1 do_catchsql_test 16.23 { CREATE TABLE y1_segments AS SELECT * FROM abc; } {1 {object name reserved for internal use: y1_segments}} do_catchsql_test 16.24 { CREATE VIEW y1_segments AS SELECT * FROM abc; } {1 {object name reserved for internal use: y1_segments}} sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 16.25 { ALTER TABLE abc RENAME TO y1_segments; } {0 {}} sqlite3_db_config db DEFENSIVE 1 do_catchsql_test 16.21 { DROP TABLE y1_segments; } {1 {table y1_segments may not be dropped}} do_execsql_test 16.30 { ALTER TABLE y1 RENAME TO z1; } do_execsql_test 16.40 { SELECT * FROM z1_segments; } |
︙ | ︙ |
Changes to test/attach.test.
︙ | ︙ | |||
756 757 758 759 760 761 762 | # do_test attach-6.1 { catchsql { ATTACH DATABASE 'no-such-file' AS nosuch; } } {0 {}} if {$tcl_platform(platform)=="unix"} { | < | | | | | | | | | > | | | | | | | > | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 | # do_test attach-6.1 { catchsql { ATTACH DATABASE 'no-such-file' AS nosuch; } } {0 {}} if {$tcl_platform(platform)=="unix"} { sqlite3 dbx cannot-read dbx eval {CREATE TABLE t1(a,b,c)} dbx close file attributes cannot-read -permission 0000 if {[file writable cannot-read]} { #puts "\n**** Tests do not work when run as root ****" forcedelete cannot-read #exit 1 } else { do_test attach-6.2 { catchsql { ATTACH DATABASE 'cannot-read' AS noread; } } {1 {unable to open database: cannot-read}} do_test attach-6.2.2 { db errorcode } {14} } forcedelete cannot-read } # Check the error message if we try to access a database that has # not been attached. do_test attach-6.3 { catchsql { |
︙ | ︙ |
Changes to test/attach4.test.
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | foreach {name f} $files { if {[permutation] == "journaltest"} { set mode delete } else { set mode wal } ifcapable !wal { set mode delete } lappend L $mode append S " PRAGMA $name.journal_mode = WAL; UPDATE $name.tbl SET x = '$name'; " } do_execsql_test 1.5 $S $L | > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | foreach {name f} $files { if {[permutation] == "journaltest"} { set mode delete } else { set mode wal } ifcapable !wal { set mode delete } if ![wal_is_ok] { set mode delete } lappend L $mode append S " PRAGMA $name.journal_mode = WAL; UPDATE $name.tbl SET x = '$name'; " } do_execsql_test 1.5 $S $L |
︙ | ︙ |
Changes to test/bind.test.
︙ | ︙ | |||
652 653 654 655 656 657 658 659 660 661 662 663 664 665 | sqlite3_reset $VM sqlite3_clear_bindings $VM sqlite3_step $VM list [sqlite3_column_type $VM 0] [sqlite3_column_type $VM 1] \ [sqlite3_column_type $VM 2] } {NULL NULL NULL} sqlite3_finalize $VM #-------------------------------------------------------------------- # These tests attempt to reproduce bug #3463. # proc param_names {db zSql} { set ret [list] set VM [sqlite3_prepare db $zSql -1 TAIL] | > > > | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | sqlite3_reset $VM sqlite3_clear_bindings $VM sqlite3_step $VM list [sqlite3_column_type $VM 0] [sqlite3_column_type $VM 1] \ [sqlite3_column_type $VM 2] } {NULL NULL NULL} sqlite3_finalize $VM do_test bind-13.5 { sqlite3_clear_bindings_null } {0} #-------------------------------------------------------------------- # These tests attempt to reproduce bug #3463. # proc param_names {db zSql} { set ret [list] set VM [sqlite3_prepare db $zSql -1 TAIL] |
︙ | ︙ |
Changes to test/cache.test.
︙ | ︙ | |||
103 104 105 106 107 108 109 | do_test cache-2.3.2 { pager_cache_size db } 2 do_execsql_test cache-2.3.3 { INSERT INTO t2 VALUES(1, 2); PRAGMA lock_status; } {main exclusive temp closed} do_test cache-2.3.4 { pager_cache_size db } 2 do_execsql_test cache-2.3.5 COMMIT | > > | | > > | > > > | > > > | > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | do_test cache-2.3.2 { pager_cache_size db } 2 do_execsql_test cache-2.3.3 { INSERT INTO t2 VALUES(1, 2); PRAGMA lock_status; } {main exclusive temp closed} do_test cache-2.3.4 { pager_cache_size db } 2 do_execsql_test cache-2.3.5 COMMIT if !$::sqlite_options(enable_purgeable_pcache) { # purgeable pcache doesn't share cache between connections do_test cache-2.3.6 { pager_cache_size db } 1 } do_execsql_test cache-2.3.7 { SELECT * FROM t1 UNION SELECT * FROM t2; } {1 2 i j x y} if !$::sqlite_options(enable_purgeable_pcache) { # purgeable pcache doesn't share cache between connections do_test cache-2.3.8 { pager_cache_size db } 1 } # Tests for cache_size = 0. # do_execsql_test cache-2.4.1 { PRAGMA cache_size = 0; BEGIN; INSERT INTO t1 VALUES(1, 2); PRAGMA lock_status; } {main reserved temp closed} do_test cache-2.4.2 { pager_cache_size db } 2 do_execsql_test cache-2.4.3 { INSERT INTO t2 VALUES(1, 2); PRAGMA lock_status; } {main exclusive temp closed} do_test cache-2.4.4 { pager_cache_size db } 2 do_execsql_test cache-2.4.5 COMMIT if !$::sqlite_options(enable_purgeable_pcache) { # purgeable pcache doesn't share cache between connections do_test cache-2.4.6 { pager_cache_size db } 0 } do_execsql_test cache-2.4.7 { SELECT * FROM t1 UNION SELECT * FROM t2; } {1 2 i j x y} if !$::sqlite_options(enable_purgeable_pcache) { # purgeable pcache doesn't share cache between connections do_test cache-2.4.8 { pager_cache_size db } 0 } sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) finish_test |
Changes to test/dbstatus2.test.
︙ | ︙ | |||
38 39 40 41 42 43 44 45 46 47 48 49 50 51 | } proc db_spill {db {reset 0}} { sqlite3_db_status $db CACHE_SPILL $reset } do_test 1.1 { db close sqlite3 db test.db execsql { PRAGMA mmap_size = 0 } expr {[file size test.db] / 1024} } 6 do_test 1.2 { | > > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | } proc db_spill {db {reset 0}} { sqlite3_db_status $db CACHE_SPILL $reset } do_test 1.1 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close sqlite3 db test.db execsql { PRAGMA mmap_size = 0 } expr {[file size test.db] / 1024} } 6 do_test 1.2 { |
︙ | ︙ |
Changes to test/e_wal.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 | # # 1.1: "create" tests. # 1.2: "read" tests. # 1.3: "write" tests. # # All three done with VFS "oldvfs", which has iVersion==1 and so does # not support shared memory. | | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # # 1.1: "create" tests. # 1.2: "read" tests. # 1.3: "write" tests. # # All three done with VFS "oldvfs", which has iVersion==1 and so does # not support shared memory. # forcedelete test.db-shm sqlite3 db test.db -vfs oldvfs do_execsql_test 1.1.1 { PRAGMA journal_mode = WAL; } {delete} do_execsql_test 1.1.2 { PRAGMA locking_mode = EXCLUSIVE; PRAGMA journal_mode = WAL; |
︙ | ︙ |
Changes to test/e_walckpt.test.
︙ | ︙ | |||
436 437 438 439 440 441 442 443 444 445 446 447 448 449 | # # EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked # in the SQLITE_CHECKPOINT_PASSIVE mode. # # It's not. Test case "$tp.6". # do_test $tp.4 { forcecopy test.db abc.db sqlite3 db4 abc.db db4 eval { SELECT * FROM t1 UNION ALL SELECT * FROM t2 } } {1 2 3 4 5 6} do_test $tp.5 { set ::sync_counter } 0 do_test $tp.6 { set ::busy_handler_counter } 0 db4 close | > | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | # # EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked # in the SQLITE_CHECKPOINT_PASSIVE mode. # # It's not. Test case "$tp.6". # do_test $tp.4 { forcedelete abc.db-shm abc.db-wal forcecopy test.db abc.db sqlite3 db4 abc.db db4 eval { SELECT * FROM t1 UNION ALL SELECT * FROM t2 } } {1 2 3 4 5 6} do_test $tp.5 { set ::sync_counter } 0 do_test $tp.6 { set ::busy_handler_counter } 0 db4 close |
︙ | ︙ |
Changes to test/exclusive.test.
︙ | ︙ | |||
400 401 402 403 404 405 406 | # db close sqlite3 db test.db # if we're using proxy locks, we use 3 filedescriptors for a db # that is open but NOT writing changes, normally # sqlite uses 1 (proxy locking adds the conch and the local lock) | < < < < | | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | # db close sqlite3 db test.db # if we're using proxy locks, we use 3 filedescriptors for a db # that is open but NOT writing changes, normally # sqlite uses 1 (proxy locking adds the conch and the local lock) set extrafds 0 if {[forced_proxy_locking]} { set extrafds 2 } do_test exclusive-5.0 { execsql { CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE); BEGIN; |
︙ | ︙ |
Changes to test/fallocate.test.
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 | # The following tests - fallocate-2.* - test that things work in WAL # mode as well. # set skipwaltests [expr { [permutation]=="journaltest" || [permutation]=="inmemory_journal" }] ifcapable !wal { set skipwaltests 1 } if {!$skipwaltests} { db close forcedelete test.db sqlite3 db test.db | > > > > > > > > > > | | > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # The following tests - fallocate-2.* - test that things work in WAL # mode as well. # set skipwaltests [expr { [permutation]=="journaltest" || [permutation]=="inmemory_journal" }] ifcapable !wal { set skipwaltests 1 } if {![wal_is_ok]} { set skipwaltests 1 } if {!$skipwaltests} { db close forcedelete test.db ifcapable enable_persist_wal { forcedelete test.db-journal forcedelete test.db-wal forcedelete test.db-shm } if {[forced_proxy_locking]} { forcedelete .test.db-conch } sqlite3 db test.db ifcapable enable_persist_wal { file_control_persist_wal db 0 } file_control_chunksize_test db main [expr 32*1024] do_test fallocate-2.1 { execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); } file size test.db |
︙ | ︙ |
Changes to test/filter1.test.
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 | } {2.0 5.0 10.0} do_execsql_test 4.3 { SELECT a, avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY avg(c); } {c 2.0 a 10.0 b 5.0} do_execsql_test 4.4 { SELECT a, avg(c) FILTER (WHERE b!=1) FROM t1 GROUP BY a ORDER BY 2 } {c 2.0 b 5.0 a 10.0} #------------------------------------------------------------------------- reset_db do_execsql_test 5.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(1, 3); | > > > > > > > > > > > > > > > > > > > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | } {2.0 5.0 10.0} do_execsql_test 4.3 { SELECT a, avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY avg(c); } {c 2.0 a 10.0 b 5.0} do_execsql_test 4.4 { SELECT a, avg(c) FILTER (WHERE b!=1) FROM t1 GROUP BY a ORDER BY 2 } {c 2.0 b 5.0 a 10.0} #------------------------------------------------------------------------- reset_db do_execsql_test 5.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(1, 3); } do_execsql_test 5.1 { SELECT count(*) FILTER (WHERE b>2) FROM (SELECT * FROM t1) } {1} do_execsql_test 5.2 { SELECT count(*) FILTER (WHERE b>2) OVER () FROM (SELECT * FROM t1) } {1 1} do_execsql_test 5.3 { SELECT count(*) FILTER (WHERE b>2) OVER (ORDER BY b) FROM (SELECT * FROM t1) } {0 1} #------------------------------------------------------------------------- reset_db do_execsql_test 5.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(1, 3); |
︙ | ︙ |
Changes to test/incrblob3.test.
︙ | ︙ | |||
256 257 258 259 260 261 262 | set dbversion [hexio_get_int [hexio_read test.db 24 4]] incr dbversion hexio_write test.db 24 [hexio_render_int32 $dbversion] return "" } | > > > > | | | | | | > | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | set dbversion [hexio_get_int [hexio_read test.db 24 4]] incr dbversion hexio_write test.db 24 [hexio_render_int32 $dbversion] return "" } #set sqlite_os_trace 1 # AFP asserts because the "db incrblob blobs v 1" clears the file locks and the unlock fails (HFS doesn't care about a failed unlock) if {[path_is_local "."]} { do_test incrblob3-7.2 { sqlite3 db test.db sqlite3_db_config_lookaside db 0 0 0 list [catch {db incrblob blobs v 1} msg] $msg } {1 {database schema has changed}} db close } tvfs delete finish_test |
Changes to test/incrvacuum2.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # This file implements regression tests for SQLite library. The # focus of this file is testing the incremental vacuum feature. # # $Id: incrvacuum2.test,v 1.6 2009/07/25 13:42:50 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # If this build of the library does not support auto-vacuum, omit this # whole file. ifcapable {!autovacuum || !pragma} { finish_test return } | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # This file implements regression tests for SQLite library. The # focus of this file is testing the incremental vacuum feature. # # $Id: incrvacuum2.test,v 1.6 2009/07/25 13:42:50 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl # If this build of the library does not support auto-vacuum, omit this # whole file. ifcapable {!autovacuum || !pragma} { finish_test return } |
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 | DELETE FROM abc; PRAGMA incremental_vacuum; COMMIT; } } {} integrity_check incrvacuum2-3.3 if {[wal_is_capable]} { # At one point, when a specific page was being extracted from the b-tree # free-list (e.g. during an incremental-vacuum), all trunk pages that # occurred before the specific page in the free-list trunk were being # written to the journal or wal file. This is not necessary. Only the # extracted page and the page that contains the pointer to it need to | > > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | DELETE FROM abc; PRAGMA incremental_vacuum; COMMIT; } } {} integrity_check incrvacuum2-3.3 if ![wal_is_ok] { finish_test; return } if {[wal_is_capable]} { # At one point, when a specific page was being extracted from the b-tree # free-list (e.g. during an incremental-vacuum), all trunk pages that # occurred before the specific page in the free-list trunk were being # written to the journal or wal file. This is not necessary. Only the # extracted page and the page that contains the pointer to it need to |
︙ | ︙ |
Changes to test/join.test.
︙ | ︙ | |||
879 880 881 882 883 884 885 886 887 888 889 890 891 892 | INSERT INTO t1(x) VALUES(0),(1); SELECT * FROM t1 LEFT JOIN (SELECT abs(1) AS y FROM t1) ON x WHERE NOT(y='a'); } {1 1 1 1} do_execsql_test join-17.110 { SELECT * FROM t1 LEFT JOIN (SELECT abs(1)+2 AS y FROM t1) ON x WHERE NOT(y='a'); } {1 3 1 3} #------------------------------------------------------------------------- reset_db do_execsql_test join-18.1 { CREATE TABLE t0(a); CREATE TABLE t1(b); CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0; | > > > > > > > > > > > > > > > > > > > > > | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | INSERT INTO t1(x) VALUES(0),(1); SELECT * FROM t1 LEFT JOIN (SELECT abs(1) AS y FROM t1) ON x WHERE NOT(y='a'); } {1 1 1 1} do_execsql_test join-17.110 { SELECT * FROM t1 LEFT JOIN (SELECT abs(1)+2 AS y FROM t1) ON x WHERE NOT(y='a'); } {1 3 1 3} #------------------------------------------------------------------------- reset_db do_execsql_test join-18.1 { CREATE TABLE t0(a); CREATE TABLE t1(b); CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0; INSERT INTO t1 VALUES (1); } {} do_execsql_test join-18.2 { SELECT * FROM v0 WHERE NOT(v0.a IS FALSE); } {{}} do_execsql_test join-18.3 { SELECT * FROM t1 LEFT JOIN t0 WHERE NOT(a IS FALSE); } {1 {}} do_execsql_test join-18.4 { SELECT NOT(v0.a IS FALSE) FROM v0 } {1} #------------------------------------------------------------------------- reset_db do_execsql_test join-18.1 { CREATE TABLE t0(a); CREATE TABLE t1(b); CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0; |
︙ | ︙ |
Changes to test/journal3.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | source $testdir/lock_common.tcl source $testdir/malloc_common.tcl #------------------------------------------------------------------------- # If a connection is required to create a journal file, it creates it with # the same file-system permissions as the database file itself. Test this. # | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | source $testdir/lock_common.tcl source $testdir/malloc_common.tcl #------------------------------------------------------------------------- # If a connection is required to create a journal file, it creates it with # the same file-system permissions as the database file itself. Test this. # if {$::tcl_platform(platform) == "unix" && ![path_is_dos "."] && [atomic_batch_write test.db]==0 } { # Changed on 2012-02-13: umask is deliberately ignored for -wal, -journal, # and -shm files. #set umask [exec /bin/sh -c umask] faultsim_delete_and_reopen |
︙ | ︙ |
Changes to test/lock5.test.
︙ | ︙ | |||
102 103 104 105 106 107 108 | forcedelete test.db if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} { finish_test return } | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | < | < < > > > > > > | | | | | | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | forcedelete test.db if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} { finish_test return } # Only run the flock tests on a local file system if { [path_is_local "."] } { do_test lock5-flock.1 { sqlite3 db test.db -vfs unix-flock execsql { CREATE TABLE t1(a, b); BEGIN; INSERT INTO t1 VALUES(1, 2); } } {} # Make sure we are not accidentally using the dotfile locking scheme. do_test lock5-flock.2 { file exists test.db.lock } {0} do_test lock5-flock.3 { catch { sqlite3 db2 test.db -vfs unix-flock } catchsql { SELECT * FROM t1 } db2 } {1 {database is locked}} do_test lock5-flock.4 { execsql COMMIT catchsql { SELECT * FROM t1 } db2 } {0 {1 2}} do_test lock5-flock.5 { execsql BEGIN catchsql { SELECT * FROM t1 } db2 } {0 {1 2}} do_test lock5-flock.6 { execsql {SELECT * FROM t1} catchsql { SELECT * FROM t1 } db2 } {1 {database is locked}} do_test lock5-flock.7 { db close catchsql { SELECT * FROM t1 } db2 } {0 {1 2}} do_test lock5-flock.8 { db2 close } {} ##################################################################### do_test lock5-none.1 { sqlite3 db test.db -vfs unix-none sqlite3 db2 test.db -vfs unix-none execsql { BEGIN; INSERT INTO t1 VALUES(3, 4); } } {} do_test lock5-none.2 { execsql { SELECT * FROM t1 } } {1 2 3 4} do_test lock5-flock.3 { execsql { SELECT * FROM t1 } db2 } {1 2} do_test lock5-none.4 { execsql { BEGIN; SELECT * FROM t1; } db2 } {1 2} do_test lock5-none.5 { execsql COMMIT } {} do_test lock5-none.6 { sqlite3_release_memory 1000000 execsql {SELECT * FROM t1} db2 } {1 2} ifcapable memorymanage { do_test lock5-none.6 { sqlite3_release_memory 1000000 execsql {SELECT * FROM t1} db2 } {1 2 3 4} } do_test lock5-flock.X { db close db2 close } {} } ifcapable lock_proxy_pragmas { set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy } finish_test |
Changes to test/lock6.test.
︙ | ︙ | |||
122 123 124 125 126 127 128 129 130 | set lockpath [execsql { PRAGMA lock_proxy_file=":auto:"; PRAGMA lock_proxy_file; } db] set lockpath } {{:auto: (not held)}} do_test lock6-1.4.1 { catchsql { | > > < | > > < | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | set lockpath [execsql { PRAGMA lock_proxy_file=":auto:"; PRAGMA lock_proxy_file; } db] set lockpath } {{:auto: (not held)}} set lpp [exec mktemp -t fail] do_test lock6-1.4.1 { execsql "PRAGMA lock_proxy_file='$lpp'" catchsql { select * from sqlite_master; } db } {1 {database is locked}} do_test lock6-1.4.2 { execsql { PRAGMA lock_proxy_file; } db } $lpp do_test lock6-1.5 { testfixture $::tf1 { db eval { BEGIN; SELECT * FROM sqlite_master; } } } {} catch {testfixture $::tf1 {db close}} set lpp [exec mktemp -t ok] do_test lock6-1.6 { execsql "PRAGMA lock_proxy_file='$lpp'" execsql { select * from sqlite_master; } db } {} catch {close $::tf1} set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy set sqlite_hostid_num 0 |
︙ | ︙ |
Added test/lock_proxy.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | # 2008 June 28 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database proxy locks. # # $Id$ set testdir [file dirname $argv0] source $testdir/tester.tcl # This file is only run if using the unix backend compiled with the # SQLITE_ENABLE_LOCKING_STYLE macro. db close if {[catch {sqlite3 db test.db -vfs unix-none} msg]} { finish_test return } db close file delete -force test.db.lock ##################################################################### ifcapable lock_proxy_pragmas&&prefer_proxy_locking { set ::using_proxy 0 foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] { set ::using_proxy $value } # enable the proxy locking for these tests set env(SQLITE_FORCE_PROXY_LOCKING) "1" # test conch file creation # catch { file delete lock_proxy_test.db } catch { file delete .lock_proxy_test.db-conch } # test that proxy locking mode creates conch files do_test lock_proxy1.0 { sqlite3 db2 lock_proxy_test.db catchsql { create table x(y); } db2 file exists .lock_proxy_test.db-conch } {1} catch { db2 close } # test proxy locking readonly file system handling # if {[file exists /usr/bin/hdiutil]} { puts "Creating readonly file system for proxy locking tests..." if {[file exists /Volumes/readonly]} { exec hdiutil detach /Volumes/readonly } if {[file exists readonly.dmg]} { file delete readonly.dmg } exec hdiutil create -megabytes 1 -fs HFS+ readonly.dmg -volname readonly exec hdiutil attach readonly.dmg # create test1.db and a .test1.db-conch for host4 set sqlite_hostid_num 4 sqlite3 db2 /Volumes/readonly/test1.db execsql { create table x(y); } db2 db2 close # create test2.db and a .test2.db-conch for host5 set sqlite_hostid_num 5 sqlite3 db2 /Volumes/readonly/test2.db execsql { create table x(y); } db2 db2 close # create test3.db without a conch file set env(SQLITE_FORCE_PROXY_LOCKING) "0" sqlite3 db2 /Volumes/readonly/test3.db execsql { create table x(y); } db2 db2 close exec hdiutil detach /Volumes/readonly exec hdiutil attach -readonly readonly.dmg # test that an unwritable, host-mismatched conch file prevents # read only proxy-locking mode database access set env(SQLITE_FORCE_PROXY_LOCKING) "1" do_test lock_proxy2.0 { sqlite3 db2 /Volumes/readonly/test1.db catchsql { select * from sqlite_master; } db2 } {1 {database is locked}} catch { db2 close } # test that an unwritable, host-matching conch file allows # read only proxy-locking mode database access do_test lock_proxy2.1 { sqlite3 db2 /Volumes/readonly/test2.db catchsql { select * from sqlite_master; } db2 } {0 {table x x 2 {CREATE TABLE x(y)}}} catch { db2 close } # test that an unwritable, nonexistant conch file allows # read only proxy-locking mode database access do_test lock_proxy2.2 { sqlite3 db2 /Volumes/readonly/test3.db catchsql { select * from sqlite_master; } db2 } {0 {table x x 2 {CREATE TABLE x(y)}}} catch { db2 close } exec hdiutil detach /Volumes/readonly file delete readonly.dmg } set env(SQLITE_FORCE_PROXY_LOCKING) "0" set sqlite_hostid_num 0 } ##################################################################### file delete -force test.db ifcapable lock_proxy_pragmas&&prefer_proxy_locking { set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy } finish_test |
Changes to test/main.test.
︙ | ︙ | |||
310 311 312 313 314 315 316 | } {0 {}} } # Here are some tests for tokenize.c. # do_test main-3.1 { catch {db close} | | | | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | } {0 {}} } # Here are some tests for tokenize.c. # do_test main-3.1 { catch {db close} catch {foreach f [glob -nocomplain testdb/*] {forcedelete $f}} forcedelete testdb sqlite3 db testdb set v [catch {execsql {SELECT * from T1 where x!!5}} msg] lappend v $msg } {1 {unrecognized token: "!"}} do_test main-3.2 { catch {db close} catch {foreach f [glob -nocomplain testdb/*] {forcedelete $f}} forcedelete testdb sqlite3 db testdb set v [catch {execsql {SELECT * from T1 where ^x}} msg] lappend v $msg } {1 {unrecognized token: "^"}} do_test main-3.2.2 { catchsql {select 'abc} |
︙ | ︙ | |||
438 439 440 441 442 443 444 | do_test main-3.2.30 { catchsql {select 123--5} } {0 123} do_test main-3.3 { catch {db close} | | | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | do_test main-3.2.30 { catchsql {select 123--5} } {0 123} do_test main-3.3 { catch {db close} catch {foreach f [glob -nocomplain testdb/*] {forcedelete $f}} forcedelete testdb sqlite3 db testdb execsql { create table T1(X REAL); /* C-style comments allowed */ insert into T1 values(0.5); insert into T1 values(0.5e2); insert into T1 values(0.5e-002); |
︙ | ︙ |
Changes to test/malloc_common.tcl.
︙ | ︙ | |||
441 442 443 444 445 446 447 | # fails and then subsequent calls succeed. If $::iRepeat is 1, # then the failure is persistent - once malloc() fails it keeps # failing. # set zRepeat "transient" if {$::iRepeat} {set zRepeat "persistent"} restore_prng_state | | | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | # fails and then subsequent calls succeed. If $::iRepeat is 1, # then the failure is persistent - once malloc() fails it keeps # failing. # set zRepeat "transient" if {$::iRepeat} {set zRepeat "persistent"} restore_prng_state catch {foreach file [glob -nocomplain test.db-mj*] {forcedelete $file}} do_test ${tn}.${zRepeat}.${::n} { # Remove all traces of database files test.db and test2.db # from the file-system. Then open (empty database) "test.db" # with the handle [db]. # |
︙ | ︙ |
Changes to test/manydb.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 | set testdir [file dirname $argv0] source $testdir/tester.tcl set N 300 # if we're using proxy locks, we use 5 filedescriptors for a db # that is open and in the middle of writing changes, normally # sqlite uses 3 (proxy locking adds the conch and the local lock) | < < < < | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | set testdir [file dirname $argv0] source $testdir/tester.tcl set N 300 # if we're using proxy locks, we use 5 filedescriptors for a db # that is open and in the middle of writing changes, normally # sqlite uses 3 (proxy locking adds the conch and the local lock) set num_fd_per_openwrite_db 3 if {[forced_proxy_locking]} { set num_fd_per_openwrite_db 5 } # First test how many file descriptors are available for use. To open a # database for writing SQLite requires 3 file descriptors (the database, the # journal and the directory). set filehandles {} |
︙ | ︙ |
Changes to test/memdb.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is in-memory database backend. # | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is in-memory database backend. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable memorydb { |
︙ | ︙ | |||
403 404 405 406 407 408 409 | DELETE FROM t1; SELECT count(*) FROM t1; } } 0 # Test that auto-vacuum works with in-memory databases. # | > > | | | | | | | | | | | | | | | | | > | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | DELETE FROM t1; SELECT count(*) FROM t1; } } 0 # Test that auto-vacuum works with in-memory databases. # set msize [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] if {[lindex $msize 2]!=0} { ifcapable autovacuum { do_test memdb-9.1 { db close sqlite3 db test.db db cache size 0 execsql { PRAGMA auto_vacuum = full; CREATE TABLE t1(a); INSERT INTO t1 VALUES(randstr(1000,1000)); INSERT INTO t1 VALUES(randstr(1000,1000)); INSERT INTO t1 VALUES(randstr(1000,1000)); } set before [db one {PRAGMA page_count}] execsql { DELETE FROM t1 } set after [db one {PRAGMA page_count}] expr {$before>$after} } {1} } } } ;# ifcapable memorydb finish_test |
Changes to test/memsubsys1.test.
︙ | ︙ | |||
120 121 122 123 124 125 126 | db close sqlite3_shutdown sqlite3_config_pagecache [expr 512+$xtra_size] 20 sqlite3_config singlethread sqlite3_initialize reset_highwater_marks build_test_db memsubsys1-3.1 {PRAGMA page_size=1024} | > | | | | | | | | | | | | > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | db close sqlite3_shutdown sqlite3_config_pagecache [expr 512+$xtra_size] 20 sqlite3_config singlethread sqlite3_initialize reset_highwater_marks build_test_db memsubsys1-3.1 {PRAGMA page_size=1024} if !$::sqlite_options(enable_purgeable_pcache) { do_test memsubsys1-3.1.3 { set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] } 0 do_test memsubsys1-3.1.4 { set overflow [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] # Note: The measured PAGECACHE_OVERFLOW is amount malloc() returns, not what # was requested. System malloc() implementations might (arbitrarily) return # slightly different oversize buffers, which can result in different # PAGECACHE_OVERFLOW sizes between consecutive runs. So we cannot do an # exact comparison. Simply verify that the amount is within 5%. expr {$overflow>=$max_pagecache*0.95 && $overflow<=$max_pagecache*1.05} } 1 } do_test memsubsys1-3.1.5 { set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] } 0 db close sqlite3_shutdown sqlite3_config_pagecache [expr 2048+$xtra_size] 20 sqlite3_initialize |
︙ | ︙ | |||
165 166 167 168 169 170 171 | reset_highwater_marks build_test_db memsubsys1-4 {PRAGMA page_size=1024} #show_memstats do_test memsubsys1-4.3 { set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] expr {$pg_used>=45 && $pg_used<=50} } 1 | > | | | > | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | reset_highwater_marks build_test_db memsubsys1-4 {PRAGMA page_size=1024} #show_memstats do_test memsubsys1-4.3 { set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] expr {$pg_used>=45 && $pg_used<=50} } 1 if !$::sqlite_options(enable_purgeable_pcache) { do_test memsubsys1-4.4 { set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] } 0 } do_test memsubsys1-4.5 { set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] expr {$maxreq<7000} } 1 db close sqlite3_shutdown |
︙ | ︙ |
Changes to test/multiplex.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl # The tests in this file assume that SQLite is compiled without # ENABLE_8_3_NAMES. # ifcapable 8_3_names { puts -nonewline "SQLite compiled with SQLITE_ENABLE_8_3_NAMES. " puts "Skipping tests multiplex-*." | > > > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl # AFP doesn't like multiplex db tests if { ![path_is_local "."] } { finish_test return } # The tests in this file assume that SQLite is compiled without # ENABLE_8_3_NAMES. # ifcapable 8_3_names { puts -nonewline "SQLite compiled with SQLITE_ENABLE_8_3_NAMES. " puts "Skipping tests multiplex-*." |
︙ | ︙ |
Changes to test/pager1.test.
︙ | ︙ | |||
549 550 551 552 553 554 555 556 557 558 559 560 561 562 | } faultsim_save incr ::mj_delete_cnt } return SQLITE_OK } foreach {tn1 tcl} { 1 { set prefix "test.db" } 2 { # This test depends on the underlying VFS being able to open paths # 512 bytes in length. The idea is to create a hot-journal file that # contains a master-journal pointer so large that it could contain # a valid page record (if the file page-size is 512 bytes). So as to | > > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | } faultsim_save incr ::mj_delete_cnt } return SQLITE_OK } if {![forced_proxy_locking]} { # proxy locking uses can't deal with auto proxy file paths longer than MAXPATHLEN foreach {tn1 tcl} { 1 { set prefix "test.db" } 2 { # This test depends on the underlying VFS being able to open paths # 512 bytes in length. The idea is to create a hot-journal file that # contains a master-journal pointer so large that it could contain # a valid page record (if the file page-size is 512 bytes). So as to |
︙ | ︙ | |||
735 736 737 738 739 740 741 742 743 744 745 746 747 748 | } cd $pwd } db close tv delete forcedelete $dirname # Set up a VFS to make a copy of the file-system just before deleting a # journal file to commit a transaction. The transaction modifies exactly # two database pages (and page 1 - the change counter). # testvfs tv -default 1 tv sectorsize 512 | > | 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 | } cd $pwd } db close tv delete forcedelete $dirname } # Set up a VFS to make a copy of the file-system just before deleting a # journal file to commit a transaction. The transaction modifies exactly # two database pages (and page 1 - the change counter). # testvfs tv -default 1 tv sectorsize 512 |
︙ | ︙ | |||
1216 1217 1218 1219 1220 1221 1222 | # $sql: SQL to execute. # $res: Expected result of executing $sql. # $js: The expected size of the journal file, in bytes, after executing # the SQL script. Or -1 if the journal is not expected to exist. # $ws: The expected size of the WAL file, in bytes, after executing # the SQL script. Or -1 if the WAL is not expected to exist. # | | | 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 | # $sql: SQL to execute. # $res: Expected result of executing $sql. # $js: The expected size of the journal file, in bytes, after executing # the SQL script. Or -1 if the journal is not expected to exist. # $ws: The expected size of the WAL file, in bytes, after executing # the SQL script. Or -1 if the WAL is not expected to exist. # if {$::sqlite_options(wal) && [wal_is_ok]} { faultsim_delete_and_reopen foreach {tn sql res js ws} [subst { 1 { CREATE TABLE t1(a, b); PRAGMA auto_vacuum=OFF; PRAGMA synchronous=NORMAL; |
︙ | ︙ | |||
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 | 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 }] { do_execsql_test pager1-7.1.$tn.1 $sql $res catch { set J -1 ; set J [file size test.db-journal] } catch { set W -1 ; set W [file size test.db-wal] } do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] } } | > > > | 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 | 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 }] { ifcapable enable_persist_wal { file_control_persist_wal db 0 } do_execsql_test pager1-7.1.$tn.1 $sql $res catch { set J -1 ; set J [file size test.db-journal] } catch { set W -1 ; set W [file size test.db-wal] } do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] } } |
︙ | ︙ | |||
2044 2045 2046 2047 2048 2049 2050 | do_test pager1-20.2.2 { execsql { BEGIN EXCLUSIVE; COMMIT; } } {} | | | 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 | do_test pager1-20.2.2 { execsql { BEGIN EXCLUSIVE; COMMIT; } } {} if {$::sqlite_options(wal) && [wal_is_ok]} { do_test pager1-20.3.1 { faultsim_delete_and_reopen db func a_string a_string execsql { PRAGMA cache_size = 10; PRAGMA journal_mode = wal; BEGIN; |
︙ | ︙ | |||
2079 2080 2081 2082 2083 2084 2085 | #------------------------------------------------------------------------- # Test that a WAL database may not be opened if: # # pager1-21.1.*: The VFS has an iVersion less than 2, or # pager1-21.2.*: The VFS does not provide xShmXXX() methods. # | | | 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 | #------------------------------------------------------------------------- # Test that a WAL database may not be opened if: # # pager1-21.1.*: The VFS has an iVersion less than 2, or # pager1-21.2.*: The VFS does not provide xShmXXX() methods. # if {$::sqlite_options(wal) && [wal_is_ok]} { do_test pager1-21.0 { faultsim_delete_and_reopen execsql { PRAGMA journal_mode = WAL; CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); INSERT INTO ko DEFAULT VALUES; } |
︙ | ︙ | |||
2110 2111 2112 2113 2114 2115 2116 | #------------------------------------------------------------------------- # Test that a "PRAGMA wal_checkpoint": # # pager1-22.1.*: is a no-op on a non-WAL db, and # pager1-22.2.*: does not cause xSync calls with a synchronous=off db. # | < | | | | | | | | | | | | | < | > > > > > > > > > | | < | > | < | | < < < | 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 | #------------------------------------------------------------------------- # Test that a "PRAGMA wal_checkpoint": # # pager1-22.1.*: is a no-op on a non-WAL db, and # pager1-22.2.*: does not cause xSync calls with a synchronous=off db. # do_test pager1-22.1.1 { faultsim_delete_and_reopen execsql { CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); INSERT INTO ko DEFAULT VALUES; } execsql { PRAGMA wal_checkpoint } } {0 -1 -1} do_test pager1-22.2.1 { testvfs tv -default 1 tv filter xSync tv script xSyncCb proc xSyncCb {args} {incr ::synccount} sqlite3 db test.db # Switch the db to WAL mode. And then execute a SELECT to make sure # that the WAL file is open. Note that this may change the synchronous # setting if DEFAULT_WAL_SAFETYLEVEL is defined. execsql { PRAGMA journal_mode = WAL ; SELECT * FROM ko } # Set synchronous=OFF. Insert some data and run a checkpoint. Since # sync=off, this should not cause any calls to the xSync() method. set ::synccount 0 execsql { PRAGMA synchronous = off; INSERT INTO ko DEFAULT VALUES; PRAGMA wal_checkpoint; } set synccount } {0} #------------------------------------------------------------------------- # Tests for changing journal mode. # # pager1-23.1.*: Test that when changing from PERSIST to DELETE mode, # the journal file is deleted. # |
︙ | ︙ | |||
2384 2385 2386 2387 2388 2389 2390 | #------------------------------------------------------------------------- # Test that attempting to open a write-transaction with # locking_mode=exclusive in WAL mode fails if there are other clients on # the same database. # catch { db close } | | | 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 | #------------------------------------------------------------------------- # Test that attempting to open a write-transaction with # locking_mode=exclusive in WAL mode fails if there are other clients on # the same database. # catch { db close } if {$::sqlite_options(wal) && [wal_is_ok]} { do_multiclient_test tn { do_test pager1-28.$tn.1 { sql1 { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('a', 'b'); } |
︙ | ︙ |
Changes to test/pagerfault.test.
︙ | ︙ | |||
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 | sqlite3 db test.db execsql { PRAGMA integrity_check } } {ok} db close } } #------------------------------------------------------------------------- # When a 3.7.0 client opens a write-transaction on a database file that # has been appended to or truncated by a pre-370 client, it updates # the db-size in the file header immediately. This test case provokes # errors during that operation. # | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | sqlite3 db test.db execsql { PRAGMA integrity_check } } {ok} db close } } #------------------------------------------------------------------------- # When a 3.7.0 client opens a write-transaction on a database file that # has been appended to or truncated by a pre-370 client, it updates # the db-size in the file header immediately. This test case provokes # errors during that operation. # do_test pagerfault-22-pre1 { faultsim_delete_and_reopen db func a_string a_string execsql { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; CREATE TABLE t1(a); CREATE INDEX i1 ON t1(a); INSERT INTO t1 VALUES(a_string(3000)); CREATE TABLE t2(a); INSERT INTO t2 VALUES(1); } db close sql36231 { INSERT INTO t1 VALUES(a_string(3000)) } faultsim_save_and_close } {} do_faultsim_test pagerfault-22 -prep { faultsim_restore_and_reopen } -body { execsql { INSERT INTO t2 VALUES(2) } execsql { SELECT * FROM t2 } } -test { faultsim_test_result {0 {1 2}} faultsim_integrity_check } #------------------------------------------------------------------------- # When a 3.7.0 client opens a write-transaction on a database file that # has been appended to or truncated by a pre-370 client, it updates # the db-size in the file header immediately. This test case provokes # errors during that operation. # |
︙ | ︙ |
Changes to test/pcache.test.
︙ | ︙ | |||
113 114 115 116 117 118 119 | pcache_stats } {current 24 max 22 min 20 recyclable 0} # Rolling back the transaction held by db2 at this point releases a pinned # page. Because the number of allocated pages is greater than the # configured maximum, this page should be freed immediately instead of # recycled. | | > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | pcache_stats } {current 24 max 22 min 20 recyclable 0} # Rolling back the transaction held by db2 at this point releases a pinned # page. Because the number of allocated pages is greater than the # configured maximum, this page should be freed immediately instead of # recycled. # Note- purgable_pcache doesn't share caches between connections and these tests # are only useful for testing that feature. if !$::sqlite_options(enable_purgeable_pcache) { do_test pcache-1.8 { execsql {ROLLBACK} db2 pcache_stats } {current 23 max 22 min 20 recyclable 0} do_test pcache-1.9 { execsql COMMIT |
︙ | ︙ | |||
174 175 176 177 178 179 180 | SELECT * FROM t6 ORDER BY a; SELECT * FROM t6; SELECT * FROM t7 ORDER BY a; SELECT * FROM t7; SELECT * FROM t8 ORDER BY a; SELECT * FROM t8; SELECT * FROM t9 ORDER BY a; SELECT * FROM t9; } pcache_stats } {current 14 max 15 min 10 recyclable 14} | > > | > | 176 177 178 179 180 181 182 183 184 185 186 187 | SELECT * FROM t6 ORDER BY a; SELECT * FROM t6; SELECT * FROM t7 ORDER BY a; SELECT * FROM t7; SELECT * FROM t8 ORDER BY a; SELECT * FROM t8; SELECT * FROM t9 ORDER BY a; SELECT * FROM t9; } pcache_stats } {current 14 max 15 min 10 recyclable 14} } else { db2 close } finish_test |
Changes to test/pragma.test.
︙ | ︙ | |||
1526 1527 1528 1529 1530 1531 1532 | } # Reset the sqlite3_temp_directory variable for the next run of tests: sqlite3 dbX :memory: dbX eval {PRAGMA temp_store_directory = ""} dbX close | > | > > > > > > < | | < < | | < > < | < > < | | < > > > < | < > > > < | | | | < > | > > > > > > < | > | > | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 | } # Reset the sqlite3_temp_directory variable for the next run of tests: sqlite3 dbX :memory: dbX eval {PRAGMA temp_store_directory = ""} dbX close set skip_lock_proxy_tests [path_is_dos "."] ifcapable !(lock_proxy_pragmas&&prefer_proxy_locking) { set skip_lock_proxy_tests 1 } if !$skip_lock_proxy_tests { set sqlite_hostid_num 1 set using_proxy 0 foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] { set using_proxy $value } # Test the lock_proxy_file pragmas. # db close set env(SQLITE_FORCE_PROXY_LOCKING) "0" sqlite3 db test.db # set lock proxy name and then query it via pragma interface set lpp [exec mktemp -t "proxy1"] do_test pragma-16.1 { execsql "PRAGMA lock_proxy_file='$lpp'" execsql "select * from sqlite_master" execsql "PRAGMA lock_proxy_file" } $lpp # 2 database connections can share a lock proxy file do_test pragma-16.2 { sqlite3 db2 test.db execsql "PRAGMA lock_proxy_file='$lpp'" db2 } {} db2 close # 2nd database connection should auto-name an existing lock proxy file do_test pragma-16.2.1 { sqlite3 db2 test.db execsql { PRAGMA lock_proxy_file=":auto:"; select * from sqlite_master; } db2 execsql "PRAGMA lock_proxy_file" db2 } $lpp db2 close set lpp2 [exec mktemp -t "proxy2"] # 2nd database connection cannot override the lock proxy file do_test pragma-16.3 { sqlite3 db2 test.db execsql "PRAGMA lock_proxy_file='$lpp2'" db2 catchsql { select * from sqlite_master; } db2 } {1 {database is locked}} set lpp3 [exec mktemp -t "proxy3"] # lock proxy file can be renamed if no other connections are active do_test pragma-16.4 { db2 close db close sqlite3 db2 test.db execsql "PRAGMA lock_proxy_file='$lpp3'" db2 execsql "PRAGMA lock_proxy_file='$lpp2'" db2 execsql "PRAGMA lock_proxy_file" db2 } $lpp2 db2 close set env(SQLITE_FORCE_PROXY_LOCKING) "1" # auto-naming should reuse the last proxy name when available do_test pragma-16.5 { sqlite3 db2 test.db execsql { PRAGMA lock_proxy_file=":auto:"; PRAGMA lock_proxy_file; } db2 } $lpp2 # auto-naming a new proxy should use a predictable & unique name do_test pragma-16.6 { db2 close sqlite3 db2 test2.db set lockpath [execsql { PRAGMA lock_proxy_file=":auto:"; PRAGMA lock_proxy_file; } db2] string match "*test2.db:auto:" $lockpath } {1} set sqlite_hostid_num 2 # db access should be limited to one host at a time (simulate 2nd host id) do_test pragma-16.7 { list [catch { sqlite3 db test2.db execsql { PRAGMA lock_proxy_file=":auto:"; select * from sqlite_master; } } msg] $msg } {1 {database is locked}} db close # default to using proxy locking (simulate network file system detection) do_test pragma-16.8 { list [catch { sqlite3 db test2.db execsql { select * from sqlite_master } } msg] $msg } {1 {database is locked}} db2 close set lpp4 [exec mktemp -t "proxy4"] # check that db is unlocked after first host connection closes do_test pragma-16.8.1 { execsql "PRAGMA lock_proxy_file='$lpp4'" execsql "select * from sqlite_master" execsql "PRAGMA lock_proxy_file" } $lpp4 do_test pragma-16.8.2 { execsql { create table if not exists mine(x); insert into mine values (1); } } {} db close file delete -force proxytest.db file delete -force .proxytest.db-conch do_test pragma-16.9 { sqlite3 db proxytest.db set lockpath2 [execsql { PRAGMA lock_proxy_file=":auto:"; PRAGMA lock_proxy_file; } db] string match "*proxytest.db:auto:" $lockpath2 } {1} # ensure creating directories for a lock proxy file works set lpp5d [exec mktemp -d -t "proxy5"] set lpp5 $lpp5d/sub/dir/lock db close do_test pragma-16.10.1 { sqlite3 db proxytest.db execsql "PRAGMA lock_proxy_file='$lpp5'" set lockpath2 [execsql { PRAGMA lock_proxy_file; } db] string match "*sub/dir/lock" $lockpath2 } {1} # ensure that after deleting the path, setting ":auto:" works correctly db close file delete -force $lpp5d do_test pragma-16.10.2 { sqlite3 db proxytest.db set lockpath3 [execsql { PRAGMA lock_proxy_file=":auto:"; create table if not exists pt(y); PRAGMA lock_proxy_file; } db] string match "*sub/dir/lock" $lockpath3 } {1} # ensure that if the path can not be created (file instead of dir) # setting :auto: deals with it by creating a new autonamed lock file db close file delete -force $lpp5d close [open "$lpp5d" a] do_test pragma-16.10.3 { sqlite3 db proxytest.db set lockpath2 [execsql { PRAGMA lock_proxy_file=":auto:"; create table if not exists zz(y); PRAGMA lock_proxy_file; } db] string match "*proxytest.db:auto:" $lockpath2 } {1} # make sure we can deal with ugly file paths correctly db close file delete -force $lpp5d set lpp6 [exec mktemp -d -t "proxy6"]/./././////./proxytest/../proxytest/sub/dir/lock do_test pragma-16.10.4 { sqlite3 db proxytest.db execsql "PRAGMA lock_proxy_file='$lpp6'" set lockpath4 [execsql { create table if not exists aa(bb); PRAGMA lock_proxy_file; } db] string match "*proxytest/sub/dir/lock" $lockpath4 } {1} # ensure that if the path can not be created (perm), setting :auto: deals db close file delete -force $lpp5d do_test pragma-16.10.5 { sqlite3 db proxytest.db execsql "PRAGMA lock_proxy_file='$lpp5'" execsql { create table if not exists bb(bb); } db close file delete -force $lpp5d file mkdir $lpp5d file attributes $lpp5d -permission 0000 sqlite3 db proxytest.db set lockpath5 [execsql { PRAGMA lock_proxy_file=":auto:"; create table if not exists cc(bb); PRAGMA lock_proxy_file; } db] string match "*proxytest.db:auto:" $lockpath5 } {1} # ensure that if the path can not be created, locking fails db close do_test pragma-16.10.6 { sqlite3 db proxytest.db execsql "PRAGMA lock_proxy_file='$lpp5'" catchsql { create table if not exists faily(y); PRAGMA lock_proxy_file; } db } {1 {database is locked}} db close file attributes $lpp5d -permission 0777 file delete -force $lpp5d set env(SQLITE_FORCE_PROXY_LOCKING) $using_proxy set sqlite_hostid_num 0 } # Parsing of auto_vacuum settings. # |
︙ | ︙ |
Changes to test/pragma4.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | set ::stmt 0 set ::stmt [sqlite3_prepare_v2 db $sql -1 dummy] uplevel [list do_test $tn { sqlite3_column_count $::stmt } $nCol] sqlite3_finalize $::stmt } # If there is no RHS argument, the following PRAGMA statements operate as | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | set ::stmt 0 set ::stmt [sqlite3_prepare_v2 db $sql -1 dummy] uplevel [list do_test $tn { sqlite3_column_count $::stmt } $nCol] sqlite3_finalize $::stmt } # If there is no RHS argument, the following PRAGMA statements operate as # queries, returning a single row containing a single column. # # Or, if there is RHS argument, they return zero rows of zero columns. # foreach {tn sql} { 1 "PRAGMA application_id = 10" 2 "PRAGMA automatic_index = 1" 3 "PRAGMA auto_vacuum = 1" |
︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 20 "PRAGMA query_only = false" 21 "PRAGMA read_uncommitted = true" 22 "PRAGMA recursive_triggers = false" 23 "PRAGMA reverse_unordered_selects = false" 24 "PRAGMA schema_version = 211" 25 "PRAGMA short_column_names = 1" 26 "PRAGMA synchronous = full" 29 "PRAGMA temp_store = memory" 30 "PRAGMA user_version = 405" 31 "PRAGMA writable_schema = 1" } { reset_db # Without RHS: do_pragma_ncol_test 1.$tn.1 [lindex [split $sql =] 0] 1 | > > | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 20 "PRAGMA query_only = false" 21 "PRAGMA read_uncommitted = true" 22 "PRAGMA recursive_triggers = false" 23 "PRAGMA reverse_unordered_selects = false" 24 "PRAGMA schema_version = 211" 25 "PRAGMA short_column_names = 1" 26 "PRAGMA synchronous = full" 27 "PRAGMA temp_store_directory = '/tmp'" 28 "PRAGMA temp_store_directory = ''" 29 "PRAGMA temp_store = memory" 30 "PRAGMA user_version = 405" 31 "PRAGMA writable_schema = 1" } { reset_db # Without RHS: do_pragma_ncol_test 1.$tn.1 [lindex [split $sql =] 0] 1 # With RHS: do_pragma_ncol_test 1.$tn.2 $sql 0 } # These pragmas should never return any values. # foreach {tn sql} { 1 "PRAGMA shrink_memory" 2 "PRAGMA shrink_memory = 10" 3 "PRAGMA case_sensitive_like = 0" 4 "PRAGMA case_sensitive_like = 1" 5 "PRAGMA case_sensitive_like" } { do_pragma_ncol_test 2.$tn.1 $sql 0 } # EXPLAIN on a PRAGMA integrity_check. # Verify that that P4_INTARRAY argument to OP_IntegrityCk is rendered # correctly. # db close |
︙ | ︙ |
Changes to test/rowallock.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 2015-05-28 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing locks on read-only WAL-mode databases. set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set testprefix rowallock set mmap_res 1000000 ifcapable !mmap { set mmap_res 0 } do_multiclient_test tn { | > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 2015-05-28 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing locks on read-only WAL-mode databases. # # Note that the apple-osx branch does not allow read-only WAL-mode # databases (per check-in from Adam Swift on 2011-06-24 20:47:06) and # so this test module is disabled in the apple-osx branch. set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set testprefix rowallock finish_test; return ;# This test module disabled in the apple-osx branch set mmap_res 1000000 ifcapable !mmap { set mmap_res 0 } do_multiclient_test tn { |
︙ | ︙ |
Changes to test/shared.test.
︙ | ︙ | |||
41 42 43 44 45 46 47 | break } } # if we're using proxy locks, we use 2 filedescriptors for a db # that is open but NOT yet locked, after a lock is taken we'll have 3, # normally sqlite uses 1 (proxy locking adds the conch and the local lock) | < < < < | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | break } } # if we're using proxy locks, we use 2 filedescriptors for a db # that is open but NOT yet locked, after a lock is taken we'll have 3, # normally sqlite uses 1 (proxy locking adds the conch and the local lock) set extrafds_prelock 0 set extrafds_postlock 0 if {[forced_proxy_locking]} { set extrafds_prelock 1 set extrafds_postlock 2 } # $av is currently 0 if this loop iteration is to test with auto-vacuum turned # off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum) # and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer |
︙ | ︙ |
Changes to test/shrink.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # the PRAGMA shrink_memory statement. # set testdir [file dirname $argv0] source $testdir/tester.tcl test_set_config_pagecache 0 0 unset -nocomplain baseline do_test shrink-1.1 { db eval { PRAGMA cache_size = 2000; CREATE TABLE t1(x,y); INSERT INTO t1 VALUES(randomblob(1000000),1); } | > > > > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # the PRAGMA shrink_memory statement. # set testdir [file dirname $argv0] source $testdir/tester.tcl test_set_config_pagecache 0 0 # purgeable pcache tracks memory differently ifcapable {enable_purgeable_pcache} { finish_test return } unset -nocomplain baseline do_test shrink-1.1 { db eval { PRAGMA cache_size = 2000; CREATE TABLE t1(x,y); INSERT INTO t1 VALUES(randomblob(1000000),1); } |
︙ | ︙ |
Changes to test/stmt.test.
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | # # This only work if SQLITE_TEMP_STORE!=3 # if {$::TEMP_STORE==3} { finish_test return } do_test stmt-1.2 { set sqlite_open_file_count } {1} do_test stmt-1.3 { execsql { PRAGMA temp_store = file; BEGIN; INSERT INTO t1 VALUES(1, 1); } set sqlite_open_file_count } {2} do_test stmt-1.4 { execsql { INSERT INTO t1 SELECT a+1, b+1 FROM t1; } set sqlite_open_file_count # 2016-03-04: statement-journal open deferred } {2} do_test stmt-1.5 { execsql COMMIT set sqlite_open_file_count } {1} do_test stmt-1.6.1 { execsql { BEGIN; INSERT INTO t1 SELECT a+2, b+2 FROM t1; } set sqlite_open_file_count } {2} do_test stmt-1.6.2 { execsql { INSERT INTO t1 SELECT a+4, b+4 FROM t1 } set sqlite_open_file_count # 2016-03-04: statement-journal open deferred } {2} do_test stmt-1.7 { execsql COMMIT set sqlite_open_file_count } {1} | > > > > > > > > > > > > > > > > > | | | | | | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | # # This only work if SQLITE_TEMP_STORE!=3 # if {$::TEMP_STORE==3} { finish_test return } # if we're using proxy locks, we use 3 filedescriptors for a db # that is open but NOT writing changes, normally # sqlite uses 1 (proxy locking adds the conch and the local lock) set extrafds 0 if {[forced_proxy_locking]} { set extrafds 2 } do_test stmt-1.2 { set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds } {1} do_test stmt-1.3 { execsql { PRAGMA temp_store = file; BEGIN; INSERT INTO t1 VALUES(1, 1); } set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds } {2} do_test stmt-1.4 { execsql { INSERT INTO t1 SELECT a+1, b+1 FROM t1; } set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds # 2016-03-04: statement-journal open deferred } {2} do_test stmt-1.5 { execsql COMMIT set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds } {1} do_test stmt-1.6.1 { execsql { BEGIN; INSERT INTO t1 SELECT a+2, b+2 FROM t1; } set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds } {2} do_test stmt-1.6.2 { execsql { INSERT INTO t1 SELECT a+4, b+4 FROM t1 } set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds # 2016-03-04: statement-journal open deferred } {2} do_test stmt-1.7 { execsql COMMIT set sqlite_open_file_count expr $sqlite_open_file_count-$extrafds } {1} proc filecount {testname sql expected extrafds} { uplevel [list do_test $testname [subst -nocommand { execsql BEGIN execsql { $sql } set ret [set sqlite_open_file_count] execsql ROLLBACK set ret }] [ expr $expected+$extrafds ] ] } filecount stmt-2.1 { INSERT INTO t1 VALUES(9, 9) } 2 $extrafds filecount stmt-2.2 { REPLACE INTO t1 VALUES(9, 9) } 2 $extrafds filecount stmt-2.3 { INSERT INTO t1 SELECT 9, 9 } 2 $extrafds filecount stmt-2.4 { INSERT INTO t1 SELECT 9, 9; INSERT INTO t1 SELECT 10, 10; } 2 $extrafds do_test stmt-2.5 { execsql { CREATE INDEX i1 ON t1(b) } } {} filecount stmt-2.6 { REPLACE INTO t1 VALUES(5, 5); REPLACE INTO t1 VALUES(5, 5); } 2 $extrafds finish_test |
Changes to test/superlock.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set testprefix superlock do_not_use_codec # Test organization: # # 1.*: Test superlock on a rollback database. Test that once the db is | > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl set testprefix superlock do_not_use_codec # Test organization: # # 1.*: Test superlock on a rollback database. Test that once the db is |
︙ | ︙ | |||
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # handler returns 0 before said clients relinquish their locks. # # 6.*: Test that if a superlocked WAL database is overwritten, existing # clients run the recovery to build the new wal-index after the # superlock is released. # # do_execsql_test 1.1 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); PRAGMA journal_mode = DELETE; } {delete} ifcapable !wal { finish_test return } do_test 1.2 { sqlite3demo_superlock unlock test.db } {unlock} do_catchsql_test 1.3 { SELECT * FROM t1 } {1 {database is locked}} do_test 1.4 { unlock } {} do_execsql_test 2.1 { INSERT INTO t1 VALUES(3, 4); PRAGMA journal_mode = WAL; } {wal} do_test 2.2 { sqlite3demo_superlock unlock test.db } {unlock} | > > > > > > > > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | # handler returns 0 before said clients relinquish their locks. # # 6.*: Test that if a superlocked WAL database is overwritten, existing # clients run the recovery to build the new wal-index after the # superlock is released. # # if {[forced_proxy_locking]} { finish_test return } do_execsql_test 1.1 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); PRAGMA journal_mode = DELETE; } {delete} ifcapable !wal { finish_test return } do_test 1.2 { sqlite3demo_superlock unlock test.db } {unlock} do_catchsql_test 1.3 { SELECT * FROM t1 } {1 {database is locked}} do_test 1.4 { unlock } {} ifcapable !wal {finish_test ; return } if { ![wal_is_ok] } { finish_test return } do_execsql_test 2.1 { INSERT INTO t1 VALUES(3, 4); PRAGMA journal_mode = WAL; } {wal} do_test 2.2 { sqlite3demo_superlock unlock test.db } {unlock} |
︙ | ︙ |
Changes to test/tempdb.test.
︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 65 | # Verify that no writes occurred in t1. # do_test tempdb-1.2 { execsql { SELECT * FROM t1 } } {} do_test tempdb-2.1 { # Set $::jrnl_in_memory if the journal file is expected to be in-memory. # Similarly, set $::subj_in_memory if the sub-journal file is expected # to be in memory. These variables are used to calculate the expected # number of open files in the test cases below. # | > > > > > | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | # Verify that no writes occurred in t1. # do_test tempdb-1.2 { execsql { SELECT * FROM t1 } } {} set extrafds 0 if {[forced_proxy_locking]} { set extrafds 2 } do_test tempdb-2.1 { # Set $::jrnl_in_memory if the journal file is expected to be in-memory. # Similarly, set $::subj_in_memory if the sub-journal file is expected # to be in memory. These variables are used to calculate the expected # number of open files in the test cases below. # |
︙ | ︙ | |||
77 78 79 80 81 82 83 | INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); INSERT INTO t2 VALUES(7, 8, 9); INSERT INTO t2 SELECT * FROM t1; } catchsql { INSERT INTO t1 SELECT * FROM t2 } set sqlite_open_file_count | | | | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); INSERT INTO t2 VALUES(7, 8, 9); INSERT INTO t2 SELECT * FROM t1; } catchsql { INSERT INTO t1 SELECT * FROM t2 } set sqlite_open_file_count } [expr 1 + $extrafds + (0==$jrnl_in_memory)] do_test tempdb-2.3 { execsql { PRAGMA temp_store = 'memory'; ROLLBACK; BEGIN; INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); INSERT INTO t2 SELECT * FROM t1; } catchsql { INSERT INTO t1 SELECT * FROM t2 } set sqlite_open_file_count } [expr 1 + $extrafds + (0==$jrnl_in_memory)] finish_test |
Changes to test/tester.tcl.
︙ | ︙ | |||
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | # Update the soft-heap-limit each time this script is run. In that # way if an individual test file changes the soft-heap-limit, it # will be reset at the start of the next test file. # sqlite3_soft_heap_limit64 $cmdlinearg(soft-heap-limit) sqlite3_hard_heap_limit64 $cmdlinearg(hard-heap-limit) # Create a test database # proc reset_db {} { catch {db close} forcedelete test.db forcedelete test.db-journal forcedelete test.db-wal sqlite3 db ./test.db set ::DB [sqlite3_connection_pointer db] if {[info exists ::SETUP_SQL]} { db eval $::SETUP_SQL } } reset_db | > > > > > > > > > > > > > > > > > > > > > > > > > | 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | # Update the soft-heap-limit each time this script is run. In that # way if an individual test file changes the soft-heap-limit, it # will be reset at the start of the next test file. # sqlite3_soft_heap_limit64 $cmdlinearg(soft-heap-limit) sqlite3_hard_heap_limit64 $cmdlinearg(hard-heap-limit) proc forced_proxy_locking {} { if $::sqlite_options(lock_proxy_pragmas)&&$::sqlite_options(prefer_proxy_locking) { set force_proxy_value 0 set force_key "SQLITE_FORCE_PROXY_LOCKING=" foreach {env_pair} [exec env] { if { [string first $force_key $env_pair] == 0} { set force_proxy_value [string range $env_pair [string length $force_key] end] } } if { "$force_proxy_value " == "1 " } { return 1 } } return 0 } # Create a test database # proc reset_db {} { catch {db close} forcedelete test.db forcedelete test.db-journal forcedelete test.db-wal if {[forced_proxy_locking]} { sqlite3 db ./test.db set lock_proxy_path [db eval "PRAGMA lock_proxy_file;"] catch {db close} # puts "deleting $lock_proxy_path" file delete -force $lock_proxy_path file delete -force test.db } sqlite3 db ./test.db set ::DB [sqlite3_connection_pointer db] if {[info exists ::SETUP_SQL]} { db eval $::SETUP_SQL } } reset_db |
︙ | ︙ | |||
1310 1311 1312 1313 1314 1315 1316 | sqlite3_memdebug_log sync memdebug_log_sql leaks.tcl } } if {[info commands vdbe_coverage]!=""} { vdbe_coverage_report } | > | | | > > | | > | 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | sqlite3_memdebug_log sync memdebug_log_sql leaks.tcl } } if {[info commands vdbe_coverage]!=""} { vdbe_coverage_report } catch { foreach f [glob -nocomplain test.db-*-journal] { forcedelete $f } } catch { foreach f [glob -nocomplain test.db-mj*] { forcedelete $f } } exit [expr {$nErr>0}] } proc vdbe_coverage_report {} { puts "Writing vdbe coverage report to vdbe_coverage.txt" set lSrc [list] |
︙ | ︙ | |||
2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 | set perm } proc presql {} { set presql "" catch {set presql $::G(perm:presql)} set presql } proc isquick {} { set ret 0 catch {set ret $::G(isquick)} set ret } | > > > > > > > > > > > > > | 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 | set perm } proc presql {} { set presql "" catch {set presql $::G(perm:presql)} set presql } proc wal_is_ok {} { if { [forced_proxy_locking] } { return 1 } if { ![path_is_local "."] } { return 0 } if { [path_is_dos "."] } { return 0 } return 1 } proc isquick {} { set ret 0 catch {set ret $::G(isquick)} set ret } |
︙ | ︙ |
Changes to test/tkt-2d1a5c67d.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix tkt-2d1a5c67d ifcapable {!vtab} {finish_test; return} if {[wal_is_capable]==0} {finish_test; return} for {set ii 1} {$ii<=10} {incr ii} { do_test tkt-2d1a5c67d.1.$ii { db close forcedelete test.db test.db-wal sqlite3 db test.db db eval "PRAGMA cache_size=$::ii" | > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix tkt-2d1a5c67d ifcapable {!vtab} {finish_test; return} if {[wal_is_capable]==0} {finish_test; return} if {![wal_is_ok]} {finish_test; return} for {set ii 1} {$ii<=10} {incr ii} { do_test tkt-2d1a5c67d.1.$ii { db close forcedelete test.db test.db-wal sqlite3 db test.db db eval "PRAGMA cache_size=$::ii" |
︙ | ︙ |
Changes to test/tkt-313723c356.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl if {![wal_is_capable]} { finish_test ; return } do_execsql_test tkt-313723c356.1 { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); INSERT INTO t1 VALUES(randomblob(400), randomblob(400)); | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl if {![wal_is_capable]} { finish_test ; return } if ![wal_is_ok] { finish_test; return } do_execsql_test tkt-313723c356.1 { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); INSERT INTO t1 VALUES(randomblob(400), randomblob(400)); |
︙ | ︙ |
Changes to test/tkt3457.test.
︙ | ︙ | |||
70 71 72 73 74 75 76 | # permission bits on us # catch { test_syscall install fchmod test_syscall fault 1 1 } | > | | | | | | | | | | | | | | | < | | | | | > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | # permission bits on us # catch { test_syscall install fchmod test_syscall fault 1 1 } if { ![path_is_dos "."] } { do_test tkt3457-1.2 { forcecopy bak.db-journal test.db-journal file attributes test.db-journal -permissions --------- catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} do_test tkt3457-1.3 { forcecopy bak.db-journal test.db-journal file attributes test.db-journal -permissions -w--w--w- catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} do_test tkt3457-1.4 { forcecopy bak.db-journal test.db-journal file attributes test.db-journal -permissions r--r--r-- catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} do_test tkt3457-1.5 { forcecopy bak.db-journal test.db-journal file attributes test.db-journal -permissions rw-rw-rw- catchsql { SELECT * FROM t1 } } {0 {1 2 3 4 5 6}} } # Reenable fchmod catch { test_syscall uninstall test_syscall fault 0 0 } |
︙ | ︙ |
Changes to test/wal.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl set testprefix wal ifcapable !wal {finish_test ; return } test_set_config_pagecache 0 0 proc reopen_db {} { catch { db close } forcedelete test.db test.db-wal test.db-wal-summary sqlite3_wal db test.db } | > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl set testprefix wal ifcapable !wal {finish_test ; return } if { ![wal_is_ok] } { finish_test return } test_set_config_pagecache 0 0 proc reopen_db {} { catch { db close } forcedelete test.db test.db-wal test.db-wal-summary sqlite3_wal db test.db } |
︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 | execsql { COMMIT; SELECT * FROM t1; } } {a b} do_test wal-4.4.1 { db close sqlite3 db test.db db func blob blob list [execsql { SELECT * FROM t1 }] [file size test.db-wal] } {{a b} 0} do_test wal-4.4.2 { execsql { PRAGMA cache_size = 10 } | > > > | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | execsql { COMMIT; SELECT * FROM t1; } } {a b} do_test wal-4.4.1 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close sqlite3 db test.db db func blob blob list [execsql { SELECT * FROM t1 }] [file size test.db-wal] } {{a b} 0} do_test wal-4.4.2 { execsql { PRAGMA cache_size = 10 } |
︙ | ︙ | |||
220 221 222 223 224 225 226 227 228 229 230 231 232 233 | do_test wal-4.4.7 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close do_test wal-4.5.1 { reopen_db db func blob blob execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('a', 'b'); } sqlite3 db test.db | > > > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | do_test wal-4.4.7 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close do_test wal-4.5.1 { reopen_db ifcapable enable_persist_wal { file_control_persist_wal db 0 } db func blob blob execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('a', 'b'); } sqlite3 db test.db |
︙ | ︙ | |||
334 335 336 337 338 339 340 341 342 343 344 345 346 347 | foreach sector {512 4096} { sqlite3_simulate_device -sectorsize $sector foreach pgsz {512 1024 2048 4096} { forcedelete test.db test.db-wal do_test wal-6.$sector.$pgsz.1 { sqlite3 db test.db -vfs devsym execsql " PRAGMA page_size = $pgsz; PRAGMA auto_vacuum = 0; PRAGMA journal_mode = wal; " execsql " CREATE TABLE t1(a, b); | > > > | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | foreach sector {512 4096} { sqlite3_simulate_device -sectorsize $sector foreach pgsz {512 1024 2048 4096} { forcedelete test.db test.db-wal do_test wal-6.$sector.$pgsz.1 { sqlite3 db test.db -vfs devsym ifcapable enable_persist_wal { file_control_persist_wal db 0 } execsql " PRAGMA page_size = $pgsz; PRAGMA auto_vacuum = 0; PRAGMA journal_mode = wal; " execsql " CREATE TABLE t1(a, b); |
︙ | ︙ | |||
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | } } {16 ok} do_test wal-11.8 { execsql { PRAGMA wal_checkpoint } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 37 [wal_file_size 40 1024]] do_test wal-11.9 { db close list [expr [file size test.db]/1024] [log_deleted test.db-wal] } {37 1} sqlite3_wal db test.db # After adding the capability of WAL to overwrite prior uncommitted # frame in the WAL-file with revised content, the size of the WAL file # following cache-spill is smaller. # #set nWal 39 #if {[permutation]!="mmap"} {set nWal 37} #ifcapable !mmap {set nWal 37} set nWal 34 do_test wal-11.10 { execsql { PRAGMA cache_size = 10; BEGIN; INSERT INTO t1 SELECT blob(900) FROM t1; -- 32 SELECT count(*) FROM t1; } | > > > > > > | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | } } {16 ok} do_test wal-11.8 { execsql { PRAGMA wal_checkpoint } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 37 [wal_file_size 40 1024]] do_test wal-11.9 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close list [expr [file size test.db]/1024] [log_deleted test.db-wal] } {37 1} sqlite3_wal db test.db # After adding the capability of WAL to overwrite prior uncommitted # frame in the WAL-file with revised content, the size of the WAL file # following cache-spill is smaller. # #set nWal 39 #if {[permutation]!="mmap"} {set nWal 37} #ifcapable !mmap {set nWal 37} set nWal 34 ifcapable enable_persist_wal { file_control_persist_wal db 0 } do_test wal-11.10 { execsql { PRAGMA cache_size = 10; BEGIN; INSERT INTO t1 SELECT blob(900) FROM t1; -- 32 SELECT count(*) FROM t1; } |
︙ | ︙ | |||
781 782 783 784 785 786 787 788 789 790 791 792 793 794 | CREATE TABLE t1(x, y); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES('A', 1); } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 1 [wal_file_size 5 1024]] do_test wal-12.2 { db close sqlite3 db test.db execsql { PRAGMA synchronous = normal; UPDATE t1 SET y = 0 WHERE x = 'A'; } list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] | > > > | 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 | CREATE TABLE t1(x, y); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES('A', 1); } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 1 [wal_file_size 5 1024]] do_test wal-12.2 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close sqlite3 db test.db execsql { PRAGMA synchronous = normal; UPDATE t1 SET y = 0 WHERE x = 'A'; } list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] |
︙ | ︙ | |||
818 819 820 821 822 823 824 825 826 827 828 829 830 831 | do_test wal-12.6 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3_wal db2 test2.db execsql { SELECT * FROM t2 } db2 } {B 2} db2 close db close #------------------------------------------------------------------------- # Check a fun corruption case has been fixed. # # The problem was that after performing a checkpoint using a connection # that had an out-of-date pager-cache, the next time the connection was | > > > | 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | do_test wal-12.6 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3_wal db2 test2.db execsql { SELECT * FROM t2 } db2 } {B 2} db2 close ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close #------------------------------------------------------------------------- # Check a fun corruption case has been fixed. # # The problem was that after performing a checkpoint using a connection # that had an out-of-date pager-cache, the next time the connection was |
︙ | ︙ | |||
975 976 977 978 979 980 981 982 983 984 | sqlite3 db test.db execsql { ATTACH 'test2.db' AS aux; PRAGMA main.auto_vacuum = 0; PRAGMA aux.auto_vacuum = 0; PRAGMA main.journal_mode = WAL; PRAGMA aux.journal_mode = WAL; PRAGMA main.synchronous = NORMAL; PRAGMA aux.synchronous = NORMAL; } | > > | | 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | sqlite3 db test.db execsql { ATTACH 'test2.db' AS aux; PRAGMA main.auto_vacuum = 0; PRAGMA aux.auto_vacuum = 0; PRAGMA main.journal_mode = WAL; PRAGMA aux.journal_mode = WAL; SELECT count(*) FROM main.sqlite_master, aux.sqlite_master; PRAGMA main.synchronous = NORMAL; PRAGMA aux.synchronous = NORMAL; PRAGMA aux.synchronous = FULL; } } {wal wal 0} do_test wal-16.$tn.2 { execsql { CREATE TABLE main.t1(a, b, PRIMARY KEY(a, b)); CREATE TABLE aux.t2(a, b, PRIMARY KEY(a, b)); INSERT INTO t2 VALUES(1, randomblob(1000)); |
︙ | ︙ | |||
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | do_test wal-17.$tn.1 { execsql { PRAGMA auto_vacuum = 0; PRAGMA page_size = 512; PRAGMA cache_size = -2000; PRAGMA journal_mode = WAL; PRAGMA synchronous = FULL; } execsql { BEGIN; CREATE TABLE t(x); } for {set i 0} {$i<166} {incr i} { | > | 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 | do_test wal-17.$tn.1 { execsql { PRAGMA auto_vacuum = 0; PRAGMA page_size = 512; PRAGMA cache_size = -2000; PRAGMA journal_mode = WAL; SELECT * FROM sqlite_master; PRAGMA synchronous = FULL; } execsql { BEGIN; CREATE TABLE t(x); } for {set i 0} {$i<166} {incr i} { |
︙ | ︙ | |||
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 | do_test wal-19.2 { execsql { INSERT INTO t1 VALUES(5, 6); SELECT * FROM t1; } } {1 2 3 4 5 6} do_test wal-19.3 { db close db2 close file exists test.db-wal } {0} do_test wal-19.4 { # When the bug was present, the following was returning {1 2 3 4} only, # as [db2] had an out-of-date copy of the wal-index header when it was | > > > | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 | do_test wal-19.2 { execsql { INSERT INTO t1 VALUES(5, 6); SELECT * FROM t1; } } {1 2 3 4 5 6} do_test wal-19.3 { ifcapable enable_persist_wal { file_control_persist_wal db2 0 } db close db2 close file exists test.db-wal } {0} do_test wal-19.4 { # When the bug was present, the following was returning {1 2 3 4} only, # as [db2] had an out-of-date copy of the wal-index header when it was |
︙ | ︙ | |||
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 | faultsim_delete_and_reopen execsql { CREATE TABLE t1(a, b); PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } faultsim_save_and_close sqlite3_shutdown test_sqlite3_log [list lappend ::log] set ::log [list] sqlite3 db test.db execsql { SELECT * FROM t1 } | > > > | 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 | faultsim_delete_and_reopen execsql { CREATE TABLE t1(a, b); PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } ifcapable enable_persist_wal { file_control_persist_wal db 0 } faultsim_save_and_close sqlite3_shutdown test_sqlite3_log [list lappend ::log] set ::log [list] sqlite3 db test.db execsql { SELECT * FROM t1 } |
︙ | ︙ | |||
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 | INSERT INTO t1 VALUES(randomblob(5000)); INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; } {wal} do_test 24.2 { execsql { DELETE FROM t1; PRAGMA wal_checkpoint; } db close sqlite3 db test.db file exists test.db-wal | > > > | 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 | INSERT INTO t1 VALUES(randomblob(5000)); INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; } {wal} do_test 24.2 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } execsql { DELETE FROM t1; PRAGMA wal_checkpoint; } db close sqlite3 db test.db file exists test.db-wal |
︙ | ︙ | |||
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 | # It would be two frames (the new root page and a padding frame) if the # ZERO_DAMAGE flag were not set. do_test 24.5 { file size test.db-wal } [wal_file_size 1 1024] } db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize # Make sure PRAGMA journal_mode=WAL works with ATTACHED databases in # all journal modes. | > > > | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 | # It would be two frames (the new root page and a padding frame) if the # ZERO_DAMAGE flag were not set. do_test 24.5 { file size test.db-wal } [wal_file_size 1 1024] } ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize # Make sure PRAGMA journal_mode=WAL works with ATTACHED databases in # all journal modes. |
︙ | ︙ |
Changes to test/wal2.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl set testprefix wal2 ifcapable !wal {finish_test ; return } set sqlite_sync_count 0 proc cond_incr_sync_count {adj} { global sqlite_sync_count if {$::tcl_platform(platform) == "windows"} { incr sqlite_sync_count $adj } { | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl set testprefix wal2 ifcapable !wal {finish_test ; return } if ![wal_is_ok] {finish_test ; return } set sqlite_sync_count 0 proc cond_incr_sync_count {adj} { global sqlite_sync_count if {$::tcl_platform(platform) == "windows"} { incr sqlite_sync_count $adj } { |
︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 | proc incr_tvfs_hdr {file idx incrval} { set ints [set_tvfs_hdr $file] set v [lindex $ints $idx] incr v $incrval lset ints $idx $v set_tvfs_hdr $file $ints } #------------------------------------------------------------------------- # Test case wal2-1.*: # # Set up a small database containing a single table. The database is not # checkpointed during the test - all content resides in the log file. | > > > > > > > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | proc incr_tvfs_hdr {file idx incrval} { set ints [set_tvfs_hdr $file] set v [lindex $ints $idx] incr v $incrval lset ints $idx $v set_tvfs_hdr $file $ints } set shmpath test.db-shm if {[forced_proxy_locking]} { sqlite3 db test.db set shmpath [execsql { pragma lock_proxy_file }]-shm db close } #------------------------------------------------------------------------- # Test case wal2-1.*: # # Set up a small database containing a single table. The database is not # checkpointed during the test - all content resides in the log file. |
︙ | ︙ | |||
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | INSERT INTO t1 VALUES('Chico'); INSERT INTO t1 VALUES('Harpo'); COMMIT; } list [file exists test.db-wal] [file exists test.db-journal] } {1 0} do_test wal2-6.3.2 { execsql { PRAGMA journal_mode = DELETE } file exists test.db-wal } {0} do_test wal2-6.3.3 { execsql { PRAGMA lock_status } } {main exclusive temp closed} do_test wal2-6.3.4 { execsql { BEGIN; INSERT INTO t1 VALUES('Groucho'); | > > > > > > | 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | INSERT INTO t1 VALUES('Chico'); INSERT INTO t1 VALUES('Harpo'); COMMIT; } list [file exists test.db-wal] [file exists test.db-journal] } {1 0} do_test wal2-6.3.2 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } execsql { PRAGMA journal_mode = DELETE } file exists test.db-wal } {0} do_test wal2-6.3.2.1 { execsql { PRAGMA journal_mode; } } {delete} do_test wal2-6.3.3 { execsql { PRAGMA lock_status } } {main exclusive temp closed} do_test wal2-6.3.4 { execsql { BEGIN; INSERT INTO t1 VALUES('Groucho'); |
︙ | ︙ | |||
726 727 728 729 730 731 732 | if {[string match {#*} $sq]==0} {append S "$sq\n"} } set ::locks [list] do_test wal2-6.4.$tn.1 { execsql $S } $res do_test wal2-6.4.$tn.2 { set ::locks } $L } | > > | | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | if {[string match {#*} $sq]==0} {append S "$sq\n"} } set ::locks [list] do_test wal2-6.4.$tn.1 { execsql $S } $res do_test wal2-6.4.$tn.2 { set ::locks } $L } ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close tvfs delete do_test wal2-6.5.1 { sqlite3 db test.db execsql { PRAGMA auto_vacuum = 0; |
︙ | ︙ | |||
957 958 959 960 961 962 963 964 965 966 967 968 969 970 | execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } faultsim_save_and_close } {} do_test wal2-10.1.2 { faultsim_restore_and_reopen execsql { SELECT * FROM t1 } } {1 2 3 4} do_test wal2-10.1.3 { | > > > | 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 | execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } if {[forced_proxy_locking]} { forcecopy $shmpath sv_test.db-shm } faultsim_save_and_close } {} do_test wal2-10.1.2 { faultsim_restore_and_reopen execsql { SELECT * FROM t1 } } {1 2 3 4} do_test wal2-10.1.3 { |
︙ | ︙ | |||
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | #------------------------------------------------------------------------- # If a connection is required to create a WAL or SHM file, it creates # the new files with the same file-system permissions as the database # file itself. Test this. # if {$::tcl_platform(platform) == "unix"} { faultsim_delete_and_reopen # Changed on 2012-02-13: umask is deliberately ignored for -wal files. #set umask [exec /bin/sh -c umask] set umask 0 do_test wal2-12.1 { sqlite3 db test.db execsql { CREATE TABLE tx(y, z); PRAGMA journal_mode = WAL; } db close | > > > > > | | | | > > > | | > > > > | > > > > > > | | > > > > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 | #------------------------------------------------------------------------- # If a connection is required to create a WAL or SHM file, it creates # the new files with the same file-system permissions as the database # file itself. Test this. # if {$::tcl_platform(platform) == "unix"} { if {[forced_proxy_locking]} { # faultsim_delete_and_reopen doesn't know about the shm file redirect... forcedelete $shmpath } faultsim_delete_and_reopen # Changed on 2012-02-13: umask is deliberately ignored for -wal files. #set umask [exec /bin/sh -c umask] set umask 0 do_test wal2-12.1 { sqlite3 db test.db execsql { CREATE TABLE tx(y, z); PRAGMA journal_mode = WAL; } db close list [file exists test.db-wal] [file exists $shmpath] } {0 0} foreach {tn permissions} { 1 00644 2 00666 3 00600 4 00755 } { set effective [format %.5o [expr $permissions & ~$umask]] do_test wal2-12.2.$tn.1 { file attributes test.db -permissions $permissions string map {o 0} [file attributes test.db -permissions] } $permissions do_test wal2-12.2.$tn.2 { list [file exists test.db-wal] [file exists $shmpath] } {0 0} do_test wal2-12.2.$tn.3 { sqlite3 db test.db execsql { INSERT INTO tx DEFAULT VALUES } list [file exists test.db-wal] [file exists $shmpath] } {1 1} do_test wal2-12.2.$tn.4 { set x [list [file attr test.db-wal -perm] [file attr $shmpath -perm]] string map {o 0} $x } [list $effective $effective] do_test wal2-12.2.$tn.5 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close list [file exists test.db-wal] [file exists $shmpath] } {0 0} } } #------------------------------------------------------------------------- # Test the libraries response to discovering that one or more of the # database, wal or shm files cannot be opened, or can only be opened # read-only. # if {$::tcl_platform(platform) == "unix"} { proc perm {} { set L [list] foreach f {test.db test.db-wal $shmpath} { if {[file exists $f]} { lappend L [file attr $f -perm] } else { lappend L {} } } set L } if {[forced_proxy_locking]} { # faultsim_delete_and_reopen doesn't know about the shm file redirect... forcedelete $shmpath } faultsim_delete_and_reopen execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES('3.14', '2.72'); } do_test wal2-13.1.1 { list [file exists $shmpath] [file exists test.db-wal] } {1 1} if {[forced_proxy_locking]} { forcecopy $shmpath proxysv_test.db-shm } faultsim_save_and_close foreach {tn db_perm wal_perm shm_perm can_open can_read can_write} { 2 00644 00644 00644 1 1 1 3 00644 00400 00644 1 1 0 4 00644 00644 00400 1 1 0 5 00400 00644 00644 1 1 0 7 00644 00000 00644 1 0 0 8 00644 00644 00000 1 0 0 9 00000 00644 00644 0 0 0 } { faultsim_restore if {[forced_proxy_locking]} { forcecopy proxysv_test.db-shm $shmpath } do_test wal2-13.$tn.1 { file attr test.db -perm $db_perm file attr test.db-wal -perm $wal_perm file attr $shmpath -perm $shm_perm set L [file attr test.db -perm] lappend L [file attr test.db-wal -perm] lappend L [file attr $shmpath -perm] string map {o 0} $L } [list $db_perm $wal_perm $shm_perm] # If $can_open is true, then it should be possible to open a database # handle. Otherwise, if $can_open is 0, attempting to open the db # handle throws an "unable to open database file" exception. # set r(1) {0 ok} set r(0) {1 {unable to open database file}} do_test wal2-13.$tn.2 { list [catch {sqlite3 db test.db ; set {} ok} msg] $msg } $r($can_open) if {$can_open} { # Different behavior, because Darwin does an access() call prior # to attempting to open the SHM in read/write mode and demotes to # read-only if the SHM is read-only. if {$tn==4 && $::tcl_platform(os)=="Darwin"} {set can_read 1} # If $can_read is true, then the client should be able to read from # the database file. If $can_read is false, attempting to read should # throw the "unable to open database file" exception. # set a(0) {1 {unable to open database file}} set a(1) {0 {3.14 2.72}} |
︙ | ︙ | |||
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 | execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;} execsql $sql do_execsql_test wal2-14.$tn.0 { PRAGMA page_size = 4096 } {} do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal} set sqlite_sync_count 0 set sqlite_fullsync_count 0 do_execsql_test wal2-14.$tn.2 { PRAGMA wal_autocheckpoint = 10; CREATE TABLE t1(a, b); -- 2 wal syncs INSERT INTO t1 VALUES(1, 2); -- 2 wal sync PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync BEGIN; INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); COMMIT; -- 2 wal sync PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync } {10 0 3 3 0 1 1} do_test wal2-14.$tn.3 { cond_incr_sync_count 1 list $sqlite_sync_count $sqlite_fullsync_count | > > | | | | 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;} execsql $sql do_execsql_test wal2-14.$tn.0 { PRAGMA page_size = 4096 } {} do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal} set sqlite_sync_count 0 set sqlite_fullsync_count 0 set useres $reslist do_execsql_test wal2-14.$tn.2 { PRAGMA wal_autocheckpoint = 10; CREATE TABLE t1(a, b); -- 2 wal syncs INSERT INTO t1 VALUES(1, 2); -- 2 wal sync PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync BEGIN; INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); COMMIT; -- 2 wal sync PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync } {10 0 3 3 0 1 1} do_test wal2-14.$tn.3 { cond_incr_sync_count 1 list $sqlite_sync_count $sqlite_fullsync_count } [lrange $useres 0 1] set sqlite_sync_count 0 set sqlite_fullsync_count 0 do_test wal2-14.$tn.4 { execsql { INSERT INTO t1 VALUES(7, zeroblob(12*4096)) } list $sqlite_sync_count $sqlite_fullsync_count } [lrange $useres 2 3] set sqlite_sync_count 0 set sqlite_fullsync_count 0 do_test wal2-14.$tn.5 { execsql { PRAGMA wal_autocheckpoint = 1000 } execsql { INSERT INTO t1 VALUES(9, 10) } execsql { INSERT INTO t1 VALUES(11, 12) } execsql { INSERT INTO t1 VALUES(13, 14) } db close list $sqlite_sync_count $sqlite_fullsync_count } [lrange $useres 4 5] } catch { db close } # PRAGMA checkpoint_fullsync # PRAGMA fullfsync # PRAGMA synchronous |
︙ | ︙ |
Changes to test/wal3.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } set a_string_counter 1 proc a_string {n} { global a_string_counter incr a_string_counter string range [string repeat "${a_string_counter}." $n] 1 $n } | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] {finish_test ; return } set a_string_counter 1 proc a_string {n} { global a_string_counter incr a_string_counter string range [string repeat "${a_string_counter}." $n] 1 $n } |
︙ | ︙ | |||
207 208 209 210 211 212 213 214 215 216 217 218 219 220 | {test.db-wal normal test.db-wal normal test.db-wal normal test.db normal} } { proc sync_counter {args} { foreach {method filename id flags} $args break lappend ::syncs [file tail $filename] $flags } do_test wal3-3.$tn { forcedelete test.db test.db-wal test.db-journal testvfs T T filter {} T script sync_counter sqlite3 db test.db -vfs T | > > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | {test.db-wal normal test.db-wal normal test.db-wal normal test.db normal} } { proc sync_counter {args} { foreach {method filename id flags} $args break lappend ::syncs [file tail $filename] $flags } set usecount $synccount do_test wal3-3.$tn { forcedelete test.db test.db-wal test.db-journal testvfs T T filter {} T script sync_counter sqlite3 db test.db -vfs T |
︙ | ︙ | |||
229 230 231 232 233 234 235 | execsql { CREATE TABLE x(y); INSERT INTO x VALUES('z'); PRAGMA wal_checkpoint; } T filter {} set ::syncs | | | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | execsql { CREATE TABLE x(y); INSERT INTO x VALUES('z'); PRAGMA wal_checkpoint; } T filter {} set ::syncs } $usecount db close T delete } #------------------------------------------------------------------------- |
︙ | ︙ |
Changes to test/wal4.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # result in database corruption # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } do_test wal4-1.1 { execsql { PRAGMA journal_mode=WAL; CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); | > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # result in database corruption # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } if { ![wal_is_ok] || [path_is_dos "."]} { finish_test return } do_test wal4-1.1 { execsql { PRAGMA journal_mode=WAL; CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); |
︙ | ︙ |
Changes to test/wal5.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } do_not_use_codec set testprefix wal5 proc db_page_count {{file test.db}} { expr [file size $file] / 1024 } proc wal_page_count {{file test.db}} { wal_frame_count ${file}-wal 1024 } | > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } do_not_use_codec set testprefix wal5 proc db_page_count {{file test.db}} { expr [file size $file] / 1024 } proc wal_page_count {{file test.db}} { wal_frame_count ${file}-wal 1024 } |
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | proc busyhandler {n} { incr ::nBusyHandler eval $::busy_handler_script return 0 } proc reopen_all {} { code1 {db close} code2 {db2 close} code3 {db3 close} code1 {sqlite3 db test.db} code2 {sqlite3 db2 test.db} code3 {sqlite3 db3 test.db} | > > > > > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | proc busyhandler {n} { incr ::nBusyHandler eval $::busy_handler_script return 0 } proc reopen_all {} { ifcapable enable_persist_wal { code1 { file_control_persist_wal db 0 } code2 { file_control_persist_wal db2 0 } code3 { file_control_persist_wal db3 0 } } code1 {db close} code2 {db2 close} code3 {db3 close} code1 {sqlite3 db test.db} code2 {sqlite3 db2 test.db} code3 {sqlite3 db3 test.db} |
︙ | ︙ | |||
339 340 341 342 343 344 345 346 347 348 349 350 351 352 | do_test 3.$tn.2 { code2 { do_wal_checkpoint db2 } } {0 2 2} do_test 3.$tn.3 { code2 { do_wal_checkpoint db2 } } {0 2 2} do_test 3.$tn.4 { code3 { do_wal_checkpoint db3 } } {0 2 2} code1 {db close} code2 {db2 close} code3 {db3 close} code1 {sqlite3 db test.db} code2 {sqlite3 db2 test.db} code3 {sqlite3 db3 test.db} | > > > > > | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | do_test 3.$tn.2 { code2 { do_wal_checkpoint db2 } } {0 2 2} do_test 3.$tn.3 { code2 { do_wal_checkpoint db2 } } {0 2 2} do_test 3.$tn.4 { code3 { do_wal_checkpoint db3 } } {0 2 2} ifcapable enable_persist_wal { code1 { file_control_persist_wal db 0 } code2 { file_control_persist_wal db2 0 } code3 { file_control_persist_wal db3 0 } } code1 {db close} code2 {db2 close} code3 {db3 close} code1 {sqlite3 db test.db} code2 {sqlite3 db2 test.db} code3 {sqlite3 db3 test.db} |
︙ | ︙ |
Changes to test/wal6.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | set testdir [file dirname $argv0] set testprefix wal6 source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } #------------------------------------------------------------------------- # Changing to WAL mode in one connection forces the change in others. # db close forcedelete test.db | > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | set testdir [file dirname $argv0] set testprefix wal6 source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } if { ![wal_is_ok] } {finish_test ; return } #------------------------------------------------------------------------- # Changing to WAL mode in one connection forces the change in others. # db close forcedelete test.db |
︙ | ︙ |
Changes to test/wal7.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # focus of this file is testing the PRAGMA journal_size_limit when # in WAL mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } # Case 1: No size limit. Journal can get large. # do_test wal7-1.0 { db close forcedelete test.db sqlite3 db test.db | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # focus of this file is testing the PRAGMA journal_size_limit when # in WAL mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } # Case 1: No size limit. Journal can get large. # do_test wal7-1.0 { db close forcedelete test.db sqlite3 db test.db |
︙ | ︙ |
Changes to test/wal8.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # size from the database file as soon as it is opened (even before the # first read transaction is executed), and the "PRAGMA page_size = XXX" # is a no-op. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix wal8 ifcapable !wal {finish_test ; return } do_not_use_codec db close forcedelete test.db test.db-wal sqlite3 db test.db sqlite3 db2 test.db | > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # size from the database file as soon as it is opened (even before the # first read transaction is executed), and the "PRAGMA page_size = XXX" # is a no-op. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix wal8 ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } do_not_use_codec db close forcedelete test.db test.db-wal sqlite3 db test.db sqlite3 db2 test.db |
︙ | ︙ |
Changes to test/wal_common.tcl.
︙ | ︙ | |||
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | upvar $ckv1 c1 upvar $ckv2 c2 foreach {v1 v2} $intlist { set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}] set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}] } } # This proc calculates checksums in the same way as those used by SQLite # in WAL files. If the $endian argument is "big", then checksums are # calculated by interpreting data as an array of big-endian integers. If # it is "little", data is interpreted as an array of little-endian integers. # | > > > > > > > > > > > > > > | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | upvar $ckv1 c1 upvar $ckv2 c2 foreach {v1 v2} $intlist { set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}] set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}] } } # If the synchronous mode for the main database of db handle $db # is either OFF or NORMAL, return $nRight. Otherwise, if it is # FULL, return $nWrite+$nTrans. # proc wal_frames {db nWrite nTrans} { set nRet $nWrite switch -- [$db one {PRAGMA main.synchronous}] { 0 { } 1 { } default { incr nRet $nTrans } } set nRet } # This proc calculates checksums in the same way as those used by SQLite # in WAL files. If the $endian argument is "big", then checksums are # calculated by interpreting data as an array of big-endian integers. If # it is "little", data is interpreted as an array of little-endian integers. # |
︙ | ︙ |
Changes to test/walbak.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | source $testdir/tester.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl do_not_use_codec ifcapable !wal {finish_test ; return } # Test organization: # # walback-1.*: Simple tests. # # walback-2.*: Test backups when the source db is modified mid-backup. | > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | source $testdir/tester.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl do_not_use_codec ifcapable !wal {finish_test ; return } if { ![wal_is_ok] } { finish_test ; return } # Test organization: # # walback-1.*: Simple tests. # # walback-2.*: Test backups when the source db is modified mid-backup. |
︙ | ︙ | |||
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | catch { db close } catch { db2 close } forcedelete test.db test.db2 do_test walbak-4.$tn.1 { sqlite3 db test.db db eval "PRAGMA journal_mode = $src" db eval { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('I', 'II'); INSERT INTO t1 VALUES('III', 'IV'); } sqlite3 db2 test.db2 db2 eval "PRAGMA journal_mode = $dest" db2 eval { CREATE TABLE t2(x, y); INSERT INTO t2 VALUES('1', '2'); INSERT INTO t2 VALUES('3', '4'); } } {} | > > > > > > | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | catch { db close } catch { db2 close } forcedelete test.db test.db2 do_test walbak-4.$tn.1 { sqlite3 db test.db db eval "PRAGMA journal_mode = $src" ifcapable enable_persist_wal { file_control_persist_wal db 0 } db eval { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('I', 'II'); INSERT INTO t1 VALUES('III', 'IV'); } sqlite3 db2 test.db2 db2 eval "PRAGMA journal_mode = $dest" ifcapable enable_persist_wal { file_control_persist_wal db2 0 } db2 eval { CREATE TABLE t2(x, y); INSERT INTO t2 VALUES('1', '2'); INSERT INTO t2 VALUES('3', '4'); } } {} |
︙ | ︙ |
Changes to test/walbig.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal { finish_test return } # Do not use a codec for this file, as the database is manipulated using # external methods (the [fake_big_file] and [hexio_write] commands). # do_not_use_codec # If SQLITE_DISABLE_LFS is defined, omit this file. ifcapable !lfs { finish_test return } set a_string_counter 1 proc a_string {n} { incr ::a_string_counter string range [string repeat "${::a_string_counter}." $n] 1 $n } | > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal { finish_test return } if ![wal_is_ok] { finish_test; return } # Do not use a codec for this file, as the database is manipulated using # external methods (the [fake_big_file] and [hexio_write] commands). # do_not_use_codec # If SQLITE_DISABLE_LFS is defined, omit this file. ifcapable !lfs { finish_test return } if { ![wal_is_ok] } { finish_test return } set a_string_counter 1 proc a_string {n} { incr ::a_string_counter string range [string repeat "${::a_string_counter}." $n] 1 $n } |
︙ | ︙ |
Changes to test/walcksum.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } # Read and return the contents of file $filename. Treat the content as # binary data. # proc readfile {filename} { set fd [open $filename] fconfigure $fd -encoding binary | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } # Read and return the contents of file $filename. Treat the content as # binary data. # proc readfile {filename} { set fd [open $filename] fconfigure $fd -encoding binary |
︙ | ︙ |
Changes to test/walcrash.test.
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # walcrash-3.*: Recover multiple databases where the failed transaction # was a multi-file transaction. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } db close set seed 0 set REPEATS 100 # walcrash-1.* | > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # walcrash-3.*: Recover multiple databases where the failed transaction # was a multi-file transaction. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } db close set seed 0 set REPEATS 100 # walcrash-1.* |
︙ | ︙ |
Changes to test/walcrash2.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } #------------------------------------------------------------------------- # This test case demonstrates a flaw in the wal-index manipulation that # existed at one point: If a process crashes mid-transaction, it may have # already added some entries to one of the hash-tables in the wal-index. # If the transaction were to be explicitly rolled back at this point, the | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } if { ![wal_is_ok] } { finish_test ; return } #------------------------------------------------------------------------- # This test case demonstrates a flaw in the wal-index manipulation that # existed at one point: If a process crashes mid-transaction, it may have # already added some entries to one of the hash-tables in the wal-index. # If the transaction were to be explicitly rolled back at this point, the |
︙ | ︙ |
Changes to test/walcrash3.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # truncates the WAL file if "PRAGMA journal_size_limit" is configured. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } set testprefix walcrash3 db close testvfs tvfs tvfs filter {xTruncate xWrite} tvfs script tvfs_callback proc tvfs_callback {args} {} | > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # truncates the WAL file if "PRAGMA journal_size_limit" is configured. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } set testprefix walcrash3 db close testvfs tvfs tvfs filter {xTruncate xWrite} tvfs script tvfs_callback proc tvfs_callback {args} {} |
︙ | ︙ |
Changes to test/walfault.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } #------------------------------------------------------------------------- # This test case, walfault-1-*, simulates faults while executing a # # PRAGMA journal_mode = WAL; # # statement immediately after creating a new database. | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } #------------------------------------------------------------------------- # This test case, walfault-1-*, simulates faults while executing a # # PRAGMA journal_mode = WAL; # # statement immediately after creating a new database. |
︙ | ︙ |
Changes to test/walhook.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } set ::wal_hook [list] proc wal_hook {zDb nEntry} { lappend ::wal_hook $zDb $nEntry return 0 } db wal_hook wal_hook | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } set ::wal_hook [list] proc wal_hook {zDb nEntry} { lappend ::wal_hook $zDb $nEntry return 0 } db wal_hook wal_hook |
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | return 0 } execsql { CREATE TABLE t3(a PRIMARY KEY, b) } file size test.db } [expr 6*1024] db2 close db close sqlite3 db test.db do_test walhook-2.1 { execsql { PRAGMA synchronous = NORMAL } execsql { PRAGMA wal_autocheckpoint } } {1000} do_test walhook-2.2 { execsql { PRAGMA wal_autocheckpoint = 10} } {10} | > > > > > > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | return 0 } execsql { CREATE TABLE t3(a PRIMARY KEY, b) } file size test.db } [expr 6*1024] db2 close ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close sqlite3 db test.db ifcapable enable_persist_wal { file_control_persist_wal db 0 } do_test walhook-2.1 { execsql { PRAGMA synchronous = NORMAL } execsql { PRAGMA wal_autocheckpoint } } {1000} do_test walhook-2.2 { execsql { PRAGMA wal_autocheckpoint = 10} } {10} |
︙ | ︙ |
Changes to test/walmode.test.
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | do_test walmode-0.3 { execsql { PRAGMA main.journal_mode } } {delete} finish_test return } do_test walmode-1.1 { set sqlite_sync_count 0 execsql { PRAGMA page_size = 1024 } execsql { PRAGMA journal_mode = wal } } {wal} do_test walmode-1.2 { file size test.db } {1024} | > > > > > > > > > > > > > > | > > > > > > | > | | | < > > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | do_test walmode-0.3 { execsql { PRAGMA main.journal_mode } } {delete} finish_test return } if { ![wal_is_ok] && ![path_is_dos "."]} { do_test walmode-0.1 { execsql { PRAGMA journal_mode = wal } } {delete} do_test walmode-0.2 { execsql { PRAGMA main.journal_mode = wal } } {delete} do_test walmode-0.3 { execsql { PRAGMA main.journal_mode } } {delete} finish_test return } do_test walmode-1.1 { set sqlite_sync_count 0 execsql { PRAGMA page_size = 1024 } execsql { PRAGMA journal_mode = wal } } {wal} do_test walmode-1.2 { file size test.db } {1024} # Determine how many sync() calls to expect from the "journal_mode=WAL" # command above. Note that if DEFAULT_WAL_SAFETYLEVEL is defined, the # safety-level may have been modified while compiling the "journal_mode=WAL" # statement. switch -- [db eval {PRAGMA main.synchronous}] { 0 { set expected_sync_count 0 } 1 { set expected_sync_count 2 } default { set expected_sync_count 3 } } if {$::tcl_platform(platform)!="windows"} { ifcapable dirsync { incr expected_sync_count } do_test walmode-1.3 { set sqlite_sync_count } $expected_sync_count } do_test walmode-1.4 { file exists test.db-wal } {0} do_test walmode-1.5 { execsql { CREATE TABLE t1(a, b) } file size test.db } {1024} do_test walmode-1.6 { file exists test.db-wal } {1} do_test walmode-1.7 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close file exists test.db-wal } {0} # There is now a database file with the read and write versions set to 2 # in the file system. This file should default to WAL mode. # do_test walmode-2.1 { sqlite3 db test.db file exists test.db-wal } {0} do_test walmode-2.2 { execsql { SELECT * FROM sqlite_master } file exists test.db-wal } {1} do_test walmode-2.3 { ifcapable enable_persist_wal { file_control_persist_wal db 0 } db close file exists test.db-wal } {0} # If the first statement executed is "PRAGMA journal_mode = wal", and # the file is already configured for WAL (read and write versions set # to 2), then there should be no need to write the database. The |
︙ | ︙ | |||
102 103 104 105 106 107 108 109 110 111 112 113 114 115 | list $sqlite_sync_count [file exists test.db-wal] [file size test.db-wal] } {0 1 0} # Test that changing back to journal_mode=persist works. # do_test walmode-4.1 { execsql { INSERT INTO t1 VALUES(1, 2) } execsql { PRAGMA journal_mode = persist } } {persist} if {[atomic_batch_write test.db]==0} { do_test walmode-4.2 { list [file exists test.db-journal] [file exists test.db-wal] } {1 0} } | > > > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | list $sqlite_sync_count [file exists test.db-wal] [file size test.db-wal] } {0 1 0} # Test that changing back to journal_mode=persist works. # do_test walmode-4.1 { execsql { INSERT INTO t1 VALUES(1, 2) } ifcapable enable_persist_wal { file_control_persist_wal db 0 } execsql { PRAGMA journal_mode = persist } } {persist} if {[atomic_batch_write test.db]==0} { do_test walmode-4.2 { list [file exists test.db-journal] [file exists test.db-wal] } {1 0} } |
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | # Test that nothing goes wrong if a connection is prevented from changing # from WAL to rollback mode because a second connection has the database # open. Or from rollback to WAL. # do_test walmode-4.6 { sqlite3 db2 test.db execsql { PRAGMA main.journal_mode } db2 } {delete} do_test walmode-4.7 { execsql { PRAGMA main.journal_mode = wal } db } {wal} do_test walmode-4.8 { execsql { SELECT * FROM t1 } db2 } {1 2} do_test walmode-4.9 { catchsql { PRAGMA journal_mode = delete } db } {1 {database is locked}} do_test walmode-4.10 { execsql { PRAGMA main.journal_mode } db } {wal} do_test walmode-4.11 { db2 close execsql { PRAGMA journal_mode = delete } db } {delete} do_test walmode-4.12 { execsql { PRAGMA main.journal_mode } db } {delete} do_test walmode-4.13 { list [file exists test.db-journal] [file exists test.db-wal] | > > > > > > | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | # Test that nothing goes wrong if a connection is prevented from changing # from WAL to rollback mode because a second connection has the database # open. Or from rollback to WAL. # do_test walmode-4.6 { sqlite3 db2 test.db ifcapable enable_persist_wal { file_control_persist_wal db2 0 } execsql { PRAGMA main.journal_mode } db2 } {delete} do_test walmode-4.7 { execsql { PRAGMA main.journal_mode = wal } db } {wal} do_test walmode-4.8 { execsql { SELECT * FROM t1 } db2 } {1 2} do_test walmode-4.9 { catchsql { PRAGMA journal_mode = delete } db } {1 {database is locked}} do_test walmode-4.10 { execsql { PRAGMA main.journal_mode } db } {wal} do_test walmode-4.11 { db2 close ifcapable enable_persist_wal { file_control_persist_wal db 0 } execsql { PRAGMA journal_mode = delete } db } {delete} do_test walmode-4.12 { execsql { PRAGMA main.journal_mode } db } {delete} do_test walmode-4.13 { list [file exists test.db-journal] [file exists test.db-wal] |
︙ | ︙ | |||
299 300 301 302 303 304 305 306 307 308 309 310 311 312 | # Test the effect of a "PRAGMA journal_mode" command being the first # thing executed by a new connection. This means that the schema is not # loaded when sqlite3_prepare_v2() is called to compile the statement. # do_test walmode-7.0 { forcedelete test.db sqlite3 db test.db execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); } } {wal} foreach {tn sql result} { 1 "PRAGMA journal_mode" wal | > > > | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | # Test the effect of a "PRAGMA journal_mode" command being the first # thing executed by a new connection. This means that the schema is not # loaded when sqlite3_prepare_v2() is called to compile the statement. # do_test walmode-7.0 { forcedelete test.db sqlite3 db test.db ifcapable enable_persist_wal { file_control_persist_wal db 0 } execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); } } {wal} foreach {tn sql result} { 1 "PRAGMA journal_mode" wal |
︙ | ︙ |
Changes to test/walnoshm.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # using the xShm primitives if the connection is in exclusive-mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix walnoshm ifcapable !wal {finish_test ; return } db close testvfs tvfsshm testvfs tvfs -default 1 -iversion 1 sqlite3 db test.db #-------------------------------------------------------------------------- | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # using the xShm primitives if the connection is in exclusive-mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix walnoshm ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } db close testvfs tvfsshm testvfs tvfs -default 1 -iversion 1 sqlite3 db test.db #-------------------------------------------------------------------------- |
︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | do_test 1.5 { file exists test.db-wal } {1} do_execsql_test 1.6 { INSERT INTO t1 VALUES(3, 4) } do_execsql_test 1.7 { PRAGMA locking_mode = normal; } {exclusive} do_execsql_test 1.8 { PRAGMA journal_mode = delete; PRAGMA main.locking_mode; } {delete exclusive} do_execsql_test 1.9 { PRAGMA locking_mode = normal; } {normal} | > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | do_test 1.5 { file exists test.db-wal } {1} do_execsql_test 1.6 { INSERT INTO t1 VALUES(3, 4) } do_execsql_test 1.7 { PRAGMA locking_mode = normal; } {exclusive} ifcapable enable_persist_wal { file_control_persist_wal db 0 } do_execsql_test 1.8 { PRAGMA journal_mode = delete; PRAGMA main.locking_mode; } {delete exclusive} do_execsql_test 1.9 { PRAGMA locking_mode = normal; } {normal} |
︙ | ︙ |
Changes to test/walpersist.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | source $testdir/lock_common.tcl set ::testprefix walpersist ifcapable !wal { finish_test return } do_test walpersist-1.0 { db eval { PRAGMA journal_mode=WAL; CREATE TABLE t1(a); INSERT INTO t1 VALUES(randomblob(5000)); } file exists test.db-wal } {1} do_test walpersist-1.1 { | > > > > > > | > | | | > > > > > | > | > | | > > > > | > | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | source $testdir/lock_common.tcl set ::testprefix walpersist ifcapable !wal { finish_test return } if ![wal_is_ok] { finish_test; return } set shmpath test.db-shm if {[forced_proxy_locking]} { set shmpath [execsql { pragma lock_proxy_file }]-shm } do_test walpersist-1.0 { db eval { PRAGMA journal_mode=WAL; CREATE TABLE t1(a); INSERT INTO t1 VALUES(randomblob(5000)); } file exists test.db-wal } {1} do_test walpersist-1.1 { file exists $shmpath } {1} ifcapable enable_persist_wal { do_test walpersist-1.2-on { db close list [file exists test.db] [file exists test.db-wal] [file exists $shmpath] } {1 1 1} } { do_test walpersist-1.2-off { db close list [file exists test.db] [file exists test.db-wal] [file exists $shmpath] } {1 0 0} } do_test walpersist-1.3 { sqlite3 db test.db db eval {SELECT length(a) FROM t1} } {5000} do_test walpersist-1.4 { list [file exists test.db] [file exists test.db-wal] [file exists $shmpath] } {1 1 1} ifcapable enable_persist_wal { do_test walpersist-1.5-on { file_control_persist_wal db -1 } {0 1} } { do_test walpersist-1.5-off { file_control_persist_wal db -1 } {0 0} } do_test walpersist-1.6 { file_control_persist_wal db 1 } {0 1} do_test walpersist-1.7 { file_control_persist_wal db -1 } {0 1} do_test walpersist-1.8 { file_control_persist_wal db 0 } {0 0} do_test walpersist-1.9 { file_control_persist_wal db -1 } {0 0} do_test walpersist-1.10 { file_control_persist_wal db 1 } {0 1} do_test walpersist-1.11 { db close list [file exists test.db] [file exists test.db-wal] [file exists $shmpath] } {1 1 1} # Make sure the journal_size_limit works to limit the size of the # persisted wal file. In persistent-wal mode, any non-negative # journal_size_limit causes the WAL file to be truncated to zero bytes # when closing. # forcedelete test.db $shmpath test.db-wal do_test walpersist-2.1 { sqlite3 db test.db db eval { PRAGMA journal_mode=WAL; PRAGMA wal_autocheckpoint=OFF; PRAGMA journal_size_limit=12000; CREATE TABLE t1(x); |
︙ | ︙ | |||
93 94 95 96 97 98 99 | do_test walpersist-2.3 { sqlite3 db test.db execsql { PRAGMA integrity_check } } {ok} do_test 3.1 { catch {db close} | | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | do_test walpersist-2.3 { sqlite3 db test.db execsql { PRAGMA integrity_check } } {ok} do_test 3.1 { catch {db close} forcedelete test.db $shmpath test.db-wal sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint=128; PRAGMA journal_size_limit=16384; CREATE TABLE t1(a, b, PRIMARY KEY(a, b)); |
︙ | ︙ |
Changes to test/walro.test.
︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # And only if the build is WAL-capable. # ifcapable !wal { finish_test return } do_multiclient_test tn { # Close all connections and delete the database. # code1 { db close } code2 { db2 close } | > > > > > > > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # And only if the build is WAL-capable. # ifcapable !wal { finish_test return } if ![wal_is_ok] { finish_test; return } set shmpath test.db-shm if {[forced_proxy_locking]} { sqlite3 db test.db set shmpath [execsql { pragma lock_proxy_file }]-shm db close } do_multiclient_test tn { # Close all connections and delete the database. # code1 { db close } code2 { db2 close } |
︙ | ︙ | |||
58 59 60 61 62 63 64 | code2 { sqlite3 db2 test.db } sql2 { PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('a', 'b'); } | | | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | code2 { sqlite3 db2 test.db } sql2 { PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('a', 'b'); } file exists $shmpath } {1} do_test 1.1.2 { file attributes $shmpath -permissions r--r--r-- code1 { sqlite3 db file:test.db?readonly_shm=1 } } {} do_test 1.1.3 { sql1 "SELECT * FROM t1" } {a b} do_test 1.1.4 { sql2 "INSERT INTO t1 VALUES('c', 'd')" } {} do_test 1.1.5 { sql1 "SELECT * FROM t1" } {a b c d} |
︙ | ︙ | |||
95 96 97 98 99 100 101 | } {} do_test 1.1.12 { sql1 "SELECT * FROM t1" } {a b c d e f g h} do_test 1.1.13 { sql2 "INSERT INTO t1 VALUES('i', 'j')" } {} do_test 1.2.1 { code2 { db2 close } code1 { db close } | | | | | | | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | } {} do_test 1.1.12 { sql1 "SELECT * FROM t1" } {a b c d e f g h} do_test 1.1.13 { sql2 "INSERT INTO t1 VALUES('i', 'j')" } {} do_test 1.2.1 { code2 { db2 close } code1 { db close } list [file exists test.db-wal] [file exists $shmpath] } {1 1} do_test 1.2.2 { code1 { sqlite3 db file:test.db?readonly_shm=1 } list [catch { sql1 { SELECT * FROM t1 } } msg] $msg } {0 {a b c d e f g h i j}} do_test 1.2.3 { code1 { db close } file attributes $shmpath -permissions rw-r--r-- hexio_write $shmpath 0 01020304 file attributes $shmpath -permissions r--r--r-- code1 { sqlite3 db file:test.db?readonly_shm=1 } csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j}} do_test 1.2.4 { code1 { sqlite3_extended_errcode db } } {SQLITE_OK} do_test 1.2.5 { file attributes $shmpath -permissions rw-r--r-- code2 { sqlite3 db2 test.db } sql2 "SELECT * FROM t1" } {a b c d e f g h i j} file attributes $shmpath -permissions r--r--r-- do_test 1.2.6 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j} do_test 1.2.7 { sql2 { PRAGMA wal_checkpoint; INSERT INTO t1 VALUES('k', 'l'); } |
︙ | ︙ | |||
148 149 150 151 152 153 154 155 156 | code1 { sqlite3 db test.db } csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j k l}} # Also test that if the -shm file can be opened for read/write access, # it is not if readonly_shm=1 is present in the URI. do_test 1.3.2.1 { code1 { db close } code2 { db2 close } | > > > > | | | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | code1 { sqlite3 db test.db } csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j k l}} # Also test that if the -shm file can be opened for read/write access, # it is not if readonly_shm=1 is present in the URI. do_test 1.3.2.1 { ifcapable enable_persist_wal { code1 { file_control_persist_wal db 0 } code2 { file_control_persist_wal db2 0 } } code1 { db close } code2 { db2 close } file exists $shmpath } {0} do_test 1.3.2.2 { code1 { sqlite3 db file:test.db?readonly_shm=1 } csql1 { SELECT * FROM sqlite_master } } {1 {unable to open database file}} do_test 1.3.2.3 { code1 { db close } close [open $shmpath w] file attributes $shmpath -permissions r--r--r-- code1 { sqlite3 db file:test.db?readonly_shm=1 } csql1 { SELECT * FROM t1 } } {0 {a b c d e f g h i j k l}} do_test 1.3.2.4 { code1 { sqlite3_extended_errcode db } } {SQLITE_OK} |
︙ | ︙ | |||
293 294 295 296 297 298 299 300 | do_test 2.1.5 { code1 { db close } code1 { tv delete } } {} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | do_test 2.1.5 { code1 { db close } code1 { tv delete } } {} } forcedelete $shmpath if {$tcl_platform(os)=="Darwin"} { ifcapable enable_persist_wal { #-------------------------------------------------------------------------- catch {db2 close} reset_db do_execsql_test 3.1 { CREATE TABLE t1(a, b); PRAGMA journal_mode = wal; INSERT INTO t1 VALUES(1, 2); } {wal} db_save db close db_restore sqlite3 db test.db -readonly 1 do_execsql_test 3.2 { SELECT * FROM t1 } {1 2} do_catchsql_test 3.3 { INSERT INTO t1 VALUES(3, 4) } {1 {attempt to write a readonly database}} sqlite3 db2 test.db do_test 3.4 { db2 eval { INSERT INTO t1 VALUES(3, 4) } } {} do_execsql_test 3.5 { SELECT * FROM t1 } {1 2 3 4} db close db2 close db_restore file attributes $shmpath -permissions r--r--r-- sqlite3 db test.db -readonly 1 do_execsql_test 3.6 { SELECT * FROM t1 } {1 2} db close db_restore file attributes $shmpath -permissions r--r--r-- sqlite3 db test.db do_test 3.7 { catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} db close db_restore file attributes $shmpath -permissions r--r--r-- sqlite3 db test.db -readonly 1 do_execsql_test 3.8 { SELECT * FROM t1 } {1 2} sqlite3 db2 test.db do_test 3.9 { db2 eval { SELECT * FROM t1 } } {1 2} do_test 3.10 { catchsql { INSERT INTO t1 VALUES(3, 4) } db2 } {1 {attempt to write a readonly database}} catch { db close } catch { db2 close } forcedelete $shmpath } ;# endif capable enable_persist_wal } ;# endif os Darwin finish_test |
Changes to test/walshared.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # "PRAGMA journal_mode=WAL" mode with shared-cache turned on. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } db close set ::enable_shared_cache [sqlite3_enable_shared_cache 1] sqlite3 db test.db sqlite3 db2 test.db | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # "PRAGMA journal_mode=WAL" mode with shared-cache turned on. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } db close set ::enable_shared_cache [sqlite3_enable_shared_cache 1] sqlite3 db test.db sqlite3 db2 test.db |
︙ | ︙ |
Changes to test/walslow.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } if ![wal_is_ok] { finish_test; return } set testprefix walslow proc reopen_db {} { catch { db close } forcedelete test.db test.db-wal sqlite3 db test.db execsql { PRAGMA journal_mode = wal } |
︙ | ︙ |
Changes to test/walthread.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl if {[run_thread_tests]==0} { finish_test ; return } ifcapable !wal { finish_test ; return } set sqlite_walsummary_mmap_incr 64 # How long, in seconds, to run each test for. If a test is set to run for # 0 seconds, it is omitted entirely. # unset -nocomplain seconds | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl if {[run_thread_tests]==0} { finish_test ; return } ifcapable !wal { finish_test ; return } if ![wal_is_ok] { finish_test; return } set sqlite_walsummary_mmap_incr 64 # How long, in seconds, to run each test for. If a test is set to run for # 0 seconds, it is omitted entirely. # unset -nocomplain seconds |
︙ | ︙ |
Changes to test/window1.test.
︙ | ︙ | |||
1588 1589 1590 1591 1592 1593 1594 | FROM (SELECT (SELECT sum(a) FROM t1) AS x FROM t1); } {12 12 12} do_execsql_test 48.1 { SELECT (SELECT max(x)OVER(ORDER BY x) + min(x)OVER(ORDER BY x)) FROM (SELECT (SELECT sum(a) FROM t1 GROUP BY a) AS x FROM t1); } {2 2 2} | < | 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | FROM (SELECT (SELECT sum(a) FROM t1) AS x FROM t1); } {12 12 12} do_execsql_test 48.1 { SELECT (SELECT max(x)OVER(ORDER BY x) + min(x)OVER(ORDER BY x)) FROM (SELECT (SELECT sum(a) FROM t1 GROUP BY a) AS x FROM t1); } {2 2 2} #------------------------------------------------------------------------- reset_db do_execsql_test 49.1 { CREATE TABLE t1 (a PRIMARY KEY); INSERT INTO t1 VALUES(1); } |
︙ | ︙ |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
118 119 120 121 122 123 124 125 126 127 128 129 130 131 | sqlite3session.h sqlite3.h sqlite3ext.h sqlite3rbu.h sqliteicu.h sqliteInt.h sqliteLimit.h vdbe.h vdbeInt.h vxworks.h wal.h whereInt.h } { set available_hdr($hdr) 1 | > | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | sqlite3session.h sqlite3.h sqlite3ext.h sqlite3rbu.h sqliteicu.h sqliteInt.h sqliteLimit.h sqlrr.h vdbe.h vdbeInt.h vxworks.h wal.h whereInt.h } { set available_hdr($hdr) 1 |
︙ | ︙ | |||
393 394 395 396 397 398 399 400 401 402 403 404 405 406 | fts3_unicode.c fts3_unicode2.c json1.c rtree.c icu.c fts3_icu.c sqlite3rbu.c dbstat.c dbpage.c sqlite3session.c fts5.c stmt.c } { | > | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | fts3_unicode.c fts3_unicode2.c json1.c rtree.c icu.c fts3_icu.c sqlrr.c sqlite3rbu.c dbstat.c dbpage.c sqlite3session.c fts5.c stmt.c } { |
︙ | ︙ |