Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge latest trunk changes into experimental branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | experimental |
Files: | files | file ages | folders |
SHA1: |
7e515055f219b01dd72df4e27bdcabfa |
User & Date: | dan 2011-08-12 16:30:30.031 |
Context
2011-08-12
| ||
16:34 | Update Makefile.in and configure to account for new source file vdbesort.c. (Closed-Leaf check-in: 69e4b41de2 user: dan tags: experimental) | |
16:30 | Merge latest trunk changes into experimental branch. (check-in: 7e515055f2 user: dan tags: experimental) | |
16:11 | Remove an unused parameter from a function in vdbesort.c. Fix some comments and other details in the same file. (check-in: 1a8498d803 user: dan tags: experimental) | |
2011-08-10
| ||
01:52 | Make the openDirectory routine in os_unix.c overrideable so that it can be turned into a harmless no-op for the chromium sandbox. (check-in: 6b236069e1 user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
513 514 515 516 517 518 519 520 521 522 523 524 525 526 | $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new mv vdbe.new tsrc/vdbe.c touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl # Rule to build the amalgamation # sqlite3.lo: sqlite3.c $(LTCOMPILE) $(TEMP_STORE) -c sqlite3.c # Rules to build the LEMON compiler generator # | > > > | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new mv vdbe.new tsrc/vdbe.c touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/split-sqlite3c.tcl # Rule to build the amalgamation # sqlite3.lo: sqlite3.c $(LTCOMPILE) $(TEMP_STORE) -c sqlite3.c # Rules to build the LEMON compiler generator # |
︙ | ︙ | |||
781 782 783 784 785 786 787 | cp $(TOP)/src/parse.y . rm -f parse.h ./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y mv parse.h parse.h.temp $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION | | | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | cp $(TOP)/src/parse.y . rm -f parse.h ./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y mv parse.h parse.h.temp $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h keywordhash.h: $(TOP)/tool/mkkeywordhash.c $(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c ./mkkeywordhash$(BEXE) >keywordhash.h |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and # includes extra comments when "EXPLAIN stmt" is used. # TCC = $(TCC) -DNDEBUG # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # prior to running nmake in order to match the actual installed location and # version on this machine. # !if "$(TCLINCDIR)" == "" | > > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and # includes extra comments when "EXPLAIN stmt" is used. # TCC = $(TCC) -DNDEBUG # # Prevent warnings about "insecure" runtime library functions being used. # TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment # prior to running nmake in order to match the actual installed location and # version on this machine. # !if "$(TCLINCDIR)" == "" |
︙ | ︙ | |||
481 482 483 484 485 486 487 488 489 490 491 492 493 494 | del /Q tsrc\sqlite.h.in tsrc\parse.y $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl # Rule to build the amalgamation # sqlite3.lo: sqlite3.c $(LTCOMPILE) -c sqlite3.c # Rules to build the LEMON compiler generator | > > > | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | del /Q tsrc\sqlite.h.in tsrc\parse.y $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/split-sqlite3c.tcl # Rule to build the amalgamation # sqlite3.lo: sqlite3.c $(LTCOMPILE) -c sqlite3.c # Rules to build the LEMON compiler generator |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.7.8 |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.62 for sqlite 3.7.8. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## |
︙ | ︙ | |||
739 740 741 742 743 744 745 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.7.8' PACKAGE_STRING='sqlite 3.7.8' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> |
︙ | ︙ | |||
1481 1482 1483 1484 1485 1486 1487 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF | | | 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sqlite 3.7.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.7.8:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | | 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 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.7.8 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.7.8, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
14026 14027 14028 14029 14030 14031 14032 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 14026 14027 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sqlite $as_me 3.7.8, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
14079 14080 14081 14082 14083 14084 14085 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ | | | 14079 14080 14081 14082 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ sqlite config.status 3.7.8 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to doc/lemon.html.
︙ | ︙ | |||
278 279 280 281 282 283 284 | tokens) and it honors the same commenting conventions as C and C++.</p> <h3>Terminals and Nonterminals</h3> <p>A terminal symbol (token) is any string of alphanumeric and underscore characters that begins with an upper case letter. | | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | tokens) and it honors the same commenting conventions as C and C++.</p> <h3>Terminals and Nonterminals</h3> <p>A terminal symbol (token) is any string of alphanumeric and underscore characters that begins with an upper case letter. A terminal can contain lowercase letters after the first character, but the usual convention is to make terminals all upper case. A nonterminal, on the other hand, is any string of alphanumeric and underscore characters than begins with a lower case letter. Again, the usual convention is to make nonterminals use all lower case letters.</p> <p>In Lemon, terminal and nonterminal symbols do not need to |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
379 380 381 382 383 384 385 386 387 388 389 390 391 392 | sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl tclsh $(TOP)/ext/fts2/mkfts2amal.tcl fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl tclsh $(TOP)/ext/fts3/mkfts3amal.tcl | > > > | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c sqlite3-all.c: sqlite3.c $(TOP)/tool/split-sqlite3c.tcl tclsh $(TOP)/tool/split-sqlite3c.tcl fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl tclsh $(TOP)/ext/fts2/mkfts2amal.tcl fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl tclsh $(TOP)/ext/fts3/mkfts3amal.tcl |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 | int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } #endif } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ Table *pTab; | > > > > > > > > > > > > > > > > > > > > > > > | 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 | int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } #endif } /* ** Remove entries from the sqlite_stat1 and sqlite_stat2 tables ** after a DROP INDEX or DROP TABLE command. */ static void sqlite3ClearStatTables( Parse *pParse, /* The parsing context */ int iDb, /* The database number */ const char *zType, /* "idx" or "tbl" */ const char *zName /* Name of index or table */ ){ static const char *azStatTab[] = { "sqlite_stat1", "sqlite_stat2" }; int i; const char *zDbName = pParse->db->aDb[iDb].zName; for(i=0; i<ArraySize(azStatTab); i++){ if( sqlite3FindTable(pParse->db, azStatTab[i], zDbName) ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE %s=%Q", zDbName, azStatTab[i], zType, zName ); } } } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ Table *pTab; |
︙ | ︙ | |||
2115 2116 2117 2118 2119 2120 2121 | ** dropped. Triggers are handled seperately because a trigger can be ** created in the temp database that refers to a table in another ** database. */ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); | | < < < < < < < | 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 | ** dropped. Triggers are handled seperately because a trigger can be ** created in the temp database that refers to a table in another ** database. */ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } /* Remove the table entry from SQLite's internal schema and modify ** the schema cookie. */ |
︙ | ︙ | |||
2975 2976 2977 2978 2979 2980 2981 | /* Generate code to remove the index and from the master table */ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", | | < < < < | < < | 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 | /* Generate code to remove the index and from the master table */ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName ); sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); sqlite3ChangeCookie(pParse, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); } exit_drop_index: sqlite3SrcListDelete(db, pName); |
︙ | ︙ |
Changes to src/os.c.
︙ | ︙ | |||
132 133 134 135 136 137 138 | ){ int rc; DO_OS_MALLOC_TEST(0); /* 0x87f3f 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. */ | | | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | ){ int rc; DO_OS_MALLOC_TEST(0); /* 0x87f3f 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. */ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); assert( rc==SQLITE_OK || pFile->pMethods==0 ); return rc; } int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ return pVfs->xDelete(pVfs, zPath, dirSync); } int sqlite3OsAccess( |
︙ | ︙ |
Changes to src/os_common.h.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** switch. The following code should catch this problem at compile-time. */ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif #ifdef SQLITE_DEBUG | > > > | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** switch. The following code should catch this problem at compile-time. */ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif #ifdef SQLITE_DEBUG # ifndef SQLITE_DEBUG_OS_TRACE # define SQLITE_DEBUG_OS_TRACE 0 # endif int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; # define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X #else # define OSTRACE(X) #endif /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. */ #ifdef SQLITE_PERFORMANCE_TRACE |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
204 205 206 207 208 209 210 | ** VFS implementations. */ typedef struct unixFile unixFile; struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ unixInodeInfo *pInode; /* Info about locks on this inode */ int h; /* The file descriptor */ | < | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | ** VFS implementations. */ typedef struct unixFile unixFile; struct unixFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ unixInodeInfo *pInode; /* Info about locks on this inode */ int h; /* The file descriptor */ unsigned char eFileLock; /* The type of lock held on this fd */ unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ |
︙ | ︙ | |||
246 247 248 249 250 251 252 | char aPadding[32]; #endif }; /* ** Allowed values for the unixFile.ctrlFlags bitmask: */ | | | > > | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | char aPadding[32]; #endif }; /* ** Allowed values for the unixFile.ctrlFlags bitmask: */ #define UNIXFILE_EXCL 0x01 /* Connections from one process only */ #define UNIXFILE_RDONLY 0x02 /* Connection is read only */ #define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ #define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */ /* ** Include code that is common to all os_*.c files */ #include "os_common.h" /* |
︙ | ︙ | |||
293 294 295 296 297 298 299 300 301 302 303 304 305 306 | ** The safest way to deal with the problem is to always use this wrapper ** which always has the same well-defined interface. */ static int posixOpen(const char *zFile, int flags, int mode){ return open(zFile, flags, mode); } /* ** Many system calls are accessed through pointer-to-functions so that ** they may be overridden at runtime to facilitate fault injection during ** testing and sandboxing. The following array holds the names and pointers ** to all overrideable system calls. */ static struct unix_syscall { | > > > | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | ** The safest way to deal with the problem is to always use this wrapper ** which always has the same well-defined interface. */ static int posixOpen(const char *zFile, int flags, int mode){ return open(zFile, flags, mode); } /* Forward reference */ static int openDirectory(const char*, int*); /* ** Many system calls are accessed through pointer-to-functions so that ** they may be overridden at runtime to facilitate fault injection during ** testing and sandboxing. The following array holds the names and pointers ** to all overrideable system calls. */ static struct unix_syscall { |
︙ | ︙ | |||
389 390 391 392 393 394 395 396 397 398 399 400 401 402 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else { "fallocate", (sqlite3_syscall_ptr)0, 0 }, #endif #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) }; /* End of the overrideable system calls */ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the ** "unix" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. | > > > > > > | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else { "fallocate", (sqlite3_syscall_ptr)0, 0 }, #endif #define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent) { "unlink", (sqlite3_syscall_ptr)unlink, 0 }, #define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent) { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 }, #define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent) }; /* End of the overrideable system calls */ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the ** "unix" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. |
︙ | ︙ | |||
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | case EIO: case EBADF: case EINVAL: case ENOTCONN: case ENODEV: case ENXIO: case ENOENT: case ESTALE: case ENOSYS: /* these should force the client to close the file and reconnect */ default: return sqliteIOErr; } } | > > | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 | case EIO: case EBADF: case EINVAL: case ENOTCONN: case ENODEV: case ENXIO: case ENOENT: #ifdef ESTALE /* ESTALE is not defined on Interix systems */ case ESTALE: #endif case ENOSYS: /* these should force the client to close the file and reconnect */ default: return sqliteIOErr; } } |
︙ | ︙ | |||
1743 1744 1745 1746 1747 1748 1749 | ** ** It is *not* necessary to hold the mutex when this routine is called, ** even on VxWorks. A mutex will be acquired on VxWorks by the ** vxworksReleaseFileId() routine. */ static int closeUnixFile(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; | < < < < | | 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 | ** ** It is *not* necessary to hold the mutex when this routine is called, ** even on VxWorks. A mutex will be acquired on VxWorks by the ** vxworksReleaseFileId() routine. */ static int closeUnixFile(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; if( pFile->h>=0 ){ robust_close(pFile, pFile->h, __LINE__); pFile->h = -1; } #if OS_VXWORKS if( pFile->pId ){ if( pFile->isDelete ){ osUnlink(pFile->pId->zCanonicalName); } vxworksReleaseFileId(pFile->pId); pFile->pId = 0; } #endif OSTRACE(("CLOSE %-3d\n", pFile->h)); OpenCounter(-1); |
︙ | ︙ | |||
2003 2004 2005 2006 2007 2008 2009 | if( eFileLock==SHARED_LOCK ){ pFile->eFileLock = SHARED_LOCK; return SQLITE_OK; } /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); | | | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 | if( eFileLock==SHARED_LOCK ){ pFile->eFileLock = SHARED_LOCK; return SQLITE_OK; } /* To fully unlock the database, delete the lock file */ assert( eFileLock==NO_LOCK ); if( osUnlink(zLockFile) ){ int rc = 0; int tErrno = errno; if( ENOENT != tErrno ){ rc = SQLITE_IOERR_UNLOCK; } if( IS_LOCK_ERROR(rc) ){ pFile->lastErrno = tErrno; |
︙ | ︙ | |||
3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 | #endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ if( OS_VXWORKS && rc!= -1 ){ rc = 0; } return rc; } /* ** Make sure all writes to a particular file are committed to disk. ** ** If dataOnly==0 then both the file itself and its metadata (file ** size, access time, etc) are synced. If dataOnly!=0 then only the ** file data is synced. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 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 | #endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ if( OS_VXWORKS && rc!= -1 ){ rc = 0; } return rc; } /* ** Open a file descriptor to the directory containing file zFilename. ** If successful, *pFd is set to the opened file descriptor and ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined ** value. ** ** The directory file descriptor is used for only one thing - to ** fsync() a directory to make sure file creation and deletion events ** are flushed to disk. Such fsyncs are not needed on newer ** journaling filesystems, but are required on older filesystems. ** ** This routine can be overridden using the xSetSysCall interface. ** The ability to override this routine was added in support of the ** chromium sandbox. Opening a directory is a security risk (we are ** told) so making it overrideable allows the chromium sandbox to ** replace this routine with a harmless no-op. To make this routine ** a no-op, replace it with a stub that returns SQLITE_OK but leaves ** *pFd set to a negative number. ** ** If SQLITE_OK is returned, the caller is responsible for closing ** the file descriptor *pFd using close(). */ static int openDirectory(const char *zFilename, int *pFd){ int ii; int fd = -1; char zDirname[MAX_PATHNAME+1]; sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); if( ii>0 ){ zDirname[ii] = '\0'; fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); if( fd>=0 ){ #ifdef FD_CLOEXEC osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); } } *pFd = fd; return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); } /* ** Make sure all writes to a particular file are committed to disk. ** ** If dataOnly==0 then both the file itself and its metadata (file ** size, access time, etc) are synced. If dataOnly!=0 then only the ** file data is synced. |
︙ | ︙ | |||
3279 3280 3281 3282 3283 3284 3285 | OSTRACE(("SYNC %-3d\n", pFile->h)); rc = full_fsync(pFile->h, isFullsync, isDataOnly); SimulateIOError( rc=1 ); if( rc ){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } | > > > > > | > | < | < | < | < < < < < < | < < < < | | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 | OSTRACE(("SYNC %-3d\n", pFile->h)); rc = full_fsync(pFile->h, isFullsync, isDataOnly); SimulateIOError( rc=1 ); if( rc ){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } /* Also fsync the directory containing the file if the DIRSYNC flag ** is set. This is a one-time occurrance. Many systems (examples: AIX) ** are unable to fsync a directory, so ignore errors on the fsync. */ 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 && dirfd>=0 ){ full_fsync(dirfd, 0, 0); robust_close(pFile, dirfd, __LINE__); } pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC; } return rc; } /* ** Truncate an open file to a specified size */ |
︙ | ︙ | |||
3389 3390 3391 3392 3393 3394 3395 | ** file-control operation. ** ** If the user has configured a chunk-size for this file, it could be ** that the file needs to be extended at this point. Otherwise, the ** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix. */ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ | | > | > > > > > | 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 | ** file-control operation. ** ** If the user has configured a chunk-size for this file, it could be ** that the file needs to be extended at this point. Otherwise, the ** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix. */ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ { /* preserve indentation of removed "if" */ i64 nSize; /* Required file size */ i64 szChunk; /* Chunk size */ struct stat buf; /* Used to hold return values of fstat() */ if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT; szChunk = pFile->szChunk; if( szChunk==0 ){ nSize = nByte; }else{ nSize = ((nByte+szChunk-1) / szChunk) * szChunk; } if( nSize>(i64)buf.st_size ){ #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE /* The code below is handling the return value of osFallocate() ** correctly. posix_fallocate() is defined to "returns zero on success, ** or an error number on failure". See the manpage for details. */ int err; |
︙ | ︙ | |||
3438 3439 3440 3441 3442 3443 3444 3445 3446 | return SQLITE_OK; } /* ** Information and control of an open file handle. */ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { | > | | | | > > > > > > > > > > > | 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 3527 3528 3529 | return SQLITE_OK; } /* ** Information and control of an open file handle. */ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ unixFile *pFile = (unixFile*)id; switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = pFile->eFileLock; return SQLITE_OK; } case SQLITE_LAST_ERRNO: { *(int*)pArg = pFile->lastErrno; return SQLITE_OK; } case SQLITE_FCNTL_CHUNK_SIZE: { pFile->szChunk = *(int *)pArg; return SQLITE_OK; } case SQLITE_FCNTL_SIZE_HINT: { return fcntlSizeHint(pFile, *(i64 *)pArg); } case SQLITE_FCNTL_PERSIST_WAL: { int bPersist = *(int*)pArg; if( bPersist<0 ){ *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0; }else if( bPersist==0 ){ pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL; }else{ pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL; } return SQLITE_OK; } #ifndef NDEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and ** it hence it is OK for the transaction change counter to be ** unchanged. */ |
︙ | ︙ | |||
4137 4138 4139 4140 4141 4142 4143 | /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ unixEnterMutex(); assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ | | | 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 | /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ unixEnterMutex(); assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); unixShmPurge(pDbFd); } unixLeaveMutex(); return SQLITE_OK; } |
︙ | ︙ | |||
4450 4451 4452 4453 4454 4455 4456 | /* ** Initialize the contents of the unixFile structure pointed to by pId. */ static int fillInUnixFile( sqlite3_vfs *pVfs, /* Pointer to vfs object */ int h, /* Open file descriptor of file being opened */ | | | 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 | /* ** Initialize the contents of the unixFile structure pointed to by pId. */ static int fillInUnixFile( sqlite3_vfs *pVfs, /* Pointer to vfs object */ int h, /* Open file descriptor of file being opened */ int syncDir, /* True to sync directory on first sync */ sqlite3_file *pId, /* Write to the unixFile structure here */ const char *zFilename, /* Name of the file being opened */ int noLock, /* Omit locking if true */ int isDelete, /* Delete on close if true */ int isReadOnly /* True if the file is opened read-only */ ){ const sqlite3_io_methods *pLockingStyle; |
︙ | ︙ | |||
4481 4482 4483 4484 4485 4486 4487 | || pVfs->pAppData==(void*)&autolockIoFinder ); #else assert( zFilename==0 || zFilename[0]=='/' ); #endif OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; | < > > > | 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 | || pVfs->pAppData==(void*)&autolockIoFinder ); #else assert( zFilename==0 || zFilename[0]=='/' ); #endif OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; pNew->zPath = zFilename; if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ pNew->ctrlFlags = UNIXFILE_EXCL; }else{ pNew->ctrlFlags = 0; } if( isReadOnly ){ pNew->ctrlFlags |= UNIXFILE_RDONLY; } if( syncDir ){ pNew->ctrlFlags |= UNIXFILE_DIRSYNC; } #if OS_VXWORKS pNew->pId = vxworksFindFileId(zFilename); if( pNew->pId==0 ){ noLock = 1; rc = SQLITE_NOMEM; } |
︙ | ︙ | |||
4617 4618 4619 4620 4621 4622 4623 | #endif pNew->lastErrno = 0; #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 | #endif pNew->lastErrno = 0; #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; osUnlink(zFilename); isDelete = 0; } pNew->isDelete = isDelete; #endif if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); }else{ pNew->pMethod = pLockingStyle; OpenCounter(+1); } return rc; } /* ** Return the name of a directory in which to put temporary files. ** If no suitable temporary file directory can be found, return NULL. */ static const char *unixTempFileDir(void){ static const char *azDirs[] = { 0, |
︙ | ︙ | |||
4777 4778 4779 4780 4781 4782 4783 | ** almost certain that an open() call on the same path will also fail. ** For this reason, if an error occurs in the stat() call here, it is ** ignored and -1 is returned. The caller will try to open a new file ** descriptor on the same path, fail, and return an error to SQLite. ** ** Even if a subsequent open() call does succeed, the consequences of ** not searching for a resusable file descriptor are not dire. */ | | | 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 | ** almost certain that an open() call on the same path will also fail. ** For this reason, if an error occurs in the stat() call here, it is ** ignored and -1 is returned. The caller will try to open a new file ** descriptor on the same path, fail, and return an error to SQLite. ** ** Even if a subsequent open() call does succeed, the consequences of ** not searching for a resusable file descriptor are not dire. */ if( 0==osStat(zPath, &sStat) ){ unixInodeInfo *pInode; unixEnterMutex(); pInode = inodeList; while( pInode && (pInode->fileId.dev!=sStat.st_dev || pInode->fileId.ino!=sStat.st_ino) ){ pInode = pInode->pNext; |
︙ | ︙ | |||
4853 4854 4855 4856 4857 4858 4859 | */ nDb = sqlite3Strlen30(zPath) - 1; while( nDb>0 && zPath[nDb]!='-' ) nDb--; if( nDb==0 ) return SQLITE_OK; memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; | | | 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 | */ nDb = sqlite3Strlen30(zPath) - 1; while( nDb>0 && zPath[nDb]!='-' ) nDb--; if( nDb==0 ) return SQLITE_OK; memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; if( 0==osStat(zDb, &sStat) ){ *pMode = sStat.st_mode & 0777; }else{ rc = SQLITE_IOERR_FSTAT; } }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; } |
︙ | ︙ | |||
4895 4896 4897 4898 4899 4900 4901 | const char *zPath, /* Pathname of file to be opened */ 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() */ | < | | 4928 4929 4930 4931 4932 4933 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 | const char *zPath, /* Pathname of file to be opened */ 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() */ int eType = flags&0xFFFFFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ int rc = SQLITE_OK; /* Function Return Code */ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); int isReadonly = (flags & SQLITE_OPEN_READONLY); int isReadWrite = (flags & SQLITE_OPEN_READWRITE); #if SQLITE_ENABLE_LOCKING_STYLE int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY); #endif /* If creating a master or main-file journal, this function will open ** a file-descriptor on the directory too. The first time unixSync() ** is called the directory file descriptor will be fsync()ed and close()d. */ int syncDir = (isCreate && ( eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL )); /* If argument zPath is a NULL pointer, this function is required to open ** a temporary file. Use this buffer to store the file name in. |
︙ | ︙ | |||
4968 4969 4970 4971 4972 4973 4974 | if( !pUnused ){ return SQLITE_NOMEM; } } p->pUnused = pUnused; }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ | | | 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 | if( !pUnused ){ return SQLITE_NOMEM; } } p->pUnused = pUnused; }else if( !zName ){ /* If zName is NULL, the upper layer is requesting a temp file. */ assert(isDelete && !syncDir); rc = unixGetTempname(MAX_PATHNAME+1, zTmpname); if( rc!=SQLITE_OK ){ return rc; } zName = zTmpname; } |
︙ | ︙ | |||
5024 5025 5026 5027 5028 5029 5030 | p->pUnused->flags = flags; } if( isDelete ){ #if OS_VXWORKS zPath = zName; #else | | < < < < < < < < < < < < < < | 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 | p->pUnused->flags = flags; } if( isDelete ){ #if OS_VXWORKS zPath = zName; #else osUnlink(zName); #endif } #if SQLITE_ENABLE_LOCKING_STYLE else{ p->openFlags = openFlags; } #endif #ifdef FD_CLOEXEC osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif noLock = eType!=SQLITE_OPEN_MAIN_DB; #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE struct statfs fsInfo; if( fstatfs(fd, &fsInfo) == -1 ){ ((unixFile*)pFile)->lastErrno = errno; robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; } #endif |
︙ | ︙ | |||
5089 5090 5091 5092 5093 5094 5095 | ** with fd is a database file, and there are other connections open ** on that file that are currently holding advisory locks on it, ** then the call to close() will cancel those locks. In practice, ** we're assuming that statfs() doesn't fail very often. At least ** not while other file descriptors opened by the same process on ** the same file are working. */ p->lastErrno = errno; | < < < | | | 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 | ** with fd is a database file, and there are other connections open ** on that file that are currently holding advisory locks on it, ** then the call to close() will cancel those locks. In practice, ** we're assuming that statfs() doesn't fail very often. At least ** not while other file descriptors opened by the same process on ** the same file are working. */ p->lastErrno = errno; robust_close(p, fd, __LINE__); rc = SQLITE_IOERR_ACCESS; goto open_finished; } useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, isDelete, isReadonly); 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 */ unixClose(pFile); return rc; } } goto open_finished; } } #endif rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock, isDelete, isReadonly); open_finished: if( rc!=SQLITE_OK ){ sqlite3_free(p->pUnused); } return rc; } |
︙ | ︙ | |||
5139 5140 5141 5142 5143 5144 5145 | sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ const char *zPath, /* Name of file to be deleted */ int dirSync /* If true, fsync() directory after deleting file */ ){ int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); | | | | 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 | sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ const char *zPath, /* Name of file to be deleted */ int dirSync /* If true, fsync() directory after deleting file */ ){ int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); } #ifndef SQLITE_DISABLE_DIRSYNC if( dirSync ){ int fd; rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ #if OS_VXWORKS if( fsync(fd)==-1 ) #else if( fsync(fd) ) #endif { |
︙ | ︙ | |||
5198 5199 5200 5201 5202 5203 5204 | default: assert(!"Invalid flags argument"); } *pResOut = (osAccess(zPath, amode)==0); if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ struct stat buf; | | | 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 | default: assert(!"Invalid flags argument"); } *pResOut = (osAccess(zPath, amode)==0); if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){ struct stat buf; if( 0==osStat(zPath, &buf) && buf.st_size==0 ){ *pResOut = 0; } } return SQLITE_OK; } |
︙ | ︙ | |||
5717 5718 5719 5720 5721 5722 5723 | */ static int proxyCreateUnixFile( const char *path, /* path for the new unixFile */ unixFile **ppFile, /* unixFile created and returned by ref */ int islockfile /* if non zero missing dirs will be created */ ) { int fd = -1; | < | 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 | */ static int proxyCreateUnixFile( const char *path, /* path for the new unixFile */ unixFile **ppFile, /* unixFile created and returned by ref */ int islockfile /* if non zero missing dirs will be created */ ) { int fd = -1; unixFile *pNew; int rc = SQLITE_OK; int openFlags = O_RDWR | O_CREAT; sqlite3_vfs dummyVfs; int terrno = 0; UnixUnusedFd *pUnused = NULL; |
︙ | ︙ | |||
5782 5783 5784 5785 5786 5787 5788 | memset(&dummyVfs, 0, sizeof(dummyVfs)); dummyVfs.pAppData = (void*)&autolockIoFinder; dummyVfs.zName = "dummy"; pUnused->fd = fd; pUnused->flags = openFlags; pNew->pUnused = pUnused; | | | 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 | memset(&dummyVfs, 0, sizeof(dummyVfs)); dummyVfs.pAppData = (void*)&autolockIoFinder; dummyVfs.zName = "dummy"; pUnused->fd = fd; pUnused->flags = openFlags; pNew->pUnused = pUnused; rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0); if( rc==SQLITE_OK ){ *ppFile = pNew; return SQLITE_OK; } end_create_proxy: robust_close(pNew, fd, __LINE__); sqlite3_free(pNew); |
︙ | ︙ | |||
5896 5897 5898 5899 5900 5901 5902 | robust_close(pFile, conchFile->h, __LINE__); conchFile->h = fd; conchFile->openFlags = O_RDWR | O_CREAT; end_breaklock: if( rc ){ if( fd>=0 ){ | | | 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 | robust_close(pFile, conchFile->h, __LINE__); conchFile->h = fd; conchFile->openFlags = O_RDWR | O_CREAT; end_breaklock: if( rc ){ if( fd>=0 ){ osUnlink(tPath); robust_close(pFile, fd, __LINE__); } fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg); } return rc; } |
︙ | ︙ | |||
6719 6720 6721 6722 6723 6724 6725 | UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ | | | 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 | UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ assert( ArraySize(aSyscall)==18 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } return SQLITE_OK; } |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
98 99 100 101 102 103 104 | ** portability layer. */ typedef struct winFile winFile; struct winFile { const sqlite3_io_methods *pMethod; /*** Must be first ***/ sqlite3_vfs *pVfs; /* The VFS used to open this file */ HANDLE h; /* Handle for accessing the file */ | | > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | ** portability layer. */ typedef struct winFile winFile; struct winFile { const sqlite3_io_methods *pMethod; /*** Must be first ***/ sqlite3_vfs *pVfs; /* The VFS used to open this file */ HANDLE h; /* Handle for accessing the file */ u8 locktype; /* Type of lock currently held on this file */ short sharedLockByte; /* Randomly chosen byte used as a shared lock */ u8 bPersistWal; /* True to persist WAL files */ DWORD lastErrno; /* The Windows errno from the last I/O error */ DWORD sectorSize; /* Sector size of the device file is on */ winShm *pShm; /* Instance of shared memory on this file */ const char *zPath; /* Full pathname of this file */ int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ #if SQLITE_OS_WINCE WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ |
︙ | ︙ | |||
399 400 401 402 403 404 405 | iLine, iErrno, zFunc, zPath, zMsg ); return errcode; } /* | | | > > | > > > > > | > > | | > > > > > > > > > > > > | 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 | iLine, iErrno, zFunc, zPath, zMsg ); return errcode; } /* ** The number of times that a ReadFile(), WriteFile(), and DeleteFile() ** will be retried following a locking error - probably caused by ** antivirus software. Also the initial delay before the first retry. ** The delay increases linearly with each retry. */ #ifndef SQLITE_WIN32_IOERR_RETRY # define SQLITE_WIN32_IOERR_RETRY 10 #endif #ifndef SQLITE_WIN32_IOERR_RETRY_DELAY # define SQLITE_WIN32_IOERR_RETRY_DELAY 25 #endif static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY; static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY; /* ** If a ReadFile() or WriteFile() error occurs, invoke this routine ** to see if it should be retried. Return TRUE to retry. Return FALSE ** to give up with an error. */ static int retryIoerr(int *pnRetry){ DWORD e; if( *pnRetry>=win32IoerrRetry ){ return 0; } e = GetLastError(); if( e==ERROR_ACCESS_DENIED || e==ERROR_LOCK_VIOLATION || e==ERROR_SHARING_VIOLATION ){ Sleep(win32IoerrRetryDelay*(1+*pnRetry)); ++*pnRetry; return 1; } return 0; } /* ** Log a I/O error retry episode. */ static void logIoerr(int nRetry){ if( nRetry ){ sqlite3_log(SQLITE_IOERR, "delayed %dms for lock/sharing conflict", win32IoerrRetryDelay*nRetry*(nRetry+1)/2 ); } } #if SQLITE_OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ /* ** WindowsCE does not have a localtime() function. So create a |
︙ | ︙ | |||
857 858 859 860 861 862 863 864 865 866 867 868 869 870 | return SQLITE_FULL; } while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ if( retryIoerr(&nRetry) ) continue; pFile->lastErrno = GetLastError(); return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath); } if( nRead<(DWORD)amt ){ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[nRead], 0, amt-nRead); return SQLITE_IOERR_SHORT_READ; } return SQLITE_OK; | > | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 | return SQLITE_FULL; } while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ if( retryIoerr(&nRetry) ) continue; pFile->lastErrno = GetLastError(); return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath); } logIoerr(nRetry); if( nRead<(DWORD)amt ){ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[nRead], 0, amt-nRead); return SQLITE_IOERR_SHORT_READ; } return SQLITE_OK; |
︙ | ︙ | |||
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | sqlite3_file *id, /* File to write into */ const void *pBuf, /* The bytes to be written */ int amt, /* Number of bytes to write */ sqlite3_int64 offset /* Offset into the file to begin writing at */ ){ int rc; /* True if error has occured, else false */ winFile *pFile = (winFile*)id; /* File handle */ assert( amt>0 ); assert( pFile ); SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); rc = seekWinFile(pFile, offset); if( rc==0 ){ u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ int nRem = amt; /* Number of bytes yet to be written */ DWORD nWrite; /* Bytes written by each WriteFile() call */ | > < | 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 | sqlite3_file *id, /* File to write into */ const void *pBuf, /* The bytes to be written */ int amt, /* Number of bytes to write */ sqlite3_int64 offset /* Offset into the file to begin writing at */ ){ int rc; /* True if error has occured, else false */ winFile *pFile = (winFile*)id; /* File handle */ int nRetry = 0; /* Number of retries */ assert( amt>0 ); assert( pFile ); SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); rc = seekWinFile(pFile, offset); if( rc==0 ){ u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ int nRem = amt; /* Number of bytes yet to be written */ DWORD nWrite; /* Bytes written by each WriteFile() call */ while( nRem>0 ){ if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ if( retryIoerr(&nRetry) ) continue; break; } if( nWrite<=0 ) break; |
︙ | ︙ | |||
914 915 916 917 918 919 920 921 922 923 924 925 926 927 | if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ return SQLITE_FULL; } return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath); } return SQLITE_OK; } /* ** Truncate an open file to a specified size */ | > > | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 | if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ return SQLITE_FULL; } return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile->zPath); }else{ logIoerr(nRetry); } return SQLITE_OK; } /* ** Truncate an open file to a specified size */ |
︙ | ︙ | |||
1307 1308 1309 1310 1311 1312 1313 1314 1315 | return rc; } /* ** Control and query of the open file handle. */ static int winFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { | > | | | > > > > > > > > > > > > > > > > > > > > > > > | 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 | return rc; } /* ** Control and query of the open file handle. */ static int winFileControl(sqlite3_file *id, int op, void *pArg){ winFile *pFile = (winFile*)id; switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = pFile->locktype; return SQLITE_OK; } case SQLITE_LAST_ERRNO: { *(int*)pArg = (int)pFile->lastErrno; return SQLITE_OK; } case SQLITE_FCNTL_CHUNK_SIZE: { pFile->szChunk = *(int *)pArg; return SQLITE_OK; } case SQLITE_FCNTL_SIZE_HINT: { sqlite3_int64 sz = *(sqlite3_int64*)pArg; SimulateIOErrorBenign(1); winTruncate(id, sz); SimulateIOErrorBenign(0); 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_SYNC_OMITTED: { return SQLITE_OK; } case SQLITE_FCNTL_WIN32_AV_RETRY: { int *a = (int*)pArg; if( a[0]>0 ){ win32IoerrRetry = a[0]; }else{ a[0] = win32IoerrRetry; } if( a[1]>0 ){ win32IoerrRetryDelay = a[1]; }else{ a[1] = win32IoerrRetryDelay; } return SQLITE_OK; } } return SQLITE_NOTFOUND; } /* ** Return the sector size in bytes of the underlying block device for |
︙ | ︙ | |||
2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 | DWORD dwFlagsAndAttributes = 0; #if SQLITE_OS_WINCE int isTemp = 0; #endif winFile *pFile = (winFile*)id; void *zConverted; /* Filename in OS encoding */ const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ /* If argument zPath is a NULL pointer, this function is required to open ** a temporary file. Use this buffer to store the file name in. */ char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ int rc = SQLITE_OK; /* Function Return Code */ | > | 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 | DWORD dwFlagsAndAttributes = 0; #if SQLITE_OS_WINCE int isTemp = 0; #endif winFile *pFile = (winFile*)id; void *zConverted; /* Filename in OS encoding */ const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ int cnt = 0; /* If argument zPath is a NULL pointer, this function is required to open ** a temporary file. Use this buffer to store the file name in. */ char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ int rc = SQLITE_OK; /* Function Return Code */ |
︙ | ︙ | |||
2257 2258 2259 2260 2261 2262 2263 | /* Reports from the internet are that performance is always ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ #if SQLITE_OS_WINCE dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; #endif if( isNT() ){ | | | | < | | | < > | | | < | | | < > > > | 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 | /* Reports from the internet are that performance is always ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ #if SQLITE_OS_WINCE dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; #endif if( isNT() ){ while( (h = CreateFileW((WCHAR*)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL))==INVALID_HANDLE_VALUE && retryIoerr(&cnt) ){} /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. ** Since the ASCII version of these Windows API do not exist for WINCE, ** it's important to not reference them for WINCE builds. */ #if SQLITE_OS_WINCE==0 }else{ while( (h = CreateFileA((char*)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL))==INVALID_HANDLE_VALUE && retryIoerr(&cnt) ){} #endif } logIoerr(cnt); OSTRACE(("OPEN %d %s 0x%lx %s\n", h, zName, dwDesiredAccess, h==INVALID_HANDLE_VALUE ? "failed" : "ok")); if( h==INVALID_HANDLE_VALUE ){ pFile->lastErrno = GetLastError(); |
︙ | ︙ | |||
2347 2348 2349 2350 2351 2352 2353 | ** will open a journal file shortly after it is created in order to do ** whatever it does. While this other process is holding the ** file open, we will be unable to delete it. To work around this ** problem, we delay 100 milliseconds and try to delete again. Up ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving ** up and returning an error. */ | < | < < > > | < | < < < > > | < | < < > > > > > | < < < | < < | 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 | ** will open a journal file shortly after it is created in order to do ** whatever it does. While this other process is holding the ** file open, we will be unable to delete it. To work around this ** problem, we delay 100 milliseconds and try to delete again. Up ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving ** up and returning an error. */ static int winDelete( sqlite3_vfs *pVfs, /* Not used on win32 */ const char *zFilename, /* Name of file to delete */ int syncDir /* Not used on win32 */ ){ int cnt = 0; int rc; void *zConverted; UNUSED_PARAMETER(pVfs); UNUSED_PARAMETER(syncDir); SimulateIOError(return SQLITE_IOERR_DELETE); zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ rc = 1; while( GetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES && (rc = DeleteFileW(zConverted))==0 && retryIoerr(&cnt) ){} rc = rc ? SQLITE_OK : SQLITE_ERROR; /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. ** Since the ASCII version of these Windows API do not exist for WINCE, ** it's important to not reference them for WINCE builds. */ #if SQLITE_OS_WINCE==0 }else{ rc = 1; while( GetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES && (rc = DeleteFileA(zConverted))==0 && retryIoerr(&cnt) ){} rc = rc ? SQLITE_OK : SQLITE_ERROR; #endif } if( rc ){ rc = winLogError(SQLITE_IOERR_DELETE, "winDelete", zFilename); }else{ logIoerr(cnt); } free(zConverted); OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" ))); return rc; } /* ** Check the existance and status of a file. */ static int winAccess( sqlite3_vfs *pVfs, /* Not used on win32 */ |
︙ | ︙ | |||
2416 2417 2418 2419 2420 2421 2422 2423 2424 | SimulateIOError( return SQLITE_IOERR_ACCESS; ); zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); | > | | > > | 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 | SimulateIOError( return SQLITE_IOERR_ACCESS; ); zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ int cnt = 0; WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); while( !(rc = GetFileAttributesExW((WCHAR*)zConverted, GetFileExInfoStandard, &sAttrData)) && retryIoerr(&cnt) ){} if( rc ){ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file ** as if it does not exist. */ if( flags==SQLITE_ACCESS_EXISTS && sAttrData.nFileSizeHigh==0 && sAttrData.nFileSizeLow==0 ){ attr = INVALID_FILE_ATTRIBUTES; }else{ attr = sAttrData.dwFileAttributes; } }else{ logIoerr(cnt); if( GetLastError()!=ERROR_FILE_NOT_FOUND ){ winLogError(SQLITE_IOERR_ACCESS, "winAccess", zFilename); free(zConverted); return SQLITE_IOERR_ACCESS; }else{ attr = INVALID_FILE_ATTRIBUTES; } |
︙ | ︙ | |||
2456 2457 2458 2459 2460 2461 2462 | free(zConverted); switch( flags ){ case SQLITE_ACCESS_READ: case SQLITE_ACCESS_EXISTS: rc = attr!=INVALID_FILE_ATTRIBUTES; break; case SQLITE_ACCESS_READWRITE: | > | | 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 | free(zConverted); switch( flags ){ case SQLITE_ACCESS_READ: case SQLITE_ACCESS_EXISTS: rc = attr!=INVALID_FILE_ATTRIBUTES; break; case SQLITE_ACCESS_READWRITE: rc = attr!=INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)==0; break; default: assert(!"Invalid flags argument"); } *pResOut = rc; return SQLITE_OK; } |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ ** Some specialized VFSes need this signal in order to operate correctly ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most ** VFSes do not need this signal and should silently ignore this opcode. ** Applications should not call [sqlite3_file_control()] with this ** opcode as doing so may disrupt the operation of the specialized VFSes ** that do require it. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_SYNC_OMITTED 8 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 732 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 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 | ** when the database connection has [PRAGMA synchronous] set to OFF.)^ ** Some specialized VFSes need this signal in order to operate correctly ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most ** VFSes do not need this signal and should silently ignore this opcode. ** Applications should not call [sqlite3_file_control()] with this ** opcode as doing so may disrupt the operation of the specialized VFSes ** that do require it. ** ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic ** retry counts and intervals for certain disk I/O operations for the ** windows [VFS] in order to work to provide robustness against ** anti-virus programs. By default, the windows VFS will retry file read, ** file write, and file delete opertions up to 10 times, with a delay ** of 25 milliseconds before the first retry and with the delay increasing ** by an additional 25 milliseconds with each subsequent retry. This ** opcode allows those to values (10 retries and 25 milliseconds of delay) ** to be adjusted. The values are changed for all database connections ** within the same process. The argument is a pointer to an array of two ** integers where the first integer i the new retry count and the second ** integer is the delay. If either integer is negative, then the setting ** is not changed but instead the prior value of that setting is written ** into the array entry, allowing the current retry settings to be ** interrogated. The zDbName parameter is ignored. ** ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the ** persistent [WAL | Write AHead Log] setting. By default, the auxiliary ** write ahead log and shared memory files used for transaction control ** are automatically deleted when the latest connection to the database ** closes. Setting persistent WAL mode causes those files to persist after ** close. Persisting the files is useful when other processes that do not ** have write permission on the directory containing the database file want ** to read the database file, as the WAL and shared memory files must exist ** in order for the database to be readable. The fourth parameter to ** [sqlite3_file_control()] for this opcode should be a pointer to an integer. ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent ** WAL mode. If the integer is -1, then it is overwritten with the current ** WAL persistence setting. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_SYNC_OMITTED 8 #define SQLITE_FCNTL_WIN32_AV_RETRY 9 #define SQLITE_FCNTL_PERSIST_WAL 10 /* ** CAPI3REF: Mutex Handle ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an ** abstract type for a mutex object. The SQLite core never looks ** at the internal representation of an [sqlite3_mutex]. It only |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 | return TCL_ERROR; } } #endif return TCL_OK; } /* ** tclcmd: sqlite3_vfs_list ** ** Return a tcl list containing the names of all registered vfs's. */ static int vfs_list( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 | return TCL_ERROR; } } #endif return TCL_OK; } /* ** 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. */ static int file_control_win32_av_retry( 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 rc; int a[2]; char z[100]; if( objc!=4 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR; rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a); sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]); Tcl_AppendResult(interp, z, (char*)0); return TCL_OK; } /* ** tclcmd: file_control_persist_wal DB PERSIST-FLAG ** ** This TCL command runs the sqlite3_file_control interface with ** the SQLITE_FCNTL_PERSIST_WAL opcode. */ static int file_control_persist_wal( 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 rc; int bPersist; char z[100]; if( objc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ return TCL_ERROR; } 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: sqlite3_vfs_list ** ** Return a tcl list containing the names of all registered vfs's. */ static int vfs_list( |
︙ | ︙ | |||
5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 | #if SQLITE_OS_WIN /* ** Information passed from the main thread into the windows file locker ** background thread. */ struct win32FileLocker { HANDLE h; /* Handle of the file to be locked */ int delay1; /* Delay before locking */ int delay2; /* Delay before unlocking */ int ok; /* Finished ok */ int err; /* True if an error occurs */ }; #endif #if SQLITE_OS_WIN /* ** The background thread that does file locking. */ static void win32_file_locker(void *pAppData){ struct win32FileLocker *p = (struct win32FileLocker*)pAppData; if( p->delay1 ) Sleep(p->delay1); if( LockFile(p->h, 0, 0, 100000000, 0) ){ Sleep(p->delay2); UnlockFile(p->h, 0, 0, 100000000, 0); p->ok = 1; }else{ p->err = 1; | > > > > > > > > | 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 | #if SQLITE_OS_WIN /* ** Information passed from the main thread into the windows file locker ** background thread. */ struct win32FileLocker { char *evName; /* Name of event to signal thread startup */ HANDLE h; /* Handle of the file to be locked */ int delay1; /* Delay before locking */ int delay2; /* Delay before unlocking */ int ok; /* Finished ok */ int err; /* True if an error occurs */ }; #endif #if SQLITE_OS_WIN /* ** The background thread that does file locking. */ static void win32_file_locker(void *pAppData){ struct win32FileLocker *p = (struct win32FileLocker*)pAppData; if( p->evName ){ HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName); if ( ev ){ SetEvent(ev); CloseHandle(ev); } } if( p->delay1 ) Sleep(p->delay1); if( LockFile(p->h, 0, 0, 100000000, 0) ){ Sleep(p->delay2); UnlockFile(p->h, 0, 0, 100000000, 0); p->ok = 1; }else{ p->err = 1; |
︙ | ︙ | |||
5619 5620 5621 5622 5623 5624 5625 | */ static int win32_file_lock( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ | | > > > < | > > > > > > > > > > > > > | 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 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 | */ static int win32_file_lock( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 }; const char *zFilename; char zBuf[200]; int retry = 0; HANDLE ev; DWORD wResult; if( objc!=4 && objc!=1 ){ Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2"); return TCL_ERROR; } if( objc==1 ){ sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d", x.ok, x.err, x.delay1, x.delay2, x.h); Tcl_AppendResult(interp, zBuf, (char*)0); return TCL_OK; } while( x.h && retry<30 ){ retry++; Sleep(100); } if( x.h ){ Tcl_AppendResult(interp, "busy", (char*)0); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR; zFilename = Tcl_GetString(objv[1]); x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if( !x.h ){ Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0); return TCL_ERROR; } ev = CreateEvent(NULL, TRUE, FALSE, x.evName); if ( !ev ){ Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0); return TCL_ERROR; } _beginthread(win32_file_locker, 0, (void*)&x); Sleep(0); if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){ sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult); Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0); CloseHandle(ev); return TCL_ERROR; } CloseHandle(ev); return TCL_OK; } #endif /* ** optimization_control DB OPT BOOLEAN ** ** Enable or disable query optimizations using the sqlite3_test_control() ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true. ** OPT is the name of the optimization to be disabled. |
︙ | ︙ | |||
5888 5889 5890 5891 5892 5893 5894 | { "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 }, | | > > | 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 | { "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_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_persist_wal", file_control_persist_wal, 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 }, |
︙ | ︙ |
Changes to src/test_multiplex.c.
︙ | ︙ | |||
122 123 124 125 126 127 128 | ** makeup a single SQLite DB file. This allows the size of the DB ** to exceed the limits imposed by the file system. ** ** There is an instance of the following object for each defined multiplex ** group. */ struct multiplexGroup { | > > > | | | < | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | ** makeup a single SQLite DB file. This allows the size of the DB ** to exceed the limits imposed by the file system. ** ** There is an instance of the following object for each defined multiplex ** group. */ struct multiplexGroup { struct multiplexReal { /* For each chunk */ sqlite3_file *p; /* Handle for the chunk */ char *z; /* Name of this chunk */ } *aReal; /* list of all chunks */ int nReal; /* Number of chunks */ char *zName; /* Base filename of this group */ int nName; /* Length of base filename */ int flags; /* Flags used for original opening */ unsigned int szChunk; /* Chunk size used for this group */ int bEnabled; /* TRUE to use Multiplex VFS for this file */ multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */ }; /* ** An instance of the following object represents each open connection ** to a file that is multiplex'ed. This object is a |
︙ | ︙ | |||
187 188 189 190 191 192 193 | ** shim, the following mutex must be held. */ sqlite3_mutex *pMutex; /* List of multiplexGroup objects. */ multiplexGroup *pGroups; | < < < < < < | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | ** shim, the following mutex must be held. */ sqlite3_mutex *pMutex; /* List of multiplexGroup objects. */ multiplexGroup *pGroups; } gMultiplex; /************************* Utility Routines *********************************/ /* ** Acquire and release the mutex used to serialize access to the ** list of multiplexGroups. */ |
︙ | ︙ | |||
268 269 270 271 272 273 274 | j = multiplexStrlen30(zBuf); if( (j + 8 + 1 + 3 + 1) <= nBuf ){ /* Make 3 attempts to generate a unique name. */ do { attempts++; sqlite3_randomness(8, &zBuf[j]); for(i=0; i<8; i++){ | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > | | | < | | < | < < | > > | | > | | | < | < | < < < | 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 | j = multiplexStrlen30(zBuf); if( (j + 8 + 1 + 3 + 1) <= nBuf ){ /* Make 3 attempts to generate a unique name. */ do { attempts++; sqlite3_randomness(8, &zBuf[j]); for(i=0; i<8; i++){ unsigned char uc = (unsigned char)zBuf[j+i]; zBuf[j+i] = (char)zChars[uc%(sizeof(zChars)-1)]; } memcpy(&zBuf[j+i], ".tmp", 5); rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists); } while ( (rc==SQLITE_OK) && exists && (attempts<3) ); if( rc==SQLITE_OK && exists ){ rc = SQLITE_ERROR; } } } return rc; } /* Compute the filename for the iChunk-th chunk */ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ if( iChunk>=pGroup->nReal ){ struct multiplexReal *p; p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p)); if( p==0 ){ return SQLITE_NOMEM; } memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal)); pGroup->aReal = p; pGroup->nReal = iChunk+1; } if( pGroup->aReal[iChunk].z==0 ){ char *z; int n = pGroup->nName; pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+3 ); if( z==0 ){ return SQLITE_NOMEM; } memcpy(z, pGroup->zName, n+1); if( iChunk>0 ){ #ifdef SQLITE_ENABLE_8_3_NAMES if( n>3 && z[n-3]=='.' ){ n--; }else if( n>4 && z[n-4]=='.' ){ n -= 2; } #endif sqlite3_snprintf(3,&z[n],"%02d",iChunk); } } return SQLITE_OK; } /* Translate an sqlite3_file* that is really a multiplexGroup* into ** the sqlite3_file* for the underlying original VFS. */ static sqlite3_file *multiplexSubOpen( multiplexGroup *pGroup, int iChunk, int *rc, int *pOutFlags ){ sqlite3_file *pSubOpen = 0; sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ *rc = multiplexSubFilename(pGroup, iChunk); if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){ pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile ); if( pSubOpen==0 ){ *rc = SQLITE_NOMEM; return 0; } pGroup->aReal[iChunk].p = pSubOpen; *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen, pGroup->flags, pOutFlags); if( *rc!=SQLITE_OK ){ sqlite3_free(pSubOpen); pGroup->aReal[iChunk].p = 0; return 0; } } return pSubOpen; } /* ** This is the implementation of the multiplex_control() SQL function. */ static void multiplexControlFunc( sqlite3_context *context, |
︙ | ︙ | |||
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | const sqlite3_api_routines *pApi ){ int rc; rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, 0, multiplexControlFunc, 0, 0); return rc; } /************************* VFS Method Wrappers *****************************/ /* ** This is the xOpen method used for the "multiplex" VFS. ** ** Most of the work is done by the underlying original VFS. This method ** simply links the new file into the appropriate multiplex group if it is a ** file that needs to be tracked. */ static int multiplexOpen( sqlite3_vfs *pVfs, /* The multiplex VFS */ const char *zName, /* Name of file to be opened */ sqlite3_file *pConn, /* Fill in this file descriptor */ int flags, /* Flags to control the opening */ int *pOutFlags /* Flags showing results of opening */ ){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | < > > > > > > | < > | < < < | < < < < < < < | < | > > | | | > > | | < > | < > | | < | < < < > > > > | > < < < > > | | > > > > > > > > > > > > > > > | | > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | 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 | const sqlite3_api_routines *pApi ){ int rc; rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, 0, multiplexControlFunc, 0, 0); return rc; } /* ** Close a single sub-file in the connection group. */ static void multiplexSubClose( multiplexGroup *pGroup, int iChunk, sqlite3_vfs *pOrigVfs ){ sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p; if( pSubOpen ){ pSubOpen->pMethods->xClose(pSubOpen); if( pOrigVfs ) pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0); sqlite3_free(pGroup->aReal[iChunk].p); } sqlite3_free(pGroup->aReal[iChunk].z); memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk])); } /* ** Deallocate memory held by a multiplexGroup */ static void multiplexFreeComponents(multiplexGroup *pGroup){ int i; for(i=0; i<pGroup->nReal; i++){ multiplexSubClose(pGroup, i, 0); } sqlite3_free(pGroup->aReal); pGroup->aReal = 0; pGroup->nReal = 0; } /************************* VFS Method Wrappers *****************************/ /* ** This is the xOpen method used for the "multiplex" VFS. ** ** Most of the work is done by the underlying original VFS. This method ** simply links the new file into the appropriate multiplex group if it is a ** file that needs to be tracked. */ static int multiplexOpen( sqlite3_vfs *pVfs, /* The multiplex VFS */ const char *zName, /* Name of file to be opened */ sqlite3_file *pConn, /* Fill in this file descriptor */ int flags, /* Flags to control the opening */ int *pOutFlags /* Flags showing results of opening */ ){ int rc = SQLITE_OK; /* Result code */ multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */ multiplexGroup *pGroup; /* Corresponding multiplexGroup object */ sqlite3_file *pSubOpen = 0; /* Real file descriptor */ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ int nName; int sz; char *zToFree = 0; UNUSED_PARAMETER(pVfs); memset(pConn, 0, pVfs->szOsFile); /* We need to create a group structure and manage ** access to this group of files. */ multiplexEnter(); pMultiplexOpen = (multiplexConn*)pConn; /* If the second argument to this function is NULL, generate a ** temporary file name to use. This will be handled by the ** original xOpen method. We just need to allocate space for ** it. */ if( !zName ){ zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 ); if( zName==0 ){ rc = SQLITE_NOMEM; }else{ rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree); } } if( rc==SQLITE_OK ){ /* allocate space for group */ nName = multiplexStrlen30(zName); sz = sizeof(multiplexGroup) /* multiplexGroup */ + nName + 1; /* zName */ pGroup = sqlite3_malloc( sz ); if( pGroup==0 ){ rc = SQLITE_NOMEM; } } if( rc==SQLITE_OK ){ /* assign pointers to extra space allocated */ char *p = (char *)&pGroup[1]; pMultiplexOpen->pGroup = pGroup; memset(pGroup, 0, sz); pGroup->bEnabled = -1; pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE; if( flags & SQLITE_OPEN_URI ){ const char *zChunkSize; zChunkSize = sqlite3_uri_parameter(zName, "chunksize"); if( zChunkSize ){ unsigned int n = 0; int i; for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){ n = n*10 + zChunkSize[i] - '0'; } if( n>0 ){ pGroup->szChunk = (n+0xffff)&~0xffff; }else{ /* A zero or negative chunksize disabled the multiplexor */ pGroup->bEnabled = 0; } } } pGroup->zName = p; /* save off base filename, name length, and original open flags */ memcpy(pGroup->zName, zName, nName+1); pGroup->nName = nName; pGroup->flags = flags; rc = multiplexSubFilename(pGroup, 1); if( rc==SQLITE_OK ){ pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags); } if( pSubOpen ){ int exists, rc2, rc3; sqlite3_int64 sz; rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); if( rc2==SQLITE_OK ){ /* If the first overflow file exists and if the size of the main file ** is different from the chunk size, that means the chunk size is set ** set incorrectly. So fix it. ** ** Or, if the first overflow file does not exist and the main file is ** larger than the chunk size, that means the chunk size is too small. ** But we have no way of determining the intended chunk size, so ** just disable the multiplexor all togethre. */ rc3 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z, SQLITE_ACCESS_EXISTS, &exists); if( rc3==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0 && sz!=pGroup->szChunk ){ pGroup->szChunk = sz; }else if( rc3==SQLITE_OK && !exists && sz>pGroup->szChunk ){ pGroup->bEnabled = 0; } } if( pSubOpen->pMethods->iVersion==1 ){ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1; }else{ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2; } /* place this group at the head of our list */ pGroup->pNext = gMultiplex.pGroups; if( gMultiplex.pGroups ) gMultiplex.pGroups->pPrev = pGroup; gMultiplex.pGroups = pGroup; }else{ multiplexFreeComponents(pGroup); sqlite3_free(pGroup); } } multiplexLeave(); sqlite3_free(zToFree); return rc; } /* ** This is the xDelete method used for the "multiplex" VFS. ** It attempts to delete the filename specified. */ static int multiplexDelete( sqlite3_vfs *pVfs, /* The multiplex VFS */ const char *zName, /* Name of file to delete */ int syncDir ){ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ return pOrigVfs->xDelete(pOrigVfs, zName, syncDir); } static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){ return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d); } static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){ return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d); |
︙ | ︙ | |||
581 582 583 584 585 586 587 | ** The group structure for this file is unlinked from ** our list of groups and freed. */ static int multiplexClose(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; | < < < | < < < < < < | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | ** The group structure for this file is unlinked from ** our list of groups and freed. */ static int multiplexClose(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); multiplexFreeComponents(pGroup); /* remove from linked list */ if( pGroup->pNext ) pGroup->pNext->pPrev = pGroup->pPrev; if( pGroup->pPrev ){ pGroup->pPrev->pNext = pGroup->pNext; }else{ gMultiplex.pGroups = pGroup->pNext; } |
︙ | ︙ | |||
619 620 621 622 623 624 625 | sqlite3_int64 iOfst ){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); if( !pGroup->bEnabled ){ | | > > > | > | | | | > | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | sqlite3_int64 iOfst ){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen==0 ){ rc = SQLITE_IOERR_READ; }else{ rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst); } }else{ while( iAmt > 0 ){ int i = (int)(iOfst / pGroup->szChunk); sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL); if( pSubOpen ){ int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk; if( extra<0 ) extra = 0; iAmt -= extra; rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst % pGroup->szChunk); if( rc!=SQLITE_OK ) break; pBuf = (char *)pBuf + iAmt; iOfst += iAmt; iAmt = extra; }else{ rc = SQLITE_IOERR_READ; break; |
︙ | ︙ | |||
659 660 661 662 663 664 665 | sqlite3_int64 iOfst ){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); if( !pGroup->bEnabled ){ | | > > > | > | | | > | > | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | sqlite3_int64 iOfst ){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen==0 ){ rc = SQLITE_IOERR_WRITE; }else{ rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst); } }else{ while( iAmt > 0 ){ int i = (int)(iOfst / pGroup->szChunk); sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL); if( pSubOpen ){ int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk; if( extra<0 ) extra = 0; iAmt -= extra; rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst % pGroup->szChunk); if( rc!=SQLITE_OK ) break; pBuf = (char *)pBuf + iAmt; iOfst += iAmt; iAmt = extra; }else{ rc = SQLITE_IOERR_WRITE; break; |
︙ | ︙ | |||
694 695 696 697 698 699 700 | */ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); if( !pGroup->bEnabled ){ | | > > > | > < | < < < < < < < < < < < < < | < < < < | | | < < | > | > > > | > > | | < < < < < | | | < < < < < < < < < < | | | | | | | | < | | | | | 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 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | */ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexEnter(); if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen==0 ){ rc = SQLITE_IOERR_TRUNCATE; }else{ rc = pSubOpen->pMethods->xTruncate(pSubOpen, size); } }else{ int rc2; int i; sqlite3_file *pSubOpen; sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ /* delete the chunks above the truncate limit */ for(i=(int)(size / pGroup->szChunk)+1; i<pGroup->nReal; i++){ multiplexSubClose(pGroup, i, pOrigVfs); } pSubOpen = multiplexSubOpen(pGroup, (int)(size/pGroup->szChunk), &rc2,0); if( pSubOpen ){ rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk); if( rc2!=SQLITE_OK ) rc = rc2; }else{ rc = SQLITE_IOERR_TRUNCATE; } } multiplexLeave(); return rc; } /* Pass xSync requests through to the original VFS without change */ static int multiplexSync(sqlite3_file *pConn, int flags){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; int i; multiplexEnter(); for(i=0; i<pGroup->nReal; i++){ sqlite3_file *pSubOpen = pGroup->aReal[i].p; if( pSubOpen ){ int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags); if( rc2!=SQLITE_OK ) rc = rc2; } } multiplexLeave(); return rc; } /* Pass xFileSize requests through to the original VFS. ** Aggregate the size of all the chunks before returning. */ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; int rc2; int i; multiplexEnter(); if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen==0 ){ rc = SQLITE_IOERR_FSTAT; }else{ rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize); } }else{ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; *pSize = 0; for(i=0; 1; i++){ sqlite3_file *pSubOpen = 0; int exists = 0; rc = multiplexSubFilename(pGroup, i); if( rc ) break; rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z, SQLITE_ACCESS_EXISTS, &exists); if( rc2==SQLITE_OK && exists){ /* if it exists, open it */ pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL); }else{ /* stop at first "gap" */ break; } if( pSubOpen ){ sqlite3_int64 sz; rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); if( rc2!=SQLITE_OK ){ rc = rc2; }else{ if( sz>pGroup->szChunk ){ rc = SQLITE_IOERR_FSTAT; } *pSize += sz; } }else{ break; } } } multiplexLeave(); return rc; } /* Pass xLock requests through to the original VFS unchanged. */ static int multiplexLock(sqlite3_file *pConn, int lock){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xLock(pSubOpen, lock); } return SQLITE_BUSY; } /* Pass xUnlock requests through to the original VFS unchanged. */ static int multiplexUnlock(sqlite3_file *pConn, int lock){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xUnlock(pSubOpen, lock); } return SQLITE_IOERR_UNLOCK; } /* Pass xCheckReservedLock requests through to the original VFS unchanged. */ static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut); } return SQLITE_IOERR_CHECKRESERVEDLOCK; } /* Pass xFileControl requests through to the original VFS unchanged, |
︙ | ︙ | |||
876 877 878 879 880 881 882 | int bEnabled = *(int *)pArg; pGroup->bEnabled = bEnabled; rc = SQLITE_OK; } break; case MULTIPLEX_CTRL_SET_CHUNK_SIZE: if( pArg ) { | | | | | | < < < < < < | < < | | | | | | | | | 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | int bEnabled = *(int *)pArg; pGroup->bEnabled = bEnabled; rc = SQLITE_OK; } break; case MULTIPLEX_CTRL_SET_CHUNK_SIZE: if( pArg ) { unsigned int szChunk = *(unsigned*)pArg; if( szChunk<1 ){ rc = SQLITE_MISUSE; }else{ /* Round up to nearest multiple of MAX_PAGE_SIZE. */ szChunk = (szChunk + (MAX_PAGE_SIZE-1)); szChunk &= ~(MAX_PAGE_SIZE-1); pGroup->szChunk = szChunk; rc = SQLITE_OK; } } break; case MULTIPLEX_CTRL_SET_MAX_CHUNKS: rc = SQLITE_OK; break; case SQLITE_FCNTL_SIZE_HINT: case SQLITE_FCNTL_CHUNK_SIZE: /* no-op these */ rc = SQLITE_OK; break; default: pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen ){ rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); } break; } return rc; } /* Pass xSectorSize requests through to the original VFS unchanged. */ static int multiplexSectorSize(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xSectorSize(pSubOpen); } return DEFAULT_SECTOR_SIZE; } /* Pass xDeviceCharacteristics requests through to the original VFS unchanged. */ static int multiplexDeviceCharacteristics(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen); } return 0; } /* Pass xShmMap requests through to the original VFS unchanged. */ static int multiplexShmMap( sqlite3_file *pConn, /* Handle open on database file */ int iRegion, /* Region to retrieve */ int szRegion, /* Size of regions */ int bExtend, /* True to extend file if necessary */ void volatile **pp /* OUT: Mapped memory */ ){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp); } return SQLITE_IOERR; } /* Pass xShmLock requests through to the original VFS unchanged. */ static int multiplexShmLock( sqlite3_file *pConn, /* Database file holding the shared memory */ int ofst, /* First lock to acquire or release */ int n, /* Number of locks to acquire or release */ int flags /* What to do with the lock */ ){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags); } return SQLITE_BUSY; } /* Pass xShmBarrier requests through to the original VFS unchanged. */ static void multiplexShmBarrier(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ pSubOpen->pMethods->xShmBarrier(pSubOpen); } } /* Pass xShmUnmap requests through to the original VFS unchanged. */ static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){ multiplexConn *p = (multiplexConn*)pConn; int rc; sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL); if( pSubOpen ){ return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag); } return SQLITE_OK; } /************************** Public Interfaces *****************************/ |
︙ | ︙ | |||
1019 1020 1021 1022 1023 1024 1025 | pOrigVfs = sqlite3_vfs_find(zOrigVfsName); if( pOrigVfs==0 ) return SQLITE_ERROR; assert( pOrigVfs!=&gMultiplex.sThisVfs ); gMultiplex.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); if( !gMultiplex.pMutex ){ return SQLITE_NOMEM; } | < < < < < | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 | pOrigVfs = sqlite3_vfs_find(zOrigVfsName); if( pOrigVfs==0 ) return SQLITE_ERROR; assert( pOrigVfs!=&gMultiplex.sThisVfs ); gMultiplex.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); if( !gMultiplex.pMutex ){ return SQLITE_NOMEM; } gMultiplex.pGroups = NULL; gMultiplex.isInitialized = 1; gMultiplex.pOrigVfs = pOrigVfs; gMultiplex.sThisVfs = *pOrigVfs; gMultiplex.sThisVfs.szOsFile += sizeof(multiplexConn); gMultiplex.sThisVfs.zName = SQLITE_MULTIPLEX_VFS_NAME; gMultiplex.sThisVfs.xOpen = multiplexOpen; |
︙ | ︙ | |||
1056 1057 1058 1059 1060 1061 1062 | gMultiplex.sIoMethodsV1.xSync = multiplexSync; gMultiplex.sIoMethodsV1.xFileSize = multiplexFileSize; gMultiplex.sIoMethodsV1.xLock = multiplexLock; gMultiplex.sIoMethodsV1.xUnlock = multiplexUnlock; gMultiplex.sIoMethodsV1.xCheckReservedLock = multiplexCheckReservedLock; gMultiplex.sIoMethodsV1.xFileControl = multiplexFileControl; gMultiplex.sIoMethodsV1.xSectorSize = multiplexSectorSize; | | > | 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 | gMultiplex.sIoMethodsV1.xSync = multiplexSync; gMultiplex.sIoMethodsV1.xFileSize = multiplexFileSize; gMultiplex.sIoMethodsV1.xLock = multiplexLock; gMultiplex.sIoMethodsV1.xUnlock = multiplexUnlock; gMultiplex.sIoMethodsV1.xCheckReservedLock = multiplexCheckReservedLock; gMultiplex.sIoMethodsV1.xFileControl = multiplexFileControl; gMultiplex.sIoMethodsV1.xSectorSize = multiplexSectorSize; gMultiplex.sIoMethodsV1.xDeviceCharacteristics = multiplexDeviceCharacteristics; gMultiplex.sIoMethodsV2 = gMultiplex.sIoMethodsV1; gMultiplex.sIoMethodsV2.iVersion = 2; gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap; gMultiplex.sIoMethodsV2.xShmLock = multiplexShmLock; gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier; gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap; sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault); |
︙ | ︙ | |||
1083 1084 1085 1086 1087 1088 1089 | ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ int sqlite3_multiplex_shutdown(void){ if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; if( gMultiplex.pGroups ) return SQLITE_MISUSE; gMultiplex.isInitialized = 0; | < | 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ int sqlite3_multiplex_shutdown(void){ if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; if( gMultiplex.pGroups ) return SQLITE_MISUSE; gMultiplex.isInitialized = 0; sqlite3_mutex_free(gMultiplex.pMutex); sqlite3_vfs_unregister(&gMultiplex.sThisVfs); memset(&gMultiplex, 0, sizeof(gMultiplex)); return SQLITE_OK; } /***************************** Test Code ***********************************/ |
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | Tcl_NewStringObj(pGroup->zName, -1)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->nName)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->flags)); /* count number of chunks with open handles */ | | | | | | 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 | Tcl_NewStringObj(pGroup->zName, -1)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->nName)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->flags)); /* count number of chunks with open handles */ for(i=0; i<pGroup->nReal; i++){ if( pGroup->aReal[i].p!=0 ) nChunks++; } Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(nChunks)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->szChunk)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->nReal)); Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); } multiplexLeave(); Tcl_SetObjResult(interp, pResult); return TCL_OK; } |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | if( x>=0 ) return x; if( x==(int)0x80000000 ) return 0x7fffffff; return -x; } #ifdef SQLITE_ENABLE_8_3_NAMES /* | | > > > > | > > | 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 | if( x>=0 ) return x; if( x==(int)0x80000000 ) return 0x7fffffff; return -x; } #ifdef SQLITE_ENABLE_8_3_NAMES /* ** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database ** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and ** if filename in z[] has a suffix (a.k.a. "extension") that is longer than ** three characters, then shorten the suffix on z[] to be the last three ** characters of the original suffix. ** ** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always ** do the suffix shortening regardless of URI parameter. ** ** Examples: ** ** test.db-journal => test.nal ** test.db-wal => test.wal ** test.db-shm => test.shm */ void sqlite3FileSuffix3(const char *zBaseFilename, char *z){ #if SQLITE_ENABLE_8_3_NAMES<2 const char *zOk; zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names"); if( zOk && sqlite3GetBoolean(zOk) ) #endif { int i, sz; sz = sqlite3Strlen30(z); for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4); } } #endif |
Changes to src/vdbe.c.
︙ | ︙ | |||
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 | assert( pOut<=&aMem[p->nMem] ); assert( pIn1<=&aMem[p->nMem] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); zMalloc = pOut->zMalloc; pOut->zMalloc = 0; sqlite3VdbeMemMove(pOut, pIn1); pIn1->zMalloc = zMalloc; REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; } break; } | > > > > > | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | assert( pOut<=&aMem[p->nMem] ); assert( pIn1<=&aMem[p->nMem] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); zMalloc = pOut->zMalloc; pOut->zMalloc = 0; sqlite3VdbeMemMove(pOut, pIn1); #ifdef SQLITE_DEBUG if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ pOut->pScopyFrom += p1 - pOp->p2; } #endif pIn1->zMalloc = zMalloc; REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; } break; } |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
327 328 329 330 331 332 333 | /* ** Initialize the temporary index cursor just opened as a sorter cursor. */ int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ assert( pCsr->pKeyInfo && pCsr->pBt ); pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter)); | | | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | /* ** Initialize the temporary index cursor just opened as a sorter cursor. */ int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ assert( pCsr->pKeyInfo && pCsr->pBt ); pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter)); return (pCsr->pSorter ? SQLITE_OK : SQLITE_NOMEM); } /* ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines. */ void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ VdbeSorter *pSorter = pCsr->pSorter; |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 | ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); if( rc==SQLITE_OK ){ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } rc = sqlite3WalCheckpoint( pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 ); | > > | | 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 | ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); if( rc==SQLITE_OK ){ int bPersistWal = -1; if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } rc = sqlite3WalCheckpoint( pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 ); sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersistWal); if( rc==SQLITE_OK && bPersistWal!=1 ){ isDelete = 1; } } walIndexClose(pWal, isDelete); sqlite3OsClose(pWal->pWalFd); if( isDelete ){ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 | ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); testcase( pTerm->eOperator==WO_IN ); testcase( pTerm->eOperator==WO_ISNULL ); if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; nTerm++; } /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. */ | > | 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 | ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); testcase( pTerm->eOperator==WO_IN ); testcase( pTerm->eOperator==WO_ISNULL ); if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; nTerm++; } /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. */ |
︙ | ︙ | |||
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); testcase( pTerm->eOperator==WO_IN ); testcase( pTerm->eOperator==WO_ISNULL ); if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; pIdxCons[j].op = (u8)pTerm->eOperator; /* The direct assignment in the previous line is possible only because ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The ** following asserts verify this fact. */ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); | > | 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); testcase( pTerm->eOperator==WO_IN ); testcase( pTerm->eOperator==WO_ISNULL ); if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; pIdxCons[j].op = (u8)pTerm->eOperator; /* The direct assignment in the previous line is possible only because ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The ** following asserts verify this fact. */ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
︙ | ︙ | |||
3107 3108 3109 3110 3111 3112 3113 | nRow = (double)(aiRowEst[nEq] * nInMul); if( bInEst && nRow*2>aiRowEst[0] ){ nRow = aiRowEst[0]/2; nInMul = (int)(nRow / aiRowEst[nEq]); } #ifdef SQLITE_ENABLE_STAT2 | | > | | 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 | nRow = (double)(aiRowEst[nEq] * nInMul); if( bInEst && nRow*2>aiRowEst[0] ){ nRow = aiRowEst[0]/2; nInMul = (int)(nRow / aiRowEst[nEq]); } #ifdef SQLITE_ENABLE_STAT2 /* If the constraint is of the form x=VALUE or x IN (E1,E2,...) ** and we do not think that values of x are unique and if histogram ** data is available for column x, then it might be possible ** to get a better estimate on the number of rows based on ** VALUE and how common that value is according to the histogram. */ if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){ if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ testcase( pFirstTerm->eOperator==WO_EQ ); testcase( pFirstTerm->eOperator==WO_ISNULL ); whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow); }else if( pFirstTerm->eOperator==WO_IN && bInEst==0 ){ whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow); } |
︙ | ︙ |
Changes to test/8_3_names.test.
︙ | ︙ | |||
63 64 65 66 67 68 69 | } file exists test.db-journal } 0 do_test 8_3_names-2.1 { file exists test.nal } 1 forcedelete test2.db test2.nal test2.db-journal | | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | } file exists test.db-journal } 0 do_test 8_3_names-2.1 { file exists test.nal } 1 forcedelete test2.db test2.nal test2.db-journal copy_file test.db test2.db copy_file test.nal test2.nal do_test 8_3_names-2.2 { db eval { COMMIT; SELECT length(x) FROM t1 } } 15000 do_test 8_3_names-2.3 { |
︙ | ︙ | |||
97 98 99 100 101 102 103 | } file exists test.db-journal } 1 do_test 8_3_names-3.1 { file exists test.nal } 0 forcedelete test2.db test2.nal test2.db-journal | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | } file exists test.db-journal } 1 do_test 8_3_names-3.1 { file exists test.nal } 0 forcedelete test2.db test2.nal test2.db-journal copy_file test.db test2.db copy_file test.db-journal test2.db-journal do_test 8_3_names-3.2 { db eval { COMMIT; SELECT length(x) FROM t1 } } 15000 do_test 8_3_names-3.3 { |
︙ | ︙ |
Changes to test/alter.test.
︙ | ︙ | |||
217 218 219 220 221 222 223 | index {sqlite_autoindex_<t2>_2} <t2> \ ] # Check that ALTER TABLE works on attached databases. # ifcapable attach { do_test alter-1.8.1 { | | | | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | index {sqlite_autoindex_<t2>_2} <t2> \ ] # Check that ALTER TABLE works on attached databases. # ifcapable attach { do_test alter-1.8.1 { forcedelete test2.db forcedelete test2.db-journal execsql { ATTACH 'test2.db' AS aux; } } {} do_test alter-1.8.2 { execsql { CREATE TABLE t4(a PRIMARY KEY, b, c); |
︙ | ︙ | |||
408 409 410 411 412 413 414 | INSERT INTO t9 VALUES(4, 5, 6); } set ::TRIGGER } {trig3 4 5 6} # Make sure "ON" cannot be used as a database, table or column name without # quoting. Otherwise the sqlite_alter_trigger() function might not work. | | | | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 | INSERT INTO t9 VALUES(4, 5, 6); } set ::TRIGGER } {trig3 4 5 6} # Make sure "ON" cannot be used as a database, table or column name without # quoting. Otherwise the sqlite_alter_trigger() function might not work. forcedelete test3.db forcedelete test3.db-journal ifcapable attach { do_test alter-3.2.1 { catchsql { ATTACH 'test3.db' AS ON; } } {1 {near "ON": syntax error}} do_test alter-3.2.2 { |
︙ | ︙ |
Changes to test/alter2.test.
︙ | ︙ | |||
311 312 313 314 315 316 317 | db close set_file_format 2 sqlite3 db test.db get_file_format } {2} ifcapable attach { do_test alter2-6.2 { | | | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | db close set_file_format 2 sqlite3 db test.db get_file_format } {2} ifcapable attach { do_test alter2-6.2 { forcedelete test2.db-journal forcedelete test2.db execsql { ATTACH 'test2.db' AS aux; CREATE TABLE aux.t1(a, b); } get_file_format test2.db } $default_file_format } |
︙ | ︙ |
Changes to test/alter3.test.
︙ | ︙ | |||
192 193 194 195 196 197 198 | PRAGMA schema_version; } } {11} } do_test alter3-4.1 { db close | | | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | PRAGMA schema_version; } } {11} } do_test alter3-4.1 { db close forcedelete test.db set ::DB [sqlite3 db test.db] execsql { PRAGMA legacy_file_format=ON; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 100); INSERT INTO t1 VALUES(2, 300); SELECT * FROM t1; |
︙ | ︙ | |||
233 234 235 236 237 238 239 | execsql { DROP TABLE t1; } } {} ifcapable attach { do_test alter3-5.1 { | | | | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | execsql { DROP TABLE t1; } } {} ifcapable attach { do_test alter3-5.1 { forcedelete test2.db forcedelete test2.db-journal execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); ATTACH 'test2.db' AS aux; CREATE TABLE aux.t1 AS SELECT * FROM t1; PRAGMA aux.schema_version = 30; |
︙ | ︙ |
Changes to test/alter4.test.
︙ | ︙ | |||
174 175 176 177 178 179 180 | PRAGMA schema_version; } } {10} } do_test alter4-4.1 { db close | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | PRAGMA schema_version; } } {10} } do_test alter4-4.1 { db close forcedelete test.db set ::DB [sqlite3 db test.db] execsql { CREATE TEMP TABLE t1(a, b); INSERT INTO t1 VALUES(1, 100); INSERT INTO t1 VALUES(2, 300); SELECT * FROM t1; } |
︙ | ︙ | |||
209 210 211 212 213 214 215 | execsql { DROP TABLE t1; } } {} ifcapable attach { do_test alter4-5.1 { | | | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | execsql { DROP TABLE t1; } } {} ifcapable attach { do_test alter4-5.1 { forcedelete test2.db forcedelete test2.db-journal execsql { CREATE TEMP TABLE t1(a, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); ATTACH 'test2.db' AS aux; CREATE TABLE aux.t1 AS SELECT * FROM t1; PRAGMA aux.schema_version = 30; |
︙ | ︙ |
Changes to test/analyze.test.
︙ | ︙ | |||
282 283 284 285 286 287 288 289 290 291 292 293 294 295 | } db close sqlite3 db test.db execsql { SELECT * FROM t4 WHERE x=1234; } } {} # This test corrupts the database file so it must be the last test # in the series. # do_test analyze-99.1 { execsql { PRAGMA writable_schema=on; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } db close sqlite3 db test.db execsql { SELECT * FROM t4 WHERE x=1234; } } {} # Verify that DROP TABLE and DROP INDEX remove entries from the # sqlite_stat1 and sqlite_stat2 tables. # do_test analyze-5.0 { execsql { DELETE FROM t3; DELETE FROM t4; INSERT INTO t3 VALUES(1,2,3,4); INSERT INTO t3 VALUES(5,6,7,8); INSERT INTO t3 SELECT a+8, b+8, c+8, d+8 FROM t3; INSERT INTO t3 SELECT a+16, b+16, c+16, d+16 FROM t3; INSERT INTO t3 SELECT a+32, b+32, c+32, d+32 FROM t3; INSERT INTO t3 SELECT a+64, b+64, c+64, d+64 FROM t3; INSERT INTO t4 SELECT a, b, c FROM t3; ANALYZE; SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4} ifcapable stat2 { do_test analyze-5.1 { execsql { SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1; } } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4} } do_test analyze-5.2 { execsql { DROP INDEX t3i2; SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t3i1 t3i3 t4i1 t4i2 t3 t4} ifcapable stat2 { do_test analyze-5.3 { execsql { SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1; } } {t3i1 t3i3 t4i1 t4i2 t3 t4} } do_test analyze-5.4 { execsql { DROP TABLE t3; SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t4i1 t4i2 t4} ifcapable stat2 { do_test analyze-5.5 { execsql { SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1; } } {t4i1 t4i2 t4} } # This test corrupts the database file so it must be the last test # in the series. # do_test analyze-99.1 { execsql { PRAGMA writable_schema=on; |
︙ | ︙ |
Changes to test/async.test.
︙ | ︙ | |||
64 65 66 67 68 69 70 | foreach testfile [lsort -dictionary [glob $testdir/*.test]] { set tail [file tail $testfile] if {[lsearch -exact $ASYNC_INCLUDE $tail]<0} continue source $testfile # Make sure everything is flushed through. This is because [source]ing # the next test file will delete the database file on disk (using | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | foreach testfile [lsort -dictionary [glob $testdir/*.test]] { set tail [file tail $testfile] if {[lsearch -exact $ASYNC_INCLUDE $tail]<0} continue source $testfile # Make sure everything is flushed through. This is because [source]ing # the next test file will delete the database file on disk (using # [delete_file]). If the asynchronous backend still has the file # open, it will become confused. # flush_async_queue } # Flush the write-queue and disable asynchronous IO. This should ensure # all allocated memory is cleaned up. |
︙ | ︙ |
Changes to test/async2.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 | db close foreach err [list ioerr malloc-transient malloc-persistent] { set ::go 10 for {set n 1} {$::go} {incr n} { set ::sqlite_io_error_pending 0 sqlite3_memdebug_fail -1 | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | db close foreach err [list ioerr malloc-transient malloc-persistent] { set ::go 10 for {set n 1} {$::go} {incr n} { set ::sqlite_io_error_pending 0 sqlite3_memdebug_fail -1 forcedelete test.db test.db-journal sqlite3 db test.db execsql $::setup_script db close sqlite3async_initialize "" 1 sqlite3 db test.db sqlite3_db_config_lookaside db 0 0 0 |
︙ | ︙ |
Changes to test/async3.test.
︙ | ︙ | |||
37 38 39 40 41 42 43 | chocolate/banana/./vanilla/file.db chocolate/banana/../banana/vanilla/file.db chocolate/banana/./vanilla/extra_bit/../file.db } do_test async3-1.0 { file mkdir [file join chocolate banana vanilla] | | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | chocolate/banana/./vanilla/file.db chocolate/banana/../banana/vanilla/file.db chocolate/banana/./vanilla/extra_bit/../file.db } do_test async3-1.0 { file mkdir [file join chocolate banana vanilla] forcedelete chocolate/banana/vanilla/file.db forcedelete chocolate/banana/vanilla/file.db-journal } {} do_test async3-1.1 { sqlite3 db chocolate/banana/vanilla/file.db execsql { CREATE TABLE abc(a, b, c); BEGIN; |
︙ | ︙ |
Changes to test/async5.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | if {[info commands sqlite3async_initialize] eq ""} { # The async logic is not built into this system finish_test return } db close | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | if {[info commands sqlite3async_initialize] eq ""} { # The async logic is not built into this system finish_test return } db close forcedelete test2.db sqlite3async_initialize "" 1 sqlite3async_control halt never sqlite3 db test.db do_test async5-1.1 { execsql { ATTACH 'test2.db' AS next; |
︙ | ︙ |
Changes to test/attach.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | ifcapable !attach { finish_test return } for {set i 2} {$i<=15} {incr i} { | | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ifcapable !attach { finish_test return } for {set i 2} {$i<=15} {incr i} { forcedelete test$i.db forcedelete test$i.db-journal } do_test attach-1.1 { execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); |
︙ | ︙ | |||
624 625 626 627 628 629 630 | # Tests for the sqliteFix...() routines in attach.c # ifcapable {trigger} { do_test attach-5.1 { db close sqlite3 db test.db db2 close | | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | # Tests for the sqliteFix...() routines in attach.c # ifcapable {trigger} { do_test attach-5.1 { db close sqlite3 db test.db db2 close forcedelete test2.db sqlite3 db2 test2.db catchsql { ATTACH DATABASE 'test.db' AS orig; CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN SELECT 'no-op'; END; } db2 |
︙ | ︙ | |||
721 722 723 724 725 726 727 | do_test attach-6.2 { 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 ****" | | | | | | | 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 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | do_test attach-6.2 { 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 } 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 { CREATE TABLE no_such_db.t1(a, b, c); } } {1 {unknown database no_such_db}} for {set i 2} {$i<=15} {incr i} { catch {db$i close} } db close forcedelete test2.db forcedelete no-such-file ifcapable subquery { do_test attach-7.1 { forcedelete test.db test.db-journal sqlite3 db test.db catchsql { DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL ) } } {1 {no such table: AAAAAA}} } |
︙ | ︙ | |||
773 774 775 776 777 778 779 | catchsql { ATTACH 'test2.db' AS t2; } } {1 {file is encrypted or is not a database}} do_test attach-8.2 { db errorcode } {26} | | | | | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 | catchsql { ATTACH 'test2.db' AS t2; } } {1 {file is encrypted or is not a database}} do_test attach-8.2 { db errorcode } {26} forcedelete test2.db do_test attach-8.3 { sqlite3 db2 test2.db db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE} catchsql { ATTACH 'test2.db' AS t2; } } {1 {database is locked}} do_test attach-8.4 { db errorcode } {5} db2 close forcedelete test2.db # Test that it is possible to attach the same database more than # once when not in shared-cache mode. That this is not possible in # shared-cache mode is tested in shared7.test. do_test attach-9.1 { forcedelete test4.db execsql { ATTACH 'test4.db' AS aux1; CREATE TABLE aux1.t1(a, b); INSERT INTO aux1.t1 VALUES(1, 2); ATTACH 'test4.db' AS aux2; SELECT * FROM aux2.t1; } |
︙ | ︙ |
Changes to test/attach2.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 | # sure we can attach test2.db from test.db. # do_test attach2-1.1 { db eval { CREATE TABLE t1(a,b); CREATE INDEX x1 ON t1(a); } | | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # sure we can attach test2.db from test.db. # do_test attach2-1.1 { db eval { CREATE TABLE t1(a,b); CREATE INDEX x1 ON t1(a); } forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db db2 eval { CREATE TABLE t1(a,b); CREATE INDEX x1 ON t1(a); } catchsql { ATTACH 'test2.db' AS t2; |
︙ | ︙ | |||
323 324 325 326 327 328 329 | } {} do_test attach2-4.15 { execsql {SELECT * FROM t1} db2 } {1 2 1 2} db close db2 close | | | | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | } {} do_test attach2-4.15 { execsql {SELECT * FROM t1} db2 } {1 2 1 2} db close db2 close forcedelete test2.db sqlite3_soft_heap_limit $soft_limit # These tests - attach2-5.* - check that the master journal file is deleted # correctly when a multi-file transaction is committed or rolled back. # # Update: It's not actually created if a rollback occurs, so that test # doesn't really prove too much. foreach f [glob test.db*] {forcedelete $f} do_test attach2-5.1 { sqlite3 db test.db execsql { ATTACH 'test.db2' AS aux; } } {} do_test attach2-5.2 { |
︙ | ︙ |
Changes to test/attach3.test.
︙ | ︙ | |||
31 32 33 34 35 36 37 | # Create tables t1 and t2 in the main database execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } # Create tables t1 and t2 in database file test2.db | | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | # Create tables t1 and t2 in the main database execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } # Create tables t1 and t2 in database file test2.db forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } db2 db2 close |
︙ | ︙ |
Changes to test/attachmalloc.test.
︙ | ︙ | |||
25 26 27 28 29 30 31 | source $testdir/malloc_common.tcl do_malloc_test attachmalloc-1 -tclprep { catch { db close } for {set i 2} {$i<=4} {incr i} { catch { db$i close } | | | | | | 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 | source $testdir/malloc_common.tcl do_malloc_test attachmalloc-1 -tclprep { catch { db close } for {set i 2} {$i<=4} {incr i} { catch { db$i close } forcedelete test$i.db forcedelete test$i.db-journal } } -tclbody { if {[catch {sqlite3 db test.db}]} { error "out of memory" } sqlite3_db_config_lookaside db 0 0 0 sqlite3_extended_result_codes db 1 } -sqlbody { ATTACH 'test2.db' AS two; CREATE TABLE two.t1(x); ATTACH 'test3.db' AS three; CREATE TABLE three.t1(x); ATTACH 'test4.db' AS four; CREATE TABLE four.t1(x); } do_malloc_test attachmalloc-2 -tclprep { forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db db2 eval { CREATE TABLE t1(a, b, c); CREATE INDEX i1 ON t1(a, b); } db2 close } -sqlbody { |
︙ | ︙ |
Changes to test/autoinc.test.
︙ | ︙ | |||
423 424 425 426 427 428 429 | } {} } # Make sure AUTOINCREMENT works on ATTACH-ed tables. # ifcapable tempdb&&attach { do_test autoinc-5.1 { | | | | 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | } {} } # Make sure AUTOINCREMENT works on ATTACH-ed tables. # ifcapable tempdb&&attach { do_test autoinc-5.1 { forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db execsql { CREATE TABLE t4(m INTEGER PRIMARY KEY AUTOINCREMENT, n); CREATE TABLE t5(o, p INTEGER PRIMARY KEY AUTOINCREMENT); } db2; execsql { ATTACH 'test2.db' as aux; |
︙ | ︙ | |||
516 517 518 519 520 521 522 | # Ticket #1283. Make sure that preparing but never running a statement # that creates the sqlite_sequence table does not mess up the database. # do_test autoinc-8.1 { catch {db2 close} catch {db close} | | | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | # Ticket #1283. Make sure that preparing but never running a statement # that creates the sqlite_sequence table does not mess up the database. # do_test autoinc-8.1 { catch {db2 close} catch {db close} forcedelete test.db sqlite3 db test.db set DB [sqlite3_connection_pointer db] set STMT [sqlite3_prepare $DB { CREATE TABLE t1( x INTEGER PRIMARY KEY AUTOINCREMENT ) } -1 TAIL] |
︙ | ︙ |
Changes to test/autovacuum.test.
︙ | ︙ | |||
463 464 465 466 467 468 469 | PRAGMA auto_vacuum = 0; PRAGMA auto_vacuum; } } {1} do_test autovacuum-3.4 { db close | | | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | PRAGMA auto_vacuum = 0; PRAGMA auto_vacuum; } } {1} do_test autovacuum-3.4 { db close forcedelete test.db sqlite3 db test.db execsql { PRAGMA auto_vacuum; } } $AUTOVACUUM do_test autovacuum-3.5 { execsql { |
︙ | ︙ | |||
498 499 500 501 502 503 504 | # rolled back no corruption occurs. # do_test autovacuum-4.0 { # The last round of tests may have left the db in non-autovacuum mode. # Reset everything just in case. # db close | | | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | # rolled back no corruption occurs. # do_test autovacuum-4.0 { # The last round of tests may have left the db in non-autovacuum mode. # Reset everything just in case. # db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA auto_vacuum = 1; PRAGMA auto_vacuum; } } {1} do_test autovacuum-4.1 { |
︙ | ︙ | |||
595 596 597 598 599 600 601 | #--------------------------------------------------------------------- # Test cases autovacuum-7.X test the case where a page must be moved # and the destination location collides with at least one other # entry in the page hash-table (internal to the pager.c module. # do_test autovacuum-7.1 { db close | | | | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | #--------------------------------------------------------------------- # Test cases autovacuum-7.X test the case where a page must be moved # and the destination location collides with at least one other # entry in the page hash-table (internal to the pager.c module. # do_test autovacuum-7.1 { db close forcedelete test.db forcedelete test.db-journal sqlite3 db test.db execsql { PRAGMA auto_vacuum=1; CREATE TABLE t1(a, b, PRIMARY KEY(a, b)); INSERT INTO t1 VALUES(randstr(400,400),randstr(400,400)); INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2 |
︙ | ︙ |
Changes to test/autovacuum_ioerr2.test.
︙ | ︙ | |||
71 72 73 74 75 76 77 | BEGIN; INSERT INTO abc2 VALUES(10); DROP TABLE abc; COMMIT; DROP TABLE abc2; } | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | BEGIN; INSERT INTO abc2 VALUES(10); DROP TABLE abc; COMMIT; DROP TABLE abc2; } forcedelete backup.db ifcapable subquery { do_ioerr_test autovacuum-ioerr2-4 -tclprep { if {![file exists backup.db]} { sqlite3 dbb backup.db execsql { PRAGMA auto_vacuum = 1; BEGIN; |
︙ | ︙ | |||
95 96 97 98 99 100 101 | execsql { COMMIT; PRAGMA cache_size = 10; } dbb dbb close } db close | | | | | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | execsql { COMMIT; PRAGMA cache_size = 10; } dbb dbb close } db close forcedelete test.db forcedelete test.db-journal forcecopy backup.db test.db set ::DB [sqlite3 db test.db] execsql { PRAGMA cache_size = 10; } } -sqlbody { BEGIN; DELETE FROM abc WHERE oid < 3; |
︙ | ︙ |
Changes to test/backcompat.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 | puts -nonewline "Testing against $bin - " flush stdout puts "version [get_version $bin]" } proc do_backcompat_test {rv bin1 bin2 script} { | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | puts -nonewline "Testing against $bin - " flush stdout puts "version [get_version $bin]" } proc do_backcompat_test {rv bin1 bin2 script} { forcedelete test.db if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] } set ::bc_chan2 [launch_testfixture $bin2] if { $rv } { proc code2 {tcl} { uplevel #0 $tcl } if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } } |
︙ | ︙ | |||
148 149 150 151 152 153 154 | set ret [list] foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] } set ret } proc write_file_system {data} { foreach f {test.db test.db-journal test.db-wal} d $data { if {[string length $d] == 0} { | | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | set ret [list] foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] } set ret } proc write_file_system {data} { foreach f {test.db test.db-journal test.db-wal} d $data { if {[string length $d] == 0} { forcedelete $f } else { write_file $f $d } } } #------------------------------------------------------------------------- |
︙ | ︙ |
Changes to test/backup.test.
︙ | ︙ | |||
69 70 71 72 73 74 75 | # Sanity check to verify that the [test_contents] proc works. # test_contents backup-1.2 db main db main # Check that it is possible to create and finish backup operations. # do_test backup-1.3.1 { | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | # Sanity check to verify that the [test_contents] proc works. # test_contents backup-1.2 db main db main # Check that it is possible to create and finish backup operations. # do_test backup-1.3.1 { delete_file test2.db sqlite3 db2 test2.db sqlite3_backup B db2 main db main } {B} do_test backup-1.3.2 { B finish } {SQLITE_OK} do_test backup-1.3.3 { |
︙ | ︙ | |||
164 165 166 167 168 169 170 | set file_dest temp }] { foreach rows_dest {0 3 10} { foreach pgsz_dest {512 1024 2048} { foreach nPagePerStep {1 200} { # Open the databases. | | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | set file_dest temp }] { foreach rows_dest {0 3 10} { foreach pgsz_dest {512 1024 2048} { foreach nPagePerStep {1 200} { # Open the databases. catch { delete_file test.db } catch { delete_file test2.db } eval $zOpenScript # Set to true if copying to an in-memory destination. Copying to an # in-memory destination is only possible if the initial destination # page size is the same as the source page size (in this case 1024 bytes). # set isMemDest [expr { |
︙ | ︙ | |||
275 276 277 278 279 280 281 | # * Target database page-size is smaller than the source. # set iTest 1 foreach nSrcPg {10 64 65 66 100} { foreach nDestRow {10 100} { foreach nDestPgsz {512 1024 2048 4096} { | | | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | # * Target database page-size is smaller than the source. # set iTest 1 foreach nSrcPg {10 64 65 66 100} { foreach nDestRow {10 100} { foreach nDestPgsz {512 1024 2048 4096} { catch { delete_file test.db } catch { delete_file test2.db } sqlite3 db test.db sqlite3 db2 test2.db # Set up the content of the two databases. # execsql { PRAGMA page_size = 1024 } execsql "PRAGMA page_size = $nDestPgsz" db2 |
︙ | ︙ | |||
323 324 325 326 327 328 329 | incr iTest } } } #-------------------------------------------------------------------- do_test backup-3.$iTest.1 { | | | | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | incr iTest } } } #-------------------------------------------------------------------- do_test backup-3.$iTest.1 { catch { forcedelete test.db } catch { forcedelete test2.db } sqlite3 db test.db set iTab 1 db eval { PRAGMA page_size = 512 } while {[file size test.db] <= $::sqlite_pending_byte} { db eval "CREATE TABLE t${iTab}(a, b, c)" incr iTab |
︙ | ︙ | |||
388 389 390 391 392 393 394 | catch { sqlite3_backup B db main db2 aux } } {1} do_test backup-4.1.4 { sqlite3_errmsg db } {unknown database aux} do_test backup-4.2.1 { | | | | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | catch { sqlite3_backup B db main db2 aux } } {1} do_test backup-4.1.4 { sqlite3_errmsg db } {unknown database aux} do_test backup-4.2.1 { catch { forcedelete test3.db } catch { forcedelete test4.db } execsql { ATTACH 'test3.db' AS aux1; CREATE TABLE aux1.t1(a, b); } execsql { ATTACH 'test4.db' AS aux2; CREATE TABLE aux2.t2(a, b); |
︙ | ︙ | |||
435 436 437 438 439 440 441 | set rc [catch {sqlite3_backup B db main db aux1}] list $rc [sqlite3_errcode db] [sqlite3_errmsg db] } {1 SQLITE_ERROR {source and destination must be distinct}} db close db2 close do_test backup-4.5.1 { | | | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | set rc [catch {sqlite3_backup B db main db aux1}] list $rc [sqlite3_errcode db] [sqlite3_errmsg db] } {1 SQLITE_ERROR {source and destination must be distinct}} db close db2 close do_test backup-4.5.1 { catch { forcedelete test.db } sqlite3 db test.db sqlite3 db2 :memory: execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } execsql { |
︙ | ︙ | |||
487 488 489 490 491 492 493 | # # 1) Backing up file-to-file. The writer writes via an external pager. # 2) Backing up file-to-file. The writer writes via the same pager as # is used by the backup operation. # 3) Backing up memory-to-file. # set iTest 0 | | | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | # # 1) Backing up file-to-file. The writer writes via an external pager. # 2) Backing up file-to-file. The writer writes via the same pager as # is used by the backup operation. # 3) Backing up memory-to-file. # set iTest 0 forcedelete bak.db-wal foreach {writer file} {db test.db db3 test.db db :memory:} { incr iTest catch { delete_file bak.db } sqlite3 db2 bak.db catch { delete_file $file } sqlite3 db $file sqlite3 db3 $file do_test backup-5.$iTest.1.1 { execsql { BEGIN; CREATE TABLE t1(a, b); |
︙ | ︙ | |||
593 594 595 596 597 598 599 | } {SQLITE_OK} integrity_check backup-5.$iTest.4.5 db2 test_contents backup-5.$iTest.4.6 db main db2 main catch {db close} catch {db2 close} catch {db3 close} | | | | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | } {SQLITE_OK} integrity_check backup-5.$iTest.4.5 db2 test_contents backup-5.$iTest.4.6 db main db2 main catch {db close} catch {db2 close} catch {db3 close} catch { delete_file bak.db } sqlite3 db2 bak.db catch { delete_file $file } sqlite3 db $file sqlite3 db3 $file do_test backup-5.$iTest.5.1 { execsql { PRAGMA auto_vacuum = incremental; BEGIN; CREATE TABLE t1(a, b); |
︙ | ︙ | |||
640 641 642 643 644 645 646 | # End of backup-5.* tests. #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Test the sqlite3_backup_remaining() and backup_pagecount() APIs. # do_test backup-6.1 { | | | | 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 | # End of backup-5.* tests. #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Test the sqlite3_backup_remaining() and backup_pagecount() APIs. # do_test backup-6.1 { catch { forcedelete test.db } catch { forcedelete test2.db } sqlite3 db test.db sqlite3 db2 test2.db execsql { BEGIN; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); INSERT INTO t1 VALUES(1, randstr(1000,1000)); |
︙ | ︙ | |||
697 698 699 700 701 702 703 | # backup-7.2.*: Attempt to step the backup process while a # write-transaction is underway on the source pager (return # SQLITE_LOCKED). # # backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY). # do_test backup-7.0 { | | | | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | # backup-7.2.*: Attempt to step the backup process while a # write-transaction is underway on the source pager (return # SQLITE_LOCKED). # # backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY). # do_test backup-7.0 { catch { forcedelete test.db } catch { forcedelete test2.db } sqlite3 db2 test2.db sqlite3 db test.db execsql { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); INSERT INTO t1 VALUES(1, randstr(1000,1000)); INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1; |
︙ | ︙ | |||
750 751 752 753 754 755 756 | } {SQLITE_OK} test_contents backup-7.2.5 db main db2 main integrity_check backup-7.3.6 db2 do_test backup-7.3.1 { db2 close db3 close | | | 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | } {SQLITE_OK} test_contents backup-7.2.5 db main db2 main integrity_check backup-7.3.6 db2 do_test backup-7.3.1 { db2 close db3 close forcedelete test2.db sqlite3 db2 test2.db sqlite3 db3 test2.db sqlite3_backup B db2 main db main execsql { BEGIN ; CREATE TABLE t2(a, b); } db3 B step 5 |
︙ | ︙ | |||
779 780 781 782 783 784 785 | # The following tests, backup-8.*, test attaching multiple backup # processes to the same source database. Also, reading from the source # database while a read transaction is active. # # These tests reuse the database "test.db" left over from backup-7.*. # do_test backup-8.1 { | | | | 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | # The following tests, backup-8.*, test attaching multiple backup # processes to the same source database. Also, reading from the source # database while a read transaction is active. # # These tests reuse the database "test.db" left over from backup-7.*. # do_test backup-8.1 { catch { forcedelete test2.db } catch { forcedelete test3.db } sqlite3 db2 test2.db sqlite3 db3 test3.db sqlite3_backup B2 db2 main db main sqlite3_backup B3 db3 main db main list [B2 finish] [B3 finish] } {SQLITE_OK SQLITE_OK} |
︙ | ︙ | |||
861 862 863 864 865 866 867 | do_test backup-9.2.3 { B finish } {SQLITE_OK} catch {db2 close} ifcapable memorymanage { db close | | | | 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 | do_test backup-9.2.3 { B finish } {SQLITE_OK} catch {db2 close} ifcapable memorymanage { db close forcedelete test.db forcedelete bak.db sqlite3 db test.db sqlite3 db2 test.db sqlite3 db3 bak.db do_test backup-10.1.1 { execsql { |
︙ | ︙ | |||
914 915 916 917 918 919 920 | # Test that if the database is written to via the same database handle being # used as the source by a backup operation: # # 10.1.*: If the db is in-memory, the backup is restarted. # 10.2.*: If the db is a file, the backup is not restarted. # db close | | | 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 | # Test that if the database is written to via the same database handle being # used as the source by a backup operation: # # 10.1.*: If the db is in-memory, the backup is restarted. # 10.2.*: If the db is a file, the backup is not restarted. # db close forcedelete test.db test.db-journal foreach {tn file rc} { 1 test.db SQLITE_DONE 2 :memory: SQLITE_OK } { do_test backup-10.$tn.1 { sqlite3 db $file execsql { |
︙ | ︙ | |||
944 945 946 947 948 949 950 | do_test backup-10.$tn.2 { set pgs [execsql {pragma page_count}] expr {$pgs > 50 && $pgs < 75} } {1} do_test backup-10.$tn.3 { | | | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 | do_test backup-10.$tn.2 { set pgs [execsql {pragma page_count}] expr {$pgs > 50 && $pgs < 75} } {1} do_test backup-10.$tn.3 { forcedelete bak.db bak.db-journal sqlite3 db2 bak.db sqlite3_backup B db2 main db main B step 50 } {SQLITE_OK} do_test backup-10.$tn.4 { execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) } |
︙ | ︙ |
Changes to test/backup2.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 | unset -nocomplain cksum set cksum [dbcksum db main] # Make a backup of the test data. Verify that the backup copy # is identical to the original. # do_test backup2-2 { | | | | | | 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 | unset -nocomplain cksum set cksum [dbcksum db main] # Make a backup of the test data. Verify that the backup copy # is identical to the original. # do_test backup2-2 { forcedelete bu1.db db backup bu1.db sqlite3 db2 bu1.db dbcksum db2 main } $cksum # Delete the original. Restore from backup. Verify the content is # unchanged. # do_test backup2-3.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db db2 eval {BEGIN EXCLUSIVE} set rc [catch {db restore bu1.db} res] lappend rc $res db2 eval {ROLLBACK} set rc } {1 {restore failed: source database busy}} do_test backup2-3.2 { db close forcedelete test.db test.db-journal sqlite3 db test.db db restore bu1.db dbcksum db main } $cksum # Use alternative databases - other than "main". # do_test backup2-4 { db restore temp bu1.db dbcksum db temp } $cksum do_test backup2-5 { db2 close forcedelete bu1.db bu2.db db backup temp bu2.db sqlite3 db2 bu2.db dbcksum db2 main } $cksum # Try to backup to a readonly file. # |
︙ | ︙ | |||
123 124 125 126 127 128 129 | set rc [catch {db backup temp bu2.db} res] lappend rc $res } {1 {backup failed: file is encrypted or is not a database}} # Try to backup database that does not exist # do_test backup2-8 { | | | | | | | 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 | set rc [catch {db backup temp bu2.db} res] lappend rc $res } {1 {backup failed: file is encrypted or is not a database}} # Try to backup database that does not exist # do_test backup2-8 { forcedelete bu1.db set rc [catch {db backup aux1 bu1.db} res] lappend rc $res } {1 {backup failed: unknown database aux1}} # Invalid syntax on the backup method # do_test backup2-9 { set rc [catch {db backup} res] lappend rc $res } {1 {wrong # args: should be "db backup ?DATABASE? FILENAME"}} # Try to restore from an unreadable file. # if {$tcl_platform(platform)=="windows"} { do_test backup2-10 { forcedelete bu3.db file mkdir bu3.db set rc [catch {db restore temp bu3.db} res] lappend rc $res } {1 {cannot open source database: unable to open database file}} } if {$tcl_platform(platform)!="windows"} { do_test backup2-10 { forcedelete bu3.db file mkdir bu3.db set rc [catch {db restore temp bu3.db} res] lappend rc $res } {1 {cannot open source database: disk I/O error}} } # Try to restore from something that is not a database file. # do_test backup2-11 { set rc [catch {db restore temp bu2.db} res] lappend rc $res } {1 {restore failed: file is encrypted or is not a database}} # Try to restore a database that does not exist # do_test backup2-12 { set rc [catch {db restore aux1 bu2.db} res] lappend rc $res } {1 {restore failed: unknown database aux1}} do_test backup2-13 { forcedelete bu4.db set rc [catch {db restore bu4.db} res] lappend rc $res } {1 {cannot open source database: unable to open database file}} # Invalid syntax on the restore method # do_test backup2-14 { set rc [catch {db restore} res] lappend rc $res } {1 {wrong # args: should be "db restore ?DATABASE? FILENAME"}} forcedelete bu1.db bu2.db bu3.db bu4.db finish_test |
Changes to test/backup_ioerr.test.
︙ | ︙ | |||
56 57 58 59 60 61 62 | expr {$nPage>130 && $nPage<160} } {1} do_test backup_ioerr-1.2 { expr {[file size test.db] > $sqlite_pending_byte} } {1} do_test backup_ioerr-1.3 { db close | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | expr {$nPage>130 && $nPage<160} } {1} do_test backup_ioerr-1.2 { expr {[file size test.db] > $sqlite_pending_byte} } {1} do_test backup_ioerr-1.3 { db close forcedelete test.db } {} # Turn off IO error simulation. # proc clear_ioerr_simulation {} { set ::sqlite_io_error_hit 0 set ::sqlite_io_error_hardhit 0 |
︙ | ︙ | |||
151 152 153 154 155 156 157 | set bStop 0 for {set iError 1} {$bStop == 0} {incr iError} { # Disable IO error simulation. clear_ioerr_simulation catch { ddb close } catch { sdb close } | | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | set bStop 0 for {set iError 1} {$bStop == 0} {incr iError} { # Disable IO error simulation. clear_ioerr_simulation catch { ddb close } catch { sdb close } catch { forcedelete test.db } catch { forcedelete bak.db } # Open the source and destination databases. sqlite3 sdb test.db sqlite3 ddb bak.db # Step 1: Populate the source and destination databases. populate_database sdb |
︙ | ︙ |
Changes to test/capi3.test.
︙ | ︙ | |||
693 694 695 696 697 698 699 | db close } if {![sqlite3 -has-codec]} { # Now test that the library correctly handles bogus entries in the # sqlite_master table (schema corruption). do_test capi3-8.1 { | | | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | db close } if {![sqlite3 -has-codec]} { # Now test that the library correctly handles bogus entries in the # sqlite_master table (schema corruption). do_test capi3-8.1 { forcedelete test.db test.db-journal sqlite3 db test.db execsql { CREATE TABLE t1(a); } db close } {} do_test capi3-8.2 { |
︙ | ︙ | |||
718 719 720 721 722 723 724 | SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close | | | | | 718 719 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 748 749 750 | SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL); } db close } {}; do_test capi3-8.5 { catch { sqlite3 db test.db } catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} db close } forcedelete test.db forcedelete test.db-journal # Test the english language string equivalents for sqlite error codes set code2english [list \ SQLITE_OK {not an error} \ SQLITE_ERROR {SQL logic error or missing database} \ SQLITE_PERM {access permission denied} \ |
︙ | ︙ |
Changes to test/capi3c.test.
︙ | ︙ | |||
666 667 668 669 670 671 672 | db close } if {![sqlite3 -has-codec]} { # Now test that the library correctly handles bogus entries in the # sqlite_master table (schema corruption). do_test capi3c-8.1 { | | | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | db close } if {![sqlite3 -has-codec]} { # Now test that the library correctly handles bogus entries in the # sqlite_master table (schema corruption). do_test capi3c-8.1 { forcedelete test.db test.db-journal sqlite3 db test.db execsql { CREATE TABLE t1(a); } db close } {} do_test capi3c-8.2 { |
︙ | ︙ | |||
691 692 693 694 695 696 697 | SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3c-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close | | | | | 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 | SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} do_test capi3c-8.4 { # Build a 5-field row record. The first field is a string 'table', and # subsequent fields are all NULL. db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL); } db close } {}; do_test capi3c-8.5 { catch { sqlite3 db test.db } catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema (?)}} db close } forcedelete test.db forcedelete test.db-journal # Test the english language string equivalents for sqlite error codes set code2english [list \ SQLITE_OK {not an error} \ SQLITE_ERROR {SQL logic error or missing database} \ SQLITE_PERM {access permission denied} \ |
︙ | ︙ |
Changes to test/collate7.test.
︙ | ︙ | |||
40 41 42 43 44 45 46 | do_test collate7-1.4 { sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del} db close set ::caseless_del } {2} do_test collate7-2.1 { | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | do_test collate7-1.4 { sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del} db close set ::caseless_del } {2} do_test collate7-2.1 { forcedelete test.db test.db-journal sqlite3 db test.db sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del} execsql { PRAGMA encoding='utf-16'; CREATE TABLE abc16(a COLLATE CASELESS, b, c); } db set ::caseless_del |
︙ | ︙ |
Changes to test/corrupt.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # This file implements regression tests for SQLite library. # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. # # $Id: corrupt.test,v 1.12 2009/07/13 09:41:45 danielk1977 Exp $ | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # This file implements regression tests for SQLite library. # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. # # $Id: corrupt.test,v 1.12 2009/07/13 09:41:45 danielk1977 Exp $ catch {forcedelete test.db test.db-journal test.bu} set testdir [file dirname $argv0] source $testdir/tester.tcl # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # |
︙ | ︙ | |||
47 48 49 50 51 52 53 | CREATE TABLE t2 AS SELECT * FROM t1; DELETE FROM t2 WHERE rowid%5!=0; COMMIT; } } {} integrity_check corrupt-1.2 | < < < < < < < < < < < < | | | 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 | CREATE TABLE t2 AS SELECT * FROM t1; DELETE FROM t2 WHERE rowid%5!=0; COMMIT; } } {} integrity_check corrupt-1.2 # Setup for the tests. Make a backup copy of the good database in test.bu. # Create a string of garbage data that is 256 bytes long. # forcecopy test.db test.bu set fsize [file size test.db] set junk "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" while {[string length $junk]<256} {append junk $junk} set junk [string range $junk 0 255] # Go through the database and write garbage data into each 256 segment # of the file. Then do various operations on the file to make sure that # the database engine can recover gracefully from the corruption. # for {set i [expr {1*256}]} {$i<$fsize-256} {incr i 256} { set tn [expr {$i/256}] db close forcecopy test.bu test.db set fd [open test.db r+] fconfigure $fd -translation binary seek $fd $i puts -nonewline $fd $junk close $fd do_test corrupt-2.$tn.1 { sqlite3 db test.db |
︙ | ︙ | |||
128 129 130 131 132 133 134 | #------------------------------------------------------------------------ # For these tests, swap the rootpage entries of t1 (a table) and t1i1 (an # index on t1) in sqlite_master. Then perform a few different queries # and make sure this is detected as corruption. # do_test corrupt-3.1 { db close | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #------------------------------------------------------------------------ # For these tests, swap the rootpage entries of t1 (a table) and t1i1 (an # index on t1) in sqlite_master. Then perform a few different queries # and make sure this is detected as corruption. # do_test corrupt-3.1 { db close forcecopy test.bu test.db sqlite3 db test.db list } {} do_test corrupt-3.2 { set t1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1i1'}] set t1i1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1'}] set cookie [expr [execsql {PRAGMA schema_version}] + 1] |
︙ | ︙ | |||
177 178 179 180 181 182 183 | catchsql { SELECT * FROM t1 WHERE x = 'abcde'; } } {1 {database disk image is malformed}} do_test corrupt-4.1 { db close | | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | catchsql { SELECT * FROM t1 WHERE x = 'abcde'; } } {1 {database disk image is malformed}} do_test corrupt-4.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT); } for {set i 0} {$i < 10} {incr i} { set text [string repeat $i 220] |
︙ | ︙ | |||
209 210 211 212 213 214 215 | # index b-tree as expected. At one point this was causing an assert() # to fail. catchsql { DELETE FROM t1 WHERE rowid = 3 } } {1 {database disk image is malformed}} do_test corrupt-5.1 { db close | | | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | # index b-tree as expected. At one point this was causing an assert() # to fail. catchsql { DELETE FROM t1 WHERE rowid = 3 } } {1 {database disk image is malformed}} do_test corrupt-5.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA page_size = 1024 } set ct "CREATE TABLE t1(c0 " set i 0 while {[string length $ct] < 950} { append ct ", c[incr i]" } append ct ")" |
︙ | ︙ | |||
232 233 234 235 236 237 238 | } {1 {database disk image is malformed}} # At one point, the specific corruption caused by this test case was # causing a buffer overwrite. Although a crash was never demonstrated, # running this testcase under valgrind revealed the problem. do_test corrupt-6.1 { db close | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | } {1 {database disk image is malformed}} # At one point, the specific corruption caused by this test case was # causing a buffer overwrite. Although a crash was never demonstrated, # running this testcase under valgrind revealed the problem. do_test corrupt-6.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA page_size = 1024; CREATE TABLE t1(x); } # The root page of t1 is 1024 bytes in size. The header is 8 bytes, and # each of the cells inserted by the following INSERT statements consume |
︙ | ︙ | |||
260 261 262 263 264 265 266 | sqlite3 db test.db catchsql { INSERT INTO t1 VALUES( randomblob(10) ) } } {1 {database disk image is malformed}} ifcapable oversize_cell_check { db close | | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | sqlite3 db test.db catchsql { INSERT INTO t1 VALUES( randomblob(10) ) } } {1 {database disk image is malformed}} ifcapable oversize_cell_check { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA page_size = 1024; CREATE TABLE t1(x); } do_test corrupt-7.1 { for {set i 0} {$i < 39} {incr i} { |
︙ | ︙ | |||
313 314 315 316 317 318 319 | catchsql { INSERT INTO t1 VALUES(X'000100020003000400050006000700080009000A'); } } {1 {database disk image is malformed}} } db close | | | | 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 | catchsql { INSERT INTO t1 VALUES(X'000100020003000400050006000700080009000A'); } } {1 {database disk image is malformed}} } db close forcedelete test.db test.db-journal do_test corrupt-8.1 { sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA secure_delete = on; PRAGMA auto_vacuum = 0; CREATE TABLE t1(x INTEGER PRIMARY KEY, y); INSERT INTO t1 VALUES(5, randomblob(1900)); } hexio_write test.db 2044 [hexio_render_int32 2] hexio_write test.db 24 [hexio_render_int32 45] catchsql { INSERT OR REPLACE INTO t1 VALUES(5, randomblob(1900)) } } {1 {database disk image is malformed}} db close forcedelete test.db test.db-journal do_test corrupt-8.2 { sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA secure_delete = on; PRAGMA auto_vacuum = 0; CREATE TABLE t1(x INTEGER PRIMARY KEY, y); |
︙ | ︙ |
Changes to test/corrupt2.test.
︙ | ︙ | |||
37 38 39 40 41 42 43 | CREATE TABLE abc(a, b, c); } } {} do_test corrupt2-1.2 { # Corrupt the 16 byte magic string at the start of the file | | | | | | | | | | | | | | | | | 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 | CREATE TABLE abc(a, b, c); } } {} do_test corrupt2-1.2 { # Corrupt the 16 byte magic string at the start of the file forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db set f [open corrupt.db RDWR] seek $f 8 start puts $f blah close $f sqlite3 db2 corrupt.db catchsql " $::presql SELECT * FROM sqlite_master; " db2 } {1 {file is encrypted or is not a database}} do_test corrupt2-1.3 { db2 close # Corrupt the page-size (bytes 16 and 17 of page 1). forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db set f [open corrupt.db RDWR] fconfigure $f -encoding binary seek $f 16 start puts -nonewline $f "\x00\xFF" close $f sqlite3 db2 corrupt.db catchsql " $::presql SELECT * FROM sqlite_master; " db2 } {1 {file is encrypted or is not a database}} do_test corrupt2-1.4 { db2 close # Corrupt the free-block list on page 1. forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db set f [open corrupt.db RDWR] fconfigure $f -encoding binary seek $f 101 start puts -nonewline $f "\xFF\xFF" close $f sqlite3 db2 corrupt.db catchsql " $::presql SELECT * FROM sqlite_master; " db2 } {1 {database disk image is malformed}} do_test corrupt2-1.5 { db2 close # Corrupt the free-block list on page 1. forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db set f [open corrupt.db RDWR] fconfigure $f -encoding binary seek $f 101 start puts -nonewline $f "\x00\xC8" seek $f 200 start puts -nonewline $f "\x00\x00" puts -nonewline $f "\x10\x00" close $f sqlite3 db2 corrupt.db catchsql " $::presql SELECT * FROM sqlite_master; " db2 } {1 {database disk image is malformed}} db2 close # Corrupt a database by having 2 indices of the same name: do_test corrupt2-2.1 { forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db sqlite3 db2 corrupt.db execsql " $::presql CREATE INDEX a1 ON abc(a); CREATE INDEX a2 ON abc(b); PRAGMA writable_schema = 1; |
︙ | ︙ | |||
146 147 148 149 150 151 152 | SELECT * FROM sqlite_master; " db2 } {1 {malformed database schema (a3) - index a3 already exists}} db2 close do_test corrupt2-3.1 { | | | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | SELECT * FROM sqlite_master; " db2 } {1 {malformed database schema (a3) - index a3 already exists}} db2 close do_test corrupt2-3.1 { forcedelete corrupt.db forcedelete corrupt.db-journal sqlite3 db2 corrupt.db execsql " $::presql PRAGMA auto_vacuum = 1; PRAGMA page_size = 1024; CREATE TABLE t1(a, b, c); |
︙ | ︙ | |||
196 197 198 199 200 201 202 | } db2 } {1 {database disk image is malformed}} db2 close unset -nocomplain result do_test corrupt2-5.1 { | | | | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | } db2 } {1 {database disk image is malformed}} db2 close unset -nocomplain result do_test corrupt2-5.1 { forcedelete corrupt.db forcedelete corrupt.db-journal sqlite3 db2 corrupt.db execsql " $::presql PRAGMA auto_vacuum = 0; PRAGMA page_size = 1024; CREATE TABLE t1(a, b, c); |
︙ | ︙ | |||
253 254 255 256 257 258 259 | proc corruption_test {args} { set A(-corrupt) {} set A(-sqlprep) {} set A(-tclprep) {} array set A $args catch {db close} | | | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | proc corruption_test {args} { set A(-corrupt) {} set A(-sqlprep) {} set A(-tclprep) {} array set A $args catch {db close} forcedelete corrupt.db forcedelete corrupt.db-journal sqlite3 db corrupt.db db eval $::presql eval $A(-tclprep) db eval $A(-sqlprep) db close |
︙ | ︙ |
Changes to test/corrupt9.test.
︙ | ︙ | |||
82 83 84 85 86 87 88 | } {1} integrity_check corrupt9-1.2 # Corrupt the freelist by adding duplicate entries to the freelist. # Make sure the corruption is detected. # db close | | | | | 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 | } {1} integrity_check corrupt9-1.2 # Corrupt the freelist by adding duplicate entries to the freelist. # Make sure the corruption is detected. # db close forcecopy test.db test.db-template corrupt_freelist test.db 1 sqlite3 db test.db do_test corrupt9-2.1 { set x [db eval {PRAGMA integrity_check}] expr {$x!="ok"} } {1} do_test corrupt9-2.2 { catchsql { CREATE INDEX i2 ON t2(b,a); REINDEX; } } {1 {database disk image is malformed}} db close forcecopy test.db-template test.db corrupt_freelist test.db 2 sqlite3 db test.db do_test corrupt9-3.1 { set x [db eval {PRAGMA integrity_check}] expr {$x!="ok"} } {1} do_test corrupt9-3.2 { catchsql { CREATE INDEX i2 ON t2(b,a); REINDEX; } } {1 {database disk image is malformed}} db close forcecopy test.db-template test.db corrupt_freelist test.db 3 sqlite3 db test.db do_test corrupt9-4.1 { set x [db eval {PRAGMA integrity_check}] expr {$x!="ok"} } {1} do_test corrupt9-4.2 { |
︙ | ︙ |
Changes to test/corruptA.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 | } {1} integrity_check corruptA-1.2 # Corrupt the file header in various ways and make sure the corruption # is detected when opening the database file. # db close | | | | | | | 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 | } {1} integrity_check corruptA-1.2 # Corrupt the file header in various ways and make sure the corruption # is detected when opening the database file. # db close forcecopy test.db test.db-template set unreadable_version 02 ifcapable wal { set unreadable_version 03 } do_test corruptA-2.1 { forcecopy test.db-template test.db hexio_write test.db 19 $unreadable_version ;# the read format number sqlite3 db test.db catchsql {SELECT * FROM t1} } {1 {file is encrypted or is not a database}} do_test corruptA-2.2 { db close forcecopy test.db-template test.db hexio_write test.db 21 41 ;# max embedded payload fraction sqlite3 db test.db catchsql {SELECT * FROM t1} } {1 {file is encrypted or is not a database}} do_test corruptA-2.3 { db close forcecopy test.db-template test.db hexio_write test.db 22 1f ;# min embedded payload fraction sqlite3 db test.db catchsql {SELECT * FROM t1} } {1 {file is encrypted or is not a database}} do_test corruptA-2.4 { db close forcecopy test.db-template test.db hexio_write test.db 23 21 ;# min leaf payload fraction sqlite3 db test.db catchsql {SELECT * FROM t1} } {1 {file is encrypted or is not a database}} finish_test |
Changes to test/corruptB.test.
︙ | ︙ | |||
42 43 44 45 46 47 48 | INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; } expr {[file size test.db] > (1024*9)} } {1} integrity_check corruptB-1.2 | | | | | | | 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 | INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; } expr {[file size test.db] > (1024*9)} } {1} integrity_check corruptB-1.2 forcecopy test.db bak.db # Set the right-child of a B-Tree rootpage to refer to the root-page itself. # do_test corruptB-1.3.1 { set ::root [execsql {SELECT rootpage FROM sqlite_master}] set ::offset [expr {($::root-1)*1024}] hexio_write test.db [expr $offset+8] [hexio_render_int32 $::root] } {4} do_test corruptB-1.3.2 { sqlite3 db test.db catchsql { SELECT * FROM t1 } } {1 {database disk image is malformed}} # Set the left-child of a cell in a B-Tree rootpage to refer to the # root-page itself. # do_test corruptB-1.4.1 { db close forcecopy bak.db test.db set cell_offset [hexio_get_int [hexio_read test.db [expr $offset+12] 2]] hexio_write test.db [expr $offset+$cell_offset] [hexio_render_int32 $::root] } {4} do_test corruptB-1.4.2 { sqlite3 db test.db catchsql { SELECT * FROM t1 } } {1 {database disk image is malformed}} # Now grow the table B-Tree so that it is more than 2 levels high. # do_test corruptB-1.5.1 { db close forcecopy bak.db test.db sqlite3 db test.db execsql { INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; INSERT INTO t1 SELECT randomblob(200) FROM t1; } } {} forcecopy test.db bak.db # Set the right-child pointer of the right-child of the root page to point # back to the root page. # do_test corruptB-1.6.1 { db close set iRightChild [hexio_get_int [hexio_read test.db [expr $offset+8] 4]] set c_offset [expr ($iRightChild-1)*1024] hexio_write test.db [expr $c_offset+8] [hexio_render_int32 $::root] } {4} do_test corruptB-1.6.2 { sqlite3 db test.db catchsql { SELECT * FROM t1 } } {1 {database disk image is malformed}} # Set the left-child pointer of a cell of the right-child of the root page to # point back to the root page. # do_test corruptB-1.7.1 { db close forcecopy bak.db test.db set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]] hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root] } {4} do_test corruptB-1.7.2 { sqlite3 db test.db catchsql { SELECT * FROM t1 } } {1 {database disk image is malformed}} |
︙ | ︙ | |||
136 137 138 139 140 141 142 | } {1 {database disk image is malformed}} # Set the left-child pointer of a cell of the right-child of the root page to # point back to the root page. # do_test corruptB-1.9.1 { db close | | | | | 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 | } {1 {database disk image is malformed}} # Set the left-child pointer of a cell of the right-child of the root page to # point back to the root page. # do_test corruptB-1.9.1 { db close forcecopy bak.db test.db set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]] hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root] } {4} do_test corruptB-1.9.2 { sqlite3 db test.db catchsql { SELECT * FROM t1 } } {1 {database disk image is malformed}} #--------------------------------------------------------------------------- do_test corruptB-2.1.1 { db close forcecopy bak.db test.db hexio_write test.db [expr $offset+8] [hexio_render_int32 0x6FFFFFFF] } {4} do_test corruptB-2.1.2 { sqlite3 db test.db catchsql { SELECT * FROM t1 } } {1 {database disk image is malformed}} #--------------------------------------------------------------------------- # Corrupt the header-size field of a database record. # do_test corruptB-3.1.1 { db close forcecopy bak.db test.db sqlite3 db test.db set v [string repeat abcdefghij 200] execsql { CREATE TABLE t2(a); INSERT INTO t2 VALUES($v); } set t2_root [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't2'}] |
︙ | ︙ |
Changes to test/corruptC.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 | # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. It creates a base # data base file, then tests that single byte corruptions in # increasingly larger quantities are handled gracefully. # # $Id: corruptC.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $ | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. It creates a base # data base file, then tests that single byte corruptions in # increasingly larger quantities are handled gracefully. # # $Id: corruptC.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $ catch {forcedelete test.db test.db-journal test.bu} set testdir [file dirname $argv0] source $testdir/tester.tcl # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # |
︙ | ︙ | |||
54 55 56 57 58 59 60 | # Generate random integer # proc random {range} { return [expr {round(rand()*$range)}] } | < < < < < < | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | # Generate random integer # proc random {range} { return [expr {round(rand()*$range)}] } # Setup for the tests. Make a backup copy of the good database in test.bu. # db close forcecopy test.db test.bu sqlite3 db test.db set fsize [file size test.db] # Set a quasi-random random seed. if {[info exists ::G(issoak)]} { # If we are doing SOAK tests, we want a different # random seed for each run. Ideally we would like |
︙ | ︙ | |||
88 89 90 91 92 93 94 | # First test some specific corruption tests found from earlier runs # with specific seeds. # # test that a corrupt content offset size is handled (seed 5577) do_test corruptC-2.1 { db close | | | | | | | | | | | | | | | | | | 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 | # First test some specific corruption tests found from earlier runs # with specific seeds. # # test that a corrupt content offset size is handled (seed 5577) do_test corruptC-2.1 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 2053 [format %02x 0x04] sqlite3 db test.db catchsql {PRAGMA integrity_check} } {1 {database disk image is malformed}} # test that a corrupt content offset size is handled (seed 5649) do_test corruptC-2.2 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 27 [format %02x 0x08] hexio_write test.db 233 [format %02x 0x6a] hexio_write test.db 328 [format %02x 0x67] hexio_write test.db 750 [format %02x 0x1f] hexio_write test.db 1132 [format %02x 0x52] hexio_write test.db 1133 [format %02x 0x84] hexio_write test.db 1220 [format %02x 0x01] hexio_write test.db 3688 [format %02x 0xc1] hexio_write test.db 3714 [format %02x 0x58] hexio_write test.db 3746 [format %02x 0x9a] sqlite3 db test.db catchsql {UPDATE t1 SET y=1} } {1 {database disk image is malformed}} # test that a corrupt free cell size is handled (seed 13329) do_test corruptC-2.3 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 1094 [format %02x 0x76] sqlite3 db test.db catchsql {UPDATE t1 SET y=1} } {1 {database disk image is malformed}} # test that a corrupt free cell size is handled (seed 169571) do_test corruptC-2.4 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 3119 [format %02x 0xdf] sqlite3 db test.db catchsql {UPDATE t2 SET y='abcdef-uvwxyz'} } {1 {database disk image is malformed}} # test that a corrupt free cell size is handled (seed 169571) do_test corruptC-2.5 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 3119 [format %02x 0xdf] hexio_write test.db 4073 [format %02x 0xbf] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} catchsql {PRAGMA integrity_check} } {0 {{*** in database main *** Page 4: btreeInitPage() returns error code 11}}} # {0 {{*** in database main *** # Corruption detected in cell 710 on page 4 # Multiple uses for byte 661 of page 4 # Fragmented space is 249 byte reported as 21 on page 4}}} # test that a corrupt free cell size is handled (seed 169595) do_test corruptC-2.6 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 619 [format %02x 0xe2] hexio_write test.db 3150 [format %02x 0xa8] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 178692) do_test corruptC-2.7 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 3074 [format %02x 0xa0] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 179069) do_test corruptC-2.8 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 1393 [format %02x 0x7d] hexio_write test.db 84 [format %02x 0x19] hexio_write test.db 3287 [format %02x 0x3b] hexio_write test.db 2564 [format %02x 0xed] hexio_write test.db 2139 [format %02x 0x55] sqlite3 db test.db catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 170434) do_test corruptC-2.9 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 2095 [format %02x 0xd6] sqlite3 db test.db catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 186504) do_test corruptC-2.10 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 3130 [format %02x 0x02] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 1589) do_test corruptC-2.11 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 55 [format %02x 0xa7] sqlite3 db test.db catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;} } {1 {database disk image is malformed}} # corruption (seed 14166) do_test corruptC-2.12 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 974 [format %02x 0x2e] sqlite3 db test.db catchsql {SELECT count(*) FROM sqlite_master;} } {1 {malformed database schema (t1i1) - corrupt database}} # corruption (seed 218803) do_test corruptC-2.13 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 102 [format %02x 0x12] sqlite3 db test.db catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;} } {1 {database disk image is malformed}} do_test corruptC-2.14 { db close forcecopy test.bu test.db sqlite3 db test.db set blob [string repeat abcdefghij 10000] execsql { INSERT INTO t1 VALUES (1, $blob) } sqlite3 db test.db set filesize [file size test.db] hexio_write test.db [expr $filesize-2048] 00000001 catchsql {DELETE FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1)} } {1 {database disk image is malformed}} # At one point this particular corrupt database was causing a buffer # overread. Which caused a crash in a run of all.test once. # do_test corruptC-2.15 { db close forcecopy test.bu test.db hexio_write test.db 986 b9 sqlite3 db test.db catchsql {SELECT count(*) FROM sqlite_master;} } {1 {malformed database schema (t1i1) - no such table: main.t1}} # # Now test for a series of quasi-random seeds. # We loop over the entire file size and touch # each byte at least once. for {set tn 0} {$tn<$fsize} {incr tn 1} { # setup for test db close forcecopy test.bu test.db sqlite3 db test.db # Seek to a random location in the file, and write a random single byte # value. Then do various operations on the file to make sure that # the database engine can handle the corruption gracefully. # set last 0 |
︙ | ︙ |
Changes to test/corruptD.test.
︙ | ︙ | |||
81 82 83 84 85 86 87 | } execsql { DELETE FROM t1 WHERE a = 10; DELETE FROM t1 WHERE a = 20; DELETE FROM t1 WHERE a = 30; DELETE FROM t1 WHERE a = 40; } | | | | 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 | } execsql { DELETE FROM t1 WHERE a = 10; DELETE FROM t1 WHERE a = 20; DELETE FROM t1 WHERE a = 30; DELETE FROM t1 WHERE a = 40; } forcecopy test.db test.bu } {} proc incr_change_counter {} { hexio_write test.db 24 [ hexio_render_int32 [expr [hexio_get_int [hexio_read test.db 24 4]] + 1] ] } proc restore_file {} { db close forcecopy test.bu test.db sqlite3 db test.db } #------------------------------------------------------------------------- # The following tests, corruptD-1.1.*, focus on the page header field # containing the offset of the first free block in a page. # |
︙ | ︙ |
Changes to test/corruptE.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. It specifcally # focuses on rowid order corruption. # # $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $ | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. It specifcally # focuses on rowid order corruption. # # $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $ catch {forcedelete test.db test.db-journal test.bu} set testdir [file dirname $argv0] source $testdir/tester.tcl # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # |
︙ | ︙ | |||
56 57 58 59 60 61 62 | } } {} ifcapable {integrityck} { integrity_check corruptE-1.2 } | < < < < < < | | | | | | 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 | } } {} ifcapable {integrityck} { integrity_check corruptE-1.2 } # Setup for the tests. Make a backup copy of the good database in test.bu. # db close forcecopy test.db test.bu sqlite3 db test.db set fsize [file size test.db] do_test corruptE-2.1 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 2041 [format %02x 0x2e] sqlite3 db test.db set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] list [regexp {out of order.*previous was} $ans] \ [regexp {out of order.*max larger than parent max} $ans] } {1 1} do_test corruptE-2.2 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 2047 [format %02x 0x84] sqlite3 db test.db set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] list [regexp {out of order.*previous was} $ans] \ [regexp {out of order.*min less than parent min} $ans] } {1 1} do_test corruptE-2.3 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 7420 [format %02x 0xa8] hexio_write test.db 10459 [format %02x 0x8d] sqlite3 db test.db set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] list [regexp {out of order.*max larger than parent min} $ans] } {1} do_test corruptE-2.4 { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db 10233 [format %02x 0xd0] sqlite3 db test.db set res [ catchsql {PRAGMA integrity_check} ] |
︙ | ︙ | |||
161 162 163 164 165 166 167 | {12297 0xd7} \ {13303 0x53} ] set tc 1 foreach test $tests { do_test corruptE-3.$tc { db close | | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | {12297 0xd7} \ {13303 0x53} ] set tc 1 foreach test $tests { do_test corruptE-3.$tc { db close forcecopy test.bu test.db # insert corrupt byte(s) hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]] sqlite3 db test.db set res [ catchsql {PRAGMA integrity_check} ] |
︙ | ︙ |
Changes to test/crash.test.
︙ | ︙ | |||
211 212 213 214 215 216 217 | # crash-4.2.*: Test recovery when crash occurs during sync() of an # attached database journal file. # crash-4.3.*: Test recovery when crash occurs during sync() of the master # journal file. # ifcapable attach { do_test crash-4.0 { | | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | # crash-4.2.*: Test recovery when crash occurs during sync() of an # attached database journal file. # crash-4.3.*: Test recovery when crash occurs during sync() of the master # journal file. # ifcapable attach { do_test crash-4.0 { forcedelete test2.db forcedelete test2.db-journal execsql { ATTACH 'test2.db' AS aux; PRAGMA aux.default_cache_size = 10; CREATE TABLE aux.abc2 AS SELECT 2*a as a, 2*b as b, 2*c as c FROM abc; } expr ([file size test2.db] / 1024) > 450 } {1} |
︙ | ︙ | |||
314 315 316 317 318 319 320 | #-------------------------------------------------------------------------- # The following test cases - crash-5.* - exposes a bug that existed in the # sqlite3pager_movepage() API used by auto-vacuum databases. # database when a crash occurs during a multi-file transaction. See comments # in test crash-5.3 for details. # db close | | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | #-------------------------------------------------------------------------- # The following test cases - crash-5.* - exposes a bug that existed in the # sqlite3pager_movepage() API used by auto-vacuum databases. # database when a crash occurs during a multi-file transaction. See comments # in test crash-5.3 for details. # db close forcedelete test.db sqlite3 db test.db do_test crash-5.1 { execsql { CREATE TABLE abc(a, b, c); -- Root page 3 INSERT INTO abc VALUES(randstr(1500,1500), 0, 0); -- Overflow page 4 INSERT INTO abc SELECT * FROM abc; INSERT INTO abc SELECT * FROM abc; |
︙ | ︙ |
Changes to test/crash3.test.
︙ | ︙ | |||
69 70 71 72 73 74 75 | {UPDATE abc SET a = 2} {2 2 3} \ {INSERT INTO abc VALUES(4, 5, randstr(1000,1000))} {n/a} \ {CREATE TABLE def(d, e, f)} {n/a} \ ] { for {set ii 0} {$ii < 10} {incr ii} { db close | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | {UPDATE abc SET a = 2} {2 2 3} \ {INSERT INTO abc VALUES(4, 5, randstr(1000,1000))} {n/a} \ {CREATE TABLE def(d, e, f)} {n/a} \ ] { for {set ii 0} {$ii < 10} {incr ii} { db close forcedelete test.db test.db-journal sqlite3 db test.db do_test crash3-1.$tn.1 { execsql { PRAGMA page_size = 1024; BEGIN; CREATE TABLE abc(a, b, c); INSERT INTO abc VALUES(1, 2, 3); |
︙ | ︙ | |||
102 103 104 105 106 107 108 | incr tn } } # This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags. # db close | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | incr tn } } # This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags. # db close forcedelete test.db test.db-journal sqlite3 db test.db do_test crash3-2.0 { execsql { BEGIN; CREATE TABLE abc(a PRIMARY KEY, b, c); CREATE TABLE def(d PRIMARY KEY, e, f); PRAGMA default_cache_size = 10; |
︙ | ︙ | |||
173 174 175 176 177 178 179 | # IOCAP_SEQUENTIAL. At one point, if both flags were set, small # journal files that contained only a single page, but were required # for some other reason (i.e. nTrunk) were not being written to # disk. # for {set ii 0} {$ii < 10} {incr ii} { db close | | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | # IOCAP_SEQUENTIAL. At one point, if both flags were set, small # journal files that contained only a single page, but were required # for some other reason (i.e. nTrunk) were not being written to # disk. # for {set ii 0} {$ii < 10} {incr ii} { db close forcedelete test.db test.db-journal crashsql -file test.db -char {sequential atomic} { CREATE TABLE abc(a, b, c); } sqlite3 db test.db do_test crash3-3.$ii { execsql {PRAGMA integrity_check} } {ok} } finish_test |
Changes to test/crash4.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 | # # Slowly increase the delay before the crash, repeating the test # over and over. Stop testing when the entire sequence of SQL # statements runs to completing without hitting the crash. # for {set cnt 1; set fin 0} {!$fin} {incr cnt} { db close | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # # Slowly increase the delay before the crash, repeating the test # over and over. Stop testing when the entire sequence of SQL # statements runs to completing without hitting the crash. # for {set cnt 1; set fin 0} {!$fin} {incr cnt} { db close forcedelete test.db test.db-journal do_test crash4-1.$cnt.1 { set seed [expr {int(abs(rand()*10000))}] set delay [expr {int($cnt/50)+1}] set file [expr {($cnt&1)?"test.db":"test.db-journal"}] set c [crashsql -delay $delay -file $file -seed $seed -tclbody { db eval {CREATE TABLE a(id INTEGER, name CHAR(50))} db eval {INSERT INTO a(id,name) VALUES(1,'one')} |
︙ | ︙ |
Changes to test/crash5.test.
︙ | ︙ | |||
30 31 32 33 34 35 36 | for {set ii 0} {$ii < 10} {incr ii} { for {set jj 50} {$jj < 100} {incr jj} { # Set up the database so that it is an auto-vacuum database # containing a single table (root page 3) with a single row. # The row has an overflow page (page 4). | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | for {set ii 0} {$ii < 10} {incr ii} { for {set jj 50} {$jj < 100} {incr jj} { # Set up the database so that it is an auto-vacuum database # containing a single table (root page 3) with a single row. # The row has an overflow page (page 4). forcedelete test.db test.db-journal sqlite3 db test.db set c [string repeat 3 1500] db eval { pragma auto_vacuum = 1; CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES('1111111111', '2222222222', $c); } |
︙ | ︙ |
Changes to test/crash6.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ifcapable !crashtest { finish_test return } for {set ii 0} {$ii < 10} {incr ii} { catch {db close} | | | | 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 | ifcapable !crashtest { finish_test return } for {set ii 0} {$ii < 10} {incr ii} { catch {db close} forcedelete test.db test.db-journal crashsql -delay 2 -file test.db { PRAGMA auto_vacuum=OFF; PRAGMA page_size=4096; BEGIN; CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c; COMMIT; BEGIN; CREATE TABLE def AS SELECT 1 AS d, 2 AS e, 3 AS f; COMMIT; } sqlite3 db test.db integrity_check crash6-1.$ii } for {set ii 0} {$ii < 10} {incr ii} { catch {db close} forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA auto_vacuum=OFF; PRAGMA page_size=2048; BEGIN; CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c; COMMIT; |
︙ | ︙ | |||
62 63 64 65 66 67 68 | } # Test case for crashing during database sync with page-size values # from 1024 to 8192. # for {set ii 0} {$ii < 30} {incr ii} { db close | | | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | } # Test case for crashing during database sync with page-size values # from 1024 to 8192. # for {set ii 0} {$ii < 30} {incr ii} { db close forcedelete test.db sqlite3 db test.db set pagesize [expr 1024 << ($ii % 4)] if {$pagesize>$::SQLITE_MAX_PAGE_SIZE} { set pagesize $::SQLITE_MAX_PAGE_SIZE } do_test crash6-3.$ii.0 { |
︙ | ︙ |
Changes to test/crash7.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 | proc signature {} { return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}] } foreach f [list test.db test.db-journal] { for {set ii 1} {$ii < 64} {incr ii} { db close | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | proc signature {} { return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}] } foreach f [list test.db test.db-journal] { for {set ii 1} {$ii < 64} {incr ii} { db close delete_file test.db sqlite3 db test.db set from_size [expr 1024 << ($ii&3)] set to_size [expr 1024 << (($ii>>2)&3)] execsql " PRAGMA page_size = $from_size; |
︙ | ︙ |
Changes to test/crash8.test.
︙ | ︙ | |||
239 240 241 242 243 244 245 | # # This block of tests test that SQLite correctly truncates such # journal files, and that the results behave correctly if a hot-journal # rollback occurs. # ifcapable pragma { reset_db | | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | # # This block of tests test that SQLite correctly truncates such # journal files, and that the results behave correctly if a hot-journal # rollback occurs. # ifcapable pragma { reset_db forcedelete test2.db do_test crash8-4.1 { execsql { PRAGMA journal_mode = persist; CREATE TABLE ab(a, b); INSERT INTO ab VALUES(0, 'abc'); INSERT INTO ab VALUES(1, NULL); |
︙ | ︙ | |||
332 333 334 335 336 337 338 | } {1} do_test crash8-4.9 { execsql { SELECT b FROM aux.ab WHERE a = 0 } } {def} do_test crash8-4.10 { | | | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | } {1} do_test crash8-4.9 { execsql { SELECT b FROM aux.ab WHERE a = 0 } } {def} do_test crash8-4.10 { delete_file $zMasterJournal execsql { SELECT b FROM main.ab WHERE a = 0 } } {jkl} } for {set i 1} {$i < 10} {incr i} { catch { db close } forcedelete test.db test.db-journal sqlite3 db test.db do_test crash8-5.$i.1 { execsql { CREATE TABLE t1(x PRIMARY KEY); INSERT INTO t1 VALUES(randomblob(900)); INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; |
︙ | ︙ | |||
363 364 365 366 367 368 369 | ROLLBACK; INSERT INTO t1 VALUES(randomblob(900)); } execsql { PRAGMA integrity_check } } {ok} catch { db close } | | | | | | 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 | ROLLBACK; INSERT INTO t1 VALUES(randomblob(900)); } execsql { PRAGMA integrity_check } } {ok} catch { db close } forcedelete test.db test.db-journal sqlite3 db test.db do_test crash8-5.$i.2 { execsql { PRAGMA cache_size = 10; CREATE TABLE t1(x PRIMARY KEY); INSERT INTO t1 VALUES(randomblob(900)); INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 64 rows */ BEGIN; UPDATE t1 SET x = randomblob(900); } forcedelete testX.db testX.db-journal testX.db-wal forcecopy test.db testX.db forcecopy test.db-journal testX.db-journal db close crashsql -file test.db -delay [expr ($::i%2) + 1] { SELECT * FROM sqlite_master; INSERT INTO t1 VALUES(randomblob(900)); } |
︙ | ︙ |
Changes to test/createtab.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 | set upperBound 0 } # Run these tests for all possible values of autovacuum. # for {set av 0} {$av<=$upperBound} {incr av} { db close | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | set upperBound 0 } # Run these tests for all possible values of autovacuum. # for {set av 0} {$av<=$upperBound} {incr av} { db close forcedelete test.db test.db-journal sqlite3 db test.db # Create a table that spans multiple pages. It is important # that part of the database be in pages beyond the root page. # do_test createtab-$av.1 { execsql "PRAGMA auto_vacuum=$av" |
︙ | ︙ |
Changes to test/dbstatus.test.
︙ | ︙ | |||
151 152 153 154 155 156 157 | CREATE VIRTUAL TABLE t2 USING echo(t1); } } { set tn "$::lookaside_buffer_size-$tn" # Step 1. db close | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | CREATE VIRTUAL TABLE t2 USING echo(t1); } } { set tn "$::lookaside_buffer_size-$tn" # Step 1. db close forcedelete test.db sqlite3 db test.db sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500 db cache size 0 catch { register_echo_module db } ifcapable !vtab { if {[string match *x $tn]} continue } |
︙ | ︙ | |||
283 284 285 286 287 288 289 | SELECT * FROM t2 WHERE b='abcdefg'; } } { set tn "$::lookaside_buffer_size-$tn" # Step 1. db close | | | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | SELECT * FROM t2 WHERE b='abcdefg'; } } { set tn "$::lookaside_buffer_size-$tn" # Step 1. db close forcedelete test.db sqlite3 db test.db sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500 db cache size 1000 catch { register_echo_module db } ifcapable !vtab { if {[string match *x $tn]} continue } |
︙ | ︙ |
Changes to test/delete.test.
︙ | ︙ | |||
271 272 273 274 275 276 277 | execsql { PRAGMA count_changes=OFF; INSERT INTO t3 VALUES(123); SELECT * FROM t3; } } {123} db close | | | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | execsql { PRAGMA count_changes=OFF; INSERT INTO t3 VALUES(123); SELECT * FROM t3; } } {123} db close catch {forcedelete test.db-journal} catch {file attributes test.db -permissions 0444} catch {file attributes test.db -readonly 1} sqlite3 db test.db set ::DB [sqlite3_connection_pointer db] do_test delete-8.1 { catchsql { DELETE FROM t3; |
︙ | ︙ | |||
308 309 310 311 312 313 314 | } {1 {attempt to write a readonly database}} do_test delete-8.6 { execsql {SELECT * FROM t3} } {123} integrity_check delete-8.7 # Need to do the following for tcl 8.5 on mac. On that configuration, the | | | | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | } {1 {attempt to write a readonly database}} do_test delete-8.6 { execsql {SELECT * FROM t3} } {123} integrity_check delete-8.7 # Need to do the following for tcl 8.5 on mac. On that configuration, the # -readonly flag is taken so seriously that a subsequent [forcedelete] # (required before the next test file can be executed) will fail. # catch {file attributes test.db -readonly 0} db close forcedelete test.db test.db-journal # The following tests verify that SQLite correctly handles the case # where an index B-Tree is being scanned, the rowid column being read # from each index entry and another statement deletes some rows from # the index B-Tree. At one point this (obscure) scenario was causing # SQLite to return spurious SQLITE_CORRUPT errors and arguably incorrect # query results. |
︙ | ︙ |
Changes to test/descidx1.test.
︙ | ︙ | |||
293 294 295 296 297 298 299 | # Test the legacy_file_format pragma here because we have access to # the get_file_format command. # ifcapable legacyformat { do_test descidx1-6.1 { db close | | | | 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | # Test the legacy_file_format pragma here because we have access to # the get_file_format command. # ifcapable legacyformat { do_test descidx1-6.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql {PRAGMA legacy_file_format} } {1} } else { do_test descidx1-6.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql {PRAGMA legacy_file_format} } {0} } do_test descidx1-6.2 { execsql {PRAGMA legacy_file_format=YES} execsql {PRAGMA legacy_file_format} |
︙ | ︙ | |||
324 325 326 327 328 329 330 | do_test descidx1-6.3.1 { execsql {VACUUM} get_file_format } {1} } do_test descidx1-6.4 { db close | | | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | do_test descidx1-6.3.1 { execsql {VACUUM} get_file_format } {1} } do_test descidx1-6.4 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql {PRAGMA legacy_file_format=NO} execsql {PRAGMA legacy_file_format} } {0} do_test descidx1-6.5 { execsql { CREATE TABLE t1(a,b,c); |
︙ | ︙ |
Changes to test/diskfull.test.
︙ | ︙ | |||
78 79 80 81 82 83 84 | integrity_check ${prefix}.$::i.2 } } do_diskfull_test diskfull-2 VACUUM # db close | | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | integrity_check ${prefix}.$::i.2 } } do_diskfull_test diskfull-2 VACUUM # db close # forcedelete test.db # forcedelete test.db-journal # sqlite3 db test.db # # do_test diskfull-3.1 { # execsql { # PRAGMA default_cache_size = 10; # CREATE TABLE t3(a, b, UNIQUE(a, b)); # INSERT INTO t3 VALUES( randstr(100, 100), randstr(100, 100) ); |
︙ | ︙ |
Changes to test/e_expr.test.
︙ | ︙ | |||
653 654 655 656 657 658 659 | do_execsql_test e_expr-12.2.6 {SELECT CURRENT_TIME} {00:00:01} do_execsql_test e_expr-12.2.7 {SELECT CURRENT_DATE} {1970-01-01} do_execsql_test e_expr-12.2.8 {SELECT CURRENT_TIMESTAMP} {{1970-01-01 00:00:01}} set sqlite_current_time 0 # EVIDENCE-OF: R-57598-59332 -- syntax diagram expr # | | | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | do_execsql_test e_expr-12.2.6 {SELECT CURRENT_TIME} {00:00:01} do_execsql_test e_expr-12.2.7 {SELECT CURRENT_DATE} {1970-01-01} do_execsql_test e_expr-12.2.8 {SELECT CURRENT_TIMESTAMP} {{1970-01-01 00:00:01}} set sqlite_current_time 0 # EVIDENCE-OF: R-57598-59332 -- syntax diagram expr # forcedelete test.db2 execsql { ATTACH 'test.db2' AS dbname; CREATE TABLE dbname.tblname(cname); } proc glob {args} {return 1} db function glob glob |
︙ | ︙ | |||
1671 1672 1673 1674 1675 1676 1677 | db3 close } #------------------------------------------------------------------------- # Test statements related to the EXISTS and NOT EXISTS operators. # catch { db close } | | | 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 | db3 close } #------------------------------------------------------------------------- # Test statements related to the EXISTS and NOT EXISTS operators. # catch { db close } forcedelete test.db sqlite3 db test.db do_execsql_test e_expr-34.1 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(NULL, 2); INSERT INTO t1 VALUES(1, NULL); |
︙ | ︙ | |||
1752 1753 1754 1755 1756 1757 1758 | } #------------------------------------------------------------------------- # Test statements related to scalar sub-queries. # catch { db close } | | | 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 | } #------------------------------------------------------------------------- # Test statements related to scalar sub-queries. # catch { db close } forcedelete test.db sqlite3 db test.db do_test e_expr-35.0 { execsql { CREATE TABLE t2(a, b); INSERT INTO t2 VALUES('one', 'two'); INSERT INTO t2 VALUES('three', NULL); INSERT INTO t2 VALUES(4, 5.0); |
︙ | ︙ |
Changes to test/e_fts3.test.
︙ | ︙ | |||
56 57 58 59 60 61 62 | #if {$DO_MALLOC_TEST} break # Reset the database and database connection. If this iteration of the # [foreach] loop is testing with OOM errors, disable the lookaside buffer. # db close | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #if {$DO_MALLOC_TEST} break # Reset the database and database connection. If this iteration of the # [foreach] loop is testing with OOM errors, disable the lookaside buffer. # db close forcedelete test.db test.db-journal sqlite3 db test.db if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 } db eval "PRAGMA encoding = '$enc'" proc mit {blob} { set scan(littleEndian) i* set scan(bigEndian) I* |
︙ | ︙ | |||
633 634 635 636 637 638 639 | #------------------------------------------------------------------------- # Test that FTS3 tables can be renamed using the ALTER RENAME command. # OOM errors are tested during ALTER RENAME commands also. # foreach DO_MALLOC_TEST {0 1 2} { db close | | | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | #------------------------------------------------------------------------- # Test that FTS3 tables can be renamed using the ALTER RENAME command. # OOM errors are tested during ALTER RENAME commands also. # foreach DO_MALLOC_TEST {0 1 2} { db close forcedelete test.db test.db-journal sqlite3 db test.db if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 } ddl_test 9.1.1 { CREATE VIRTUAL TABLE t10 USING fts3(x) } write_test 9.1.2 t10_content { INSERT INTO t10 VALUES('fts3 tables') } write_test 9.1.3 t10_content { INSERT INTO t10 VALUES('are renameable') } |
︙ | ︙ |
Changes to test/enc2.test.
︙ | ︙ | |||
138 139 140 141 142 143 144 | # The three unicode encodings understood by SQLite. set encodings [list UTF-8 UTF-16le UTF-16be] set sqlite_os_trace 0 set i 1 foreach enc $encodings { | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # The three unicode encodings understood by SQLite. set encodings [list UTF-8 UTF-16le UTF-16be] set sqlite_os_trace 0 set i 1 foreach enc $encodings { forcedelete test.db sqlite3 db test.db db eval "PRAGMA encoding = \"$enc\"" execsql $dbcontents do_test enc2-$i.0.1 { db eval {PRAGMA encoding} } $enc do_test enc2-$i.0.2 { |
︙ | ︙ | |||
168 169 170 171 172 173 174 | incr i } # Test that it is an error to try to attach a database with a different # encoding to the main database. ifcapable attach { do_test enc2-4.1 { | | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | incr i } # Test that it is an error to try to attach a database with a different # encoding to the main database. ifcapable attach { do_test enc2-4.1 { forcedelete test.db sqlite3 db test.db db eval "PRAGMA encoding = 'UTF-8'" db eval "CREATE TABLE abc(a, b, c);" } {} do_test enc2-4.2 { forcedelete test2.db sqlite3 db2 test2.db db2 eval "PRAGMA encoding = 'UTF-16'" db2 eval "CREATE TABLE abc(a, b, c);" } {} do_test enc2-4.3 { catchsql { ATTACH 'test2.db' as aux; |
︙ | ︙ | |||
202 203 204 205 206 207 208 | set l [lsearch -exact $::values $lhs] set r [lsearch -exact $::values $rhs] set res [expr $l - $r] # puts "enc=$enc lhs=$lhs/$l rhs=$rhs/$r res=$res" return $res } | | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | set l [lsearch -exact $::values $lhs] set r [lsearch -exact $::values $rhs] set res [expr $l - $r] # puts "enc=$enc lhs=$lhs/$l rhs=$rhs/$r res=$res" return $res } forcedelete test.db sqlite3 db test.db; set DB [sqlite3_connection_pointer db] do_test enc2-5.0 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); INSERT INTO t5 VALUES('two'); INSERT INTO t5 VALUES('five'); |
︙ | ︙ | |||
231 232 233 234 235 236 237 | do_test enc2-5.3 { add_test_collate $DB 0 0 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16BE} db close | | | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | do_test enc2-5.3 { add_test_collate $DB 0 0 1 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-16BE} db close forcedelete test.db sqlite3 db test.db; set DB [sqlite3_connection_pointer db] execsql {pragma encoding = 'UTF-16LE'} do_test enc2-5.4 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); INSERT INTO t5 VALUES('two'); |
︙ | ︙ | |||
261 262 263 264 265 266 267 | do_test enc2-5.7 { add_test_collate $DB 1 0 0 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-8} db close | | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | do_test enc2-5.7 { add_test_collate $DB 1 0 0 set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}] lappend res $::test_collate_enc } {one two three four five UTF-8} db close forcedelete test.db sqlite3 db test.db; set DB [sqlite3_connection_pointer db] execsql {pragma encoding = 'UTF-16BE'} do_test enc2-5.8 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); INSERT INTO t5 VALUES('two'); |
︙ | ︙ | |||
307 308 309 310 311 312 313 | lappend res $::test_collate_enc } {one two three four five UTF-16BE} do_test enc2-5.14 { set ::sqlite_last_needed_collation } test_collate db close | | | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | lappend res $::test_collate_enc } {one two three four five UTF-16BE} do_test enc2-5.14 { set ::sqlite_last_needed_collation } test_collate db close forcedelete test.db do_test enc2-5.15 { sqlite3 db test.db; set ::DB [sqlite3_connection_pointer db] add_test_collate_needed $::DB set ::sqlite_last_needed_collation } {} do_test enc2-5.16 { |
︙ | ︙ | |||
329 330 331 332 333 334 335 | # user function when more than one is available. proc test_function {enc arg} { return "$enc $arg" } db close | | | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | # user function when more than one is available. proc test_function {enc arg} { return "$enc $arg" } db close forcedelete test.db sqlite3 db test.db; set DB [sqlite3_connection_pointer db] execsql {pragma encoding = 'UTF-8'} do_test enc2-6.0 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('one'); } |
︙ | ︙ | |||
362 363 364 365 366 367 368 | add_test_function $DB 0 0 1 execsql { SELECT test_function('sqlite') } } {{UTF-16BE sqlite}} db close | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | add_test_function $DB 0 0 1 execsql { SELECT test_function('sqlite') } } {{UTF-16BE sqlite}} db close forcedelete test.db sqlite3 db test.db; set DB [sqlite3_connection_pointer db] execsql {pragma encoding = 'UTF-16LE'} do_test enc2-6.3 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('sqlite'); } |
︙ | ︙ | |||
395 396 397 398 399 400 401 | add_test_function $DB 0 0 1 execsql { SELECT test_function('sqlite') } } {{UTF-16BE sqlite}} db close | | | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | add_test_function $DB 0 0 1 execsql { SELECT test_function('sqlite') } } {{UTF-16BE sqlite}} db close forcedelete test.db sqlite3 db test.db; set DB [sqlite3_connection_pointer db] execsql {pragma encoding = 'UTF-16BE'} do_test enc2-6.7 { execsql { CREATE TABLE t5(a); INSERT INTO t5 VALUES('sqlite'); } |
︙ | ︙ | |||
429 430 431 432 433 434 435 | execsql { SELECT test_function('sqlite') } } {{UTF-16BE sqlite}} db close | | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | execsql { SELECT test_function('sqlite') } } {{UTF-16BE sqlite}} db close forcedelete test.db # The following tests - enc2-7.* - function as follows: # # 1: Open an empty database file assuming UTF-16 encoding. # 2: Open the same database with a different handle assuming UTF-8. Create # a table using this handle. # 3: Read the sqlite_master table from the first handle. |
︙ | ︙ | |||
489 490 491 492 493 494 495 | do_test enc2-8.2 { sqlite3_complete16 [utf16 "SELECT * FROM"] } {0} } # Test that the encoding of an empty database may still be set after the # (empty) schema has been initialized. | | | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | do_test enc2-8.2 { sqlite3_complete16 [utf16 "SELECT * FROM"] } {0} } # Test that the encoding of an empty database may still be set after the # (empty) schema has been initialized. forcedelete test.db do_test enc2-9.1 { sqlite3 db test.db execsql { PRAGMA encoding = 'UTF-8'; PRAGMA encoding; } } {UTF-8} |
︙ | ︙ | |||
533 534 535 536 537 538 539 | } {UTF-16le} # Ticket #1987. # Disallow encoding changes once the encoding has been set. # do_test enc2-10.1 { db close | | | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | } {UTF-16le} # Ticket #1987. # Disallow encoding changes once the encoding has been set. # do_test enc2-10.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db db eval { PRAGMA encoding=UTF16; CREATE TABLE t1(a); PRAGMA encoding=UTF8; CREATE TABLE t2(b); } |
︙ | ︙ |
Changes to test/enc3.test.
︙ | ︙ | |||
77 78 79 80 81 82 83 | } {1} } # Try to attach a database with a different encoding. # ifcapable {utf16 && shared_cache} { db close | | | | 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 | } {1} } # Try to attach a database with a different encoding. # ifcapable {utf16 && shared_cache} { db close forcedelete test8.db test8.db-journal set ::enable_shared_cache [sqlite3_enable_shared_cache 1] sqlite3 dbaux test8.db sqlite3 db test.db db eval {SELECT 1 FROM sqlite_master LIMIT 1} do_test enc3-3.1 { dbaux eval { PRAGMA encoding='utf8'; CREATE TABLE t1(x); PRAGMA encoding } } {UTF-8} do_test enc3-3.2 { catchsql { ATTACH 'test.db' AS utf16; SELECT 1 FROM utf16.sqlite_master LIMIT 1; } dbaux } {1 {attached databases must use the same text encoding as main database}} dbaux close forcedelete test8.db test8.db-journal sqlite3_enable_shared_cache $::enable_shared_cache } finish_test |
Changes to test/enc4.test.
︙ | ︙ | |||
39 40 41 42 43 44 45 | "100000000000000000000000000000000000000000000000000000000"\ "1.0000000000000000000000000000000000000000000000000000000"\ ] set i 1 foreach enc $encodings { | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | "100000000000000000000000000000000000000000000000000000000"\ "1.0000000000000000000000000000000000000000000000000000000"\ ] set i 1 foreach enc $encodings { forcedelete test.db sqlite3 db test.db db eval "PRAGMA encoding = \"$enc\"" do_test enc4-$i.1 { db eval {PRAGMA encoding} } $enc |
︙ | ︙ | |||
89 90 91 92 93 94 95 | incr j } db close incr i } | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | incr j } db close incr i } forcedelete test.db sqlite3 db test.db do_test enc4-4.1 { db eval "select 1+1." } {2.0} do_test enc4-4.2.1 { |
︙ | ︙ |
Changes to test/exclusive.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 | source $testdir/tester.tcl ifcapable {!pager_pragmas} { finish_test return } | | | | | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | source $testdir/tester.tcl ifcapable {!pager_pragmas} { finish_test return } forcedelete test2.db-journal forcedelete test2.db forcedelete test3.db-journal forcedelete test3.db forcedelete test4.db-journal forcedelete test4.db #---------------------------------------------------------------------- # Test cases exclusive-1.X test the PRAGMA logic. # do_test exclusive-1.0 { execsql { pragma locking_mode; |
︙ | ︙ | |||
477 478 479 480 481 482 483 | BEGIN; INSERT INTO t4 VALUES('Macmillan', 1957); INSERT INTO t4 VALUES('Douglas-Home', 1963); INSERT INTO t4 VALUES('Wilson', 1964); } do_test exclusive-6.2 { forcedelete test2.db test2.db-journal | | | | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | BEGIN; INSERT INTO t4 VALUES('Macmillan', 1957); INSERT INTO t4 VALUES('Douglas-Home', 1963); INSERT INTO t4 VALUES('Wilson', 1964); } do_test exclusive-6.2 { forcedelete test2.db test2.db-journal copy_file test.db test2.db copy_file test.db-journal test2.db-journal sqlite3 db test2.db } {} do_execsql_test exclusive-6.3 { PRAGMA locking_mode = EXCLUSIVE; SELECT * FROM t4; } {exclusive Eden 1955} |
︙ | ︙ |
Changes to test/exclusive2.test.
︙ | ︙ | |||
255 256 257 258 259 260 261 | # is only incremented by the first change when in exclusive access # mode. In normal mode, the change-counter is incremented once # per write-transaction. # db close catch {close $::fd} | | | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | # is only incremented by the first change when in exclusive access # mode. In normal mode, the change-counter is incremented once # per write-transaction. # db close catch {close $::fd} forcedelete test.db forcedelete test.db-journal do_test exclusive2-3.0 { sqlite3 db test.db execsql { BEGIN; CREATE TABLE t1(a UNIQUE); INSERT INTO t1 VALUES(randstr(200, 200)); |
︙ | ︙ |
Changes to test/fallocate.test.
︙ | ︙ | |||
75 76 77 78 79 80 81 | set skipwaltests [expr { [permutation]=="journaltest" || [permutation]=="inmemory_journal" }] ifcapable !wal { set skipwaltests 1 } if {!$skipwaltests} { db close | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | set skipwaltests [expr { [permutation]=="journaltest" || [permutation]=="inmemory_journal" }] ifcapable !wal { set skipwaltests 1 } if {!$skipwaltests} { db close forcedelete test.db sqlite3 db test.db file_control_chunksize_test db main [expr 32*1024] do_test fallocate-2.1 { execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; |
︙ | ︙ |
Changes to test/filectrl.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 | } {} do_test filectrl-1.5 { db close sqlite3 db test_control_lockproxy.db file_control_lockproxy_test db [pwd] } {} db close | | | 33 34 35 36 37 38 39 40 41 | } {} do_test filectrl-1.5 { db close sqlite3 db test_control_lockproxy.db file_control_lockproxy_test db [pwd] } {} db close forcedelete .test_control_lockproxy.db-conch test.proxy finish_test |
Changes to test/filefmt.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # do_not_use_codec db close | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # do_not_use_codec db close forcedelete test.db test.db-journal # Database begins with valid 16-byte header string. # do_test filefmt-1.1 { sqlite3 db test.db db eval {CREATE TABLE t1(x)} db close |
︙ | ︙ | |||
59 60 61 62 63 64 65 | # ifcapable pager_pragmas { foreach pagesize {512 1024 2048 4096 8192 16384 32768} { if {[info exists SQLITE_MAX_PAGE_SIZE] && $pagesize>$SQLITE_MAX_PAGE_SIZE} continue do_test filefmt-1.5.$pagesize.1 { db close | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # ifcapable pager_pragmas { foreach pagesize {512 1024 2048 4096 8192 16384 32768} { if {[info exists SQLITE_MAX_PAGE_SIZE] && $pagesize>$SQLITE_MAX_PAGE_SIZE} continue do_test filefmt-1.5.$pagesize.1 { db close forcedelete test.db sqlite3 db test.db db eval "PRAGMA auto_vacuum=OFF" db eval "PRAGMA page_size=$pagesize" db eval {CREATE TABLE t1(x)} file size test.db } [expr $pagesize*2] do_test filefmt-1.5.$pagesize.2 { |
︙ | ︙ | |||
101 102 103 104 105 106 107 | # Usable space per page (page-size minus unused space per page) # must be at least 480 bytes # ifcapable pager_pragmas { do_test filefmt-1.8 { db close | | | | 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 | # Usable space per page (page-size minus unused space per page) # must be at least 480 bytes # ifcapable pager_pragmas { do_test filefmt-1.8 { db close forcedelete test.db sqlite3 db test.db db eval {PRAGMA page_size=512; CREATE TABLE t1(x)} db close hexio_write test.db 20 21 sqlite3 db test.db catchsql { SELECT count(*) FROM sqlite_master } } {1 {file is encrypted or is not a database}} } #------------------------------------------------------------------------- # The following block of tests - filefmt-2.* - test that versions 3.7.0 # and later can read and write databases that have been modified or created # by 3.6.23.1 and earlier. The difference difference is that 3.7.0 stores # the size of the database in the database file header, whereas 3.6.23.1 # always derives this from the size of the file. # db close forcedelete test.db set a_string_counter 1 proc a_string {n} { incr ::a_string_counter string range [string repeat "${::a_string_counter}." $n] 1 $n } sqlite3 db test.db |
︙ | ︙ | |||
153 154 155 156 157 158 159 | } {} do_execsql_test filefmt-2.1.4 { INSERT INTO t2 VALUES(2) } {} integrity_check filefmt-2.1.5 do_test filefmt-2.1.6 { hexio_read test.db 28 4 } {00000010} db close | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | } {} do_execsql_test filefmt-2.1.4 { INSERT INTO t2 VALUES(2) } {} integrity_check filefmt-2.1.5 do_test filefmt-2.1.6 { hexio_read test.db 28 4 } {00000010} db close forcedelete test.db sqlite3 db test.db db func a_string a_string do_execsql_test filefmt-2.2.1 { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; CREATE TABLE t1(a); |
︙ | ︙ |
Changes to test/fts1j.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # If SQLITE_ENABLE_FTS1 is defined, omit this file. ifcapable !fts1 { finish_test return } # Clean up anything left over from a previous pass. | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # If SQLITE_ENABLE_FTS1 is defined, omit this file. ifcapable !fts1 { finish_test return } # Clean up anything left over from a previous pass. forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db db eval { CREATE VIRTUAL TABLE t3 USING fts1(content); INSERT INTO t3 (rowid, content) VALUES(1, "hello world"); } |
︙ | ︙ | |||
80 81 82 83 84 85 86 | DETACH DATABASE two; } db2 } {2} catch {db eval {DETACH DATABASE two}} catch {db2 close} | | | 80 81 82 83 84 85 86 87 88 89 | DETACH DATABASE two; } db2 } {2} catch {db eval {DETACH DATABASE two}} catch {db2 close} forcedelete test2.db finish_test |
Changes to test/fts1o.test.
︙ | ︙ | |||
91 92 93 94 95 96 97 | execsql { SELECT a, b, c FROM fts_t1 WHERE c MATCH 'four'; } } {{one three four} {one four} {one four two}} #--------------------------------------------------------------------- # Test that it is possible to rename an fts1 table in an attached # database. # | | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | execsql { SELECT a, b, c FROM fts_t1 WHERE c MATCH 'four'; } } {{one three four} {one four} {one four two}} #--------------------------------------------------------------------- # Test that it is possible to rename an fts1 table in an attached # database. # forcedelete test2.db test2.db-journal do_test fts1o-4.1 { execsql { DROP TABLE t1_term; ALTER TABLE fts_t1 RENAME to t1; SELECT a, b, c FROM t1 WHERE c MATCH 'two'; } |
︙ | ︙ |
Changes to test/fts2j.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # If SQLITE_ENABLE_FTS2 is defined, omit this file. ifcapable !fts2 { finish_test return } # Clean up anything left over from a previous pass. | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # If SQLITE_ENABLE_FTS2 is defined, omit this file. ifcapable !fts2 { finish_test return } # Clean up anything left over from a previous pass. forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db db eval { CREATE VIRTUAL TABLE t3 USING fts2(content); INSERT INTO t3 (rowid, content) VALUES(1, "hello world"); } |
︙ | ︙ | |||
80 81 82 83 84 85 86 | DETACH DATABASE two; } db2 } {2} catch {db eval {DETACH DATABASE two}} catch {db2 close} | | | 80 81 82 83 84 85 86 87 88 89 | DETACH DATABASE two; } db2 } {2} catch {db eval {DETACH DATABASE two}} catch {db2 close} forcedelete test2.db finish_test |
Changes to test/fts2o.test.
︙ | ︙ | |||
105 106 107 108 109 110 111 | } {{one three four} {one four} {one four two}} #------------------------------------------------------------------- # Close, delete and reopen the database. The following test should # be run on an initially empty db. # db close | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | } {{one three four} {one four} {one four two}} #------------------------------------------------------------------- # Close, delete and reopen the database. The following test should # be run on an initially empty db. # db close forcedelete test.db test.db-journal sqlite3 db test.db do_test fts2o-3.1 { execsql { CREATE VIRTUAL TABLE t1 USING fts2(a, b, c); INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two'); SELECT a, b, c FROM t1 WHERE c MATCH 'two'; |
︙ | ︙ | |||
130 131 132 133 134 135 136 | } } {{one three four} {one four} {one two} {one three four} {one four} {one two}} #--------------------------------------------------------------------- # Test that it is possible to rename an fts2 table in an attached # database. # | | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | } } {{one three four} {one four} {one two} {one three four} {one four} {one two}} #--------------------------------------------------------------------- # Test that it is possible to rename an fts2 table in an attached # database. # forcedelete test2.db test2.db-journal do_test fts2o-3.1 { execsql { ATTACH 'test2.db' AS aux; CREATE VIRTUAL TABLE aux.t1 USING fts2(a, b, c); INSERT INTO aux.t1(a, b, c) VALUES( 'neung song sahm', 'neung see', 'neung see song' |
︙ | ︙ |
Changes to test/fts3aj.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts3 { finish_test return } # Clean up anything left over from a previous pass. | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts3 { finish_test return } # Clean up anything left over from a previous pass. forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db db eval { CREATE VIRTUAL TABLE t3 USING fts3(content); INSERT INTO t3 (rowid, content) VALUES(1, "hello world"); } |
︙ | ︙ | |||
80 81 82 83 84 85 86 | DETACH DATABASE two; } db2 } {2} catch {db eval {DETACH DATABASE two}} catch {db2 close} | | | 80 81 82 83 84 85 86 87 88 89 | DETACH DATABASE two; } db2 } {2} catch {db eval {DETACH DATABASE two}} catch {db2 close} forcedelete test2.db finish_test |
Changes to test/fts3ao.test.
︙ | ︙ | |||
107 108 109 110 111 112 113 | } {{one three four} {one four} {one four two}} #------------------------------------------------------------------- # Close, delete and reopen the database. The following test should # be run on an initially empty db. # db close | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | } {{one three four} {one four} {one four two}} #------------------------------------------------------------------- # Close, delete and reopen the database. The following test should # be run on an initially empty db. # db close forcedelete test.db test.db-journal sqlite3 db test.db do_test fts3ao-3.1 { execsql { CREATE VIRTUAL TABLE t1 USING fts3(a, b, c); INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two'); SELECT a, b, c FROM t1 WHERE c MATCH 'two'; |
︙ | ︙ | |||
132 133 134 135 136 137 138 | } } {{one three four} {one four} {one two} {one three four} {one four} {one two}} #--------------------------------------------------------------------- # Test that it is possible to rename an fts3 table in an attached # database. # | | | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | } } {{one three four} {one four} {one two} {one three four} {one four} {one two}} #--------------------------------------------------------------------- # Test that it is possible to rename an fts3 table in an attached # database. # forcedelete test2.db test2.db-journal do_test fts3ao-3.1 { execsql { ATTACH 'test2.db' AS aux; CREATE VIRTUAL TABLE aux.t1 USING fts3(a, b, c); INSERT INTO aux.t1(a, b, c) VALUES( 'neung song sahm', 'neung see', 'neung see song' |
︙ | ︙ |
Changes to test/fts3snippet.test.
︙ | ︙ | |||
127 128 129 130 131 132 133 | foreach {DO_MALLOC_TEST enc} { 0 utf8 1 utf8 1 utf16 } { db close | | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | foreach {DO_MALLOC_TEST enc} { 0 utf8 1 utf8 1 utf16 } { db close forcedelete test.db sqlite3 db test.db sqlite3_db_config_lookaside db 0 0 0 db eval "PRAGMA encoding = \"$enc\"" # Set variable $T to the test name prefix for this iteration of the loop. # set T "fts3snippet-$enc" |
︙ | ︙ |
Changes to test/fts4aa.test.
︙ | ︙ | |||
1682 1683 1684 1685 1686 1687 1688 | } $r } # Should get the same search results when the page size is very large # do_test fts4aa-3.0 { db close | | | 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 | } $r } # Should get the same search results when the page size is very large # do_test fts4aa-3.0 { db close forcedelete test.db sqlite3 db test.db db eval { PRAGMA page_size=65536; CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter); } fts4aa_fill_table } {} |
︙ | ︙ |
Changes to test/fuzz_malloc.test.
︙ | ︙ | |||
43 44 45 46 47 48 49 | proc do_fuzzy_malloc_test {testname args} { set ::fuzzyopts(-repeats) $::REPEATS set ::fuzzyopts(-sqlprep) {} array set ::fuzzyopts $args sqlite3_memdebug_fail -1 db close | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | proc do_fuzzy_malloc_test {testname args} { set ::fuzzyopts(-repeats) $::REPEATS set ::fuzzyopts(-sqlprep) {} array set ::fuzzyopts $args sqlite3_memdebug_fail -1 db close delete_file test.db test.db-journal sqlite3 db test.db set ::prep $::fuzzyopts(-sqlprep) execsql $::prep set jj 0 for {set ii 0} {$ii < $::fuzzyopts(-repeats)} {incr ii} { expr srand($jj) incr jj |
︙ | ︙ |
Changes to test/hook.test.
︙ | ︙ | |||
91 92 93 94 95 96 97 | } set ::commit_cnt } {} # Ticket #3564. # do_test hook-3.10 { | | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | } set ::commit_cnt } {} # Ticket #3564. # do_test hook-3.10 { forcedelete test2.db test2.db-journal sqlite3 db2 test2.db proc commit_hook {} { set y [db2 one {SELECT y FROM t3 WHERE y>10}] return [expr {$y>10}] } db2 eval {CREATE TABLE t3(x,y)} db2 commit_hook commit_hook |
︙ | ︙ | |||
213 214 215 216 217 218 219 | } } # Update-hook + ATTACH set ::update_hook {} ifcapable attach { do_test hook-4.2.3 { | | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | } } # Update-hook + ATTACH set ::update_hook {} ifcapable attach { do_test hook-4.2.3 { forcedelete test2.db execsql { ATTACH 'test2.db' AS aux; CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b); INSERT INTO aux.t3 SELECT * FROM t1; UPDATE t3 SET b = 'two or so' WHERE a = 2; DELETE FROM t3 WHERE 1; -- Avoid the truncate optimization (for now) } |
︙ | ︙ |
Changes to test/incrblob.test.
︙ | ︙ | |||
116 117 118 119 120 121 122 | if {$AutoVacuumMode>0} { ifcapable !autovacuum { break } } db close | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | if {$AutoVacuumMode>0} { ifcapable !autovacuum { break } } db close forcedelete test.db test.db-journal sqlite3 db test.db execsql "PRAGMA auto_vacuum = $AutoVacuumMode" do_test incrblob-2.$AutoVacuumMode.1 { set ::str [string repeat abcdefghij 2900] execsql { |
︙ | ︙ | |||
375 376 377 378 379 380 381 | #------------------------------------------------------------------------ # incrblob-5.*: # # Test that opening a blob in an attached database works. # ifcapable attach { do_test incrblob-5.1 { | | | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | #------------------------------------------------------------------------ # incrblob-5.*: # # Test that opening a blob in an attached database works. # ifcapable attach { do_test incrblob-5.1 { forcedelete test2.db test2.db-journal set ::size [expr [file size [info script]]] execsql { ATTACH 'test2.db' AS aux; CREATE TABLE aux.files(name, text); INSERT INTO aux.files VALUES('this one', zeroblob($::size)); } set fd [db incrblob aux files text 1] |
︙ | ︙ | |||
580 581 582 583 584 585 586 | set fd [open [info script]] fconfigure $fd -translation binary set ::data [read $fd 14000] close $fd db close | | | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | set fd [open [info script]] fconfigure $fd -translation binary set ::data [read $fd 14000] close $fd db close forcedelete test.db test.db-journal sqlite3 db test.db do_test incrblob-7.2.1 { execsql { PRAGMA auto_vacuum = "incremental"; CREATE TABLE t1(a INTEGER PRIMARY KEY, b); -- root@page3 INSERT INTO t1 VALUES(123, $::data); |
︙ | ︙ |
Changes to test/incrvacuum.test.
︙ | ︙ | |||
327 328 329 330 331 332 333 | }] $control } } set ::str1 [string repeat abcdefghij 130] set ::str2 [string repeat 1234567890 105] | | | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | }] $control } } set ::str1 [string repeat abcdefghij 130] set ::str2 [string repeat 1234567890 105] forcedelete test1.db test1.db-journal test2.db test2.db-journal sqlite3 db1 test1.db sqlite3 db2 test2.db execsql { PRAGMA auto_vacuum = 'none' } db1 execsql { PRAGMA auto_vacuum = 'incremental' } db2 set tn 1 foreach sql $::TestScriptList { |
︙ | ︙ | |||
471 472 473 474 475 476 477 | } {} #--------------------------------------------------------------------- # At one point this test case was causing an assert() to fail. # do_test incrvacuum-9.1 { db close | | | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | } {} #--------------------------------------------------------------------- # At one point this test case was causing an assert() to fail. # do_test incrvacuum-9.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA auto_vacuum = 'incremental'; CREATE TABLE t1(a, b, c); CREATE TABLE t2(a, b, c); INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500)); |
︙ | ︙ | |||
589 590 591 592 593 594 595 | #---------------------------------------------------------------- # Test that if we set the auto_vacuum mode to 'incremental', then # create a database, thereafter that database defaults to incremental # vacuum mode. # db close | | | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | #---------------------------------------------------------------- # Test that if we set the auto_vacuum mode to 'incremental', then # create a database, thereafter that database defaults to incremental # vacuum mode. # db close forcedelete test.db test.db-journal sqlite3 db test.db ifcapable default_autovacuum { do_test incrvacuum-11.1-av-dflt-on { execsql { PRAGMA auto_vacuum; } |
︙ | ︙ | |||
647 648 649 650 651 652 653 | } {1} #---------------------------------------------------------------------- # Special case: What happens if the database is locked when a "PRAGMA # auto_vacuum = XXX" statement is executed. # db close | | | 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 | } {1} #---------------------------------------------------------------------- # Special case: What happens if the database is locked when a "PRAGMA # auto_vacuum = XXX" statement is executed. # db close forcedelete test.db test.db-journal sqlite3 db test.db do_test incrvacuum-12.1 { execsql { PRAGMA auto_vacuum = 1; } expr {[file size test.db]>0} |
︙ | ︙ | |||
688 689 690 691 692 693 694 | #---------------------------------------------------------------------- # Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX" # statement when the database is empty, but doesn't execute it until # after some other process has created the database. # db2 close db close | | | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 | #---------------------------------------------------------------------- # Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX" # statement when the database is empty, but doesn't execute it until # after some other process has created the database. # db2 close db close forcedelete test.db test.db-journal sqlite3 db test.db ; set ::DB [sqlite3_connection_pointer db] sqlite3 db2 test.db do_test incrvacuum-13.1 { # File size is sometimes 1 instead of 0 due to the hack we put in # to work around ticket #3260. Search for comments on #3260 in # os_unix.c. |
︙ | ︙ | |||
739 740 741 742 743 744 745 | } {1 {file is encrypted or is not a database}} db3 close } do_test incrvacuum-15.1 { db close db2 close | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 | } {1 {file is encrypted or is not a database}} db3 close } do_test incrvacuum-15.1 { db close db2 close forcedelete test.db sqlite3 db test.db set str [string repeat "abcdefghij" 500] execsql { PRAGMA cache_size = 10; PRAGMA auto_vacuum = incremental; |
︙ | ︙ |
Changes to test/incrvacuum2.test.
︙ | ︙ | |||
66 67 68 69 70 71 72 | file size test.db } {3072} # Make sure incremental vacuum works on attached databases. # ifcapable attach { do_test incrvacuum2-2.1 { | | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | file size test.db } {3072} # Make sure incremental vacuum works on attached databases. # ifcapable attach { do_test incrvacuum2-2.1 { forcedelete test2.db test2.db-journal execsql { ATTACH DATABASE 'test2.db' AS aux; PRAGMA aux.auto_vacuum=incremental; CREATE TABLE aux.t2(x); INSERT INTO t2 VALUES(zeroblob(30000)); INSERT INTO t1 SELECT * FROM t2; DELETE FROM t2; |
︙ | ︙ |
Changes to test/incrvacuum_ioerr.test.
︙ | ︙ | |||
104 105 106 107 108 109 110 | db close } ifcapable shared_cache { catch { db close } | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | db close } ifcapable shared_cache { catch { db close } forcedelete test.db set ::enable_shared_cache [sqlite3_enable_shared_cache 1] # Create two connections to a single shared-cache: # sqlite3 db1 test.db sqlite3 db2 test.db |
︙ | ︙ |
Changes to test/insert5.test.
︙ | ︙ | |||
30 31 32 33 34 35 36 | proc uses_temp_table {sql} { return [expr {[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]>=0}] } # Construct the sample database. # do_test insert5-1.0 { | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | proc uses_temp_table {sql} { return [expr {[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]>=0}] } # Construct the sample database. # do_test insert5-1.0 { forcedelete test2.db test2.db-journal execsql { CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER); CREATE TABLE B(Id INTEGER, Id1 INTEGER); CREATE VIEW v1 AS SELECT * FROM B; CREATE VIEW v2 AS SELECT * FROM MAIN; INSERT INTO MAIN(Id,Id1) VALUES(2,3); INSERT INTO B(Id,Id1) VALUES(2,3); |
︙ | ︙ |
Changes to test/io.test.
︙ | ︙ | |||
221 222 223 224 225 226 227 | file mkdir test.db-journal catchsql { INSERT INTO abc VALUES(9, randstr(1000,1000)); COMMIT } } {1 {unable to open database file}} do_test io-2.6.3 { | | | | 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 | file mkdir test.db-journal catchsql { INSERT INTO abc VALUES(9, randstr(1000,1000)); COMMIT } } {1 {unable to open database file}} do_test io-2.6.3 { forcedelete test.db-journal catchsql { COMMIT } } {0 {}} do_test io-2.6.4 { execsql { SELECT * FROM abc } } {1 2 3 4 5 6 7 8} # Test that if the database modification is part of multi-file commit, # the journal file is always created. In this case, the journal file # is created during execution of the COMMIT statement, so we have to # use the same technique to check that it is created as in the above # block. forcedelete test2.db test2.db-journal ifcapable attach { do_test io-2.7.1 { execsql { ATTACH 'test2.db' AS aux; PRAGMA aux.page_size = 1024; CREATE TABLE aux.abc2(a, b); BEGIN; |
︙ | ︙ | |||
257 258 259 260 261 262 263 | execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 } } {1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10} do_test io-2.7.4 { file mkdir test2.db-journal catchsql { COMMIT } } {1 {unable to open database file}} do_test io-2.7.5 { | | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 } } {1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10} do_test io-2.7.4 { file mkdir test2.db-journal catchsql { COMMIT } } {1 {unable to open database file}} do_test io-2.7.5 { forcedelete test2.db-journal catchsql { COMMIT } } {1 {cannot commit - no transaction is active}} do_test io-2.7.6 { execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 } } {1 2 3 4 5 6 7 8} } |
︙ | ︙ | |||
300 301 302 303 304 305 306 | INSERT INTO abc VALUES(9, 10); } file exists test.db-journal } {1} do_test io-2.9.2 { execsql { ROLLBACK; } db close | | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | INSERT INTO abc VALUES(9, 10); } file exists test.db-journal } {1} do_test io-2.9.2 { execsql { ROLLBACK; } db close forcedelete test.db test.db-journal sqlite3 db test.db -vfs devsym execsql { PRAGMA auto_vacuum = OFF; PRAGMA page_size = 2048; CREATE TABLE abc(a, b); } execsql { |
︙ | ︙ | |||
371 372 373 374 375 376 377 | #---------------------------------------------------------------------- # Test cases io-3.* test the IOCAP_SEQUENTIAL optimization. # sqlite3_simulate_device -char sequential -sectorsize 0 ifcapable pager_pragmas { do_test io-3.1 { db close | | | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | #---------------------------------------------------------------------- # Test cases io-3.* test the IOCAP_SEQUENTIAL optimization. # sqlite3_simulate_device -char sequential -sectorsize 0 ifcapable pager_pragmas { do_test io-3.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db -vfs devsym db eval { PRAGMA auto_vacuum=OFF; } # File size might be 1 due to the hack to work around ticket #3260. # Search for #3260 in os_unix.c for additional information. expr {[file size test.db]>1} |
︙ | ︙ | |||
540 541 542 543 544 545 546 | {atomic2K} 4096 4096 {atomic2K atomic} 512 8192 {atomic64K} 512 1024 } { incr tn if {$pgsize>$::SQLITE_MAX_PAGE_SIZE} continue db close | | | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 | {atomic2K} 4096 4096 {atomic2K atomic} 512 8192 {atomic64K} 512 1024 } { incr tn if {$pgsize>$::SQLITE_MAX_PAGE_SIZE} continue db close forcedelete test.db test.db-journal sqlite3_simulate_device -char $char -sectorsize $sectorsize sqlite3 db test.db -vfs devsym db eval { PRAGMA auto_vacuum=OFF; } ifcapable !atomicwrite { if {[regexp {^atomic} $char]} continue |
︙ | ︙ |
Changes to test/ioerr.test.
︙ | ︙ | |||
179 180 181 182 183 184 185 | db2 eval { PRAGMA synchronous = 0; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); BEGIN; INSERT INTO t1 VALUES(3, 4); } | | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | db2 eval { PRAGMA synchronous = 0; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); BEGIN; INSERT INTO t1 VALUES(3, 4); } forcecopy test2.db test.db forcecopy test2.db-journal test.db-journal db2 close } -tclbody { sqlite3 db test.db db eval { SELECT * FROM t1; } } -exclude 1 |
︙ | ︙ | |||
215 216 217 218 219 220 221 | do_ioerr_test ioerr-9 -ckrefcount true -tclprep { execsql { CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); BEGIN; INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); } | | | | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | do_ioerr_test ioerr-9 -ckrefcount true -tclprep { execsql { CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); BEGIN; INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2); } forcecopy test.db-journal test2.db-journal execsql { COMMIT; } forcecopy test2.db-journal test.db-journal set f [open test.db-journal a] fconfigure $f -encoding binary puts -nonewline $f "hello" puts -nonewline $f "\x00\x00\x00\x05\x01\x02\x03\x04" puts -nonewline $f "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7" close $f } -sqlbody { |
︙ | ︙ |
Changes to test/ioerr4.test.
︙ | ︙ | |||
27 28 29 30 31 32 33 | # Enable shared cache mode and incremental vacuum. # do_test ioerr4-1.1 { db close set ::enable_shared_cache [sqlite3_enable_shared_cache 1] } {0} do_test ioerr4-1.2 { | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # Enable shared cache mode and incremental vacuum. # do_test ioerr4-1.1 { db close set ::enable_shared_cache [sqlite3_enable_shared_cache 1] } {0} do_test ioerr4-1.2 { forcedelete test.db test.db-journal sqlite3 db test.db sqlite3 db2 test.db db eval { PRAGMA auto_vacuum=INCREMENTAL; CREATE TABLE a(i INTEGER, b BLOB); } db2 eval { |
︙ | ︙ | |||
75 76 77 78 79 80 81 | } {64} # Set up for an I/O error on incremental vacuum # with two connections on shared cache. # db close db2 close | | | | | | 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 | } {64} # Set up for an I/O error on incremental vacuum # with two connections on shared cache. # db close db2 close forcecopy test.db test.db-bu do_ioerr_test ioerr4-2 -tclprep { catch {db2 close} db close forcedelete test.db test.db-journal forcecopy test.db-bu test.db sqlite3_enable_shared_cache 1 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] db eval {PRAGMA auto_vacuum=INCREMENTAL} sqlite3 db2 test.db } -tclbody { db eval {PRAGMA incremental_vacuum(5)} } db2 close forcedelete test.db-bu sqlite3_enable_shared_cache $::enable_shared_cache finish_test |
Changes to test/journal1.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | # $Id: journal1.test,v 1.2 2005/03/20 22:54:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # These tests will not work on windows because windows uses | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # $Id: journal1.test,v 1.2 2005/03/20 22:54:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # These tests will not work on windows because windows uses # manditory file locking which breaks the copy_file command. # if {$tcl_platform(platform)=="windows"} { finish_test return } # Create a smaple database |
︙ | ︙ | |||
47 48 49 50 51 52 53 | # database. # do_test journal1-1.2 { execsql { BEGIN; DELETE FROM t1; } | | | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | # database. # do_test journal1-1.2 { execsql { BEGIN; DELETE FROM t1; } forcecopy test.db-journal test.db-journal-bu execsql { ROLLBACK; } db close delete_file test.db copy_file test.db-journal-bu test.db-journal sqlite3 db test.db catchsql { SELECT * FROM sqlite_master } } {0 {}} finish_test |
Changes to test/journal2.test.
︙ | ︙ | |||
163 164 165 166 167 168 169 | do_test journal2-1.13 { tvfs filter {xOpen xClose xDelete xWrite xTruncate} set ::tvfs_error_on_write 1 catchsql { COMMIT } db2 } {1 {disk I/O error}} db2 close unset ::tvfs_error_on_write | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | do_test journal2-1.13 { tvfs filter {xOpen xClose xDelete xWrite xTruncate} set ::tvfs_error_on_write 1 catchsql { COMMIT } db2 } {1 {disk I/O error}} db2 close unset ::tvfs_error_on_write forcecopy test.db testX.db do_test journal2-1.14 { file exists test.db-journal } 1 do_test journal2-1.15 { execsql { SELECT count(*) FROM t2; PRAGMA integrity_check; } |
︙ | ︙ |
Changes to test/journal3.test.
︙ | ︙ | |||
31 32 33 34 35 36 37 | 2 00666 3 00600 4 00755 } { db close set effective [format %.5o [expr $permissions & ~$umask]] do_test journal3-1.2.$tn.1 { | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 2 00666 3 00600 4 00755 } { db close set effective [format %.5o [expr $permissions & ~$umask]] do_test journal3-1.2.$tn.1 { catch { forcedelete test.db-journal } file attributes test.db -permissions $permissions file attributes test.db -permissions } $permissions do_test journal3-1.2.$tn.2 { file exists test.db-journal } {0} do_test journal3-1.2.$tn.3 { sqlite3 db test.db execsql { |
︙ | ︙ |
Changes to test/jrnlmode.test.
︙ | ︙ | |||
196 197 198 199 200 201 202 | DETACH aux2; DETACH aux3; } } {} } ifcapable attach { | | | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | DETACH aux2; DETACH aux3; } } {} } ifcapable attach { forcedelete test2.db do_test jrnlmode-2.1 { execsql { ATTACH 'test2.db' AS aux; PRAGMA main.journal_mode = persist; PRAGMA aux.journal_mode = persist; CREATE TABLE abc(a, b, c); CREATE TABLE aux.def(d, e, f); |
︙ | ︙ | |||
238 239 240 241 242 243 244 | } } {4 5 6} #---------------------------------------------------------------------- # Test caes jrnlmode-3.X verify that ticket #3127 has been fixed. # db close | | | | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | } } {4 5 6} #---------------------------------------------------------------------- # Test caes jrnlmode-3.X verify that ticket #3127 has been fixed. # db close forcedelete test2.db forcedelete test.db sqlite3 db test.db do_test jrnlmode-3.1 { execsql { CREATE TABLE x(n INTEGER); ATTACH 'test2.db' AS a; create table a.x ( n integer ); |
︙ | ︙ | |||
266 267 268 269 270 271 272 | COMMIT; } } {} } ifcapable autovacuum&&pragma { db close | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | COMMIT; } } {} } ifcapable autovacuum&&pragma { db close forcedelete test.db sqlite3 db test.db do_test jrnlmode-4.1 { execsql { PRAGMA cache_size = 1; PRAGMA auto_vacuum = 1; CREATE TABLE abc(a, b, c); } |
︙ | ︙ | |||
299 300 301 302 303 304 305 | } #------------------------------------------------------------------------ # The following test caes, jrnlmode-5.*, test the journal_size_limit # pragma. ifcapable pragma { db close | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | } #------------------------------------------------------------------------ # The following test caes, jrnlmode-5.*, test the journal_size_limit # pragma. ifcapable pragma { db close forcedelete test.db test2.db test3.db sqlite3 db test.db do_test jrnlmode-5.1 { execsql {pragma page_size=1024} execsql {pragma journal_mode=persist} } {persist} |
︙ | ︙ | |||
507 508 509 510 511 512 513 | } {0} } } ifcapable pragma { catch { db close } do_test jrnlmode-7.1 { | | | 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | } {0} } } ifcapable pragma { catch { db close } do_test jrnlmode-7.1 { foreach f [glob -nocomplain test.db*] { forcedelete $f } sqlite3 db test.db execsql { PRAGMA journal_mode = memory; PRAGMA auto_vacuum = 0; PRAGMA page_size = 1024; PRAGMA user_version = 5; PRAGMA user_version; |
︙ | ︙ |
Changes to test/jrnlmode2.test.
︙ | ︙ | |||
108 109 110 111 112 113 114 | do_test jrnlmode2-2.4 { sqlite3 db2 test.db -readonly 1 catchsql { SELECT * FROM t1 } db2 } {0 {1 2 3 4 5 6}} do_test jrnlmode2-2.5 { db close | | | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | do_test jrnlmode2-2.4 { sqlite3 db2 test.db -readonly 1 catchsql { SELECT * FROM t1 } db2 } {0 {1 2 3 4 5 6}} do_test jrnlmode2-2.5 { db close delete_file test.db-journal } {} do_test jrnlmode2-2.6 { sqlite3 db2 test.db -readonly 1 catchsql { SELECT * FROM t1 } db2 } {0 {1 2 3 4 5 6}} catch { db2 close } |
︙ | ︙ |
Changes to test/jrnlmode3.test.
︙ | ︙ | |||
44 45 46 47 48 49 50 | INSERT INTO t1 VALUES(2); ROLLBACK; SELECT * FROM t1; } } {1} db close | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | INSERT INTO t1 VALUES(2); ROLLBACK; SELECT * FROM t1; } } {1} db close forcedelete test.db test.db-journal sqlite3 db test.db do_test jrnlmode3-2.1 { db eval { PRAGMA locking_mode=EXCLUSIVE; PRAGMA journal_mode=OFF; CREATE TABLE t1(x); |
︙ | ︙ | |||
81 82 83 84 85 86 87 | # Skip the no-change cases if {$fromjmode==$tojmode} continue incr cnt # Start with a fresh database connection an empty database file. # db close | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | # Skip the no-change cases if {$fromjmode==$tojmode} continue incr cnt # Start with a fresh database connection an empty database file. # db close forcedelete test.db test.db-journal sqlite3 db test.db # Initialize the journal mode. # do_test jrnlmode3-3.$cnt.1-($fromjmode-to-$tojmode) { db eval "PRAGMA journal_mode = $fromjmode;" } $fromjmode |
︙ | ︙ |
Changes to test/loadext.test.
︙ | ︙ | |||
130 131 132 133 134 135 136 | db2 close sqlite3 db test.db sqlite3_enable_load_extension db 1 # Try to load an extension for which the file does not exist. # do_test loadext-2.1 { | | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | db2 close sqlite3 db test.db sqlite3_enable_load_extension db 1 # Try to load an extension for which the file does not exist. # do_test loadext-2.1 { forcedelete ${testextension}xx set rc [catch { sqlite3_load_extension db "${testextension}xx" } msg] list $rc $msg } [list 1 [format $dlerror_nosuchfile ${testextension}xx]] # Try to load an extension for which the file is not a shared object |
︙ | ︙ |
Changes to test/lock4.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 | # Initialize the test.db database so that it is non-empty # do_test lock4-1.1 { db eval { PRAGMA auto_vacuum=OFF; CREATE TABLE t1(x); } | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # Initialize the test.db database so that it is non-empty # do_test lock4-1.1 { db eval { PRAGMA auto_vacuum=OFF; CREATE TABLE t1(x); } forcedelete test2.db test2.db-journal sqlite3 db2 test2.db db2 eval { PRAGMA auto_vacuum=OFF; CREATE TABLE t2(x) } db2 close list [file size test.db] [file size test2.db] |
︙ | ︙ |
Changes to test/lock5.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | # SQLITE_ENABLE_LOCKING_STYLE macro. db close if {[catch {sqlite3 db test.db -vfs unix-none} msg]} { finish_test return } db close | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # SQLITE_ENABLE_LOCKING_STYLE macro. db close if {[catch {sqlite3 db test.db -vfs unix-none} msg]} { finish_test return } db close forcedelete test.db.lock ifcapable lock_proxy_pragmas { set ::using_proxy 0 foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] { set ::using_proxy $value } # Disable the proxy locking for these tests |
︙ | ︙ | |||
96 97 98 99 100 101 102 | execsql {BEGIN EXCLUSIVE} db close file exists test.db.lock } {0} ##################################################################### | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | execsql {BEGIN EXCLUSIVE} db close file exists test.db.lock } {0} ##################################################################### forcedelete test.db if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} { finish_test return } do_test lock5-flock.1 { sqlite3 db test.db -vfs unix-flock |
︙ | ︙ |
Changes to test/main.test.
︙ | ︙ | |||
297 298 299 300 301 302 303 | # Try to open a database with a corrupt database file. # if {[permutation] == ""} { do_test main-2.0 { catch {db close} | | | | | | | 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 | # Try to open a database with a corrupt database file. # if {[permutation] == ""} { do_test main-2.0 { catch {db close} forcedelete test.db set fd [open test.db w] puts $fd hi! close $fd set v [catch {sqlite3 db test.db} msg] if {$v} {lappend v $msg} {lappend v {}} } {0 {}} } # Here are some tests for tokenize.c. # do_test main-3.1 { catch {db close} 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} 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} } {1 {unrecognized token: "'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 453 | do_test main-3.2.30 { catchsql {select 123--5} } {0 123} do_test main-3.3 { catch {db close} 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); insert into T1 values(5e-002); |
︙ | ︙ |
Changes to test/malloc.test.
︙ | ︙ | |||
266 267 268 269 270 271 272 | } # This block tests malloc() failures that occur while opening a # connection to a database. do_malloc_test 10 -tclprep { catch {db2 close} db close | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | } # This block tests malloc() failures that occur while opening a # connection to a database. do_malloc_test 10 -tclprep { catch {db2 close} db close forcedelete test.db test.db-journal sqlite3 db test.db sqlite3_extended_result_codes db 1 db eval {CREATE TABLE abc(a, b, c)} } -tclbody { db close sqlite3 db2 test.db sqlite3_extended_result_codes db2 1 |
︙ | ︙ | |||
337 338 339 340 341 342 343 | PRAGMA journal_mode = DELETE; /* For inmemory_journal permutation */ PRAGMA synchronous = 0; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); BEGIN; INSERT INTO t1 VALUES(3, 4); } | | | | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | PRAGMA journal_mode = DELETE; /* For inmemory_journal permutation */ PRAGMA synchronous = 0; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); BEGIN; INSERT INTO t1 VALUES(3, 4); } forcecopy test2.db test.db forcecopy test2.db-journal test.db-journal db2 close } -tclbody { sqlite3 db test.db sqlite3_extended_result_codes db 1 # If an out-of-memory occurs within a call to a VFS layer function during # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit |
︙ | ︙ | |||
495 496 497 498 499 500 501 | # Make sure SQLITE_NOMEM is reported out on an ATTACH failure even # when the malloc failure occurs within the nested parse. # ifcapable attach { do_malloc_test 20 -tclprep { db close | | | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 | # Make sure SQLITE_NOMEM is reported out on an ATTACH failure even # when the malloc failure occurs within the nested parse. # ifcapable attach { do_malloc_test 20 -tclprep { db close forcedelete test2.db test2.db-journal sqlite3 db test2.db sqlite3_extended_result_codes db 1 db eval {CREATE TABLE t1(x);} db close } -tclbody { if {[catch {sqlite3 db test.db}]} { error "out of memory" |
︙ | ︙ |
Changes to test/malloc3.test.
︙ | ︙ | |||
459 460 461 462 463 464 465 | SELECT * FROM v1 WHERE d = g; } } {a b c a b c 1 2 3 1 2 3} } # Test a simple multi-file transaction # | | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | SELECT * FROM v1 WHERE d = g; } } {a b c a b c 1 2 3 1 2 3} } # Test a simple multi-file transaction # forcedelete test2.db ifcapable attach { SQL {ATTACH 'test2.db' AS aux;} SQL {BEGIN} SQL {CREATE TABLE aux.tbl2(x, y, z)} SQL {INSERT INTO tbl2 VALUES(1, 2, 3)} SQL {INSERT INTO def VALUES(4, 5, 6)} TEST 30 { |
︙ | ︙ | |||
646 647 648 649 650 651 652 | # run the tests with "persistent" malloc failures. sqlite3_extended_result_codes db 1 db cache size 0 run_test $::run_test_script 1 # Close and reopen the db. db close | | | 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 | # run the tests with "persistent" malloc failures. sqlite3_extended_result_codes db 1 db cache size 0 run_test $::run_test_script 1 # Close and reopen the db. db close forcedelete test.db test.db-journal test2.db test2.db-journal sqlite3 db test.db sqlite3_extended_result_codes db 1 set ::DB [sqlite3_connection_pointer db] # Turn off the Tcl interface's prepared statement caching facility in # the new connnection. Then run the tests with "transient" malloc failures. db cache size 0 run_test $::run_test_script 0 sqlite3_memdebug_fail -1 finish_test |
Changes to test/malloc5.test.
︙ | ︙ | |||
271 272 273 274 275 276 277 | # proc nPage {db} { set bt [btree_from_db $db] array set stats [btree_pager_stats $bt] set stats(page) } db close | | | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | # proc nPage {db} { set bt [btree_from_db $db] array set stats [btree_pager_stats $bt] set stats(page) } db close forcedelete test.db test.db-journal test2.db test2.db-journal # This block of test-cases (malloc5-6.1.*) prepares two database files # for the subsequent tests. do_test malloc5-6.1.1 { sqlite3 db test.db execsql { PRAGMA page_size=1024; |
︙ | ︙ | |||
300 301 302 303 304 305 306 | SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; INSERT INTO abc SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; INSERT INTO abc SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; COMMIT; } | | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; INSERT INTO abc SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; INSERT INTO abc SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; COMMIT; } forcecopy test.db test2.db sqlite3 db2 test2.db list \ [expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20] } {1 1} do_test malloc5-6.1.2 { list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2] } {10 10} |
︙ | ︙ |
Changes to test/mallocA.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 | finish_test return } # Construct a test database # | | | | 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 | finish_test return } # Construct a test database # forcedelete test.db.bu db eval { CREATE TABLE t1(a COLLATE NOCASE,b,c); INSERT INTO t1 VALUES(1,2,3); INSERT INTO t1 VALUES(1,2,4); INSERT INTO t1 VALUES(2,3,4); CREATE INDEX t1i1 ON t1(a); CREATE INDEX t1i2 ON t1(b,c); CREATE TABLE t2(x,y,z); } db close copy_file test.db test.db.bu do_malloc_test mallocA-1 -testdb test.db.bu -sqlbody { ANALYZE } do_malloc_test mallocA-1.1 -testdb test.db.bu -sqlbody { ANALYZE t1 |
︙ | ︙ | |||
70 71 72 73 74 75 76 | # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} | | | 70 71 72 73 74 75 76 77 78 | # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} forcedelete test.db.bu finish_test |
Changes to test/malloc_common.tcl.
︙ | ︙ | |||
404 405 406 407 408 409 410 | # 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 | | | | 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 | # 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 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]. # catch {db close} catch {db2 close} forcedelete test.db forcedelete test.db-journal forcedelete test.db-wal forcedelete test2.db forcedelete test2.db-journal forcedelete test2.db-wal if {[info exists ::mallocopts(-testdb)]} { copy_file $::mallocopts(-testdb) test.db } catch { sqlite3 db test.db } if {[info commands db] ne ""} { sqlite3_extended_result_codes db 1 } sqlite3_db_config_lookaside db 0 0 0 |
︙ | ︙ |
Changes to test/manydb.test.
︙ | ︙ | |||
40 41 42 43 44 45 46 | lappend filehandles [open testfile.1 w] } } foreach fd $filehandles { close $fd } catch { | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | lappend filehandles [open testfile.1 w] } } foreach fd $filehandles { close $fd } catch { forcedelete testfile.1 } set N [expr $i / $num_fd_per_openwrite_db] # Create a bunch of random database names # unset -nocomplain dbname unset -nocomplain used |
︙ | ︙ | |||
88 89 90 91 92 93 94 | # Close the databases and erase the files. # for {set i 0} {$i<$N} {incr i} { do_test manydb-3.$i { db$i close | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # Close the databases and erase the files. # for {set i 0} {$i<$N} {incr i} { do_test manydb-3.$i { db$i close forcedelete $dbname($i) } {} } finish_test |
Changes to test/memsubsys1.test.
︙ | ︙ | |||
28 29 30 31 32 33 34 | # This procedure constructs a new database in test.db. It fills # this database with many small records (enough to force multiple # rebalance operations in the btree-layer and to require a large # page cache), verifies correct results, then returns. # proc build_test_db {testname pragmas} { catch {db close} | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # This procedure constructs a new database in test.db. It fills # this database with many small records (enough to force multiple # rebalance operations in the btree-layer and to require a large # page cache), verifies correct results, then returns. # proc build_test_db {testname pragmas} { catch {db close} forcedelete test.db test.db-journal sqlite3 db test.db sqlite3_db_config_lookaside db 0 0 0 db eval $pragmas db eval { CREATE TABLE t1(x, y); CREATE TABLE t2(a, b); CREATE INDEX i1 ON t1(x,y); |
︙ | ︙ |
Changes to test/memsubsys2.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | # This procedure constructs a new database in test.db. It fills # this database with many small records (enough to force multiple # rebalance operations in the btree-layer and to require a large # page cache), verifies correct results, then returns. # proc build_test_db {testname pragmas} { catch {db close} | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # This procedure constructs a new database in test.db. It fills # this database with many small records (enough to force multiple # rebalance operations in the btree-layer and to require a large # page cache), verifies correct results, then returns. # proc build_test_db {testname pragmas} { catch {db close} forcedelete test.db test.db-journal sqlite3 db test.db db eval $pragmas db eval { CREATE TABLE t1(x, y); CREATE TABLE t2(a, b); CREATE INDEX i1 ON t1(x,y); INSERT INTO t1 VALUES(1, 100); |
︙ | ︙ |
Changes to test/misc1.test.
︙ | ︙ | |||
487 488 489 490 491 492 493 | } {0} do_test misc1-14.2b { execsql {UPDATE t1 SET a=a||'y' WHERE 1} file exists ../test.db-journal } {1} do_test misc1-14.3 { cd .. | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | } {0} do_test misc1-14.2b { execsql {UPDATE t1 SET a=a||'y' WHERE 1} file exists ../test.db-journal } {1} do_test misc1-14.3 { cd .. forcedelete tempdir execsql {COMMIT} file exists ./test.db-journal } {0} # A failed create table should not leave the table in the internal # data structures. Ticket #238. # |
︙ | ︙ |
Changes to test/misc2.test.
︙ | ︙ | |||
161 162 163 164 165 166 167 | # # 2006-08-16: This has changed. It is now permitted to update # the table being SELECTed from within the callback of the query. # ifcapable tclvar { do_test misc2-7.1 { db close | | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | # # 2006-08-16: This has changed. It is now permitted to update # the table being SELECTed from within the callback of the query. # ifcapable tclvar { do_test misc2-7.1 { db close forcedelete test.db sqlite3 db test.db execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); SELECT * FROM t1; |
︙ | ︙ | |||
261 262 263 264 265 266 267 | # Repeat the tests 7.1 through 7.8 about but this time do the SELECTs # in reverse order so that we exercise the sqlite3BtreePrev() routine # instead of sqlite3BtreeNext() # do_test misc2-7.11 { db close | | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | # Repeat the tests 7.1 through 7.8 about but this time do the SELECTs # in reverse order so that we exercise the sqlite3BtreePrev() routine # instead of sqlite3BtreeNext() # do_test misc2-7.11 { db close forcedelete test.db sqlite3 db test.db execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); SELECT * FROM t1; |
︙ | ︙ | |||
357 358 359 360 361 362 363 | } } execsql {SELECT * FROM t1} } {1 2 3 4 5 6 7 8 9 10} } db close | | | 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | } } execsql {SELECT * FROM t1} } {1 2 3 4 5 6 7 8 9 10} } db close forcedelete test.db sqlite3 db test.db catchsql { pragma recursive_triggers = off } # Ticket #453. If the SQL ended with "-", the tokenizer was calling that # an incomplete token, which caused problem. The solution was to just call # it a minus sign. # |
︙ | ︙ |
Changes to test/misc5.test.
︙ | ︙ | |||
510 511 512 513 514 515 516 | # Ticket #1370. Do not overwrite small files (less than 1024 bytes) # when trying to open them as a database. # if {[permutation] == ""} { do_test misc5-4.1 { db close | | | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 | # Ticket #1370. Do not overwrite small files (less than 1024 bytes) # when trying to open them as a database. # if {[permutation] == ""} { do_test misc5-4.1 { db close forcedelete test.db set fd [open test.db w] puts $fd "This is not really a database" close $fd sqlite3 db test.db catchsql { CREATE TABLE t1(a,b,c); } |
︙ | ︙ | |||
540 541 542 543 544 545 546 | execsql {SELECT .4e+1} } 4.0 # Ticket #1582. Ensure that an unknown table in a LIMIT clause applied to # a UNION ALL query causes an error, not a crash. # db close | | | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 | execsql {SELECT .4e+1} } 4.0 # Ticket #1582. Ensure that an unknown table in a LIMIT clause applied to # a UNION ALL query causes an error, not a crash. # db close forcedelete test.db sqlite3 db test.db ifcapable subquery&&compound { do_test misc5-6.1 { catchsql { SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_master |
︙ | ︙ |
Changes to test/misc7.test.
︙ | ︙ | |||
26 27 28 29 30 31 32 | do_test misc7-3 { c_collation_test } {} # Try to open a directory: # do_test misc7-4 { | | | | 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 | do_test misc7-3 { c_collation_test } {} # Try to open a directory: # do_test misc7-4 { delete_file mydir file mkdir mydir set rc [catch { sqlite3 db2 ./mydir } msg] list $rc $msg } {1 {unable to open database file}} # Try to open a file with a directory where its journal file should be. # do_test misc7-5 { delete_file mydir file mkdir mydir-journal sqlite3 db2 ./mydir catchsql { CREATE TABLE abc(a, b, c); } db2 } {1 {unable to open database file}} db2 close |
︙ | ︙ | |||
148 149 150 151 152 153 154 | db2 close #-------------------------------------------------------------------- # Test that nothing goes horribly wrong when attaching a database # after the omit_readlock pragma has been exercised. # do_test misc7-7.1 { | | | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | db2 close #-------------------------------------------------------------------- # Test that nothing goes horribly wrong when attaching a database # after the omit_readlock pragma has been exercised. # do_test misc7-7.1 { forcedelete test2.db forcedelete test2.db-journal execsql { PRAGMA omit_readlock = 1; ATTACH 'test2.db' AS aux; CREATE TABLE aux.hello(world); SELECT name FROM aux.sqlite_master; } } {hello} |
︙ | ︙ | |||
250 251 252 253 254 255 256 | set ::echo_module_cost 2.0e+99 execsql {SELECT * FROM t1 WHERE a = 1;} } {1 2 3} unset ::echo_module_cost } db close | | | | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | set ::echo_module_cost 2.0e+99 execsql {SELECT * FROM t1 WHERE a = 1;} } {1 2 3} unset ::echo_module_cost } db close forcedelete test.db forcedelete test.db-journal sqlite3 db test.db ifcapable explain { do_execsql_test misc7-14.1 { CREATE TABLE abc(a PRIMARY KEY, b, c); EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE rowid = 1; } { |
︙ | ︙ | |||
274 275 276 277 278 279 280 | EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 ORDER BY a; } {0 0 0 {SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (~1000000 rows)} } } db close | | | | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 ORDER BY a; } {0 0 0 {SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (~1000000 rows)} } } db close forcedelete test.db forcedelete test.db-journal sqlite3 db test.db #-------------------------------------------------------------------- # This is all to force the pager_remove_from_stmt_list() function # (inside pager.c) to remove a pager from the middle of the # statement-list. # |
︙ | ︙ | |||
319 320 321 322 323 324 325 | DELETE FROM abc WHERE rowid > 12; INSERT INTO abc SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; } } {} db close | | | | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | DELETE FROM abc WHERE rowid > 12; INSERT INTO abc SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; } } {} db close forcedelete test.db forcedelete test.db-journal sqlite3 db test.db do_ioerr_test misc7-16 -sqlprep { PRAGMA cache_size = 10; PRAGMA default_cache_size = 10; CREATE TABLE t3(a, b, UNIQUE(a, b)); INSERT INTO t3 VALUES( randstr(100, 100), randstr(100, 100) ); |
︙ | ︙ | |||
381 382 383 384 385 386 387 | if {[file attributes test.db -permissions]==0644} { do_test misc7-17.1 { execsql { BEGIN; DELETE FROM t3 WHERE (oid%3)==0; } | | | | | | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | if {[file attributes test.db -permissions]==0644} { do_test misc7-17.1 { execsql { BEGIN; DELETE FROM t3 WHERE (oid%3)==0; } forcecopy test.db bak.db forcecopy test.db-journal bak.db-journal execsql { COMMIT; } db close forcecopy bak.db test.db forcecopy bak.db-journal test.db-journal sqlite3 db test.db catch {file attributes test.db-journal -permissions r--------} catch {file attributes test.db-journal -readonly 1} catchsql { SELECT count(*) FROM t3; } |
︙ | ︙ | |||
480 481 482 483 484 485 486 | set zFile [file join [pwd] "[string repeat abcde 104].db"] set rc [catch {sqlite3 db2 $zFile} msg] list $rc $msg } {1 {unable to open database file}} db close | | | 480 481 482 483 484 485 486 487 488 489 | set zFile [file join [pwd] "[string repeat abcde 104].db"] set rc [catch {sqlite3 db2 $zFile} msg] list $rc $msg } {1 {unable to open database file}} db close forcedelete test.db finish_test |
Changes to test/misuse.test.
︙ | ︙ | |||
35 36 37 38 39 40 41 | } # Make sure the test logic works # do_test misuse-1.1 { db close | | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | } # Make sure the test logic works # do_test misuse-1.1 { db close catch {forcedelete test2.db} catch {forcedelete test2.db-journal} sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db] execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); } catchsql2 { SELECT * FROM t1 |
︙ | ︙ |
Changes to test/multiplex.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | list $msg } # This attempts to delete the base file and # and files with the chunk extension. proc multiplex_delete {name} { global g_max_chunks for {set i 0} {$i<$g_max_chunks} {incr i} { forcedelete [multiplex_name $name $i] forcedelete [multiplex_name $name-journal $i] forcedelete [multiplex_name $name-wal $i] } } | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | list $msg } # This attempts to delete the base file and # and files with the chunk extension. proc multiplex_delete {name} { global g_max_chunks forcedelete $name for {set i 0} {$i<$g_max_chunks} {incr i} { forcedelete [multiplex_name $name $i] forcedelete [multiplex_name $name-journal $i] forcedelete [multiplex_name $name-wal $i] } } |
︙ | ︙ | |||
74 75 76 77 78 79 80 | do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.9.2 { sqlite3 db test.db } {} do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK} | | < | | < | | 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 | do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.9.2 { sqlite3 db test.db } {} do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK} do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_OK} do_test multiplex-1.9.6 { multiplex_set db main 31 16 } {SQLITE_OK} do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_OK} do_test multiplex-1.9.8 { multiplex_set db main 1073741824 1 } {SQLITE_OK} do_test multiplex-1.9.9 { db close } {} do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.10.2 { sqlite3 db test.db } {} do_test multiplex-1.10.3 { lindex [ catchsql { SELECT multiplex_control(2, 32768); } ] 0 } {0} do_test multiplex-1.10.4 { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 } {0} do_test multiplex-1.10.6 { lindex [ catchsql { SELECT multiplex_control(2, 31); } ] 0 } {0} do_test multiplex-1.10.7 { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 } {0} do_test multiplex-1.10.8 { lindex [ catchsql { SELECT multiplex_control(2, 1073741824); } ] 0 } {0} do_test multiplex-1.10.9 { db close } {} do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-1.11.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK} do_test multiplex-1.11.2 { sqlite3 db test.db } {} do_test multiplex-1.11.3 { sqlite3_multiplex_control db main enable 0 } {SQLITE_OK} |
︙ | ︙ | |||
142 143 144 145 146 147 148 149 | # # multiplex-2.7.*: Disable/enable tests. # sqlite3_multiplex_initialize "" 1 multiplex_set db main 32768 16 do_test multiplex-2.1.2 { | > | | | | | | | | 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 | # # multiplex-2.7.*: Disable/enable tests. # sqlite3_multiplex_initialize "" 1 multiplex_set db main 32768 16 forcedelete test.x do_test multiplex-2.1.2 { sqlite3 db test.x execsql { PRAGMA page_size=1024; PRAGMA auto_vacuum=OFF; PRAGMA journal_mode=DELETE; } execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, randomblob(1100)); INSERT INTO t1 VALUES(2, randomblob(1100)); } } {} do_test multiplex-2.1.3 { file size [multiplex_name test.x 0] } {4096} do_test multiplex-2.1.4 { execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } } {} do_test multiplex-2.2.1 { execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } } {} do_test multiplex-2.2.3 { file size [multiplex_name test.x 0] } {6144} do_test multiplex-2.3.1 { sqlite3 db2 test2.x db2 close } {} do_test multiplex-2.4.1 { sqlite3_multiplex_shutdown } {SQLITE_MISUSE} do_test multiplex-2.4.2 { execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } } {} do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168} do_test multiplex-2.4.99 { db close sqlite3_multiplex_shutdown } {SQLITE_OK} do_test multiplex-2.5.1 { multiplex_delete test.x sqlite3_multiplex_initialize "" 1 sqlite3 db test.x multiplex_set db main 4096 16 } {SQLITE_OK} do_test multiplex-2.5.2 { execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = delete; |
︙ | ︙ | |||
232 233 234 235 236 237 238 | db eval {SELECT a,length(b) FROM t1 WHERE a=2} } {2 4000} do_test multiplex-2.5.8 { db eval {SELECT a,length(b) FROM t1 WHERE a=4} } {4 4000} | | | | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | db eval {SELECT a,length(b) FROM t1 WHERE a=2} } {2 4000} do_test multiplex-2.5.8 { db eval {SELECT a,length(b) FROM t1 WHERE a=4} } {4 4000} do_test multiplex-2.5.9 { file size [multiplex_name test.x 0] } [list $g_chunk_size] do_test multiplex-2.5.10 { file size [multiplex_name test.x 1] } [list $g_chunk_size] do_test multiplex-2.5.99 { db close sqlite3_multiplex_shutdown } {SQLITE_OK} |
︙ | ︙ | |||
510 511 512 513 514 515 516 | do_test multiplex-5.4.1 { catch { db close } multiplex_delete test.db file mkdir test.db list [catch { sqlite3 db test.db } msg] $msg } {1 {unable to open database file}} | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | | | | | 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 | do_test multiplex-5.4.1 { catch { db close } multiplex_delete test.db file mkdir test.db list [catch { sqlite3 db test.db } msg] $msg } {1 {unable to open database file}} catch { delete_file test.db } do_faultsim_test multiplex-5.5 -prep { catch { sqlite3_multiplex_shutdown } } -body { sqlite3_multiplex_initialize "" 1 multiplex_set db main 32768 16 } #------------------------------------------------------------------------- # Test that you can vacuum a multiplex'ed DB. ifcapable vacuum { sqlite3_multiplex_shutdown do_test multiplex-6.0.0 { multiplex_delete test.db multiplex_delete test.x sqlite3_multiplex_initialize "" 1 sqlite3 db test.x multiplex_set db main 4096 16 } {SQLITE_OK} do_test multiplex-6.1.0 { execsql { PRAGMA page_size=1024; PRAGMA journal_mode=DELETE; PRAGMA auto_vacuum=OFF; } execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, randomblob($g_chunk_size)); INSERT INTO t1 VALUES(2, randomblob($g_chunk_size)); } } {} do_test multiplex-6.2.1 { file size [multiplex_name test.x 0] } [list $g_chunk_size] do_test multiplex-6.2.2 { file size [multiplex_name test.x 1] } [list $g_chunk_size] do_test multiplex-6.3.0 { execsql { VACUUM } } {} do_test multiplex-6.99 { db close multiplex_delete test.x sqlite3_multiplex_shutdown } {SQLITE_OK} } catch { sqlite3_multiplex_shutdown } finish_test |
Changes to test/notify1.test.
︙ | ︙ | |||
136 137 138 139 140 141 142 | # # Test for slightly more complex deadlock involving three database # connections: db, db2 and db3. # do_test notify1-2.3.1 { db close db2 close | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | # # Test for slightly more complex deadlock involving three database # connections: db, db2 and db3. # do_test notify1-2.3.1 { db close db2 close forcedelete test.db test2.db test3.db foreach con {db db2 db3} { sqlite3 $con test.db $con eval { ATTACH 'test2.db' AS aux2 } $con eval { ATTACH 'test3.db' AS aux3 } } execsql { CREATE TABLE main.t1(a, b); |
︙ | ︙ | |||
290 291 292 293 294 295 296 | # # notify1-6.4.*: Like 6.3.*, except that instead of the second blocker # committing its transaction, the first does. The # unlock-notify callback is therefore invoked. # db close do_test notify1-6.1.1 { | | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | # # notify1-6.4.*: Like 6.3.*, except that instead of the second blocker # committing its transaction, the first does. The # unlock-notify callback is therefore invoked. # db close do_test notify1-6.1.1 { forcedelete test.db test2.db foreach conn {db db2 db3} { sqlite3 $conn test.db execsql { ATTACH 'test2.db' AS two } $conn } execsql { CREATE TABLE t1(a, b); CREATE TABLE two.t2(a, b); |
︙ | ︙ |
Changes to test/notify2.test.
︙ | ︙ | |||
163 164 165 166 167 168 169 | expr 0 } foreach {iTest xStep xPrepare} { 1 sqlite3_blocking_step sqlite3_blocking_prepare_v2 2 sqlite3_step sqlite3_nonblocking_prepare_v2 } { | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | expr 0 } foreach {iTest xStep xPrepare} { 1 sqlite3_blocking_step sqlite3_blocking_prepare_v2 2 sqlite3_step sqlite3_nonblocking_prepare_v2 } { forcedelete test.db test2.db test3.db set ThreadSetup "set xStep $xStep;set xPrepare $xPrepare;set nSecond $nSecond" # Set up the database schema used by this test. Each thread opens file # test.db as the main database, then attaches files test2.db and test3.db # as auxillary databases. Each file contains a single table (t1, t2 and t3, in # files test.db, test2.db and test3.db, respectively). |
︙ | ︙ |
Changes to test/notify3.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | finish_test return } set esc [sqlite3_enable_shared_cache 1] sqlite3 db test.db | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | finish_test return } set esc [sqlite3_enable_shared_cache 1] sqlite3 db test.db forcedelete test.db2 test.db2-journal test.db2-wal sqlite3 db2 test.db2 do_test notify3-1.1 { execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('t1 A', 't1 B'); } |
︙ | ︙ |
Changes to test/openv2.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 | # # $Id: openv2.test,v 1.2 2009/06/11 17:32:45 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl db close | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # # $Id: openv2.test,v 1.2 2009/06/11 17:32:45 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl db close forcedelete test.db test.db-journal do_test openv2-1.1 { set rc [catch {sqlite3 db test.db -create 0} msg] lappend rc $msg } {1 {unable to open database file}} do_test openv2-1.2 { info commands db } {} |
︙ | ︙ |
Changes to test/pager1.test.
︙ | ︙ | |||
448 449 450 451 452 453 454 | execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {4 ok} do_test pager1.4.2.3 { faultsim_restore_and_reopen | | | | 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 | execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {4 ok} do_test pager1.4.2.3 { faultsim_restore_and_reopen foreach f [glob test.db-mj*] { forcedelete $f } execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {64 ok} do_test pager1.4.2.4 { faultsim_restore_and_reopen hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {4 ok} do_test pager1.4.2.5 { faultsim_restore_and_reopen hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456 foreach f [glob test.db-mj*] { forcedelete $f } execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {4 ok} } |
︙ | ︙ | |||
645 646 647 648 649 650 651 | # Restore the file-system again. This time, before reopening the databases, # delete the master-journal file from the file-system. It now appears that # the transaction was committed (no master-journal file == no rollback). # do_test pager1-4.4.$tn.7 { faultsim_restore_and_reopen $prefix | | | | 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | # Restore the file-system again. This time, before reopening the databases, # delete the master-journal file from the file-system. It now appears that # the transaction was committed (no master-journal file == no rollback). # do_test pager1-4.4.$tn.7 { faultsim_restore_and_reopen $prefix foreach f [glob ${prefix}-mj*] { forcedelete $f } execsql "ATTACH '${prefix}2' AS aux" } {} do_execsql_test pager1-4.4.$tn.8 { SELECT * FROM a } {double-you why zed won too free} do_execsql_test pager1-4.4.$tn.9 { SELECT * FROM b } {won too free double-you why zed} } 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 |
︙ | ︙ | |||
878 879 880 881 882 883 884 | catch {file attributes test.db-journal -readonly 1} catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} do_test pager1.4.7.3 { db close catch {file attributes test.db-journal -permissions rw-rw-rw-} catch {file attributes test.db-journal -readonly 0} | | | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 | catch {file attributes test.db-journal -readonly 1} catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} do_test pager1.4.7.3 { db close catch {file attributes test.db-journal -permissions rw-rw-rw-} catch {file attributes test.db-journal -readonly 0} delete_file test.db-journal file exists test.db-journal } {0} #------------------------------------------------------------------------- # The following tests deal with multi-file commits. # # pager1-5.1.*: The case where a multi-file cannot be committed because |
︙ | ︙ | |||
2364 2365 2366 2367 2368 2369 2370 | # Test that if an empty database file (size 0 bytes) is opened in # exclusive-locking mode, any journal file is deleted from the file-system # without being rolled back. And that the RESERVED lock obtained while # doing this is not released. # do_test pager1-30.1 { db close | | | | 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | # Test that if an empty database file (size 0 bytes) is opened in # exclusive-locking mode, any journal file is deleted from the file-system # without being rolled back. And that the RESERVED lock obtained while # doing this is not released. # do_test pager1-30.1 { db close delete_file test.db delete_file test.db-journal set fd [open test.db-journal w] seek $fd [expr 512+1032*2] puts -nonewline $fd x close $fd sqlite3 db test.db execsql { |
︙ | ︙ | |||
2405 2406 2407 2408 2409 2410 2411 | INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; BEGIN; UPDATE t1 SET y = randomblob(1499); } | | | | 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 | INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; BEGIN; UPDATE t1 SET y = randomblob(1499); } copy_file test.db test.db2 copy_file test.db-journal test.db2-journal hexio_write test.db2-journal 24 00000000 sqlite3 db2 test.db2 execsql { PRAGMA integrity_check } db2 } {ok} } finish_test |
Changes to test/pagerfault.test.
︙ | ︙ | |||
229 230 231 232 233 234 235 | } -test { faultsim_test_result {0 {}} faultsim_integrity_check } do_faultsim_test pagerfault-5.3 -faults oom-transient -prep { faultsim_restore_and_reopen db func a_string a_string | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | } -test { faultsim_test_result {0 {}} faultsim_integrity_check } do_faultsim_test pagerfault-5.3 -faults oom-transient -prep { faultsim_restore_and_reopen db func a_string a_string forcedelete test2.db test2.db-journal test2.db-wal execsql { PRAGMA journal_mode = PERSIST; ATTACH 'test2.db' AS aux; PRAGMA aux.journal_mode = PERSIST; PRAGMA aux.journal_size_limit = 0; } } -body { |
︙ | ︙ | |||
637 638 639 640 641 642 643 | PRAGMA journal_mode = PERSIST; BEGIN; CREATE TABLE t1(x, y UNIQUE); INSERT INTO t1 VALUES(a_string(333), a_string(444)); COMMIT; } db close | | | 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | PRAGMA journal_mode = PERSIST; BEGIN; CREATE TABLE t1(x, y UNIQUE); INSERT INTO t1 VALUES(a_string(333), a_string(444)); COMMIT; } db close forcedelete test.db faultsim_save } {} do_faultsim_test pagerfault-13 -prep { faultsim_restore_and_reopen } -body { execsql { CREATE TABLE xx(a, b) } } -test { |
︙ | ︙ | |||
1102 1103 1104 1105 1106 1107 1108 | # PagerCommitPhaseOne(<in-memory-db>) -> SQLITE_OK # PagerCommitPhaseOne(<file-db>) -> SQLITE_IOERR # PagerRollback(<in-memory-db>) # PagerRollback(<file-db>) # do_faultsim_test pagerfault-23 -prep { sqlite3 db :memory: | | | 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 | # PagerCommitPhaseOne(<in-memory-db>) -> SQLITE_OK # PagerCommitPhaseOne(<file-db>) -> SQLITE_IOERR # PagerRollback(<in-memory-db>) # PagerRollback(<file-db>) # do_faultsim_test pagerfault-23 -prep { sqlite3 db :memory: foreach f [glob -nocomplain test.db*] { forcedelete $f } db eval { ATTACH 'test.db2' AS aux; CREATE TABLE t1(a, b); CREATE TABLE aux.t2(a, b); } } -body { execsql { |
︙ | ︙ |
Changes to test/pagesize.test.
︙ | ︙ | |||
38 39 40 41 42 43 44 | PRAGMA page_size=2048; PRAGMA page_size; } } 1024 do_test pagesize-1.4 { db close | | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | PRAGMA page_size=2048; PRAGMA page_size; } } 1024 do_test pagesize-1.4 { db close forcedelete test.db sqlite3 db test.db execsql { PRAGMA page_size=511; PRAGMA page_size; } } 1024 do_test pagesize-1.5 { |
︙ | ︙ | |||
95 96 97 98 99 100 101 | INSERT INTO t1 VALUES(2,3,4); SELECT * FROM t1; } } {1 2 3 2 3 4} } do_test pagesize-2.$PGSZ.1 { db close | | | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | INSERT INTO t1 VALUES(2,3,4); SELECT * FROM t1; } } {1 2 3 2 3 4} } do_test pagesize-2.$PGSZ.1 { db close forcedelete test.db sqlite3 db test.db execsql "PRAGMA page_size=$PGSZ" execsql { CREATE TABLE t1(x); PRAGMA page_size; } } $PGSZ |
︙ | ︙ | |||
186 187 188 189 190 191 192 | do_test pagesize-2.$PGSZ.16 { execsql {DROP TABLE t1} ifcapable {vacuum} {execsql VACUUM} } {} integrity_check pagesize-2.$PGSZ.17 db close | | | | 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 | do_test pagesize-2.$PGSZ.16 { execsql {DROP TABLE t1} ifcapable {vacuum} {execsql VACUUM} } {} integrity_check pagesize-2.$PGSZ.17 db close forcedelete test.db sqlite3 db test.db do_test pagesize-2.$PGSZ.30 { execsql " CREATE TABLE t1(x); PRAGMA temp.page_size=$PGSZ; CREATE TEMP TABLE t2(y); PRAGMA main.page_size; PRAGMA temp.page_size; " } [list 1024 $PGSZ] db close forcedelete test.db sqlite3 db test.db do_test pagesize-2.$PGSZ.40 { execsql " PRAGMA page_size=$PGSZ; CREATE TABLE t1(x); CREATE TEMP TABLE t2(y); PRAGMA main.page_size; PRAGMA temp.page_size; " } [list $PGSZ $PGSZ] } finish_test |
Changes to test/pcache2.test.
︙ | ︙ | |||
30 31 32 33 34 35 36 | sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1 sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0 } {0 0 0} # Open up two database connections to separate files. # do_test pcache2-1.2 { | | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1 sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0 } {0 0 0} # Open up two database connections to separate files. # do_test pcache2-1.2 { forcedelete test.db test.db-journal sqlite3 db test.db db eval {PRAGMA cache_size=10} lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1 } {2} do_test pcache2-1.3 { forcedelete test2.db test2.db-journal sqlite3 db2 test2.db db2 eval {PRAGMA cache_size=50} lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1 } {4} # Make lots of changes on the first connection. Verify that the |
︙ | ︙ |
Changes to test/permutations.test.
︙ | ︙ | |||
516 517 518 519 520 521 522 | e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test fts3snippet.test # Exclude test scripts that use tcl IO to access journal files or count # the number of fsync() calls. pager.test exclusive.test jrnlmode.test sync.test misc1.test journal1.test conflict.test crash8.test tkt3457.test io.test | | | | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test fts3snippet.test # Exclude test scripts that use tcl IO to access journal files or count # the number of fsync() calls. pager.test exclusive.test jrnlmode.test sync.test misc1.test journal1.test conflict.test crash8.test tkt3457.test io.test journal3.test 8_3_names.test pager1.test async4.test corrupt.test filefmt.test pager2.test corrupt5.test corruptA.test pageropt.test # Exclude stmt.test, which expects sub-journals to use temporary files. stmt.test # WAL mode is different. wal* tkt-2d1a5c67d.test backcompat.test }] ifcapable mem3 { test_suite "memsys3" -description { Run tests using the allocator in mem3.c. } -files [test_set $::allquicktests -exclude { autovacuum.test delete3.test manydb.test |
︙ | ︙ | |||
722 723 724 725 726 727 728 | } -initialize { catch {db close} register_jt_vfs -default "" } -shutdown { unregister_jt_vfs } -files [test_set $::allquicktests -exclude { wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test | | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | } -initialize { catch {db close} register_jt_vfs -default "" } -shutdown { unregister_jt_vfs } -files [test_set $::allquicktests -exclude { wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test async4.test bigfile.test backcompat.test }] if {[info commands register_demovfs] != ""} { test_suite "demovfs" -description { Check that the demovfs (code in test_demovfs.c) more or less works. } -initialize { register_demovfs |
︙ | ︙ | |||
861 862 863 864 865 866 867 | if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] } eval run_tests $suite $::testspec($suite) $extra } } main $argv finish_test } | < | 861 862 863 864 865 866 867 | if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] } eval run_tests $suite $::testspec($suite) $extra } } main $argv finish_test } |
Changes to test/pragma.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 | return } # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # db close | | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | return } # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # db close delete_file test.db test.db-journal delete_file test3.db test3.db-journal sqlite3 db test.db; set DB [sqlite3_connection_pointer db] ifcapable pager_pragmas { set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}] set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}] do_test pragma-1.1 { |
︙ | ︙ | |||
217 218 219 220 221 222 223 | PRAGMA bogus = -1234; -- Parsing of negative values } } {} # Test modifying the safety_level of an attached database. ifcapable pager_pragmas&&attach { do_test pragma-2.1 { | | | | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | PRAGMA bogus = -1234; -- Parsing of negative values } } {} # Test modifying the safety_level of an attached database. ifcapable pager_pragmas&&attach { do_test pragma-2.1 { forcedelete test2.db forcedelete test2.db-journal execsql { ATTACH 'test2.db' AS aux; } } {} do_test pragma-2.2 { execsql { pragma aux.synchronous; |
︙ | ︙ | |||
251 252 253 254 255 256 257 | # Construct a corrupted index and make sure the integrity_check # pragma finds it. # # These tests won't work if the database is encrypted # do_test pragma-3.1 { db close | | | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | # Construct a corrupted index and make sure the integrity_check # pragma finds it. # # These tests won't work if the database is encrypted # do_test pragma-3.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql { PRAGMA auto_vacuum=OFF; BEGIN; CREATE TABLE t2(a,b,c); CREATE INDEX i2 ON t2(a); INSERT INTO t2 VALUES(11,2,3); |
︙ | ︙ | |||
308 309 310 311 312 313 314 | } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} # Add additional corruption by appending unused pages to the end of # the database file testerr.db # do_test pragma-3.8 { execsql {DETACH t2} | | | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}} # Add additional corruption by appending unused pages to the end of # the database file testerr.db # do_test pragma-3.8 { execsql {DETACH t2} forcedelete testerr.db testerr.db-journal set out [open testerr.db w] fconfigure $out -translation binary set in [open test.db r] fconfigure $in -translation binary puts -nonewline $out [read $in] seek $in 0 puts -nonewline $out [read $in] |
︙ | ︙ | |||
415 416 417 418 419 420 421 | } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {rowid 1 missing from index i2}} } do_test pragma-3.19 { catch {db close} | | | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {rowid 1 missing from index i2}} } do_test pragma-3.19 { catch {db close} forcedelete test.db test.db-journal sqlite3 db test.db db eval {PRAGMA integrity_check} } {ok} } #exit # Test modifying the cache_size of an attached database. |
︙ | ︙ | |||
737 738 739 740 741 742 743 | sqlite3_step $::STMT } SQLITE_ERROR do_test pragma-8.1.10 { sqlite3_finalize $::STMT } SQLITE_SCHEMA # Make sure the schema-version can be manipulated in an attached database. | | | | 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 | sqlite3_step $::STMT } SQLITE_ERROR do_test pragma-8.1.10 { sqlite3_finalize $::STMT } SQLITE_SCHEMA # Make sure the schema-version can be manipulated in an attached database. forcedelete test2.db forcedelete test2.db-journal ifcapable attach { do_test pragma-8.1.11 { execsql { ATTACH 'test2.db' AS aux; CREATE TABLE aux.t1(a, b, c); PRAGMA aux.schema_version = 205; } |
︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 | } } {} } ;# ifcapable bloblit ifcapable pager_pragmas { db close | | | 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 | } } {} } ;# ifcapable bloblit ifcapable pager_pragmas { db close forcedelete test.db sqlite3 db test.db do_test pragma-14.1 { execsql { pragma auto_vacuum = 0 } execsql { pragma page_count } } {0} |
︙ | ︙ | |||
1237 1238 1239 1240 1241 1242 1243 | execsql { ROLLBACK; PRAGMA page_count; } } {2} do_test pragma-14.6 { | | | 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 | execsql { ROLLBACK; PRAGMA page_count; } } {2} do_test pragma-14.6 { forcedelete test2.db sqlite3 db2 test2.db execsql { PRAGMA auto_vacuum = 0; CREATE TABLE t1(a, b, c); CREATE TABLE t2(a, b, c); CREATE TABLE t3(a, b, c); CREATE TABLE t4(a, b, c); |
︙ | ︙ |
Changes to test/pragma2.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 | return } # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # db close | | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | return } # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # db close delete_file test.db test.db-journal delete_file test3.db test3.db-journal sqlite3 db test.db; set DB [sqlite3_connection_pointer db] db eval {PRAGMA auto_vacuum=0} do_test pragma2-1.1 { execsql { PRAGMA freelist_count; } |
︙ | ︙ | |||
57 58 59 60 61 62 63 | } {1} do_test pragma2-1.4 { execsql { PRAGMA main.freelist_count; } } {1} | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | } {1} do_test pragma2-1.4 { execsql { PRAGMA main.freelist_count; } } {1} forcedelete test2.db forcedelete test2.db-journal ifcapable attach { do_test pragma2-2.1 { execsql { ATTACH 'test2.db' AS aux; PRAGMA aux.auto_vacuum=OFF; PRAGMA aux.freelist_count; |
︙ | ︙ |
Changes to test/quota.test.
︙ | ︙ | |||
119 120 121 122 123 124 125 | proc quota_check {filename limitvar size} { upvar $limitvar limit lappend ::quota [set limit] $size if {[info exists ::quota_request_ok]} { set limit $size } } do_test quota-3.1.1 { | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | proc quota_check {filename limitvar size} { upvar $limitvar limit lappend ::quota [set limit] $size if {[info exists ::quota_request_ok]} { set limit $size } } do_test quota-3.1.1 { forcedelete test.db sqlite3_quota_initialize "" 1 sqlite3_quota_set *test.db 4096 quota_check } {SQLITE_OK} do_test quota-3.1.2 { sqlite3 db test.db execsql { PRAGMA page_size = 1024; |
︙ | ︙ | |||
154 155 156 157 158 159 160 | do_test quota-3.1.6 { db close db2 close sqlite3_quota_set *test.db 0 {} } {SQLITE_OK} do_test quota-3.2.1 { | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | do_test quota-3.1.6 { db close db2 close sqlite3_quota_set *test.db 0 {} } {SQLITE_OK} do_test quota-3.2.1 { delete_file force test.db test2.db sqlite3_quota_set * 4096 {} sqlite3 db1a test.db sqlite3 db2a test2.db foreach db {db1a db2a} { execsql { |
︙ | ︙ | |||
253 254 255 256 257 258 259 | quota_list } {*test.db *test2.db} do_test quota-4.1.5 { sqlite3_quota_set *test.db 0 {} quota_list } {*test2.db} do_test quota-4.1.6 { | | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | quota_list } {*test.db *test2.db} do_test quota-4.1.5 { sqlite3_quota_set *test.db 0 {} quota_list } {*test2.db} do_test quota-4.1.6 { forcedelete test2.db test2.db-journal test2.db-wal sqlite3 db test2.db db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');} quota_list } {*test2.db} do_test quota-4.1.7 { catchsql {INSERT INTO t2 VALUES(zeroblob(200000))} } {1 {database or disk is full}} |
︙ | ︙ | |||
353 354 355 356 357 358 359 | do_faultsim_test quota-5.2 -prep { catch {db close} } -body { sqlite3 db test.db } catch { db close } | | | | 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 | do_faultsim_test quota-5.2 -prep { catch {db close} } -body { sqlite3 db test.db } catch { db close } forcedelete test.db do_test quota-5.3.prep { sqlite3 db test.db execsql { PRAGMA auto_vacuum = 1; PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(10, zeroblob(1200)); } faultsim_save_and_close } {} do_faultsim_test quota-5.3 -prep { faultsim_restore_and_reopen } -body { execsql { DELETE FROM t1 } } do_test quota-5.4.1 { catch { db close } forcedelete test.db file mkdir test.db list [catch { sqlite3 db test.db } msg] $msg } {1 {unable to open database file}} do_faultsim_test quota-5.5 -prep { catch { sqlite3_quota_shutdown } } -body { |
︙ | ︙ |
Changes to test/rollback.test.
︙ | ︙ | |||
84 85 86 87 88 89 90 | && [permutation] ne "inmemory_journal" } { do_test rollback-2.1 { execsql { BEGIN; INSERT INTO t3 VALUES('hello world'); } | | | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | && [permutation] ne "inmemory_journal" } { do_test rollback-2.1 { execsql { BEGIN; INSERT INTO t3 VALUES('hello world'); } forcecopy test.db testA.db forcecopy test.db-journal testA.db-journal execsql { COMMIT; } } {} # At this point files testA.db and testA.db-journal are present in the # file system. This block adds a master-journal file pointer to the |
︙ | ︙ |
Changes to test/savepoint.test.
︙ | ︙ | |||
367 368 369 370 371 372 373 | #------------------------------------------------------------------------- # The following tests, savepoint-6.*, test an incr-vacuum inside of a # couple of nested savepoints. # ifcapable {autovacuum && pragma} { db close | | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | #------------------------------------------------------------------------- # The following tests, savepoint-6.*, test an incr-vacuum inside of a # couple of nested savepoints. # ifcapable {autovacuum && pragma} { db close forcedelete test.db sqlite3 db test.db do_test savepoint-6.1 { execsql { PRAGMA auto_vacuum = incremental } wal_set_journal_mode execsql { CREATE TABLE t1(a, b, c); |
︙ | ︙ | |||
415 416 417 418 419 420 421 | } #------------------------------------------------------------------------- # The following tests, savepoint-7.*, attempt to break the logic # surrounding savepoints by growing and shrinking the database file. # db close | | | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | } #------------------------------------------------------------------------- # The following tests, savepoint-7.*, attempt to break the logic # surrounding savepoints by growing and shrinking the database file. # db close forcedelete test.db sqlite3 db test.db do_test savepoint-7.1 { execsql { PRAGMA auto_vacuum = incremental } wal_set_journal_mode execsql { PRAGMA cache_size = 10; |
︙ | ︙ | |||
486 487 488 489 490 491 492 | } execsql { PRAGMA integrity_check } } {ok} wal_check_journal_mode savepoint-7.3.3 do_test savepoint-7.4.1 { db close | | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 | } execsql { PRAGMA integrity_check } } {ok} wal_check_journal_mode savepoint-7.3.3 do_test savepoint-7.4.1 { db close forcedelete test.db sqlite3 db test.db execsql { PRAGMA auto_vacuum = incremental } wal_set_journal_mode execsql { CREATE TABLE t1(a, b, PRIMARY KEY(a, b)); INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000)); BEGIN; |
︙ | ︙ | |||
636 637 638 639 640 641 642 | # of the aux1 and aux2 locks. So record the current lock status of # TEMP for use in the answers. set templockstate [lindex [db eval {PRAGMA lock_status}] 3] if {[wal_is_wal_mode]==0} { do_test savepoint-10.2.1 { | | | | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | # of the aux1 and aux2 locks. So record the current lock status of # TEMP for use in the answers. set templockstate [lindex [db eval {PRAGMA lock_status}] 3] if {[wal_is_wal_mode]==0} { do_test savepoint-10.2.1 { forcedelete test3.db forcedelete test2.db execsql { ATTACH 'test2.db' AS aux1; ATTACH 'test3.db' AS aux2; DROP TABLE t1; CREATE TABLE main.t1(x, y); CREATE TABLE aux1.t2(x, y); CREATE TABLE aux2.t3(x, y); |
︙ | ︙ | |||
758 759 760 761 762 763 764 | #------------------------------------------------------------------------- # The following tests - savepoint-11.* - test the interaction of # savepoints and creating or dropping tables and indexes in # auto-vacuum mode. # do_test savepoint-11.1 { db close | | | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | #------------------------------------------------------------------------- # The following tests - savepoint-11.* - test the interaction of # savepoints and creating or dropping tables and indexes in # auto-vacuum mode. # do_test savepoint-11.1 { db close forcedelete test.db sqlite3 db test.db execsql { PRAGMA auto_vacuum = full; } wal_set_journal_mode execsql { CREATE TABLE t1(a, b, UNIQUE(a, b)); INSERT INTO t1 VALUES(1, randstr(1000,1000)); INSERT INTO t1 VALUES(2, randstr(1000,1000)); |
︙ | ︙ | |||
864 865 866 867 868 869 870 | #------------------------------------------------------------------------- # The following tests - savepoint-13.* - test the interaction of # savepoints and "journal_mode = off". # if {[wal_is_wal_mode]==0} { do_test savepoint-13.1 { db close | | | 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | #------------------------------------------------------------------------- # The following tests - savepoint-13.* - test the interaction of # savepoints and "journal_mode = off". # if {[wal_is_wal_mode]==0} { do_test savepoint-13.1 { db close catch {forcedelete test.db} sqlite3 db test.db execsql { BEGIN; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 2); COMMIT; PRAGMA journal_mode = off; |
︙ | ︙ | |||
905 906 907 908 909 910 911 | ROLLBACK; SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} } db close | | | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | ROLLBACK; SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} } db close delete_file test.db do_multiclient_test tn { do_test savepoint-14.$tn.1 { sql1 { CREATE TABLE foo(x); INSERT INTO foo VALUES(1); INSERT INTO foo VALUES(2); } |
︙ | ︙ |
Changes to test/savepoint6.test.
︙ | ︙ | |||
242 243 244 245 246 247 248 | sql { PRAGMA cache_size = 10 } }] { unset -nocomplain ::lSavepoint unset -nocomplain ::aEntry catch { db close } | | | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | sql { PRAGMA cache_size = 10 } }] { unset -nocomplain ::lSavepoint unset -nocomplain ::aEntry catch { db close } forcedelete test.db test.db-wal test.db-journal eval $zSetup sql $DATABASE_SCHEMA wal_set_journal_mode do_test savepoint6-$testname.setup { savepoint one |
︙ | ︙ |
Changes to test/securedel.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 | } do_test securedel-1.0 { db eval {PRAGMA secure_delete;} } $DEFAULT_SECDEL | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | } do_test securedel-1.0 { db eval {PRAGMA secure_delete;} } $DEFAULT_SECDEL forcedelete test2.db test2.db-journal do_test securedel-1.1 { db eval { ATTACH 'test2.db' AS db2; PRAGMA main.secure_delete=ON; PRAGMA db2.secure_delete; } } [list 1 $DEFAULT_SECDEL] |
︙ | ︙ |
Changes to test/shared.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 | } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] foreach av [list 0 1] { # Open the database connection and execute the auto-vacuum pragma | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] foreach av [list 0 1] { # Open the database connection and execute the auto-vacuum pragma forcedelete test.db sqlite3 db test.db ifcapable autovacuum { do_test shared-[expr $av+1].1.0 { execsql "pragma auto_vacuum=$::av" execsql {pragma auto_vacuum} } "$av" |
︙ | ︙ | |||
289 290 291 292 293 294 295 | # (as well as main): # # db.main -> ./test.db # db.test2 -> ./test2.db # db2.main -> ./test2.db # db2.test -> ./test.db # | | | | | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | # (as well as main): # # db.main -> ./test.db # db.test2 -> ./test2.db # db2.main -> ./test2.db # db2.test -> ./test.db # forcedelete test.db forcedelete test2.db forcedelete test2.db-journal sqlite3 db test.db sqlite3 db2 test2.db do_test shared-$av.4.1.1 { set sqlite_open_file_count expr $sqlite_open_file_count-($extrafds_prelock*2) } {2} do_test shared-$av.4.1.2 { |
︙ | ︙ | |||
422 423 424 425 426 427 428 | catch {db2 close} catch {db close} #-------------------------------------------------------------------------- # Tests shared-5.* # foreach db [list test.db test1.db test2.db test3.db] { | | | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | catch {db2 close} catch {db close} #-------------------------------------------------------------------------- # Tests shared-5.* # foreach db [list test.db test1.db test2.db test3.db] { forcedelete $db ${db}-journal } do_test shared-$av.5.1.1 { sqlite3 db1 test.db sqlite3 db2 test.db execsql { ATTACH 'test1.db' AS test1; ATTACH 'test2.db' AS test2; |
︙ | ︙ | |||
553 554 555 556 557 558 559 | } set ret } {} catch {db1 close} catch {db2 close} foreach f [list test.db test2.db] { | | | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | } set ret } {} catch {db1 close} catch {db2 close} foreach f [list test.db test2.db] { forcedelete $f ${f}-journal } #-------------------------------------------------------------------------- # Tests shared-7.* test auto-vacuum does not invalidate cursors from # other shared-cache users when it reorganizes the database on # COMMIT. # |
︙ | ︙ | |||
639 640 641 642 643 644 645 | catch {db2 close} unset -nocomplain contents #-------------------------------------------------------------------------- # The following tests try to trick the shared-cache code into assuming # the wrong encoding for a database. # | | | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 | catch {db2 close} unset -nocomplain contents #-------------------------------------------------------------------------- # The following tests try to trick the shared-cache code into assuming # the wrong encoding for a database. # forcedelete test.db test.db-journal ifcapable utf16 { do_test shared-$av.8.1.1 { sqlite3 db test.db execsql { PRAGMA encoding = 'UTF-16'; SELECT * FROM sqlite_master; } |
︙ | ︙ | |||
671 672 673 674 675 676 677 | do_test shared-$av.8.1.5 { db2 close execsql { PRAGMA encoding; } } {UTF-8} | | | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | do_test shared-$av.8.1.5 { db2 close execsql { PRAGMA encoding; } } {UTF-8} forcedelete test2.db test2.db-journal do_test shared-$av.8.2.1 { execsql { ATTACH 'test2.db' AS aux; SELECT * FROM aux.sqlite_master; } } {} do_test shared-$av.8.2.2 { sqlite3 db2 test2.db execsql { PRAGMA encoding = 'UTF-16'; CREATE TABLE def(d, e, f); } db2 string range [execsql {PRAGMA encoding;} db2] 0 end-2 } {UTF-16} catch {db close} catch {db2 close} forcedelete test.db test2.db do_test shared-$av.8.3.2 { sqlite3 db test.db execsql { CREATE TABLE def(d, e, f) } execsql { PRAGMA encoding } } {UTF-8} do_test shared-$av.8.3.3 { |
︙ | ︙ | |||
728 729 730 731 732 733 734 | } } {1 {attached databases must use the same text encoding as main database}} } } catch {db close} catch {db2 close} | | | 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | } } {1 {attached databases must use the same text encoding as main database}} } } catch {db close} catch {db2 close} forcedelete test.db test2.db #--------------------------------------------------------------------------- # The following tests - shared-9.* - test interactions between TEMP triggers # and shared-schemas. # ifcapable trigger&&tempdb { |
︙ | ︙ | |||
768 769 770 771 772 773 774 | #--------------------------------------------------------------------------- # The following tests - shared-10.* - test that the library behaves # correctly when a connection to a shared-cache is closed. # do_test shared-$av.10.1 { # Create a small sample database with two connections to it (db and db2). | | | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | #--------------------------------------------------------------------------- # The following tests - shared-10.* - test that the library behaves # correctly when a connection to a shared-cache is closed. # do_test shared-$av.10.1 { # Create a small sample database with two connections to it (db and db2). forcedelete test.db sqlite3 db test.db sqlite3 db2 test.db execsql { CREATE TABLE ab(a PRIMARY KEY, b); CREATE TABLE de(d PRIMARY KEY, e); INSERT INTO ab VALUES('Chiang Mai', 100000); INSERT INTO ab VALUES('Bangkok', 8000000); |
︙ | ︙ | |||
849 850 851 852 853 854 855 | integrity_check shared-$av.10.10 do_test shared-$av.10.11 { db close db3 close } {} do_test shared-$av.11.1 { | | | 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 | integrity_check shared-$av.10.10 do_test shared-$av.10.11 { db close db3 close } {} do_test shared-$av.11.1 { forcedelete test.db sqlite3 db test.db sqlite3 db2 test.db execsql { CREATE TABLE abc(a, b, c); CREATE TABLE abc2(a, b, c); BEGIN; INSERT INTO abc VALUES(1, 2, 3); |
︙ | ︙ | |||
912 913 914 915 916 917 918 | do_test shared-$av.11.11 { db close db2 close } {} # This tests that if it is impossible to free any pages, SQLite will # exceed the limit set by PRAGMA cache_size. | | | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 | do_test shared-$av.11.11 { db close db2 close } {} # This tests that if it is impossible to free any pages, SQLite will # exceed the limit set by PRAGMA cache_size. forcedelete test.db test.db-journal sqlite3 db test.db ifcapable pager_pragmas { do_test shared-$av.12.1 { execsql { PRAGMA cache_size = 10; PRAGMA cache_size; } |
︙ | ︙ | |||
959 960 961 962 963 964 965 | # Internally, locks are acquired on shared B-Tree structures in the order # that the structures appear in the virtual memory address space. This # test case attempts to cause the order of the structures in memory # to be different from the order in which they are attached to a given # database handle. This covers an extra line or two. # do_test shared-$av.13.1 { | | | 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 | # Internally, locks are acquired on shared B-Tree structures in the order # that the structures appear in the virtual memory address space. This # test case attempts to cause the order of the structures in memory # to be different from the order in which they are attached to a given # database handle. This covers an extra line or two. # do_test shared-$av.13.1 { forcedelete test2.db test3.db test4.db test5.db sqlite3 db :memory: execsql { ATTACH 'test2.db' AS aux2; ATTACH 'test3.db' AS aux3; ATTACH 'test4.db' AS aux4; ATTACH 'test5.db' AS aux5; DETACH aux2; |
︙ | ︙ | |||
1022 1023 1024 1025 1026 1027 1028 | # [db2]. This is to try to find any points where shared-schema elements # are allocated using the lookaside buffer of [db]. # # Mutexes are enabled for this test as that activates a couple of useful # assert() statements in the C code. # do_test shared-$av-15.1 { | | | 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 | # [db2]. This is to try to find any points where shared-schema elements # are allocated using the lookaside buffer of [db]. # # Mutexes are enabled for this test as that activates a couple of useful # assert() statements in the C code. # do_test shared-$av-15.1 { forcedelete test.db sqlite3 db test.db -fullmutex 1 sqlite3 db2 test.db -fullmutex 1 execsql { CREATE TABLE t1(a, b, c); CREATE INDEX i1 ON t1(a, b); CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v2 AS SELECT * FROM t1, v1 |
︙ | ︙ |
Changes to test/shared2.test.
︙ | ︙ | |||
125 126 127 128 129 130 131 | db1 close db2 close do_test shared2-3.2 { sqlite3_enable_shared_cache 1 } {1} | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | db1 close db2 close do_test shared2-3.2 { sqlite3_enable_shared_cache 1 } {1} forcedelete test.db sqlite3 db test.db do_test shared2-4.1 { execsql { CREATE TABLE t0(a, b); CREATE TABLE t1(a, b DEFAULT 'hello world'); } |
︙ | ︙ |
Changes to test/shared3.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | return } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] # Ticket #1824 # do_test shared3-1.1 { | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | return } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] # Ticket #1824 # do_test shared3-1.1 { forcedelete test.db test.db-journal sqlite3 db1 test.db db1 eval { PRAGMA encoding=UTF16; CREATE TABLE t1(x,y); INSERT INTO t1 VALUES('abc','This is a test string'); } db1 close |
︙ | ︙ |
Changes to test/shared4.test.
︙ | ︙ | |||
26 27 28 29 30 31 32 | return } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] # Prepare multiple databases in shared cache mode. # do_test shared4-1.1 { | | | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | return } set ::enable_shared_cache [sqlite3_enable_shared_cache 1] # Prepare multiple databases in shared cache mode. # do_test shared4-1.1 { forcedelete test1.db test1.db-journal forcedelete test2.db test2.db-journal forcedelete test3.db test3.db-journal forcedelete test4.db test4.db-journal sqlite3 db1 test1.db sqlite3 db2 test2.db sqlite3 db3 test3.db sqlite3 db4 test4.db db1 eval { CREATE TABLE t1(a); INSERT INTO t1 VALUES(111); |
︙ | ︙ |
Changes to test/shared6.test.
︙ | ︙ | |||
231 232 233 234 235 236 237 | do_test shared6-3.X { db1 close db2 close db3 close } {} do_test shared6-4.1 { | | | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | do_test shared6-3.X { db1 close db2 close db3 close } {} do_test shared6-4.1 { #forcedelete test.db test.db-journal sqlite3 db1 test.db sqlite3 db2 test.db set ::STMT [sqlite3_prepare_v2 db1 "SELECT * FROM t1" -1 DUMMY] execsql { CREATE TABLE t5(a, b) } db2 } {} do_test shared6-4.2 { |
︙ | ︙ |
Changes to test/shared7.test.
︙ | ︙ | |||
31 32 33 34 35 36 37 | } catchsql { ATTACH 'test.db' AS err1; } } {1 {database is already attached}} do_test shared7-1.3 { | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | } catchsql { ATTACH 'test.db' AS err1; } } {1 {database is already attached}} do_test shared7-1.3 { forcedelete test2.db test2.db-journal db eval { ATTACH 'test2.db' AS test2; CREATE TABLE test2.t2(y); } catchsql { ATTACH 'test2.db' AS err2; } |
︙ | ︙ |
Changes to test/speed3.test.
︙ | ︙ | |||
112 113 114 115 116 117 118 | PRAGMA main.cache_size = 200000; PRAGMA main.auto_vacuum = 'incremental'; ATTACH 'test2.db' AS 'aux'; PRAGMA aux.auto_vacuum = 'none'; } } | | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | PRAGMA main.cache_size = 200000; PRAGMA main.auto_vacuum = 'incremental'; ATTACH 'test2.db' AS 'aux'; PRAGMA aux.auto_vacuum = 'none'; } } forcedelete test2.db test2.db-journal reset_db # Set up a database in auto-vacuum mode and create a database schema. # do_test speed3-0.1 { execsql { CREATE TABLE main.t1(a INTEGER, b TEXT, c INTEGER); |
︙ | ︙ |
Changes to test/sqllimits1.test.
︙ | ︙ | |||
755 756 757 758 759 760 761 | #-------------------------------------------------------------------- # Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit. # ifcapable attach { do_test sqllimits1-12.1 { set max $::SQLITE_MAX_ATTACHED for {set i 0} {$i < ($max)} {incr i} { | | | 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | #-------------------------------------------------------------------- # Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit. # ifcapable attach { do_test sqllimits1-12.1 { set max $::SQLITE_MAX_ATTACHED for {set i 0} {$i < ($max)} {incr i} { forcedelete test${i}.db test${i}.db-journal } for {set i 0} {$i < ($max)} {incr i} { execsql "ATTACH 'test${i}.db' AS aux${i}" } catchsql "ATTACH 'test${i}.db' AS aux${i}" } "1 {too many attached databases - max $::SQLITE_MAX_ATTACHED}" do_test sqllimits1-12.2 { |
︙ | ︙ |
Changes to test/stat.test.
︙ | ︙ | |||
135 136 137 138 139 140 141 | SELECT * FROM stat WHERE name = 't5' OR name = 'i5'; } [list \ i5 / 5 leaf 0 0 1016 0 \ t5 / 4 leaf 0 0 1016 0 \ ] db close | | | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | SELECT * FROM stat WHERE name = 't5' OR name = 'i5'; } [list \ i5 / 5 leaf 0 0 1016 0 \ t5 / 4 leaf 0 0 1016 0 \ ] db close forcedelete test.db sqlite3 db test.db register_dbstat_vtab db breakpoint do_execsql_test stat-5.1 { PRAGMA auto_vacuum = OFF; CREATE VIRTUAL TABLE temp.stat USING dbstat; CREATE TABLE t1(x); |
︙ | ︙ |
Changes to test/sync.test.
︙ | ︙ | |||
38 39 40 41 42 43 44 | incr sqlite_sync_count $adj } } } do_test sync-1.1 { set sqlite_sync_count 0 | | | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | incr sqlite_sync_count $adj } } } do_test sync-1.1 { set sqlite_sync_count 0 forcedelete test2.db forcedelete test2.db-journal execsql { PRAGMA fullfsync=OFF; CREATE TABLE t1(a,b); ATTACH DATABASE 'test2.db' AS db2; CREATE TABLE db2.t2(x,y); } cond_incr_sync_count 2 |
︙ | ︙ |
Changes to test/syscall.test.
︙ | ︙ | |||
55 56 57 58 59 60 61 | #------------------------------------------------------------------------- # Tests for the xNextSystemCall method. # foreach s { open close access getcwd stat fstat ftruncate fcntl read pread write pwrite fchmod fallocate | | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #------------------------------------------------------------------------- # Tests for the xNextSystemCall method. # foreach s { open close access getcwd stat fstat ftruncate fcntl read pread write pwrite fchmod fallocate pread64 pwrite64 unlink openDirectory } { if {[test_syscall exists $s]} {lappend syscall_list $s} } do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list] #------------------------------------------------------------------------- # This test verifies that if a call to open() fails and errno is set to |
︙ | ︙ |
Changes to test/table.test.
︙ | ︙ | |||
663 664 665 666 667 668 669 | set result [list $rc $msg] } {1 {database table is locked}} ifcapable attach { # Now attach a database and ensure that a table can be created in the # attached database whilst in a callback from a query on the main database. do_test table-14.3 { | | | | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | set result [list $rc $msg] } {1 {database table is locked}} ifcapable attach { # Now attach a database and ensure that a table can be created in the # attached database whilst in a callback from a query on the main database. do_test table-14.3 { forcedelete test2.db forcedelete test2.db-journal execsql { ATTACH 'test2.db' as aux; } db eval {SELECT * FROM tablet8 LIMIT 1} {} { db eval {CREATE TABLE aux.t1(a, b, c)} } } {} |
︙ | ︙ |
Changes to test/temptable.test.
︙ | ︙ | |||
400 401 402 403 404 405 406 | db close sqlite3 db test.db catchsql { SELECT * FROM t8,t9; } } {1 {no such table: t9}} | | | | | 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 | db close sqlite3 db test.db catchsql { SELECT * FROM t8,t9; } } {1 {no such table: t9}} forcedelete test2.db test2.db-journal ifcapable attach { do_test temptable-7.1 { catchsql { ATTACH 'test2.db' AS two; CREATE TEMP TABLE two.abc(x,y); } } {1 {temporary table name must be unqualified}} } # Need to do the following for tcl 8.5 on mac. On that configuration, the # -readonly flag is taken so seriously that a subsequent [forcedelete] # (required before the next test file can be executed) will fail. # catch {file attributes test.db -readonly 0} do_test temptable-8.0 { db close catch {forcedelete test.db} sqlite3 db test.db } {} do_test temptable-8.1 { execsql { CREATE TEMP TABLE tbl2(a, b); } execsql { CREATE TABLE tbl(a, b); INSERT INTO tbl VALUES(1, 2); |
︙ | ︙ |
Changes to test/temptrigger.test.
︙ | ︙ | |||
153 154 155 156 157 158 159 | # connection. This forces [db] to reload the 'test2.db' # schema. Check that the temp trigger is still fired # correctly. # # temptrigger-3.4: Check that the temp trigger can be dropped without error. # do_test temptrigger-3.1 { | | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | # connection. This forces [db] to reload the 'test2.db' # schema. Check that the temp trigger is still fired # correctly. # # temptrigger-3.4: Check that the temp trigger can be dropped without error. # do_test temptrigger-3.1 { catch { forcedelete test2.db test2.db-journal } catch { forcedelete test.db test.db-journal } sqlite3 db test.db sqlite3 db2 test2.db execsql { CREATE TABLE t2(a, b) } db2 execsql { ATTACH 'test2.db' AS aux; CREATE TEMP TABLE tt2(a, b); CREATE TEMP TRIGGER tr2 AFTER INSERT ON aux.t2 BEGIN |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #------------------------------------------------------------------------- # The commands provided by the code in this file to help with creating # test cases are as follows: # # Commands to manipulate the db and the file-system at a high level: # # copy_file FROM TO # drop_all_tables ?DB? # forcedelete FILENAME # # Test the capability of the SQLite version built into the interpreter to # determine if a specific test can be run: # # ifcapable EXPR # | > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #------------------------------------------------------------------------- # The commands provided by the code in this file to help with creating # test cases are as follows: # # Commands to manipulate the db and the file-system at a high level: # # copy_file FROM TO # delete_file FILENAME # drop_all_tables ?DB? # forcecopy FROM TO # forcedelete FILENAME # # Test the capability of the SQLite version built into the interpreter to # determine if a specific test can be run: # # ifcapable EXPR # |
︙ | ︙ | |||
118 119 120 121 122 123 124 125 126 127 128 129 130 131 | # This command is not opening a new database connection. Pass the # arguments through to the C implemenation as the are. # uplevel 1 sqlite_orig $args } } } proc execpresql {handle args} { trace remove execution $handle enter [list execpresql $handle] if {[info exists ::G(perm:presql)]} { $handle eval $::G(perm:presql) } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # This command is not opening a new database connection. Pass the # arguments through to the C implemenation as the are. # uplevel 1 sqlite_orig $args } } } proc getFileRetries {} { if {![info exists ::G(file-retries)]} { # # NOTE: Return the default number of retries for [file] operations. A # value of zero or less here means "disabled". # return [expr {$::tcl_platform(platform) eq "windows" ? 10 : 0}] } return $::G(file-retries) } proc getFileRetryDelay {} { if {![info exists ::G(file-retry-delay)]} { # # NOTE: Return the default number of milliseconds to wait when retrying # failed [file] operations. A value of zero or less means "do not # wait". # return 100; # TODO: Good default? } return $::G(file-retry-delay) } # Copy file $from into $to. This is used because some versions of # TCL for windows (notably the 8.4.1 binary package shipped with the # current mingw release) have a broken "file copy" command. # proc copy_file {from to} { do_copy_file false $from $to } proc forcecopy {from to} { do_copy_file true $from $to } proc do_copy_file {force from to} { set nRetry [getFileRetries] ;# Maximum number of retries. set nDelay [getFileRetryDelay] ;# Delay in ms before retrying. # On windows, sometimes even a [file copy -force] can fail. The cause is # usually "tag-alongs" - programs like anti-virus software, automatic backup # tools and various explorer extensions that keep a file open a little longer # than we expect, causing the delete to fail. # # The solution is to wait a short amount of time before retrying the copy. # if {$nRetry > 0} { for {set i 0} {$i<$nRetry} {incr i} { set rc [catch { if {$force} { file copy -force $from $to } else { file copy $from $to } } msg] if {$rc==0} break if {$nDelay > 0} { after $nDelay } } if {$rc} { error $msg } } else { if {$force} { file copy -force $from $to } else { file copy $from $to } } } # Delete a file or directory # proc delete_file {args} { do_delete_file false {*}$args } proc forcedelete {args} { do_delete_file true {*}$args } proc do_delete_file {force args} { set nRetry [getFileRetries] ;# Maximum number of retries. set nDelay [getFileRetryDelay] ;# Delay in ms before retrying. foreach filename $args { # On windows, sometimes even a [file delete -force] can fail just after # a file is closed. The cause is usually "tag-alongs" - programs like # anti-virus software, automatic backup tools and various explorer # extensions that keep a file open a little longer than we expect, causing # the delete to fail. # # The solution is to wait a short amount of time before retrying the # delete. # if {$nRetry > 0} { for {set i 0} {$i<$nRetry} {incr i} { set rc [catch { if {$force} { file delete -force $filename } else { file delete $filename } } msg] if {$rc==0} break if {$nDelay > 0} { after $nDelay } } if {$rc} { error $msg } } else { if {$force} { file delete -force $filename } else { file delete $filename } } } } proc execpresql {handle args} { trace remove execution $handle enter [list execpresql $handle] if {[info exists ::G(perm:presql)]} { $handle eval $::G(perm:presql) } } |
︙ | ︙ | |||
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | # --pause # --soft-heap-limit=NN # --maxerror=NN # --malloctrace=N # --backtrace=N # --binarylog=N # --soak=N # --start=[$permutation:]$testfile # set cmdlinearg(soft-heap-limit) 0 set cmdlinearg(maxerror) 1000 set cmdlinearg(malloctrace) 0 set cmdlinearg(backtrace) 10 set cmdlinearg(binarylog) 0 set cmdlinearg(soak) 0 set cmdlinearg(start) "" set leftover [list] foreach a $argv { switch -regexp -- $a { {^-+pause$} { # Wait for user input before continuing. This is to give the user an | > > > > | 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 | # --pause # --soft-heap-limit=NN # --maxerror=NN # --malloctrace=N # --backtrace=N # --binarylog=N # --soak=N # --file-retries=N # --file-retry-delay=N # --start=[$permutation:]$testfile # set cmdlinearg(soft-heap-limit) 0 set cmdlinearg(maxerror) 1000 set cmdlinearg(malloctrace) 0 set cmdlinearg(backtrace) 10 set cmdlinearg(binarylog) 0 set cmdlinearg(soak) 0 set cmdlinearg(file-retries) 0 set cmdlinearg(file-retry-delay) 0 set cmdlinearg(start) "" set leftover [list] foreach a $argv { switch -regexp -- $a { {^-+pause$} { # Wait for user input before continuing. This is to give the user an |
︙ | ︙ | |||
193 194 195 196 197 198 199 200 201 202 203 204 205 206 | {^-+binarylog=.+$} { foreach {dummy cmdlinearg(binarylog)} [split $a =] break } {^-+soak=.+$} { foreach {dummy cmdlinearg(soak)} [split $a =] break set ::G(issoak) $cmdlinearg(soak) } {^-+start=.+$} { foreach {dummy cmdlinearg(start)} [split $a =] break set ::G(start:file) $cmdlinearg(start) if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} { set ::G(start:permutation) ${s.perm} set ::G(start:file) ${s.file} | > > > > > > > > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | {^-+binarylog=.+$} { foreach {dummy cmdlinearg(binarylog)} [split $a =] break } {^-+soak=.+$} { foreach {dummy cmdlinearg(soak)} [split $a =] break set ::G(issoak) $cmdlinearg(soak) } {^-+file-retries=.+$} { foreach {dummy cmdlinearg(file-retries)} [split $a =] break set ::G(file-retries) $cmdlinearg(file-retries) } {^-+file-retry-delay=.+$} { foreach {dummy cmdlinearg(file-retry-delay)} [split $a =] break set ::G(file-retry-delay) $cmdlinearg(file-retry-delay) } {^-+start=.+$} { foreach {dummy cmdlinearg(start)} [split $a =] break set ::G(start:file) $cmdlinearg(start) if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} { set ::G(start:permutation) ${s.perm} set ::G(start:file) ${s.file} |
︙ | ︙ | |||
242 243 244 245 246 247 248 | # sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) # Create a test database # proc reset_db {} { catch {db close} | | | | | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | # sqlite3_soft_heap_limit $cmdlinearg(soft-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 |
︙ | ︙ | |||
618 619 620 621 622 623 624 | if {[sqlite3_memory_used]>0} { puts "Writing leaks.sql..." sqlite3_memdebug_log sync memdebug_log_sql leaks.sql } } foreach f [glob -nocomplain test.db-*-journal] { | | | | 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | if {[sqlite3_memory_used]>0} { puts "Writing leaks.sql..." sqlite3_memdebug_log sync memdebug_log_sql leaks.sql } } foreach f [glob -nocomplain test.db-*-journal] { forcedelete $f } foreach f [glob -nocomplain test.db-mj*] { forcedelete $f } exit [expr {$nErr>0}] } # Display memory statistics for analysis and debugging purposes. # proc show_memstats {} { |
︙ | ︙ | |||
736 737 738 739 740 741 742 | if {[catch {sqlite3_finalize $vm} errmsg]} { return [list 1 $errmsg] } } return $r } | < < < < < < < < < < < < < < < < < < < < < < < < | 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | if {[catch {sqlite3_finalize $vm} errmsg]} { return [list 1 $errmsg] } } return $r } # Do an integrity check of the entire database # proc integrity_check {name {db db}} { ifcapable integrityck { do_test $name [list execsql {PRAGMA integrity_check} $db] {ok} } } |
︙ | ︙ | |||
960 961 962 963 964 965 966 | # Delete the files test.db and test2.db, then execute the TCL and # SQL (in that order) to prepare for the test case. do_test $testname.$n.1 { set ::sqlite_io_error_pending 0 catch {db close} catch {db2 close} | | | | | | 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | # Delete the files test.db and test2.db, then execute the TCL and # SQL (in that order) to prepare for the test case. do_test $testname.$n.1 { set ::sqlite_io_error_pending 0 catch {db close} catch {db2 close} catch {forcedelete test.db} catch {forcedelete test.db-journal} catch {forcedelete test2.db} catch {forcedelete test2.db-journal} set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] sqlite3_extended_result_codes $::DB $::ioerropts(-erc) if {[info exists ::ioerropts(-tclprep)]} { eval $::ioerropts(-tclprep) } if {[info exists ::ioerropts(-sqlprep)]} { execsql $::ioerropts(-sqlprep) |
︙ | ︙ | |||
1237 1238 1239 1240 1241 1242 1243 | } set fd [open $filename w] puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" close $fd } | < < < < < < < < < < < < < < < < < < | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 | } set fd [open $filename w] puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" close $fd } # Drop all tables in database [db] proc drop_all_tables {{db db}} { ifcapable trigger&&foreignkey { set pk [$db one "PRAGMA foreign_keys"] $db eval "PRAGMA foreign_keys = OFF" } foreach {idx name file} [db eval {PRAGMA database_list}] { |
︙ | ︙ | |||
1436 1437 1438 1439 1440 1441 1442 | return "" } proc db_save {} { foreach f [glob -nocomplain sv_test.db*] { forcedelete $f } foreach f [glob -nocomplain test.db*] { set f2 "sv_$f" | | | | | 1523 1524 1525 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 | return "" } proc db_save {} { foreach f [glob -nocomplain sv_test.db*] { forcedelete $f } foreach f [glob -nocomplain test.db*] { set f2 "sv_$f" forcecopy $f $f2 } } proc db_save_and_close {} { db_save catch { db close } return "" } proc db_restore {} { foreach f [glob -nocomplain test.db*] { forcedelete $f } foreach f2 [glob -nocomplain sv_test.db*] { set f [string range $f2 3 end] forcecopy $f2 $f } } proc db_restore_and_reopen {{dbfile test.db}} { catch { db close } db_restore sqlite3 db $dbfile } proc db_delete_and_reopen {{file test.db}} { catch { db close } foreach f [glob -nocomplain test.db*] { forcedelete $f } sqlite3 db $file } # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) source $testdir/thread_common.tcl source $testdir/malloc_common.tcl |
Changes to test/thread002.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 | set ::enable_shared_cache [sqlite3_enable_shared_cache 1] set ::NTHREAD 10 do_test thread002.1 { # Create 3 databases with identical schemas: for {set ii 0} {$ii < 3} {incr ii} { | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | set ::enable_shared_cache [sqlite3_enable_shared_cache 1] set ::NTHREAD 10 do_test thread002.1 { # Create 3 databases with identical schemas: for {set ii 0} {$ii < 3} {incr ii} { forcedelete test${ii}.db sqlite3 db test${ii}.db execsql { CREATE TABLE t1(k, v); CREATE INDEX t1_i ON t1(v); INSERT INTO t1(v) VALUES(1.0); } db close |
︙ | ︙ |
Changes to test/thread003.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 | } } {} do_test thread003.1.2 { expr {([file size test.db] / 1024) > 2000} } {1} do_test thread003.1.3 { db close | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | } } {} do_test thread003.1.2 { expr {([file size test.db] / 1024) > 2000} } {1} do_test thread003.1.3 { db close forcedelete test2.db sqlite3 db test2.db } {} do_test thread003.1.4 { execsql { BEGIN; CREATE TABLE t1(a, b, c); } |
︙ | ︙ |
Changes to test/thread005.test.
︙ | ︙ | |||
117 118 119 120 121 122 123 | # when using an ATTACHed database. There doesn't seem to be any reason # for this, other than that operating on an ATTACHed database means there # are a few more mutex grabs and releases during the window of time open # for the race-condition. Maybe this encourages the scheduler to context # switch or something... # | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | # when using an ATTACHed database. There doesn't seem to be any reason # for this, other than that operating on an ATTACHed database means there # are a few more mutex grabs and releases during the window of time open # for the race-condition. Maybe this encourages the scheduler to context # switch or something... # forcedelete test.db test2.db unset -nocomplain finished do_test thread005-2.1 { sqlite3 db test.db execsql { ATTACH 'test2.db' AS aux } execsql { CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b UNIQUE); |
︙ | ︙ |
Changes to test/tkt-2d1a5c67d.test.
︙ | ︙ | |||
114 115 116 117 118 119 120 | execsql { SELECT * FROM t4 WHERE a = 'xyz' } } {xyz} # Check that recovery works on the WAL file. # forcedelete test.db2-wal test.db2 do_test 3.6 { | | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | execsql { SELECT * FROM t4 WHERE a = 'xyz' } } {xyz} # Check that recovery works on the WAL file. # forcedelete test.db2-wal test.db2 do_test 3.6 { copy_file test.db-wal test.db2-wal copy_file test.db test.db2 sqlite3 db2 test.db2 execsql { SELECT * FROM t4 WHERE a = 'xyz' } db2 } {xyz} finish_test |
Changes to test/tkt-5ee23731f.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt-5ee237-1.1 { db close | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt-5ee237-1.1 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(x UNIQUE); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); INSERT INTO t1 SELECT x+2 FROM t1; INSERT INTO t1 SELECT x+4 FROM t1; |
︙ | ︙ |
Added test/tkt-d635236375.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 | # 2011 August 3 # # 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 that bug [d63523637517386191d634e] # has been fixed. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix tkt-d635236375 do_test 1.0 { execsql { CREATE TABLE t1(id1 INTEGER PRIMARY KEY); INSERT INTO t1 VALUES(9999); CREATE TABLE t2(id2 INTEGER PRIMARY KEY); INSERT INTO t2 VALUES(12345); INSERT INTO t2 VALUES(54321); SELECT DISTINCT id1 AS x, id1 AS y FROM t1, t2; } } {9999 9999} do_test 1.1 { execsql { SELECT count(*) FROM t1, t2 GROUP BY id1, id1; } } {2} finish_test |
Changes to test/tkt-f3e5abed55.test.
︙ | ︙ | |||
10 11 12 13 14 15 16 | #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl | | | | 10 11 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/malloc_common.tcl foreach f [glob -nocomplain test.db*mj*] { forcedelete $f } forcedelete test.db2 do_test tkt-f3e5abed55-1.1 { execsql { ATTACH 'test.db2' AS aux; CREATE TABLE main.t1(a, b); CREATE TABLE aux.t2(c, d); } |
︙ | ︙ | |||
47 48 49 50 51 52 53 | execsql COMMIT db2 execsql COMMIT } {} do_test tkt-f3e5abed55-1.6 { glob -nocomplain test.db*mj* } {} | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | execsql COMMIT db2 execsql COMMIT } {} do_test tkt-f3e5abed55-1.6 { glob -nocomplain test.db*mj* } {} foreach f [glob -nocomplain test.db*mj*] { forcedelete $f } db close db2 close # Set up a testvfs so that the next time SQLite tries to delete the # file "test.db-journal", a snapshot of the current file-system contents |
︙ | ︙ |
Changes to test/tkt1667.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ifcapable !autovacuum||!tclvar { finish_test return } db close | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ifcapable !autovacuum||!tclvar { finish_test return } db close forcedelete test.db test.db-journal # Set the pending byte offset such that the page it is on is # the first autovacuum pointer map page in the file (assume a page # size of 1024). set first_ptrmap_page [expr 1024/5 + 3] sqlite3_test_control_pending_byte [expr 1024 * ($first_ptrmap_page-1)] |
︙ | ︙ |
Changes to test/tkt1873.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | source $testdir/tester.tcl ifcapable !attach { finish_test return } | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | source $testdir/tester.tcl ifcapable !attach { finish_test return } forcedelete test2.db test2.db-journal do_test tkt1873-1.1 { execsql { CREATE TABLE t1(x, y); ATTACH 'test2.db' AS aux; CREATE TABLE aux.t2(x, y); INSERT INTO t1 VALUES(1, 2); |
︙ | ︙ |
Changes to test/tkt2686.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | } } {} integrity_check tkt2686-$i.3 catch {db eval COMMIT} } db close | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | } } {} integrity_check tkt2686-$i.3 catch {db eval COMMIT} } db close forcedelete test.db test.db-journal sqlite3 db test.db db eval { PRAGMA page_size=1024; PRAGMA max_page_count=50; PRAGMA auto_vacuum=1; CREATE TABLE filler (fill); |
︙ | ︙ |
Changes to test/tkt2817.test.
︙ | ︙ | |||
44 45 46 47 48 49 50 | # These tests - tkt2817-2.* - are the same as the previous block, except # for the fact that the temp-table and the main table do not share the # same name. #2817 did not cause a problem with these tests. # db close | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # These tests - tkt2817-2.* - are the same as the previous block, except # for the fact that the temp-table and the main table do not share the # same name. #2817 did not cause a problem with these tests. # db close forcedelete test.db sqlite3 db test.db do_test tkt2817-2.0 { execsql { CREATE TEMP TABLE tmp(a, b, c); INSERT INTO tmp VALUES(1, 'abc', 'def'); INSERT INTO tmp VALUES(2, 'ghi', 'jkl'); } |
︙ | ︙ |
Changes to test/tkt2820.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | # set testdir [file dirname $argv0] source $testdir/tester.tcl proc test_schema_change {testid init ddl res} { db close | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # set testdir [file dirname $argv0] source $testdir/tester.tcl proc test_schema_change {testid init ddl res} { db close forcedelete test.db test.db-journal sqlite3 db test.db execsql $init do_test tkt2820-$testid.1 { set STMT [sqlite3_prepare db {SELECT * FROM sqlite_master} -1 DUMMY] sqlite3_step $STMT } {SQLITE_ROW} #if {$testid==3} {execsql {PRAGMA vdbe_trace=ON}} |
︙ | ︙ | |||
66 67 68 69 70 71 72 | # We further observe that prior to the fix associated with ticket #2820, # no statement journal would be created on an SQL statement that was run # while a second statement was active, as long as we are in autocommit # mode. This is incorrect. # do_test tkt2820-4.1 { db close | | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | # We further observe that prior to the fix associated with ticket #2820, # no statement journal would be created on an SQL statement that was run # while a second statement was active, as long as we are in autocommit # mode. This is incorrect. # do_test tkt2820-4.1 { db close forcedelete test.db test.db-journal sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); } |
︙ | ︙ |
Changes to test/tkt2854.test.
︙ | ︙ | |||
124 125 126 127 128 129 130 | execsql { SELECT * FROM abc } db2 } {} # Check that if an attempt to obtain an exclusive lock fails because an # attached db cannot be locked, the internal exclusive flag used by # shared-cache users is correctly cleared. do_test tkt2854-1.19 { | | | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | execsql { SELECT * FROM abc } db2 } {} # Check that if an attempt to obtain an exclusive lock fails because an # attached db cannot be locked, the internal exclusive flag used by # shared-cache users is correctly cleared. do_test tkt2854-1.19 { forcedelete test2.db test2.db-journal sqlite3 db4 test2.db execsql { CREATE TABLE def(d, e, f) } db4 execsql { ATTACH 'test2.db' AS aux } db } {} do_test tkt2854-1.20 { execsql {BEGIN IMMEDIATE} db4 catchsql {BEGIN EXCLUSIVE} db |
︙ | ︙ |
Changes to test/tkt3457.test.
︙ | ︙ | |||
42 43 44 45 46 47 48 | execsql { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(1, 2, 3); BEGIN; INSERT INTO t1 VALUES(4, 5, 6); } | | | | | | | | 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 | execsql { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(1, 2, 3); BEGIN; INSERT INTO t1 VALUES(4, 5, 6); } forcecopy test.db bak.db forcecopy test.db-journal bak.db-journal # Fix the first journal-header in the journal-file. Because the # journal file has not yet been synced, the 8-byte magic string at the # start of the first journal-header has not been written by SQLite. # So write it now. set fd [open bak.db-journal a+] fconfigure $fd -encoding binary -translation binary seek $fd 0 puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7" close $fd execsql COMMIT } {} 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}} finish_test |
Changes to test/tkt35xx.test.
︙ | ︙ | |||
46 47 48 49 50 51 52 | INSERT INTO t1 VALUES(1, 1, zeroblob(676)); } } {} # Trigger the problem using statement rollback. # db close | | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | INSERT INTO t1 VALUES(1, 1, zeroblob(676)); } } {} # Trigger the problem using statement rollback. # db close delete_file test.db sqlite3 db test.db set big [string repeat abcdefghij 22] ;# 220 byte string do_test tkt35xx-1.2.1 { execsql { PRAGMA auto_vacuum = 0; PRAGMA page_size = 1024; CREATE TABLE t3(a INTEGER PRIMARY KEY, b); |
︙ | ︙ |
Changes to test/trigger1.test.
︙ | ︙ | |||
530 531 532 533 534 535 536 | # correctly re-installed. # # Also verify that references within trigger programs are resolved at # statement compile time, not trigger installation time. This means, for # example, that you can drop and re-create tables referenced by triggers. ifcapable tempdb&&attach { do_test trigger1-10.0 { | | | | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | # correctly re-installed. # # Also verify that references within trigger programs are resolved at # statement compile time, not trigger installation time. This means, for # example, that you can drop and re-create tables referenced by triggers. ifcapable tempdb&&attach { do_test trigger1-10.0 { forcedelete test2.db forcedelete test2.db-journal execsql { ATTACH 'test2.db' AS aux; } } {} do_test trigger1-10.1 { execsql { CREATE TABLE main.t4(a, b, c); |
︙ | ︙ |
Changes to test/trigger4.test.
︙ | ︙ | |||
126 127 128 129 130 131 132 | update test set b=99 where id=7; select * from test2; } } {7 99} do_test trigger4-4.1 { db close | | | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | update test set b=99 where id=7; select * from test2; } } {7 99} do_test trigger4-4.1 { db close forcedelete trigtest.db forcedelete trigtest.db-journal sqlite3 db trigtest.db catchsql {drop table tbl; drop view vw} execsql { create table tbl(a integer primary key, b integer); create view vw as select * from tbl; create trigger t_del_tbl instead of delete on vw for each row begin delete from tbl where a = old.a; |
︙ | ︙ | |||
191 192 193 194 195 196 197 | } {0 {}} do_test trigger4-7.2 { execsql {select a, b from vw where a<=102 or a>=227 order by a} } {101 1001 102 2002 227 2127 228 2128} integrity_check trigger4-99.9 db close | | | 191 192 193 194 195 196 197 198 199 200 | } {0 {}} do_test trigger4-7.2 { execsql {select a, b from vw where a<=102 or a>=227 order by a} } {101 1001 102 2002 227 2127 228 2128} integrity_check trigger4-99.9 db close forcedelete trigtest.db trigtest.db-journal finish_test |
Changes to test/triggerA.test.
︙ | ︙ | |||
201 202 203 204 205 206 207 | return } source $testdir/malloc_common.tcl # Save a copy of the current database configuration. # db close | | | | | | | 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 | return } source $testdir/malloc_common.tcl # Save a copy of the current database configuration. # db close forcedelete test.db-triggerA copy_file test.db test.db-triggerA sqlite3 db test.db # Run malloc tests on the INSTEAD OF trigger firing. # do_malloc_test triggerA-3 -tclprep { db close forcedelete test.db test.db-journal forcecopy test.db-triggerA test.db sqlite3 db test.db sqlite3_extended_result_codes db 1 db eval {SELECT * FROM v5; -- warm up the cache} } -sqlbody { DELETE FROM v5 WHERE x=5; UPDATE v5 SET b=b+9900000 WHERE x BETWEEN 3 AND 5; } # Clean up the saved database copy. # forcedelete test.db-triggerA finish_test |
Changes to test/triggerC.test.
︙ | ︙ | |||
914 915 916 917 918 919 920 | INSERT INTO v2 DEFAULT VALUES; SELECT a, b, a IS NULL, b IS NULL FROM log; } } {{} {} 1 1} do_test triggerC-12.1 { db close | | | 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 | INSERT INTO v2 DEFAULT VALUES; SELECT a, b, a IS NULL, b IS NULL FROM log; } } {{} {} 1 1} do_test triggerC-12.1 { db close forcedelete test.db sqlite3 db test.db execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); |
︙ | ︙ |
Changes to test/triggerD.test.
︙ | ︙ | |||
189 190 191 192 193 194 195 | # the sqlite_master table. We cannot fix the bug simply by disallowing # "xyz.tab" since that could break legacy applications. We have to # fix the system so that the "xyz." on "xyz.tab" is ignored. # Verify that this is the case. # do_test triggerD-4.1 { db close | | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | # the sqlite_master table. We cannot fix the bug simply by disallowing # "xyz.tab" since that could break legacy applications. We have to # fix the system so that the "xyz." on "xyz.tab" is ignored. # Verify that this is the case. # do_test triggerD-4.1 { db close forcedelete test.db test2.db sqlite3 db test.db db eval { CREATE TABLE t1(x); ATTACH 'test2.db' AS db2; CREATE TABLE db2.t2(y); CREATE TABLE db2.log(z); CREATE TRIGGER db2.trig AFTER INSERT ON db2.t2 BEGIN |
︙ | ︙ |
Changes to test/vacuum.test.
︙ | ︙ | |||
204 205 206 207 208 209 210 | # Ticket #427. Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS # pragma is turned on. # do_test vacuum-3.1 { db close db2 close | | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | # Ticket #427. Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS # pragma is turned on. # do_test vacuum-3.1 { db close db2 close delete_file test.db sqlite3 db test.db execsql { PRAGMA empty_result_callbacks=on; VACUUM; } } {} |
︙ | ︙ | |||
230 231 232 233 234 235 236 | # Ticket #515. VACUUM after deleting and recreating the table that # a view refers to. Omit this test if the library is not view-enabled. # ifcapable view { do_test vacuum-5.1 { db close | | | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | # Ticket #515. VACUUM after deleting and recreating the table that # a view refers to. Omit this test if the library is not view-enabled. # ifcapable view { do_test vacuum-5.1 { db close forcedelete test.db sqlite3 db test.db catchsql { CREATE TABLE Test (TestID int primary key); INSERT INTO Test VALUES (NULL); CREATE VIEW viewTest AS SELECT * FROM Test; BEGIN; |
︙ | ︙ | |||
286 287 288 289 290 291 292 | execsql { select count(*) from "abc abc" WHERE a = X'00112233'; } } {1} } # Check what happens when an in-memory database is vacuumed. The | | | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | execsql { select count(*) from "abc abc" WHERE a = X'00112233'; } } {1} } # Check what happens when an in-memory database is vacuumed. The # [delete_file] command covers us in case the library was compiled # without in-memory database support. # forcedelete :memory: do_test vacuum-7.0 { sqlite3 db2 :memory: execsql { CREATE TABLE t1(t); VACUUM; } db2 } {} |
︙ | ︙ | |||
333 334 335 336 337 338 339 | } {1} } db2 close # Ticket #873. VACUUM a database that has ' in its name. # do_test vacuum-8.1 { | | | | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | } {1} } db2 close # Ticket #873. VACUUM a database that has ' in its name. # do_test vacuum-8.1 { forcedelete a'z.db forcedelete a'z.db-journal sqlite3 db2 a'z.db execsql { CREATE TABLE t1(t); VACUUM; } db2 } {} db2 close |
︙ | ︙ | |||
379 380 381 382 383 384 385 | execsql { VACUUM; } cksum } $::cksum } | | | 379 380 381 382 383 384 385 386 387 388 | execsql { VACUUM; } cksum } $::cksum } forcedelete {a'z.db} finish_test |
Changes to test/vacuum2.test.
︙ | ︙ | |||
131 132 133 134 135 136 137 | } {ok} db2 close ifcapable autovacuum { do_test vacuum2-4.1 { db close | | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | } {ok} db2 close ifcapable autovacuum { do_test vacuum2-4.1 { db close forcedelete test.db sqlite3 db test.db execsql { pragma auto_vacuum=1; create table t(a, b); insert into t values(1, 2); insert into t values(1, 2); pragma auto_vacuum=0; |
︙ | ︙ |
Changes to test/vacuum3.test.
︙ | ︙ | |||
192 193 194 195 196 197 198 | integrity_check vacuum3-3.$I.3 incr I } do_test vacuum3-4.1 { db close | | | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | integrity_check vacuum3-3.$I.3 incr I } do_test vacuum3-4.1 { db close delete_file test.db sqlite3 db test.db execsql { PRAGMA page_size=1024; CREATE TABLE abc(a, b, c); INSERT INTO abc VALUES(1, 2, 3); INSERT INTO abc VALUES(4, 5, 6); } |
︙ | ︙ |
Changes to test/view.test.
︙ | ︙ | |||
454 455 456 457 458 459 460 | catchsql { CREATE VIEW v12 AS SELECT a FROM t1 WHERE b=? } } {1 {parameters are not allowed in views}} ifcapable attach { do_test view-13.1 { | | | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 | catchsql { CREATE VIEW v12 AS SELECT a FROM t1 WHERE b=? } } {1 {parameters are not allowed in views}} ifcapable attach { do_test view-13.1 { forcedelete test2.db catchsql { ATTACH 'test2.db' AS two; CREATE TABLE two.t2(x,y); CREATE VIEW v13 AS SELECT y FROM two.t2; } } {1 {view v13 cannot reference objects in database two}} } |
︙ | ︙ |
Changes to test/vtab1.test.
︙ | ︙ | |||
720 721 722 723 724 725 726 | do_test vtab1-6-8.4 { execsql { SELECT * FROM techo ORDER BY a; } } {} execsql {PRAGMA count_changes=OFF} | | | | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | do_test vtab1-6-8.4 { execsql { SELECT * FROM techo ORDER BY a; } } {} execsql {PRAGMA count_changes=OFF} forcedelete test2.db forcedelete test2.db-journal sqlite3 db2 test2.db execsql { CREATE TABLE techo(a PRIMARY KEY, b, c); } db2 proc check_echo_table {tn} { set ::data1 [execsql {SELECT rowid, * FROM techo}] set ::data2 [execsql {SELECT rowid, * FROM techo} db2] |
︙ | ︙ |
Changes to test/vtab7.test.
︙ | ︙ | |||
130 131 132 133 134 135 136 | set ::rc } {1 {database table is locked}} execsql {DROP TABLE newtab} # Write to an attached database from xSync(). ifcapable attach { do_test vtab7-3.1 { | | | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | set ::rc } {1 {database table is locked}} execsql {DROP TABLE newtab} # Write to an attached database from xSync(). ifcapable attach { do_test vtab7-3.1 { forcedelete test2.db forcedelete test2.db-journal execsql { ATTACH 'test2.db' AS db2; CREATE TABLE db2.stuff(description, shape, color); } set ::callbacks(xSync,abc) { execsql { INSERT INTO db2.stuff VALUES('abc', 'square', 'green'); } } |
︙ | ︙ |
Changes to test/vtabC.test.
︙ | ︙ | |||
27 28 29 30 31 32 33 | # N will be the number of virtual tables we have defined. # unset -nocomplain N for {set N 1} {$N<=20} {incr N} { db close | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # N will be the number of virtual tables we have defined. # unset -nocomplain N for {set N 1} {$N<=20} {incr N} { db close forcedelete test.db test.db-journal sqlite3 db test.db register_echo_module [sqlite3_connection_pointer db] # Create $N tables and $N virtual tables to echo them. # unset -nocomplain tablist set tablist {} |
︙ | ︙ |
Added test/vtabF.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 | # 2011 Aug 1 # # 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. # This file checks to make sure IS NOT NULL constraints work on # virtual tables. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !vtab||!schema_pragmas { finish_test ; return } # Register the echo module register_echo_module [sqlite3_connection_pointer db] do_test vtabE-1.1 { execsql { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a); CREATE INDEX i2 ON t1(b); INSERT INTO t1 VALUES(10,110); INSERT INTO t1 VALUES(11,111); INSERT INTO t1 SELECT a+2, b+2 FROM t1; INSERT INTO t1 SELECT null, b+4 FROM t1; INSERT INTO t1 SELECT null, b+8 FROM t1; INSERT INTO t1 SELECT null, b+16 FROM t1; ANALYZE; CREATE VIRTUAL TABLE tv1 USING echo(t1); SELECT b FROM t1 WHERE a IS NOT NULL; } } {110 111 112 113} do_test vtabE-1.2 { execsql {SELECT b FROM tv1 WHERE a IS NOT NULL} } {110 111 112 113} finish_test |
Changes to test/wal.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | set testprefix wal ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | set testprefix wal ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } forcedelete test.db test.db-wal test.db-wal-summary sqlite3_wal db test.db } set ::blobcnt 0 proc blob {nByte} { incr ::blobcnt return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte] |
︙ | ︙ | |||
207 208 209 210 211 212 213 | } expr { $logsize == [file size test.db-wal] } } {1} do_test wal-4.4.5 { execsql { SELECT count(*) FROM t2 } } {1} do_test wal-4.4.6 { | | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | } expr { $logsize == [file size test.db-wal] } } {1} do_test wal-4.4.5 { execsql { SELECT count(*) FROM t2 } } {1} do_test wal-4.4.6 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2 } {1 2} do_test wal-4.4.7 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close |
︙ | ︙ | |||
265 266 267 268 269 270 271 | } expr { $logsize == [file size test.db-wal] } } {1} do_test wal-4.5.5 { execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } } {1 2} do_test wal-4.5.6 { | | | | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | } expr { $logsize == [file size test.db-wal] } } {1} do_test wal-4.5.5 { execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } } {1 2} do_test wal-4.5.6 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2 } {1 2} do_test wal-4.5.7 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close |
︙ | ︙ | |||
330 331 332 333 334 335 336 | } } {1 2 3 4} db close foreach sector {512 4096} { sqlite3_simulate_device -sectorsize $sector foreach pgsz {512 1024 2048 4096} { | | | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | } } {1 2 3 4} db close 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; " |
︙ | ︙ | |||
353 354 355 356 357 358 359 | do_test wal-6.$sector.$pgsz.2 { log_deleted test.db-wal } {1} } } do_test wal-7.1 { | | | | 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 | do_test wal-6.$sector.$pgsz.2 { log_deleted test.db-wal } {1} } } do_test wal-7.1 { forcedelete test.db test.db-wal sqlite3_wal db test.db execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } list [file size test.db] [file size test.db-wal] } [list 1024 [wal_file_size 3 1024]] do_test wal-7.2 { execsql { PRAGMA wal_checkpoint } list [file size test.db] [file size test.db-wal] } [list 2048 [wal_file_size 3 1024]] # Execute some transactions in auto-vacuum mode to test database file # truncation. # do_test wal-8.1 { reopen_db catch { db close } forcedelete test.db test.db-wal sqlite3 db test.db db function blob blob execsql { PRAGMA auto_vacuum = 1; PRAGMA journal_mode = wal; PRAGMA auto_vacuum; |
︙ | ︙ | |||
431 432 433 434 435 436 437 | } 1024 do_test wal-9.2 { sqlite3_wal db2 test.db execsql {PRAGMA integrity_check } db2 } {ok} do_test wal-9.3 { | | | | | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | } 1024 do_test wal-9.2 { sqlite3_wal db2 test.db execsql {PRAGMA integrity_check } db2 } {ok} do_test wal-9.3 { forcedelete test2.db test2.db-wal copy_file test.db test2.db copy_file test.db-wal test2.db-wal sqlite3_wal db3 test2.db execsql {PRAGMA integrity_check } db3 } {ok} db3 close do_test wal-9.4 { execsql { PRAGMA wal_checkpoint } |
︙ | ︙ | |||
782 783 784 785 786 787 788 | list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] } {3 1} do_test wal-12.3 { execsql { INSERT INTO t2 VALUES('B', 1) } list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] } {3 2} do_test wal-12.4 { | | | | | | 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 | list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] } {3 1} do_test wal-12.3 { execsql { INSERT INTO t2 VALUES('B', 1) } list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] } {3 2} do_test wal-12.4 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3_wal db2 test2.db execsql { SELECT * FROM t2 } db2 } {B 1} db2 close do_test wal-12.5 { execsql { PRAGMA wal_checkpoint; UPDATE t2 SET y = 2 WHERE x = 'B'; PRAGMA wal_checkpoint; UPDATE t1 SET y = 1 WHERE x = 'A'; PRAGMA wal_checkpoint; UPDATE t1 SET y = 0 WHERE x = 'A'; } execsql { SELECT * FROM t2 } } {B 2} 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 #------------------------------------------------------------------------- |
︙ | ︙ | |||
905 906 907 908 909 910 911 | # that had an out-of-date pager-cache, the next time the connection was # used it did not realize the cache was out-of-date and proceeded to # operate with an inconsistent cache. Leading to corruption. # catch { db close } catch { db2 close } catch { db3 close } | | | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | # that had an out-of-date pager-cache, the next time the connection was # used it did not realize the cache was out-of-date and proceeded to # operate with an inconsistent cache. Leading to corruption. # catch { db close } catch { db2 close } catch { db3 close } forcedelete test.db test.db-wal sqlite3 db test.db sqlite3 db2 test.db do_test wal-14 { execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(randomblob(10), randomblob(100)); |
︙ | ︙ | |||
943 944 945 946 947 948 949 | catch { db close } catch { db2 close } #------------------------------------------------------------------------- # The following block of tests - wal-15.* - focus on testing the # implementation of the sqlite3_wal_checkpoint() interface. # | | | 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 | catch { db close } catch { db2 close } #------------------------------------------------------------------------- # The following block of tests - wal-15.* - focus on testing the # implementation of the sqlite3_wal_checkpoint() interface. # forcedelete test.db test.db-wal sqlite3 db test.db do_test wal-15.1 { execsql { PRAGMA auto_vacuum = 0; PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; } |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | 5 {sqlite3_wal_checkpoint db aux} SQLITE_OK 0 1 6 {sqlite3_wal_checkpoint db temp} SQLITE_OK 0 0 7 {db eval "PRAGMA main.wal_checkpoint"} {0 10 10} 1 0 8 {db eval "PRAGMA aux.wal_checkpoint"} {0 16 16} 0 1 9 {db eval "PRAGMA temp.wal_checkpoint"} {0 -1 -1} 0 0 } { do_test wal-16.$tn.1 { | | | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | 5 {sqlite3_wal_checkpoint db aux} SQLITE_OK 0 1 6 {sqlite3_wal_checkpoint db temp} SQLITE_OK 0 0 7 {db eval "PRAGMA main.wal_checkpoint"} {0 10 10} 1 0 8 {db eval "PRAGMA aux.wal_checkpoint"} {0 16 16} 0 1 9 {db eval "PRAGMA temp.wal_checkpoint"} {0 -1 -1} 0 0 } { do_test wal-16.$tn.1 { forcedelete test2.db test2.db-wal test2.db-journal forcedelete test.db test.db-wal test.db-journal 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; |
︙ | ︙ | |||
1112 1113 1114 1115 1116 1117 1118 | 2 256 [wal_file_size 172 512] 3 512 [wal_file_size 172 512] 4 1024 [wal_file_size 172 512] 5 2048 [wal_file_size 172 512] 6 4096 [wal_file_size 176 512] 7 8192 [wal_file_size 184 512] " { | | | 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 | 2 256 [wal_file_size 172 512] 3 512 [wal_file_size 172 512] 4 1024 [wal_file_size 172 512] 5 2048 [wal_file_size 172 512] 6 4096 [wal_file_size 176 512] 7 8192 [wal_file_size 184 512] " { forcedelete test.db test.db-wal test.db-journal sqlite3_simulate_device -sectorsize $sectorsize sqlite3 db test.db -vfs devsym do_test wal-17.$tn.1 { execsql { PRAGMA auto_vacuum = 0; PRAGMA page_size = 512; |
︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 | # # wal-18.1.* When the first 32-bits of a frame checksum is correct but # the second 32-bits are false, and # # wal-18.2.* When the page-size field that occurs at the start of a log # file is a power of 2 greater than 16384 or smaller than 512. # | | | | | | | 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 | # # wal-18.1.* When the first 32-bits of a frame checksum is correct but # the second 32-bits are false, and # # wal-18.2.* When the page-size field that occurs at the start of a log # file is a power of 2 greater than 16384 or smaller than 512. # forcedelete test.db test.db-wal test.db-journal do_test wal-18.0 { sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; PRAGMA journal_mode = WAL; PRAGMA synchronous = OFF; CREATE TABLE t1(a, b, UNIQUE(a, b)); INSERT INTO t1 VALUES(0, 0); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(1, 2); -- frames 1 and 2 INSERT INTO t1 VALUES(3, 4); -- frames 3 and 4 INSERT INTO t1 VALUES(5, 6); -- frames 5 and 6 } forcecopy test.db testX.db forcecopy test.db-wal testX.db-wal db close list [file size testX.db] [file size testX.db-wal] } [list [expr 3*1024] [wal_file_size 6 1024]] unset -nocomplain nFrame result foreach {nFrame result} { 0 {0 0} 1 {0 0} 2 {0 0 1 2} 3 {0 0 1 2} 4 {0 0 1 2 3 4} 5 {0 0 1 2 3 4} 6 {0 0 1 2 3 4 5 6} } { do_test wal-18.1.$nFrame { forcecopy testX.db test.db forcecopy testX.db-wal test.db-wal hexio_write test.db-wal [expr 24 + $nFrame*(24+1024) + 20] 00000000 sqlite3 db test.db execsql { SELECT * FROM t1; PRAGMA integrity_check; |
︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 | binary scan $blob $scanpattern values foreach {v1 v2} $values { set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}] set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}] } } | | | | | 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 | binary scan $blob $scanpattern values foreach {v1 v2} $values { set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}] set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}] } } forcecopy test.db testX.db foreach {tn pgsz works} { 1 128 0 2 256 0 3 512 1 4 1024 1 5 2048 1 6 4096 1 7 8192 1 8 16384 1 9 32768 1 10 65536 1 11 131072 0 11 1016 0 } { if {$::SQLITE_MAX_PAGE_SIZE < $pgsz} { set works 0 } for {set pg 1} {$pg <= 3} {incr pg} { forcecopy testX.db test.db forcedelete test.db-wal # Check that the database now exists and consists of three pages. And # that there is no associated wal file. # do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0 do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1 do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3] |
︙ | ︙ | |||
1317 1318 1319 1320 1321 1322 1323 | # connection knows that it is the last connection to disconnect from # the database, so it runs a checkpoint operation. The bug was that # the connection was not updating its private copy of the wal-index # header before doing so, meaning that it could checkpoint an old # snapshot. # do_test wal-19.1 { | | | 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 | # connection knows that it is the last connection to disconnect from # the database, so it runs a checkpoint operation. The bug was that # the connection was not updating its private copy of the wal-index # header before doing so, meaning that it could checkpoint an old # snapshot. # do_test wal-19.1 { forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db sqlite3 db2 test.db execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); |
︙ | ︙ | |||
1366 1367 1368 1369 1370 1371 1372 | # the data is present and the database is not corrupt. # # At one point, SQLite was failing to grow the mapping of the wal-index # file in step 3 and the checkpoint was corrupting the database file. # do_test wal-20.1 { catch {db close} | | | 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | # the data is present and the database is not corrupt. # # At one point, SQLite was failing to grow the mapping of the wal-index # file in step 3 and the checkpoint was corrupting the database file. # do_test wal-20.1 { catch {db close} forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(x); INSERT INTO t1 VALUES(randomblob(900)); SELECT count(*) FROM t1; } |
︙ | ︙ | |||
1472 1473 1474 1475 1476 1477 1478 | #------------------------------------------------------------------------- # Test that when 1 or more pages are recovered from a WAL file, # sqlite3_log() is invoked to report this to the user. # set walfile [file nativename [file join [pwd] test.db-wal]] catch {db close} | | | 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | #------------------------------------------------------------------------- # Test that when 1 or more pages are recovered from a WAL file, # sqlite3_log() is invoked to report this to the user. # set walfile [file nativename [file join [pwd] test.db-wal]] catch {db close} forcedelete test.db do_test wal-23.1 { 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); |
︙ | ︙ |
Changes to test/wal2.test.
︙ | ︙ | |||
160 161 162 163 164 165 166 | do_test wal2-1.$tn.2 { set ::locks } $wal_locks } db close db2 close tvfs delete | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | do_test wal2-1.$tn.2 { set ::locks } $wal_locks } db close db2 close tvfs delete forcedelete test.db test.db-wal test.db-journal #------------------------------------------------------------------------- # This test case is very similar to the previous one, except, after # the reader reads the corrupt wal-index header, but before it has # a chance to re-read it under the cover of the RECOVER lock, the # wal-index header is replaced with a valid, but out-of-date, header. # |
︙ | ︙ | |||
267 268 269 270 271 272 273 | } execsql { SELECT count(a), sum(a) FROM t1 } db2 } $res1 } db close db2 close tvfs delete | | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | } execsql { SELECT count(a), sum(a) FROM t1 } db2 } $res1 } db close db2 close tvfs delete forcedelete test.db test.db-wal test.db-journal if 0 { #------------------------------------------------------------------------- # This test case - wal2-3.* - tests the response of the library to an # SQLITE_BUSY when attempting to obtain a READ or RECOVER lock. # |
︙ | ︙ | |||
340 341 342 343 344 345 346 | execsql { SELECT count(a), sum(a) FROM t1 } } {4 10} do_test wal2-3.5 { list [info exists ::sabotage] [info exists ::locked] } {0 0} db close tvfs delete | | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | execsql { SELECT count(a), sum(a) FROM t1 } } {4 10} do_test wal2-3.5 { list [info exists ::sabotage] [info exists ::locked] } {0 0} db close tvfs delete forcedelete test.db test.db-wal test.db-journal } #------------------------------------------------------------------------- # Test that a database connection using a VFS that does not support the # xShmXXX interfaces cannot open a WAL database. # |
︙ | ︙ | |||
437 438 439 440 441 442 443 | # wal2-6.5.*: # # wal2-6.6.*: Check that if the xShmLock() to reaquire a WAL read-lock when # exiting exclusive mode fails (i.e. SQLITE_IOERR), then the # connection silently remains in exclusive mode. # do_test wal2-6.1.1 { | | | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | # wal2-6.5.*: # # wal2-6.6.*: Check that if the xShmLock() to reaquire a WAL read-lock when # exiting exclusive mode fails (i.e. SQLITE_IOERR), then the # connection silently remains in exclusive mode. # do_test wal2-6.1.1 { forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { Pragma Journal_Mode = Wal; } } {wal} do_test wal2-6.1.2 { execsql { PRAGMA lock_status } |
︙ | ︙ | |||
480 481 482 483 484 485 486 | INSERT INTO t1 VALUES(3, 4); PRAGMA lock_status; } } {main shared temp closed} db close do_test wal2-6.2.1 { | | | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | INSERT INTO t1 VALUES(3, 4); PRAGMA lock_status; } } {main shared temp closed} db close do_test wal2-6.2.1 { forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { Pragma Locking_Mode = Exclusive; Pragma Journal_Mode = Wal; Pragma Lock_Status; } } {exclusive wal main exclusive temp closed} |
︙ | ︙ | |||
548 549 550 551 552 553 554 | SELECT * FROM t1; pragma lock_status; } } {1 2 3 4 5 6 main shared temp closed} db close do_test wal2-6.3.1 { | | | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | SELECT * FROM t1; pragma lock_status; } } {1 2 3 4 5 6 main shared temp closed} db close do_test wal2-6.3.1 { forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { PRAGMA journal_mode = WAL; PRAGMA locking_mode = exclusive; BEGIN; CREATE TABLE t1(x); INSERT INTO t1 VALUES('Chico'); |
︙ | ︙ | |||
593 594 595 596 597 598 599 | # This test - wal2-6.4.* - uses a single database connection and the # [testvfs] instrumentation to test that xShmLock() is being called # as expected when a WAL database is used with locking_mode=exclusive. # do_test wal2-6.4.1 { | | | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 | # This test - wal2-6.4.* - uses a single database connection and the # [testvfs] instrumentation to test that xShmLock() is being called # as expected when a WAL database is used with locking_mode=exclusive. # do_test wal2-6.4.1 { forcedelete test.db test.db-wal test.db-journal proc tvfs_cb {method args} { set ::shm_file [lindex $args 0] if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] } return "SQLITE_OK" } testvfs tvfs tvfs script tvfs_cb |
︙ | ︙ | |||
789 790 791 792 793 794 795 | db2 close T delete #------------------------------------------------------------------------- # Test a theory about the checksum algorithm. Theory was false and this # test did not provoke a bug. # | | | | | | 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 | db2 close T delete #------------------------------------------------------------------------- # Test a theory about the checksum algorithm. Theory was false and this # test did not provoke a bug. # forcedelete test.db test.db-wal test.db-journal do_test wal2-7.1.1 { sqlite3 db test.db execsql { PRAGMA page_size = 4096; PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); } file size test.db } {4096} do_test wal2-7.1.2 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal hexio_write test2.db-wal 48 FF } {1} do_test wal2-7.1.3 { sqlite3 db2 test2.db execsql { PRAGMA wal_checkpoint } db2 execsql { SELECT * FROM sqlite_master } db2 } {} db close db2 close forcedelete test.db test.db-wal test.db-journal do_test wal2-8.1.2 { sqlite3 db test.db execsql { PRAGMA auto_vacuum=OFF; PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; CREATE TABLE t1(x); |
︙ | ︙ | |||
867 868 869 870 871 872 873 | # # proc get_name {method args} { set ::filename [lindex $args 0] ; tvfs filter {} } testvfs tvfs tvfs script get_name tvfs filter xShmOpen | | | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 | # # proc get_name {method args} { set ::filename [lindex $args 0] ; tvfs filter {} } testvfs tvfs tvfs script get_name tvfs filter xShmOpen forcedelete test.db test.db-wal test.db-journal do_test wal2-9.1 { sqlite3 db test.db -vfs tvfs execsql { PRAGMA journal_mode = WAL; CREATE TABLE x(y); INSERT INTO x VALUES('Barton'); INSERT INTO x VALUES('Deakin'); |
︙ | ︙ |
Changes to test/wal3.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 | do_test wal3-1.$i.4 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close # Check that the file-system in its current state can be recovered. # | | | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | do_test wal3-1.$i.4 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close # Check that the file-system in its current state can be recovered. # forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal forcedelete test2.db-journal sqlite3 db2 test2.db do_test wal3-1.$i.5 { execsql { SELECT count(*) FROM t1 } db2 } 4018 do_test wal3-1.$i.6 { execsql { SELECT x FROM t1 WHERE rowid = $i } } $str |
︙ | ︙ | |||
204 205 206 207 208 209 210 | } { proc sync_counter {args} { foreach {method filename id flags} $args break lappend ::syncs [file tail $filename] $flags } do_test wal3-3.$tn { | | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | } { 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 execsql "PRAGMA synchronous = $syncmode" |
︙ | ︙ | |||
407 408 409 410 411 412 413 | # + The attempt to obtain the lock on aReadMark[0] fails with SQLITE_BUSY. # This can happen if a checkpoint is ongoing. In this case also simply # obtain a different read-lock. # catch {db close} testvfs T -default 1 do_test wal3-6.1.1 { | | | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | # + The attempt to obtain the lock on aReadMark[0] fails with SQLITE_BUSY. # This can happen if a checkpoint is ongoing. In this case also simply # obtain a different read-lock. # catch {db close} testvfs T -default 1 do_test wal3-6.1.1 { forcedelete test.db test.db-journal test.db wal sqlite3 db test.db execsql { PRAGMA auto_vacuum = off } execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('o', 't'); INSERT INTO t1 VALUES('t', 'f'); |
︙ | ︙ | |||
488 489 490 491 492 493 494 | } {1} db3 close db2 close db close do_test wal3-6.2.1 { | | | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | } {1} db3 close db2 close db close do_test wal3-6.2.1 { forcedelete test.db test.db-journal test.db wal sqlite3 db test.db sqlite3 db2 test.db execsql { PRAGMA auto_vacuum = off } execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES('h', 'h'); |
︙ | ︙ | |||
554 555 556 557 558 559 560 | # # + The value in the aReadMark[x] slot has been modified since it was # read. # catch {db close} testvfs T -default 1 do_test wal3-7.1.1 { | | | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | # # + The value in the aReadMark[x] slot has been modified since it was # read. # catch {db close} testvfs T -default 1 do_test wal3-7.1.1 { forcedelete test.db test.db-journal test.db wal sqlite3 db test.db execsql { PRAGMA journal_mode = WAL; CREATE TABLE blue(red PRIMARY KEY, green); } } {wal} |
︙ | ︙ | |||
611 612 613 614 615 616 617 | db close db2 close T delete #------------------------------------------------------------------------- # do_test wal3-8.1 { | | | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | db close db2 close T delete #------------------------------------------------------------------------- # do_test wal3-8.1 { forcedelete test.db test.db-journal test.db wal sqlite3 db test.db sqlite3 db2 test.db execsql { PRAGMA auto_vacuum = off; PRAGMA journal_mode = WAL; CREATE TABLE b(c); INSERT INTO b VALUES('Tehran'); |
︙ | ︙ | |||
703 704 705 706 707 708 709 | # # This test case verifies that if an exclusive lock cannot be obtained # on any aReadMark[] slot (because there are already several readers), # the client takes a shared-lock on a slot without modifying the value # and continues. # set nConn 50 | | | | 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 | # # This test case verifies that if an exclusive lock cannot be obtained # on any aReadMark[] slot (because there are already several readers), # the client takes a shared-lock on a slot without modifying the value # and continues. # set nConn 50 if { [string match *BSD $tcl_platform(os)] } { set nConn 25 } do_test wal3-9.0 { forcedelete test.db test.db-journal test.db wal sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; CREATE TABLE whoami(x); INSERT INTO whoami VALUES('nobody'); } |
︙ | ︙ | |||
780 781 782 783 784 785 786 | do_test wal3-10.$tn.2 { sql2 {PRAGMA integrity_check} } {ok} } finish_test | < | 780 781 782 783 784 785 786 | do_test wal3-10.$tn.2 { sql2 {PRAGMA integrity_check} } {ok} } finish_test |
Changes to test/wal4.test.
︙ | ︙ | |||
27 28 29 30 31 32 33 | } } {wal 1 2} do_test wal4-1.2 { # Save a copy of the file-system containing the wal and wal-index files # only (no database file). faultsim_save_and_close | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | } } {wal 1 2} do_test wal4-1.2 { # Save a copy of the file-system containing the wal and wal-index files # only (no database file). faultsim_save_and_close forcedelete sv_test.db } {} do_test wal4-1.3 { faultsim_restore_and_reopen catchsql { SELECT * FROM t1 } } {1 {no such table: t1}} |
︙ | ︙ |
Changes to test/wal5.test.
︙ | ︙ | |||
231 232 233 234 235 236 237 | } {} do_test 2.3.$tn.2 { file_page_counts } {1 5 1 5} do_test 2.3.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2} do_test 2.3.$tn.4 { sql1 { INSERT INTO t1 VALUES(3, 4) } } {} do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {} do_test 2.3.$tn.6 { file_page_counts } {1 7 1 7} do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 7 5} | < < < < | < < < | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | } {} do_test 2.3.$tn.2 { file_page_counts } {1 5 1 5} do_test 2.3.$tn.3 { sql2 { BEGIN; SELECT * FROM t1 } } {1 2} do_test 2.3.$tn.4 { sql1 { INSERT INTO t1 VALUES(3, 4) } } {} do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {} do_test 2.3.$tn.6 { file_page_counts } {1 7 1 7} do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 7 5} do_test 2.3.$tn.8 { file_page_counts } {2 7 2 7} } # Check that checkpoints block on the correct locks. And respond correctly # if they cannot obtain those locks. There are three locks that a checkpoint # may block on (in the following order): # # 1. The writer lock: FULL and RESTART checkpoints block until any writer |
︙ | ︙ | |||
346 347 348 349 350 351 352 | do_test 3.$tn.6 { code3 { do_wal_checkpoint db3 } } {0 0 0} } } finish_test | < | 339 340 341 342 343 344 345 | do_test 3.$tn.6 { code3 { do_wal_checkpoint db3 } } {0 0 0} } } finish_test |
Changes to test/wal6.test.
︙ | ︙ | |||
39 40 41 42 43 44 45 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1,2); SELECT * FROM t1; } } {1 2} # Under Windows, you'll get an error trying to delete | | < < < < < < < < | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1,2); SELECT * FROM t1; } } {1 2} # Under Windows, you'll get an error trying to delete # a file this is already opened. Close the first connection # so the other tests work. if {$tcl_platform(platform)=="windows"} { if {$jmode=="persist" || $jmode=="truncate"} { db close } } do_test wal6-1.2.$jmode { sqlite3 db2 test.db execsql { PRAGMA journal_mode=WAL; |
︙ | ︙ | |||
83 84 85 86 87 88 89 | db close db2 close forcedelete test.db } finish_test | < | 75 76 77 78 79 80 81 | db close db2 close forcedelete test.db } finish_test |
Changes to test/walbak.test.
︙ | ︙ | |||
44 45 46 47 48 49 50 | BEGIN; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES('I', 'one'); COMMIT; } } {wal} do_test walbak-1.1 { | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | BEGIN; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES('I', 'one'); COMMIT; } } {wal} do_test walbak-1.1 { forcedelete bak.db bak.db-journal bak.db-wal db backup bak.db file size bak.db } [expr 3*1024] do_test walbak-1.2 { sqlite3 db2 bak.db execsql { SELECT * FROM t1; |
︙ | ︙ | |||
102 103 104 105 106 107 108 | proc sig {{db db}} { $db eval { PRAGMA integrity_check; SELECT md5sum(a, b) FROM t1; } } db close | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | proc sig {{db db}} { $db eval { PRAGMA integrity_check; SELECT md5sum(a, b) FROM t1; } } db close delete_file test.db sqlite3 db test.db do_test walbak-2.1 { execsql { PRAGMA journal_mode = WAL } execsql { CREATE TABLE t1(a PRIMARY KEY, b); BEGIN; INSERT INTO t1 VALUES(randomblob(500), randomblob(500)); |
︙ | ︙ | |||
232 233 234 235 236 237 238 | PRAGMA page_size = 2048; PRAGMA journal_mode = PERSIST; CREATE TABLE xx(x); } } } { | | | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | PRAGMA page_size = 2048; PRAGMA journal_mode = PERSIST; CREATE TABLE xx(x); } } } { foreach f [glob -nocomplain test.db*] { forcedelete $f } eval $setup do_test walbak-3.$tn.1 { execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); |
︙ | ︙ |
Changes to test/walcksum.test.
︙ | ︙ | |||
149 150 151 152 153 154 155 | if {$::tcl_platform(byteOrder) == "littleEndian"} { set native "little" } foreach endian {big little} { # Create a database. Leave some data in the log file. # do_test walcksum-1.$endian.1 { catch { db close } | | | | | 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 | if {$::tcl_platform(byteOrder) == "littleEndian"} { set native "little" } foreach endian {big little} { # Create a database. Leave some data in the log file. # do_test walcksum-1.$endian.1 { catch { db close } forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { PRAGMA page_size = 1024; PRAGMA auto_vacuum = 0; PRAGMA synchronous = NORMAL; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t1 VALUES(3, 'three'); INSERT INTO t1 VALUES(5, 'five'); PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(8, 'eight'); INSERT INTO t1 VALUES(13, 'thirteen'); INSERT INTO t1 VALUES(21, 'twentyone'); } forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal db close list [file size test2.db] [file size test2.db-wal] } [list [expr 1024*3] [wal_file_size 6 1024]] # Verify that the checksums are valid for all frames and that they # are calculated by interpreting data in native byte-order. |
︙ | ︙ | |||
195 196 197 198 199 200 201 | for {set f 1} {$f <= 6} {incr f} { do_test walcksum-1.$endian.3.$f { log_checksum_write test2.db-wal $f $endian log_checksum_verify test2.db-wal $f $endian } {1} } do_test walcksum-1.$endian.4.1 { | | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | for {set f 1} {$f <= 6} {incr f} { do_test walcksum-1.$endian.3.$f { log_checksum_write test2.db-wal $f $endian log_checksum_verify test2.db-wal $f $endian } {1} } do_test walcksum-1.$endian.4.1 { forcecopy test2.db test.db forcecopy test2.db-wal test.db-wal sqlite3 db test.db execsql { SELECT a FROM t1 } } {1 2 3 5 8 13 21} # Following recovery, any frames written to the log should use the same # endianness as the existing frames. Check that this is the case. # |
︙ | ︙ | |||
244 245 246 247 248 249 250 | log_checksum_verify test.db-wal $f $endian } {1} } # Now that both the recoverer and non-recoverer have added frames to the # log file, check that it can still be recovered. # | | | | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | log_checksum_verify test.db-wal $f $endian } {1} } # Now that both the recoverer and non-recoverer have added frames to the # log file, check that it can still be recovered. # forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal do_test walcksum-1.$endian.7.11 { sqlite3 db3 test2.db execsql { PRAGMA integrity_check; SELECT a FROM t1; } db3 } {ok 1 2 3 5 8 13 21 34 55} |
︙ | ︙ | |||
290 291 292 293 294 295 296 | #------------------------------------------------------------------------- # Test case walcksum-2.* tests that if a statement transaction is rolled # back after frames are written to the WAL, and then (after writing some # more) the outer transaction is committed, the WAL file is still correctly # formatted (and can be recovered by a second process if required). # do_test walcksum-2.1 { | | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | #------------------------------------------------------------------------- # Test case walcksum-2.* tests that if a statement transaction is rolled # back after frames are written to the WAL, and then (after writing some # more) the outer transaction is committed, the WAL file is still correctly # formatted (and can be recovered by a second process if required). # do_test walcksum-2.1 { forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { PRAGMA synchronous = NORMAL; PRAGMA page_size = 1024; PRAGMA journal_mode = WAL; PRAGMA cache_size = 10; CREATE TABLE t1(x PRIMARY KEY); |
︙ | ︙ | |||
318 319 320 321 322 323 324 | INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 32 */ INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 64 */ INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 128 */ INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 256 */ COMMIT; } | | | | | | | | | 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 | INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 32 */ INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 64 */ INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 128 */ INSERT INTO t1 SELECT randomblob(800) FROM t1; /* 256 */ COMMIT; } forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db execsql { PRAGMA integrity_check; SELECT count(*) FROM t1; } db2 } {ok 256} catch { db close } catch { db2 close } #------------------------------------------------------------------------- # Test case walcksum-3.* tests that the checksum calculation detects single # byte changes to frame or frame-header data and considers the frame # invalid as a result. # do_test walcksum-3.1 { forcedelete test.db test.db-wal test.db-journal sqlite3 db test.db execsql { PRAGMA synchronous = NORMAL; PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, randomblob(300)); INSERT INTO t1 VALUES(2, randomblob(300)); PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(3, randomblob(300)); } file size test.db-wal } [wal_file_size 1 1024] do_test walcksum-3.2 { forcecopy test.db-wal test2.db-wal forcecopy test.db test2.db sqlite3 db2 test2.db execsql { SELECT a FROM t1 } db2 } {1 2 3} db2 close forcecopy test.db test2.db foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} { do_test walcksum-3.3.$incr { set FAIL 0 for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} { forcecopy test.db-wal test2.db-wal set fd [open test2.db-wal r+] fconfigure $fd -encoding binary fconfigure $fd -translation binary seek $fd $iOff binary scan [read $fd 1] c x seek $fd $iOff |
︙ | ︙ |
Changes to test/walcrash.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 | set seed 0 set REPEATS 100 # walcrash-1.* # for {set i 1} {$i < $REPEATS} {incr i} { | | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | set seed 0 set REPEATS 100 # walcrash-1.* # for {set i 1} {$i < $REPEATS} {incr i} { forcedelete test.db test.db-wal do_test walcrash-1.$i.1 { crashsql -delay 4 -file test.db-wal -seed [incr seed] { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 1); INSERT INTO t1 VALUES(2, 3); INSERT INTO t1 VALUES(3, 6); |
︙ | ︙ | |||
70 71 72 73 74 75 76 | } {wal} db close } # walcrash-2.* # for {set i 1} {$i < $REPEATS} {incr i} { | | | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | } {wal} db close } # walcrash-2.* # for {set i 1} {$i < $REPEATS} {incr i} { forcedelete test.db test.db-wal do_test walcrash-2.$i.1 { crashsql -delay 4 -file test.db-wal -seed [incr seed] { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 9); |
︙ | ︙ | |||
107 108 109 110 111 112 113 | } {wal} db close } # walcrash-3.* # # for {set i 1} {$i < $REPEATS} {incr i} { | | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | } {wal} db close } # walcrash-3.* # # for {set i 1} {$i < $REPEATS} {incr i} { # forcedelete test.db test.db-wal # forcedelete test2.db test2.db-wal # # do_test walcrash-3.$i.1 { # crashsql -delay 2 -file test2.db-wal -seed [incr seed] { # PRAGMA journal_mode = WAL; # ATTACH 'test2.db' AS aux; # CREATE TABLE t1(a PRIMARY KEY, b); # CREATE TABLE aux.t2(a PRIMARY KEY, b); |
︙ | ︙ | |||
139 140 141 142 143 144 145 | # # db close # } # walcrash-4.* # for {set i 1} {$i < $REPEATS} {incr i} { | | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | # # db close # } # walcrash-4.* # for {set i 1} {$i < $REPEATS} {incr i} { forcedelete test.db test.db-wal forcedelete test2.db test2.db-wal do_test walcrash-4.$i.1 { crashsql -delay 3 -file test.db-wal -seed [incr seed] -blocksize 4096 { PRAGMA journal_mode = WAL; PRAGMA page_size = 1024; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 2); |
︙ | ︙ | |||
167 168 169 170 171 172 173 | db close } # walcrash-5.* # for {set i 1} {$i < $REPEATS} {incr i} { | | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | db close } # walcrash-5.* # for {set i 1} {$i < $REPEATS} {incr i} { forcedelete test.db test.db-wal forcedelete test2.db test2.db-wal do_test walcrash-5.$i.1 { crashsql -delay 11 -file test.db-wal -seed [incr seed] -blocksize 4096 { PRAGMA journal_mode = WAL; PRAGMA page_size = 1024; BEGIN; CREATE TABLE t1(x PRIMARY KEY); |
︙ | ︙ | |||
208 209 210 211 212 213 214 | db close } # walcrash-6.* # for {set i 1} {$i < $REPEATS} {incr i} { | | | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | db close } # walcrash-6.* # for {set i 1} {$i < $REPEATS} {incr i} { forcedelete test.db test.db-wal forcedelete test2.db test2.db-wal do_test walcrash-6.$i.1 { crashsql -delay 12 -file test.db-wal -seed [incr seed] -blocksize 512 { PRAGMA journal_mode = WAL; PRAGMA page_size = 1024; BEGIN; CREATE TABLE t1(x PRIMARY KEY); |
︙ | ︙ | |||
258 259 260 261 262 263 264 | # # (a) that the database is a WAL database, and # (b) the database page-size # # based on the log file. # for {set i 1} {$i < $REPEATS} {incr i} { | | | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | # # (a) that the database is a WAL database, and # (b) the database page-size # # based on the log file. # for {set i 1} {$i < $REPEATS} {incr i} { forcedelete test.db test.db-wal # Select a page-size for this test. # set pgsz [lindex {512 1024 2048 4096 8192 16384} [expr $i%6]] do_test walcrash-7.$i.1 { crashsql -delay 3 -file test.db -seed [incr seed] -blocksize 512 " |
︙ | ︙ |
Changes to test/walfault.test.
︙ | ︙ | |||
461 462 463 464 465 466 467 | BEGIN; CREATE TABLE abc(a PRIMARY KEY); INSERT INTO abc VALUES(randomblob(1500)); INSERT INTO abc VALUES(randomblob(1500)); COMMIT; } faultsim_save_and_close | | | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | BEGIN; CREATE TABLE abc(a PRIMARY KEY); INSERT INTO abc VALUES(randomblob(1500)); INSERT INTO abc VALUES(randomblob(1500)); COMMIT; } faultsim_save_and_close delete_file sv_test.db-shm } {} do_faultsim_test walfault-13.1 -prep { faultsim_restore_and_reopen } -body { db eval { PRAGMA locking_mode = exclusive } db eval { SELECT count(*) FROM abc } |
︙ | ︙ |
Changes to test/walmode.test.
︙ | ︙ | |||
291 292 293 294 295 296 297 | #------------------------------------------------------------------------- # 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 { | | | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | #------------------------------------------------------------------------- # 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} { |
︙ | ︙ |
Changes to test/walnoshm.test.
︙ | ︙ | |||
83 84 85 86 87 88 89 | PRAGMA locking_mode = exclusive; PRAGMA journal_mode = WAL; INSERT INTO t2 VALUES('e', 'f'); INSERT INTO t2 VALUES('g', 'h'); } {exclusive wal} do_test 2.1.3 { | | | | | | 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 | PRAGMA locking_mode = exclusive; PRAGMA journal_mode = WAL; INSERT INTO t2 VALUES('e', 'f'); INSERT INTO t2 VALUES('g', 'h'); } {exclusive wal} do_test 2.1.3 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db2 test2.db catchsql { SELECT * FROM t2 } db2 } {1 {unable to open database file}} do_test 2.1.4 { catchsql { PRAGMA journal_mode = delete } db2 } {1 {unable to open database file}} do_test 2.1.5 { execsql { PRAGMA locking_mode = exclusive; PRAGMA journal_mode = delete; SELECT * FROM t2; } db2 } {exclusive delete a b c d e f g h} do_test 2.2.1 { forcecopy test.db test2.db forcecopy test.db-wal test2.db-wal sqlite3 db3 test2.db -vfs tvfsshm sqlite3 db2 test2.db execsql { SELECT * FROM t2 } db3 } {a b c d e f g h} do_test 2.2.2 { execsql { PRAGMA locking_mode = exclusive } db2 |
︙ | ︙ |
Added test/walpersist.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 | # 2011 July 26 # # 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 contains tests for using WAL with persistent WAL file mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl set ::testprefix walpersist 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 test.db-shm } {1} do_test walpersist-1.2 { db close list [file exists test.db] [file exists test.db-wal] [file exists test.db-shm] } {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 test.db-shm] } {1 1 1} do_test walpersist-1.5 { 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 test.db-shm] } {1 1 1} finish_test |
Changes to test/walslow.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 | set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } forcedelete test.db test.db-wal sqlite3 db test.db execsql { PRAGMA journal_mode = wal } } db close save_prng_state for {set seed 1} {$seed<10} {incr seed} { |
︙ | ︙ | |||
49 50 51 52 53 54 55 | do_test walslow-1.seed=$seed.$iTest.2 { execsql "PRAGMA wal_checkpoint;" execsql { PRAGMA integrity_check } } {ok} do_test walslow-1.seed=$seed.$iTest.3 { | | | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | do_test walslow-1.seed=$seed.$iTest.2 { execsql "PRAGMA wal_checkpoint;" execsql { PRAGMA integrity_check } } {ok} do_test walslow-1.seed=$seed.$iTest.3 { forcedelete testX.db testX.db-wal copy_file test.db testX.db copy_file test.db-wal testX.db-wal sqlite3 db2 testX.db execsql { PRAGMA journal_mode = WAL } db2 execsql { PRAGMA integrity_check } db2 } {ok} do_test walslow-1.seed=$seed.$iTest.4 { |
︙ | ︙ |
Changes to test/walthread.test.
︙ | ︙ | |||
125 126 127 128 129 130 131 | puts "Skipping $P(testname)" return } puts "Running $P(testname) for $P(seconds) seconds..." catch { db close } | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | puts "Skipping $P(testname)" return } puts "Running $P(testname) for $P(seconds) seconds..." catch { db close } forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db eval $P(init) catch { db close } foreach T $P(threads) { set name [lindex $T 0] |
︙ | ︙ | |||
504 505 506 507 508 509 510 | INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 8192 */ INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 16384 */ INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 32768 */ INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 65536 */ COMMIT; } | | | | | | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 8192 */ INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 16384 */ INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 32768 */ INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 65536 */ COMMIT; } forcecopy test.db-wal bak.db-wal forcecopy test.db bak.db db close forcecopy bak.db-wal test.db-wal forcecopy bak.db test.db if {[file size test.db-wal] < [log_file_size [expr 64*1024] 1024]} { error "Somehow failed to create a large log file" } puts "Database with large log file recovered. Now running clients..." } -thread T 5 { db eval { SELECT count(*) FROM t1 } } unset -nocomplain seconds finish_test |
Changes to test/win32lock.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | if {$tcl_platform(platform)!="windows"} return set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix win32lock do_test win32lock-1.1 { db eval { PRAGMA cache_size=10; CREATE TABLE t1(x,y); INSERT INTO t1 VALUES(1,randomblob(100000)); INSERT INTO t1 VALUES(2,randomblob(50000)); INSERT INTO t1 VALUES(3,randomblob(25000)); INSERT INTO t1 VALUES(4,randomblob(12500)); SELECT x, length(y) FROM t1 ORDER BY rowid; } } {1 100000 2 50000 3 25000 4 12500} unset -nocomplain delay1 rc msg | > > > > > > > > < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > | > > > > | > > > > > > | > > | 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 | if {$tcl_platform(platform)!="windows"} return set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix win32lock db close sqlite3_shutdown test_sqlite3_log xLog proc xLog {error_code msg} { lappend ::log $msg } sqlite3 db test.db do_test win32lock-1.1 { db eval { PRAGMA cache_size=10; CREATE TABLE t1(x,y); INSERT INTO t1 VALUES(1,randomblob(100000)); INSERT INTO t1 VALUES(2,randomblob(50000)); INSERT INTO t1 VALUES(3,randomblob(25000)); INSERT INTO t1 VALUES(4,randomblob(12500)); SELECT x, length(y) FROM t1 ORDER BY rowid; } } {1 100000 2 50000 3 25000 4 12500} unset -nocomplain delay1 rc msg set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000] set win32_lock_ok [list] set win32_lock_error [list] set delay1 25 while {1} { lock_win32_file test.db 0 $::delay1 set ::log {} set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg] if {$rc} { lappend win32_lock_error $::delay1 do_test win32lock-1.2-$delay1-error { set ::msg } {disk I/O error} } else { lappend win32_lock_ok $::delay1 do_test win32lock-1.2-$delay1-ok { set ::msg } {1 100000 2 50000 3 25000 4 12500} if {[info exists ::log] && $::log!=""} { do_test win32lock-1.2-$delay1-log1 { regsub {\d+} $::log # x set x } {{delayed #ms for lock/sharing conflict}} } } if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break incr delay1 25 sqlite3_sleep 10 } do_test win32lock-2.0 { file_control_win32_av_retry db -1 -1 } {0 10 25} do_test win32lock-2.1 { file_control_win32_av_retry db 1 1 } {0 1 1} # # NOTE: It is known that the win32lock-2.2-* tests may fail if the system is # experiencing heavy load (i.e. they are very timing sensitive). This is # primarily due to the AV retry delay being set to 1 millisecond in the # win32lock-2.1 test (above). While it is important to test this corner # case for the AV retry logic, a failure of this test should probably not # be interpreted as a bug in SQLite or these test cases. # set win32_lock_ok [list] set win32_lock_error [list] set delay1 1 while {1} { lock_win32_file test.db 0 $::delay1 set ::log {} set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg] if {$rc} { lappend win32_lock_error $::delay1 do_test win32lock-2.2-$delay1-error { set ::msg } {disk I/O error} } else { lappend win32_lock_ok $::delay1 do_test win32lock-2.2-$delay1-ok { set ::msg } {1 100000 2 50000 3 25000 4 12500} if {[info exists ::log] && $::log!=""} { do_test win32lock-2.2-$delay1-log1 { regsub {\d+} $::log # x set x } {{delayed #ms for lock/sharing conflict}} } } if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break incr delay1 1 sqlite3_sleep 10 } file_control_win32_av_retry db 10 25 sqlite3_test_control_pending_byte $old_pending_byte sqlite3_shutdown test_sqlite3_log sqlite3_initialize finish_test |
Added tool/extract.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 | /* ** Extract a range of bytes from a file. ** ** Usage: ** ** extract FILENAME OFFSET AMOUNT ** ** The bytes are written to standard output. */ #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv){ FILE *f; char *zBuf; int ofst; int n; size_t got; if( argc!=4 ){ fprintf(stderr, "Usage: %s FILENAME OFFSET AMOUNT\n", *argv); return 1; } f = fopen(argv[1], "rb"); if( f==0 ){ fprintf(stderr, "cannot open \"%s\"\n", argv[1]); return 1; } ofst = atoi(argv[2]); n = atoi(argv[3]); zBuf = malloc( n ); if( zBuf==0 ){ fprintf(stderr, "out of memory\n"); return 1; } fseek(f, ofst, SEEK_SET); got = fread(zBuf, 1, n, f); fclose(f); if( got<n ){ fprintf(stderr, "got only %d of %d bytes\n", got, n); return 1; }else{ fwrite(zBuf, 1, n, stdout); } return 0; } |
Added tool/offsets.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 | /* ** This program searches an SQLite database file for the lengths and ** offsets for all TEXT or BLOB entries for a particular column of a ** particular table. The rowid, size and offset for the column are ** written to standard output. There are three arguments, which are the ** name of the database file, the table, and the column. */ #include "sqlite3.h" #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> typedef unsigned char u8; typedef struct GState GState; #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Global state information for this program. */ struct GState { char *zErr; /* Error message text */ FILE *f; /* Open database file */ int szPg; /* Page size for the database file */ int iRoot; /* Root page of the table */ int iCol; /* Column number for the column */ int pgno; /* Current page number */ u8 *aPage; /* Current page content */ u8 *aStack[20]; /* Page stack */ int aPgno[20]; /* Page number stack */ int nStack; /* Depth of stack */ int bTrace; /* True for tracing output */ }; /* ** Write an error. */ static void ofstError(GState *p, const char *zFormat, ...){ va_list ap; sqlite3_free(p->zErr); va_start(ap, zFormat); p->zErr = sqlite3_vmprintf(zFormat, ap); va_end(ap); } /* ** Write a trace message */ static void ofstTrace(GState *p, const char *zFormat, ...){ va_list ap; if( p->bTrace ){ va_start(ap, zFormat); vprintf(zFormat, ap); va_end(ap); } } /* ** Find the root page of the table and the column number of the column. */ static void ofstRootAndColumn( GState *p, /* Global state */ const char *zFile, /* Name of the database file */ const char *zTable, /* Name of the table */ const char *zColumn /* Name of the column */ ){ sqlite3 *db = 0; sqlite3_stmt *pStmt = 0; char *zSql = 0; int rc; if( p->zErr ) return; rc = sqlite3_open(zFile, &db); if( rc ){ ofstError(p, "cannot open database file \"%s\"", zFile); goto rootAndColumn_exit; } zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master WHERE name=%Q", zTable); rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql); sqlite3_free(zSql); if( p->zErr ) goto rootAndColumn_exit; if( sqlite3_step(pStmt)!=SQLITE_ROW ){ ofstError(p, "cannot find table [%s]\n", zTable); sqlite3_finalize(pStmt); goto rootAndColumn_exit; } p->iRoot = sqlite3_column_int(pStmt , 0); sqlite3_finalize(pStmt); p->iCol = -1; zSql = sqlite3_mprintf("PRAGMA table_info(%Q)", zTable); rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc ) ofstError(p, "%s: [%s}", sqlite3_errmsg(db), zSql); sqlite3_free(zSql); if( p->zErr ) goto rootAndColumn_exit; while( sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zCol = sqlite3_column_text(pStmt, 1); if( strlen(zCol)==strlen(zColumn) && sqlite3_strnicmp(zCol, zColumn, strlen(zCol))==0 ){ p->iCol = sqlite3_column_int(pStmt, 0); break; } } sqlite3_finalize(pStmt); if( p->iCol<0 ){ ofstError(p, "no such column: %s.%s", zTable, zColumn); goto rootAndColumn_exit; } zSql = sqlite3_mprintf("PRAGMA page_size"); rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc ) ofstError(p, "%s: [%s]", sqlite3_errmsg(db), zSql); sqlite3_free(zSql); if( p->zErr ) goto rootAndColumn_exit; if( sqlite3_step(pStmt)!=SQLITE_ROW ){ ofstError(p, "cannot find page size"); }else{ p->szPg = sqlite3_column_int(pStmt, 0); } sqlite3_finalize(pStmt); rootAndColumn_exit: sqlite3_close(db); return; } /* ** Pop a page from the stack */ static void ofstPopPage(GState *p){ if( p->nStack<=0 ) return; p->nStack--; sqlite3_free(p->aStack[p->nStack]); p->pgno = p->aPgno[p->nStack-1]; p->aPage = p->aStack[p->nStack-1]; } /* ** Push a new page onto the stack. */ static void ofstPushPage(GState *p, int pgno){ u8 *pPage; size_t got; if( p->zErr ) return; if( p->nStack >= ArraySize(p->aStack) ){ ofstError(p, "page stack overflow"); return; } p->aPgno[p->nStack] = pgno; p->aStack[p->nStack] = pPage = sqlite3_malloc( p->szPg ); if( pPage==0 ){ fprintf(stderr, "out of memory\n"); exit(1); } p->nStack++; p->aPage = pPage; p->pgno = pgno; fseek(p->f, (pgno-1)*p->szPg, SEEK_SET); got = fread(pPage, 1, p->szPg, p->f); if( got!=p->szPg ){ ofstError(p, "unable to read page %d", pgno); ofstPopPage(p); } } /* Read a two-byte integer at the given offset into the current page */ static int ofst2byte(GState *p, int ofst){ int x = p->aPage[ofst]; return (x<<8) + p->aPage[ofst+1]; } /* Read a four-byte integer at the given offset into the current page */ static int ofst4byte(GState *p, int ofst){ int x = p->aPage[ofst]; x = (x<<8) + p->aPage[ofst+1]; x = (x<<8) + p->aPage[ofst+2]; x = (x<<8) + p->aPage[ofst+3]; return x; } /* Read a variable-length integer. Update the offset */ static sqlite3_int64 ofstVarint(GState *p, int *pOfst){ sqlite3_int64 x = 0; u8 *a = &p->aPage[*pOfst]; int n = 0; while( n<8 && (a[0] & 0x80)!=0 ){ x = (x<<7) + (a[0] & 0x7f); n++; a++; } if( n==8 ){ x = (x<<8) + a[0]; }else{ x = (x<<7) + a[0]; } *pOfst += (n+1); return x; } /* Return the absolute offset into a file for the given offset ** into the current page */ static int ofstInFile(GState *p, int ofst){ return p->szPg*(p->pgno-1) + ofst; } /* Return the size (in bytes) of the data corresponding to the ** given serial code */ static int ofstSerialSize(int scode){ if( scode<5 ) return scode; if( scode==5 ) return 6; if( scode<8 ) return 8; if( scode<12 ) return 0; return (scode-12)/2; } /* Forward reference */ static void ofstWalkPage(GState*, int); /* Walk an interior btree page */ static void ofstWalkInteriorPage(GState *p){ int nCell; int i; int ofst; int iChild; nCell = ofst2byte(p, 3); for(i=0; i<nCell; i++){ ofst = ofst2byte(p, 12+i*2); iChild = ofst4byte(p, ofst); ofstWalkPage(p, iChild); if( p->zErr ) return; } ofstWalkPage(p, ofst4byte(p, 8)); } /* Walk a leaf btree page */ static void ofstWalkLeafPage(GState *p){ int nCell; int i; int ofst; int nPayload; sqlite3_int64 rowid; int nHdr; int j; int scode; int sz; int dataOfst; char zMsg[200]; nCell = ofst2byte(p, 3); for(i=0; i<nCell; i++){ ofst = ofst2byte(p, 8+i*2); nPayload = ofstVarint(p, &ofst); rowid = ofstVarint(p, &ofst); if( nPayload > p->szPg-35 ){ sqlite3_snprintf(sizeof(zMsg), zMsg, "# overflow rowid %lld", rowid); printf("%s\n", zMsg); continue; } dataOfst = ofst; nHdr = ofstVarint(p, &ofst); dataOfst += nHdr; for(j=0; j<p->iCol; j++){ scode = ofstVarint(p, &ofst); dataOfst += ofstSerialSize(scode); } scode = ofstVarint(p, &ofst); sz = ofstSerialSize(scode); sqlite3_snprintf(sizeof(zMsg), zMsg, "rowid %12lld size %5d offset %8d", rowid, sz, ofstInFile(p, dataOfst)); printf("%s\n", zMsg); } } /* ** Output results from a single page. */ static void ofstWalkPage(GState *p, int pgno){ if( p->zErr ) return; ofstPushPage(p, pgno); if( p->zErr ) return; if( p->aPage[0]==5 ){ ofstWalkInteriorPage(p); }else if( p->aPage[0]==13 ){ ofstWalkLeafPage(p); }else{ ofstError(p, "page %d has a faulty type byte: %d", pgno, p->aPage[0]); } ofstPopPage(p); } int main(int argc, char **argv){ GState g; memset(&g, 0, sizeof(g)); if( argc>2 && strcmp(argv[1],"--trace")==0 ){ g.bTrace = 1; argc--; argv++; } if( argc!=4 ){ fprintf(stderr, "Usage: %s DATABASE TABLE COLUMN\n", *argv); exit(1); } ofstRootAndColumn(&g, argv[1], argv[2], argv[3]); if( g.zErr ){ fprintf(stderr, "%s\n", g.zErr); exit(1); } ofstTrace(&g, "# szPg = %d\n", g.szPg); ofstTrace(&g, "# iRoot = %d\n", g.iRoot); ofstTrace(&g, "# iCol = %d\n", g.iCol); g.f = fopen(argv[1], "rb"); if( g.f==0 ){ fprintf(stderr, "cannot open \"%s\"\n", argv[1]); exit(1); } ofstWalkPage(&g, g.iRoot); if( g.zErr ){ fprintf(stderr, "%s\n", g.zErr); exit(1); } return 0; } |