Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5390f95f07 | |||
| 1560045c32 | |||
| 99e8490705 | |||
| 62d9d70edd | |||
| a7829ecbdd | |||
| 642479d1cd | |||
| 09eba154b2 | |||
| eed4e1d2df | |||
| d75acb8312 | |||
| 47991d973a | |||
| ba6510a399 | |||
| 894cda4db7 | |||
| 2d960e943b | |||
| fc9b5d2a95 | |||
| bee4fb401e | |||
| c27c61586f | |||
| 427e0076a9 | |||
| 9f19ea83e7 | |||
| bf09cbe2ca | |||
| 4b60c1b49c | |||
| e34ad2b0b3 | |||
| 0ca5b1e39d | |||
| f5965e9d51 | |||
| 3ce81095f9 | |||
| 5b27bfac44 | |||
| 69eaadbee3 | |||
| d2f7dfa619 | |||
| c97abeac0b | |||
| 40ce00b546 |
+2
-7
@@ -261,6 +261,7 @@ AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
|
||||
USE_AMALGAMATION ?= @USE_AMALGAMATION@
|
||||
LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@
|
||||
AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
|
||||
EXTRA_SRC ?= @AMALGAMATION_EXTRA_SRC@
|
||||
|
||||
#
|
||||
# CFLAGS for sqlite3$(T.exe)
|
||||
@@ -322,13 +323,7 @@ misspell: ./custom.rws has_tclsh84
|
||||
# perform cleanup known to be relevant to (only) the autosetup-driven
|
||||
# build.
|
||||
#
|
||||
#clean-autosetup:
|
||||
# -if [ -f ext/wasm/GNUmakefile ]; then \
|
||||
# gmake --no-print-directory --ignore-errors -C ext/wasm clean; \
|
||||
# fi >/dev/null 2>&1; true
|
||||
#clean: clean-autosetup
|
||||
|
||||
distclean-autosetup: clean
|
||||
distclean-autosetup:
|
||||
rm -f sqlite_cfg.h config.log config.status config.defines.* Makefile sqlite3.pc
|
||||
rm -f $(TOP)/tool/emcc.sh
|
||||
rm -f libsqlite3*$(T.dll)
|
||||
|
||||
@@ -1616,7 +1616,6 @@ TESTSRC = \
|
||||
$(TOP)\src\test_quota.c \
|
||||
$(TOP)\src\test_rtree.c \
|
||||
$(TOP)\src\test_schema.c \
|
||||
$(TOP)\src\test_schemapool.c \
|
||||
$(TOP)\src\test_superlock.c \
|
||||
$(TOP)\src\test_syscall.c \
|
||||
$(TOP)\src\test_tclsh.c \
|
||||
|
||||
@@ -41,8 +41,12 @@ sqlite-configure canonical {
|
||||
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
|
||||
"Use #line macros in the amalgamation:"
|
||||
|
||||
define AMALGAMATION_EXTRA_SRC \
|
||||
[join [opt-val amalgamation-extra-src ""] " "]
|
||||
|
||||
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
|
||||
|
||||
sqlite-handle-tcl
|
||||
sqlite-handle-emsdk
|
||||
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ install-lib-0 install-lib-:
|
||||
install-lib: install-lib-$(ENABLE_LIB_STATIC)
|
||||
install: install-lib
|
||||
|
||||
|
||||
#
|
||||
# Flags to link the shell app either directly against sqlite3.c
|
||||
# (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0).
|
||||
#
|
||||
@@ -269,8 +269,10 @@ DIST_FILES := \
|
||||
sqlite3.rc sqlite3rc.h Replace.cs \
|
||||
sqlite3.pc.in sqlite3.1
|
||||
|
||||
#
|
||||
# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so
|
||||
# that tool/mkautoconfamal.sh knows how to find it.
|
||||
#
|
||||
dist_name = sqlite-$(PACKAGE_VERSION)
|
||||
dist_tarball = $(dist_name).tar.gz
|
||||
dist:
|
||||
|
||||
+23
-10
@@ -89,6 +89,7 @@ proc sqlite-configure {buildMode configScript} {
|
||||
# boolopt => "a boolean option which defaults to disabled"
|
||||
# boolopt2=1 => "a boolean option which defaults to enabled"
|
||||
# stringopt: => "an option which takes an argument, e.g. --stringopt=value"
|
||||
# stringopt:DESCR => As for stringopt: with a description for the value
|
||||
# stringopt2:=value => "an option where the argument is optional and defaults to 'value'"
|
||||
# optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help"
|
||||
#
|
||||
@@ -259,6 +260,10 @@ proc sqlite-configure {buildMode configScript} {
|
||||
with-emsdk:=auto
|
||||
=> {Top-most dir of the Emscripten SDK installation.
|
||||
Needed only by ext/wasm. Default=EMSDK env var.}
|
||||
|
||||
amalgamation-extra-src:FILES
|
||||
=> {Space-separated list of soure files to append as-is to the resulting
|
||||
sqlite3.c amalgamation file. May be provided multiple times.}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,7 +1469,8 @@ proc sqlite-handle-out-implib {} {
|
||||
#
|
||||
# It does not distinguish between msys and msys2, returning msys for
|
||||
# both. The build does not, as of this writing, specifically support
|
||||
# msys v1.
|
||||
# msys v1. Similarly, this function returns "mingw" for both "mingw32"
|
||||
# and "mingw64".
|
||||
proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
|
||||
if {"" eq $envTuple} {
|
||||
set envTuple [get-define host]
|
||||
@@ -1475,7 +1481,7 @@ proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
|
||||
*-*-ming* { set name mingw }
|
||||
*-*-msys { set name msys }
|
||||
}
|
||||
return $name;
|
||||
return $name
|
||||
}
|
||||
|
||||
########################################################################
|
||||
@@ -1562,6 +1568,9 @@ proc sqlite-process-dot-in-files {} {
|
||||
# it be done here.
|
||||
sqlite-handle-common-feature-flags
|
||||
sqlite-finalize-feature-flags
|
||||
if {"" ne [set extraSrc [get-define AMALGAMATION_EXTRA_SRC ""]]} {
|
||||
msg-result "Appending source files to amalgamation: $extraSrc"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# "Re-export" the autoconf-conventional --XYZdir flags into something
|
||||
@@ -1831,16 +1840,20 @@ proc sqlite-check-tcl {} {
|
||||
if {"" eq $with_tclsh && $cfg ne ""} {
|
||||
# We have tclConfig.sh but no tclsh. Attempt to locate a tclsh
|
||||
# based on info from tclConfig.sh.
|
||||
proj-assert {"" ne [get-define TCL_EXEC_PREFIX]}
|
||||
set with_tclsh [get-define TCL_EXEC_PREFIX]/bin/tclsh[get-define TCL_VERSION]
|
||||
if {![file-isexec $with_tclsh]} {
|
||||
set with_tclsh2 [get-define TCL_EXEC_PREFIX]/bin/tclsh
|
||||
if {![file-isexec $with_tclsh2]} {
|
||||
proj-warn "Cannot find a usable tclsh (tried: $with_tclsh $with_tclsh2)"
|
||||
} else {
|
||||
set with_tclsh $with_tclsh2
|
||||
set tclExecPrefix [get-define TCL_EXEC_PREFIX]
|
||||
proj-assert {"" ne $tclExecPrefix}
|
||||
set tryThese [list \
|
||||
$tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \
|
||||
$tclExecPrefix/bin/tclsh ]
|
||||
foreach trySh $tryThese {
|
||||
if {[file-isexec $trySh]} {
|
||||
set with_tclsh $trySh
|
||||
break
|
||||
}
|
||||
}
|
||||
if {![file-isexec $with_tclsh]} {
|
||||
proj-warn "Cannot find a usable tclsh (tried: $tryThese)
|
||||
}
|
||||
}
|
||||
define TCLSH_CMD $with_tclsh
|
||||
if {$use_tcl} {
|
||||
|
||||
@@ -725,10 +725,6 @@ as part of the output file.</p>
|
||||
<p>There can be multiple <tt>%code</tt> directives. The arguments of
|
||||
all <tt>%code</tt> directives are concatenated.</p>
|
||||
|
||||
<p>If the argument to <tt>%code</tt> is a filename within <tt><...></tt>
|
||||
then the content of the named file is inserted instead of the text of the
|
||||
argument itself.
|
||||
|
||||
<a id='default_destructor'></a>
|
||||
<h4>4.4.2 The <tt>%default_destructor</tt> directive</h4>
|
||||
|
||||
@@ -924,11 +920,6 @@ For example:</p>
|
||||
<p>This might be needed, for example, if some of the C actions in the
|
||||
grammar call functions that are prototyped in unistd.h.</p>
|
||||
|
||||
<p>If the argument to <tt>%include</tt> is a filename within
|
||||
<tt><...></tt> then the content of that file is inserted instead
|
||||
of the text of the argument itself.
|
||||
|
||||
|
||||
<p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to
|
||||
the end of the generated parser.</p>
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
|
||||
Shared-Schema Mode Notes
|
||||
========================
|
||||
|
||||
The [reuse-schema](/timeline?r=reuse-schema) branch contains changes
|
||||
to allow SQLite connections to share schemas
|
||||
between database connections within the same process in order to save memory.
|
||||
Schemas may be shared between multiple databases attached to the same or
|
||||
distinct connection handles.
|
||||
|
||||
Compile with -DSQLITE\_ENABLE\_SHARED\_SCHEMA in order to enable the
|
||||
shared-schema enhancement. Enabling the shared-schema enhancement causes
|
||||
approximately a 0.1% increase in CPU cycles consumed and about a 3000-byte
|
||||
increase in the size of the library, even if shared-schema is never used.
|
||||
|
||||
Assuming the compile-time requirements are satisfied, the shared-schema
|
||||
feature is engaged by opening the database connection using the
|
||||
sqlite3_open_v2() API with the SQLITE_OPEN_SHARED_SCHEMA
|
||||
flag specified. The main database and any attached databases will then share
|
||||
an in-memory Schema object with any other database opened within the process
|
||||
for which:
|
||||
|
||||
* the contents of the sqlite_master table, including all object names,
|
||||
SQL statements and root pages are identical, and
|
||||
* have the same values for the schema-cookie.
|
||||
|
||||
Temp databases (those populated with "CREATE TEMP TABLE" and similar
|
||||
statements) never share schemas.
|
||||
|
||||
Connections opened with the SQLITE_OPEN_SHARED_SCHEMA flag
|
||||
specified may not modify any database schema except that belonging to the
|
||||
temp database in anyway. This includes creating or dropping database
|
||||
objects, vacuuming the database, or running ANALYZE when the
|
||||
sqlite_stat\[14\] tables do not exist.
|
||||
|
||||
For SQLITE_OPEN_SHARED_SCHEMA connections, the
|
||||
SQLITE_DBSTATUS_SCHEMA_USED sqlite3_db_status() verb
|
||||
distributes the memory used for a shared schema object evenly between all
|
||||
database connections that share it.
|
||||
|
||||
## The ".shared-schema" Command
|
||||
|
||||
The shell tool on this branch contains a special dot-command to help with
|
||||
managing databases. The ".shared-schema" dot-command can be used to test
|
||||
whether or not two databases are similar enough to share in-memory schemas,
|
||||
and to fix minor problems that prevent them from doing so. To test if
|
||||
two or more database are compatible, one database is opened directly using
|
||||
the shell tool and the following command issued:
|
||||
|
||||
.shared-schema check <database-1> [<database-2>]...
|
||||
|
||||
where <database-1> etc. are replaced with the names of database files
|
||||
on disk. For each database specified on the command line, a single line of
|
||||
output is produced. If the database can share an in-memory schema with the
|
||||
main database opened by the shell tool, the output is of the form:
|
||||
|
||||
<database> is compatible
|
||||
|
||||
Otherwise, if the database cannot share a schema with the main db, the output
|
||||
is of the form:
|
||||
|
||||
<database> is NOT compatible (<reason>)
|
||||
|
||||
where <reason> indicates the cause of the incompatibility. <reason>
|
||||
is always one of the following.
|
||||
|
||||
<ul>
|
||||
<li> <b>objects</b> - the databases contain a different set schema objects
|
||||
(tables, indexes, views and triggers).
|
||||
|
||||
<li> <b>SQL</b> - the databases contain the same set of objects, but the SQL
|
||||
statements used to create them were not the same.
|
||||
|
||||
<li> <b>root pages</b> - the databases contain the same set of objects created
|
||||
by the same SQL statements, but the root pages are not the same.
|
||||
|
||||
<li> <b>order of sqlite_master rows</b> - the databases contain the same
|
||||
set of objects created by the same SQL statements with the same root pages,
|
||||
but the order of the rows in the sqlite_master tables are different.
|
||||
|
||||
<li> <b>schema cookie</b> - the database schemas are compatible, but the
|
||||
schema cookie values ("PRAGMA schema_version") are different.
|
||||
</ul>
|
||||
|
||||
The final three problems in the list above can be fixed using the
|
||||
.shared-schema command. To modify such a database so that it can share a
|
||||
schema with the main database, the following shell command is used:
|
||||
|
||||
.shared-schema fix <database-1> [<database-2>]...
|
||||
|
||||
If a database can be modified so that it may share a schema with the main
|
||||
database opened by the shell tool, output is as follows:
|
||||
|
||||
Fixing <database>... <database> is compatible
|
||||
|
||||
If a database does not require modification, or cannot be modified such that
|
||||
it can share a schema with the main database, the output of "fix" is identical
|
||||
to that of the "check" command.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
A single Schema object is never used by more than one database simultaneously,
|
||||
regardless of whether or not those databases are attached to the same or
|
||||
different database handles. Instead, a pool of schema objects is maintained
|
||||
for each unique sqlite_master-contents/schema-cookie combination
|
||||
opened within the process. Each time database schemas are required by a
|
||||
connection, for example as part of an sqlite3_prepare\*(),
|
||||
sqlite3_blob_open() or sqlite3_blob_open() call, it obtains
|
||||
the minimum number of schemas required from the various schema-pools, returning
|
||||
them at the end of the call. This means that a single schema-pool only ever
|
||||
contains more than one copy of the schema if:
|
||||
|
||||
* Two threads require schemas from the same pool at the same time, or
|
||||
* A single sqlite3_prepare\*() call requires schemas for two or more
|
||||
attached databases that use the same schema-pool.
|
||||
|
||||
The size of a schema-pool never shrinks. Each schema pool always maintains
|
||||
a number of schema objects equal to the highwater mark of schema objects
|
||||
simultaneously required by clients.
|
||||
|
||||
This approach is preferred to allowing multiple databases to use the same
|
||||
Schema object simultaneously for three reasons:
|
||||
|
||||
* The Schema object is not completely read-only. For example, the
|
||||
Index.zIdxAff string is allocated lazily.
|
||||
* Throughout the statement compiler, SQLite uses variables like
|
||||
Table.pSchema and Index.pSchema with the sqlite3SchemaToIndex() routine
|
||||
in order to determine which attached database a Table or Index object
|
||||
resides in. This mechanism does not work if the same Schema may be
|
||||
used by two or more attached databases.
|
||||
* It may be easier to modify this approach in order to allow
|
||||
SQLITE_OPEN_SHARED_SCHEMA connections to modify database
|
||||
schemas, should that be required.
|
||||
|
||||
SQLITE_OPEN_SHARED_SCHEMA connections do not store their
|
||||
virtual-table handles in the Table.pVTable list of each table. This would not
|
||||
work, as (a) there is no guarantee that a connection will be assigned the same
|
||||
Schema object each time it requests one from a schema-pool and (b) a single
|
||||
Schema (and therefore Table) object may correspond to tables in two or more
|
||||
databases attached to a single connection. Instead, all virtual-table handles
|
||||
associated with a single database are stored in a linked-list headed at
|
||||
Db.pVTable.
|
||||
@@ -62,20 +62,20 @@
|
||||
matches rows that contain both the "engineering" and "consultancy" tokens
|
||||
in the same column with not more than 10 other words between them. It does
|
||||
not matter which of the two terms occurs first in the document, only that
|
||||
they be seperated by only 10 tokens or less. The user may also specify
|
||||
they be separated by only 10 tokens or less. The user may also specify
|
||||
a different required proximity by adding "/N" immediately after the NEAR
|
||||
operator, where N is an integer. For example:
|
||||
|
||||
<col> MATCH 'engineering NEAR/5 consultancy'
|
||||
|
||||
searches for a row containing an instance of each specified token seperated
|
||||
searches for a row containing an instance of each specified token separated
|
||||
by not more than 5 other tokens. More than one NEAR operator can be used
|
||||
in as sequence. For example this query:
|
||||
|
||||
<col> MATCH 'reliable NEAR/2 engineering NEAR/5 consultancy'
|
||||
|
||||
searches for a row that contains an instance of the token "reliable"
|
||||
seperated by not more than two tokens from an instance of "engineering",
|
||||
separated by not more than two tokens from an instance of "engineering",
|
||||
which is in turn separated by not more than 5 other tokens from an
|
||||
instance of the term "consultancy". Phrases enclosed in quotes may
|
||||
also be used as arguments to the NEAR operator.
|
||||
|
||||
@@ -41,6 +41,11 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
#ifndef IsAlnum
|
||||
#define IsAlnum(X) isalnum((unsigned char)X)
|
||||
#endif
|
||||
|
||||
|
||||
/* completion_vtab is a subclass of sqlite3_vtab which will
|
||||
** serve as the underlying representation of a completion virtual table
|
||||
*/
|
||||
@@ -377,7 +382,7 @@ static int completionFilter(
|
||||
}
|
||||
if( pCur->zLine!=0 && pCur->zPrefix==0 ){
|
||||
int i = pCur->nLine;
|
||||
while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
|
||||
while( i>0 && (IsAlnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
|
||||
i--;
|
||||
}
|
||||
pCur->nPrefix = pCur->nLine - i;
|
||||
|
||||
+4
-1
@@ -27,6 +27,9 @@ SQLITE_EXTENSION_INIT1
|
||||
# define UNUSED_PARAMETER(X) (void)(X)
|
||||
#endif
|
||||
|
||||
#ifndef IsSpace
|
||||
#define IsSpace(X) isspace((unsigned char)X)
|
||||
#endif
|
||||
|
||||
/* A decimal object */
|
||||
typedef struct Decimal Decimal;
|
||||
@@ -76,7 +79,7 @@ static Decimal *decimalNewFromText(const char *zIn, int n){
|
||||
p->nFrac = 0;
|
||||
p->a = sqlite3_malloc64( n+1 );
|
||||
if( p->a==0 ) goto new_from_text_failed;
|
||||
for(i=0; isspace(zIn[i]); i++){}
|
||||
for(i=0; IsSpace(zIn[i]); i++){}
|
||||
if( zIn[i]=='-' ){
|
||||
p->sign = 1;
|
||||
i++;
|
||||
|
||||
+2
-4
@@ -519,8 +519,7 @@ static int seriesFilter(
|
||||
pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
|
||||
}
|
||||
if( pCur->ss.iTerm>iMax ){
|
||||
sqlite3_uint64 d = pCur->ss.iTerm - iMax;
|
||||
pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
|
||||
pCur->ss.iTerm = iMax;
|
||||
}
|
||||
}else{
|
||||
sqlite3_int64 szStep = -pCur->ss.iStep;
|
||||
@@ -530,8 +529,7 @@ static int seriesFilter(
|
||||
pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
|
||||
}
|
||||
if( pCur->ss.iTerm<iMin ){
|
||||
sqlite3_uint64 d = iMin - pCur->ss.iTerm;
|
||||
pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
|
||||
pCur->ss.iTerm = iMin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ do_test 1.2 {
|
||||
} [list {*}{
|
||||
{BEGIN}
|
||||
{PRAGMA writable_schema = on}
|
||||
{PRAGMA foreign_keys = off}
|
||||
{PRAGMA encoding = 'UTF-8'}
|
||||
{PRAGMA page_size = '1024'}
|
||||
{PRAGMA auto_vacuum = '0'}
|
||||
@@ -67,6 +68,7 @@ do_test 1.4 {
|
||||
} [list {*}{
|
||||
{BEGIN}
|
||||
{PRAGMA writable_schema = on}
|
||||
{PRAGMA foreign_keys = off}
|
||||
{PRAGMA encoding = 'UTF-8'}
|
||||
{PRAGMA page_size = '1024'}
|
||||
{PRAGMA auto_vacuum = '0'}
|
||||
|
||||
@@ -2574,37 +2574,53 @@ static void recoverUninstallWrapper(sqlite3_recover *p){
|
||||
static void recoverStep(sqlite3_recover *p){
|
||||
assert( p && p->errCode==SQLITE_OK );
|
||||
switch( p->eState ){
|
||||
case RECOVER_STATE_INIT:
|
||||
case RECOVER_STATE_INIT: {
|
||||
int bUseWrapper = 1;
|
||||
/* This is the very first call to sqlite3_recover_step() on this object.
|
||||
*/
|
||||
recoverSqlCallback(p, "BEGIN");
|
||||
recoverSqlCallback(p, "PRAGMA writable_schema = on");
|
||||
recoverSqlCallback(p, "PRAGMA foreign_keys = off");
|
||||
|
||||
recoverEnterMutex();
|
||||
recoverInstallWrapper(p);
|
||||
|
||||
/* Open the output database. And register required virtual tables and
|
||||
** user functions with the new handle. */
|
||||
recoverOpenOutput(p);
|
||||
|
||||
/* Open transactions on both the input and output databases. */
|
||||
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
|
||||
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
|
||||
recoverExec(p, p->dbIn, "BEGIN");
|
||||
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
|
||||
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
|
||||
recoverTransferSettings(p);
|
||||
recoverOpenRecovery(p);
|
||||
recoverCacheSchema(p);
|
||||
/* Attempt to open a transaction and read page 1 of the input database.
|
||||
** Two attempts may be made - one with a wrapper installed to ensure
|
||||
** that the database header is sane, and then if that attempt returns
|
||||
** SQLITE_NOTADB, then again with no wrapper. The second attempt is
|
||||
** required for encrypted databases. */
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
do{
|
||||
p->errCode = SQLITE_OK;
|
||||
if( bUseWrapper ) recoverInstallWrapper(p);
|
||||
|
||||
/* Open a transaction on the input database. */
|
||||
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
|
||||
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
|
||||
recoverExec(p, p->dbIn, "BEGIN");
|
||||
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
|
||||
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
|
||||
recoverTransferSettings(p);
|
||||
recoverOpenRecovery(p);
|
||||
recoverCacheSchema(p);
|
||||
|
||||
if( bUseWrapper ) recoverUninstallWrapper(p);
|
||||
}while( p->errCode==SQLITE_NOTADB
|
||||
&& (bUseWrapper--)
|
||||
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
|
||||
);
|
||||
}
|
||||
|
||||
recoverUninstallWrapper(p);
|
||||
recoverLeaveMutex();
|
||||
|
||||
recoverExec(p, p->dbOut, "BEGIN");
|
||||
|
||||
recoverWriteSchema1(p);
|
||||
p->eState = RECOVER_STATE_WRITING;
|
||||
break;
|
||||
}
|
||||
|
||||
case RECOVER_STATE_WRITING: {
|
||||
if( p->w1.pTbls==0 ){
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
_fiddle_exec
|
||||
_fiddle_interrupt
|
||||
_fiddle_experiment
|
||||
_fiddle_the_db
|
||||
_fiddle_db_arg
|
||||
_fiddle_db_filename
|
||||
_fiddle_exec
|
||||
_fiddle_experiment
|
||||
_fiddle_interrupt
|
||||
_fiddle_main
|
||||
_fiddle_reset_db
|
||||
_fiddle_db_handle
|
||||
_fiddle_db_vfs
|
||||
_fiddle_export_db
|
||||
@@ -1,72 +0,0 @@
|
||||
_sqlite3_bind_blob
|
||||
_sqlite3_bind_double
|
||||
_sqlite3_bind_int
|
||||
_sqlite3_bind_int64
|
||||
_sqlite3_bind_null
|
||||
_sqlite3_bind_parameter_count
|
||||
_sqlite3_bind_parameter_index
|
||||
_sqlite3_bind_text
|
||||
_sqlite3_changes
|
||||
_sqlite3_changes64
|
||||
_sqlite3_clear_bindings
|
||||
_sqlite3_close_v2
|
||||
_sqlite3_column_blob
|
||||
_sqlite3_column_bytes
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_double
|
||||
_sqlite3_column_int
|
||||
_sqlite3_column_int64
|
||||
_sqlite3_column_name
|
||||
_sqlite3_column_text
|
||||
_sqlite3_column_type
|
||||
_sqlite3_compileoption_get
|
||||
_sqlite3_compileoption_used
|
||||
_sqlite3_create_function_v2
|
||||
_sqlite3_data_count
|
||||
_sqlite3_db_filename
|
||||
_sqlite3_db_name
|
||||
_sqlite3_errmsg
|
||||
_sqlite3_error_offset
|
||||
_sqlite3_errstr
|
||||
_sqlite3_exec
|
||||
_sqlite3_expanded_sql
|
||||
_sqlite3_extended_errcode
|
||||
_sqlite3_extended_result_codes
|
||||
_sqlite3_finalize
|
||||
_sqlite3_initialize
|
||||
_sqlite3_interrupt
|
||||
_sqlite3_libversion
|
||||
_sqlite3_libversion_number
|
||||
_sqlite3_open
|
||||
_sqlite3_open_v2
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_reset
|
||||
_sqlite3_result_blob
|
||||
_sqlite3_result_double
|
||||
_sqlite3_result_error
|
||||
_sqlite3_result_error_code
|
||||
_sqlite3_result_error_nomem
|
||||
_sqlite3_result_error_toobig
|
||||
_sqlite3_result_int
|
||||
_sqlite3_result_null
|
||||
_sqlite3_result_text
|
||||
_sqlite3_sourceid
|
||||
_sqlite3_sql
|
||||
_sqlite3_step
|
||||
_sqlite3_strglob
|
||||
_sqlite3_strlike
|
||||
_sqlite3_total_changes
|
||||
_sqlite3_total_changes64
|
||||
_sqlite3_value_blob
|
||||
_sqlite3_value_bytes
|
||||
_sqlite3_value_double
|
||||
_sqlite3_value_text
|
||||
_sqlite3_value_type
|
||||
_sqlite3_vfs_find
|
||||
_sqlite3_vfs_register
|
||||
_sqlite3_wasm_db_error
|
||||
_sqlite3_wasm_enum_json
|
||||
_malloc
|
||||
_free
|
||||
@@ -0,0 +1,155 @@
|
||||
_malloc
|
||||
_free
|
||||
_realloc
|
||||
_sqlite3_aggregate_context
|
||||
_sqlite3_auto_extension
|
||||
_sqlite3_bind_blob
|
||||
_sqlite3_bind_double
|
||||
_sqlite3_bind_int
|
||||
_sqlite3_bind_int64
|
||||
_sqlite3_bind_null
|
||||
_sqlite3_bind_parameter_count
|
||||
_sqlite3_bind_parameter_index
|
||||
_sqlite3_bind_parameter_name
|
||||
_sqlite3_bind_pointer
|
||||
_sqlite3_bind_text
|
||||
_sqlite3_busy_handler
|
||||
_sqlite3_busy_timeout
|
||||
_sqlite3_cancel_auto_extension
|
||||
_sqlite3_changes
|
||||
_sqlite3_changes64
|
||||
_sqlite3_clear_bindings
|
||||
_sqlite3_close_v2
|
||||
_sqlite3_collation_needed
|
||||
_sqlite3_column_blob
|
||||
_sqlite3_column_bytes
|
||||
_sqlite3_column_count
|
||||
_sqlite3_column_decltype
|
||||
_sqlite3_column_double
|
||||
_sqlite3_column_int
|
||||
_sqlite3_column_int64
|
||||
_sqlite3_column_name
|
||||
_sqlite3_column_text
|
||||
_sqlite3_column_type
|
||||
_sqlite3_column_value
|
||||
_sqlite3_commit_hook
|
||||
_sqlite3_compileoption_get
|
||||
_sqlite3_compileoption_used
|
||||
_sqlite3_complete
|
||||
_sqlite3_context_db_handle
|
||||
_sqlite3_create_collation
|
||||
_sqlite3_create_collation_v2
|
||||
_sqlite3_create_function
|
||||
_sqlite3_create_function_v2
|
||||
_sqlite3_data_count
|
||||
_sqlite3_db_filename
|
||||
_sqlite3_db_handle
|
||||
_sqlite3_db_name
|
||||
_sqlite3_db_readonly
|
||||
_sqlite3_db_status
|
||||
_sqlite3_deserialize
|
||||
_sqlite3_errcode
|
||||
_sqlite3_errmsg
|
||||
_sqlite3_error_offset
|
||||
_sqlite3_errstr
|
||||
_sqlite3_exec
|
||||
_sqlite3_expanded_sql
|
||||
_sqlite3_extended_errcode
|
||||
_sqlite3_extended_result_codes
|
||||
_sqlite3_file_control
|
||||
_sqlite3_finalize
|
||||
_sqlite3_free
|
||||
_sqlite3_get_auxdata
|
||||
_sqlite3_get_autocommit
|
||||
_sqlite3_initialize
|
||||
_sqlite3_interrupt
|
||||
_sqlite3_is_interrupted
|
||||
_sqlite3_keyword_count
|
||||
_sqlite3_keyword_name
|
||||
_sqlite3_keyword_check
|
||||
_sqlite3_last_insert_rowid
|
||||
_sqlite3_libversion
|
||||
_sqlite3_libversion_number
|
||||
_sqlite3_limit
|
||||
_sqlite3_malloc
|
||||
_sqlite3_malloc64
|
||||
_sqlite3_msize
|
||||
_sqlite3_open
|
||||
_sqlite3_open_v2
|
||||
_sqlite3_overload_function
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_randomness
|
||||
_sqlite3_realloc
|
||||
_sqlite3_realloc64
|
||||
_sqlite3_reset
|
||||
_sqlite3_reset_auto_extension
|
||||
_sqlite3_result_blob
|
||||
_sqlite3_result_double
|
||||
_sqlite3_result_error
|
||||
_sqlite3_result_error_code
|
||||
_sqlite3_result_error_nomem
|
||||
_sqlite3_result_error_toobig
|
||||
_sqlite3_result_int
|
||||
_sqlite3_result_int64
|
||||
_sqlite3_result_null
|
||||
_sqlite3_result_pointer
|
||||
_sqlite3_result_subtype
|
||||
_sqlite3_result_text
|
||||
_sqlite3_result_zeroblob
|
||||
_sqlite3_result_zeroblob64
|
||||
_sqlite3_rollback_hook
|
||||
_sqlite3_serialize
|
||||
_sqlite3_set_auxdata
|
||||
_sqlite3_set_last_insert_rowid
|
||||
_sqlite3_shutdown
|
||||
_sqlite3_sourceid
|
||||
_sqlite3_sql
|
||||
_sqlite3_status
|
||||
_sqlite3_status64
|
||||
_sqlite3_step
|
||||
_sqlite3_stmt_busy
|
||||
_sqlite3_stmt_explain
|
||||
_sqlite3_stmt_isexplain
|
||||
_sqlite3_stmt_readonly
|
||||
_sqlite3_stmt_status
|
||||
_sqlite3_strglob
|
||||
_sqlite3_stricmp
|
||||
_sqlite3_strlike
|
||||
_sqlite3_strnicmp
|
||||
_sqlite3_table_column_metadata
|
||||
_sqlite3_total_changes
|
||||
_sqlite3_total_changes64
|
||||
_sqlite3_trace_v2
|
||||
_sqlite3_txn_state
|
||||
_sqlite3_update_hook
|
||||
_sqlite3_uri_boolean
|
||||
_sqlite3_uri_int64
|
||||
_sqlite3_uri_key
|
||||
_sqlite3_uri_parameter
|
||||
_sqlite3_user_data
|
||||
_sqlite3_value_blob
|
||||
_sqlite3_value_bytes
|
||||
_sqlite3_value_double
|
||||
_sqlite3_value_dup
|
||||
_sqlite3_value_free
|
||||
_sqlite3_value_frombind
|
||||
_sqlite3_value_int
|
||||
_sqlite3_value_int64
|
||||
_sqlite3_value_nochange
|
||||
_sqlite3_value_numeric_type
|
||||
_sqlite3_value_pointer
|
||||
_sqlite3_value_subtype
|
||||
_sqlite3_value_text
|
||||
_sqlite3_value_type
|
||||
_sqlite3_vfs_find
|
||||
_sqlite3_vfs_register
|
||||
_sqlite3_vfs_unregister
|
||||
_sqlite3_vtab_collation
|
||||
_sqlite3_vtab_distinct
|
||||
_sqlite3_vtab_in
|
||||
_sqlite3_vtab_in_first
|
||||
_sqlite3_vtab_in_next
|
||||
_sqlite3_vtab_nochange
|
||||
_sqlite3_vtab_on_conflict
|
||||
_sqlite3_vtab_rhs_value
|
||||
@@ -79,6 +79,48 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
capi.SQLITE_OPEN_MAIN_JOURNAL |
|
||||
capi.SQLITE_OPEN_SUPER_JOURNAL |
|
||||
capi.SQLITE_OPEN_WAL;
|
||||
const FLAG_COMPUTE_DIGEST_V2 = capi.SQLITE_OPEN_MEMORY
|
||||
/* Part of the fix for
|
||||
https://github.com/sqlite/sqlite-wasm/issues/97
|
||||
|
||||
Summary: prior to version 3.50.0 computeDigest() always computes
|
||||
a value of [0,0] due to overflows, so it does not do anything
|
||||
useful. Fixing it invalidates old persistent files, so we
|
||||
instead only fix it for files created or updated since the bug
|
||||
was discovered and fixed.
|
||||
|
||||
This flag determines whether we use the broken legacy
|
||||
computeDigest() or the v2 variant. We only use this flag for
|
||||
newly-created/overwritten files. Pre-existing files have the
|
||||
broken digest stored in them so need to continue to use that.
|
||||
|
||||
What this means, in terms of db file compatibility between
|
||||
versions:
|
||||
|
||||
- DBs created with versions older than this fix (<3.50.0)
|
||||
can be read by post-fix versions. Such DBs which are written
|
||||
to in-place (not replaced) by newer versions can still be read
|
||||
by older versions, as the affected digest is only modified
|
||||
when the SAH slot is assigned to a given filename.
|
||||
|
||||
- DBs created with post-fix versions will, when read by a pre-fix
|
||||
version, be seen as having a "bad digest" and will be
|
||||
unceremoniously replaced by that pre-fix version. When swapping
|
||||
back to a post-fix version, that version will see that the file
|
||||
entry is missing the FLAG_COMPUTE_DIGEST_V2 bit so will treat it
|
||||
as a legacy file.
|
||||
|
||||
This flag is stored in the same memory as the various
|
||||
SQLITE_OPEN_... flags and we must be careful here to not use a
|
||||
flag bit which is otherwise relevant for the VFS.
|
||||
SQLITE_OPEN_MEMORY is handled by sqlite3_open_v2() and friends,
|
||||
not the VFS, so we'll repurpose that one. If we take a
|
||||
currently-unused bit and it ends up, at some later point, being
|
||||
used, we would have to invalidate existing VFS files in order to
|
||||
move to another bit. Similarly, if the SQLITE_OPEN_MEMORY bit
|
||||
were ever reassigned (which it won't be!), we'd invalidate all
|
||||
VFS-side files.
|
||||
*/;
|
||||
|
||||
/** Subdirectory of the VFS's space where "opaque" (randomly-named)
|
||||
files are stored. Changing this effectively invalidates the data
|
||||
@@ -329,6 +371,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){
|
||||
const pool = getPoolForVfs(pVfs);
|
||||
try{
|
||||
flags &= ~FLAG_COMPUTE_DIGEST_V2;
|
||||
pool.log(`xOpen ${wasm.cstrToJs(zName)} ${flags}`);
|
||||
// First try to open a path that already exists in the file system.
|
||||
const path = (zName && wasm.peek8(zName))
|
||||
@@ -624,7 +667,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
const fileDigest = new Uint32Array(HEADER_DIGEST_SIZE / 4);
|
||||
sah.read(fileDigest, {at: HEADER_OFFSET_DIGEST});
|
||||
const compDigest = this.computeDigest(this.#apBody);
|
||||
const compDigest = this.computeDigest(this.#apBody, flags);
|
||||
//warn("getAssociatedPath() flags",'0x'+flags.toString(16), "compDigest", compDigest);
|
||||
if(fileDigest.every((v,i) => v===compDigest[i])){
|
||||
// Valid digest
|
||||
const pathBytes = this.#apBody.findIndex((v)=>0===v);
|
||||
@@ -655,10 +699,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
if(HEADER_MAX_PATH_SIZE <= enc.written + 1/*NUL byte*/){
|
||||
toss("Path too long:",path);
|
||||
}
|
||||
if(path && flags){
|
||||
/* When creating or re-writing files, update their digest, if
|
||||
needed, to v2. We continue to use v1 for the (!path) case
|
||||
(empty files) because there's little reason not to use a
|
||||
digest of 0 for empty entries. */
|
||||
flags |= FLAG_COMPUTE_DIGEST_V2;
|
||||
}
|
||||
this.#apBody.fill(0, enc.written, HEADER_MAX_PATH_SIZE);
|
||||
this.#dvBody.setUint32(HEADER_OFFSET_FLAGS, flags);
|
||||
|
||||
const digest = this.computeDigest(this.#apBody);
|
||||
const digest = this.computeDigest(this.#apBody, flags);
|
||||
//console.warn("setAssociatedPath(",path,") digest",digest);
|
||||
sah.write(this.#apBody, {at: 0});
|
||||
sah.write(digest, {at: HEADER_OFFSET_DIGEST});
|
||||
sah.flush();
|
||||
@@ -679,15 +730,22 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
metadata for each file as a validation check. Changing this
|
||||
algorithm invalidates all existing databases for this VFS, so
|
||||
don't do that.
|
||||
|
||||
See the docs for FLAG_COMPUTE_DIGEST_V2 for more details.
|
||||
*/
|
||||
computeDigest(byteArray){
|
||||
let h1 = 0xdeadbeef;
|
||||
let h2 = 0x41c6ce57;
|
||||
for(const v of byteArray){
|
||||
h1 = 31 * h1 + (v * 307);
|
||||
h2 = 31 * h2 + (v * 307);
|
||||
computeDigest(byteArray, fileFlags){
|
||||
if( fileFlags & FLAG_COMPUTE_DIGEST_V2 ){
|
||||
let h1 = 0xdeadbeef;
|
||||
let h2 = 0x41c6ce57;
|
||||
for(const v of byteArray){
|
||||
h1 = Math.imul(h1 ^ v, 2654435761);
|
||||
h2 = Math.imul(h2 ^ v, 104729);
|
||||
}
|
||||
return new Uint32Array([h1>>>0, h2>>>0]);
|
||||
}else{
|
||||
/* this is what the buggy legacy computation worked out to */
|
||||
return new Uint32Array([0,0]);
|
||||
}
|
||||
return new Uint32Array([h1>>>0, h2>>>0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//#ifnot omit-oo1
|
||||
/*
|
||||
2022-08-24
|
||||
|
||||
@@ -41,9 +42,13 @@
|
||||
- `onready` (optional, but...): this callback is called with no
|
||||
arguments when the worker fires its initial
|
||||
'sqlite3-api'/'worker1-ready' message, which it does when
|
||||
sqlite3.initWorker1API() completes its initialization. This is
|
||||
the simplest way to tell the worker to kick off work at the
|
||||
earliest opportunity.
|
||||
sqlite3.initWorker1API() completes its initialization. This is the
|
||||
simplest way to tell the worker to kick off work at the earliest
|
||||
opportunity, and the only way to know when the worker module has
|
||||
completed loading. The irony of using a callback for this, instead
|
||||
of returning a promise from sqlite3Worker1Promiser() is not lost on
|
||||
the developers: see sqlite3Worker1Promiser.v2() which uses a
|
||||
Promise instead.
|
||||
|
||||
- `onunhandled` (optional): a callback which gets passed the
|
||||
message event object for any worker.onmessage() events which
|
||||
@@ -114,7 +119,7 @@
|
||||
by all client code except that which tests this API. The `row`
|
||||
property contains the row result in the form implied by the
|
||||
`rowMode` option (defaulting to `'array'`). The `rowNumber` is a
|
||||
1-based integer value incremented by 1 on each call into th
|
||||
1-based integer value incremented by 1 on each call into the
|
||||
callback.
|
||||
|
||||
At the end of the result set, the same event is fired with
|
||||
@@ -122,8 +127,17 @@
|
||||
the end of the result set has been reached. Note that the rows
|
||||
arrive via worker-posted messages, with all the implications
|
||||
of that.
|
||||
|
||||
Notable shortcomings:
|
||||
|
||||
- This API was not designed with ES6 modules in mind. Neither Firefox
|
||||
nor Safari support, as of March 2023, the {type:"module"} flag to the
|
||||
Worker constructor, so that particular usage is not something we're going
|
||||
to target for the time being:
|
||||
|
||||
https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
|
||||
*/
|
||||
self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
// Inspired by: https://stackoverflow.com/a/52439530
|
||||
if(1===arguments.length && 'function'===typeof arguments[0]){
|
||||
const f = config;
|
||||
@@ -146,6 +160,7 @@ self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
if(!config.worker) config.worker = callee.defaultConfig.worker;
|
||||
if('function'===typeof config.worker) config.worker = config.worker();
|
||||
let dbId;
|
||||
let promiserFunc;
|
||||
config.worker.onmessage = function(ev){
|
||||
ev = ev.data;
|
||||
debug('worker1.onmessage',ev);
|
||||
@@ -153,14 +168,14 @@ self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
if(!msgHandler){
|
||||
if(ev && 'sqlite3-api'===ev.type && 'worker1-ready'===ev.result) {
|
||||
/*fired one time when the Worker1 API initializes*/
|
||||
if(config.onready) config.onready();
|
||||
if(config.onready) config.onready(promiserFunc);
|
||||
return;
|
||||
}
|
||||
msgHandler = handlerMap[ev.type] /* check for exec per-row callback */;
|
||||
if(msgHandler && msgHandler.onrow){
|
||||
msgHandler.onrow(ev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(config.onunhandled) config.onunhandled(arguments[0]);
|
||||
else err("sqlite3Worker1Promiser() unhandled worker message:",ev);
|
||||
return;
|
||||
@@ -182,19 +197,19 @@ self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
try {msgHandler.resolve(ev)}
|
||||
catch(e){msgHandler.reject(e)}
|
||||
}/*worker.onmessage()*/;
|
||||
return function(/*(msgType, msgArgs) || (msgEnvelope)*/){
|
||||
return promiserFunc = function(/*(msgType, msgArgs) || (msgEnvelope)*/){
|
||||
let msg;
|
||||
if(1===arguments.length){
|
||||
msg = arguments[0];
|
||||
}else if(2===arguments.length){
|
||||
msg = {
|
||||
type: arguments[0],
|
||||
args: arguments[1]
|
||||
};
|
||||
msg = Object.create(null);
|
||||
msg.type = arguments[0];
|
||||
msg.args = arguments[1];
|
||||
msg.dbId = msg.args.dbId;
|
||||
}else{
|
||||
toss("Invalid arugments for sqlite3Worker1Promiser()-created factory.");
|
||||
toss("Invalid arguments for sqlite3Worker1Promiser()-created factory.");
|
||||
}
|
||||
if(!msg.dbId) msg.dbId = dbId;
|
||||
if(!msg.dbId && msg.type!=='open') msg.dbId = dbId;
|
||||
msg.messageId = genMsgId(msg);
|
||||
msg.departureTime = performance.now();
|
||||
const proxy = Object.create(null);
|
||||
@@ -236,10 +251,13 @@ self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
|
||||
return p;
|
||||
};
|
||||
}/*sqlite3Worker1Promiser()*/;
|
||||
self.sqlite3Worker1Promiser.defaultConfig = {
|
||||
|
||||
globalThis.sqlite3Worker1Promiser.defaultConfig = {
|
||||
worker: function(){
|
||||
//#if target=es6-bundler-friendly
|
||||
return new Worker("sqlite3-worker1.js");
|
||||
//#if target=es6-module
|
||||
return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{
|
||||
type: 'module'
|
||||
});
|
||||
//#else
|
||||
let theJs = "sqlite3-worker1.js";
|
||||
if(this.currentScript){
|
||||
@@ -247,17 +265,82 @@ self.sqlite3Worker1Promiser.defaultConfig = {
|
||||
src.pop();
|
||||
theJs = src.join('/')+'/' + theJs;
|
||||
//sqlite3.config.warn("promiser currentScript, theJs =",this.currentScript,theJs);
|
||||
}else{
|
||||
//sqlite3.config.warn("promiser self.location =",self.location);
|
||||
const urlParams = new URL(self.location.href).searchParams;
|
||||
}else if(globalThis.location){
|
||||
//sqlite3.config.warn("promiser globalThis.location =",globalThis.location);
|
||||
const urlParams = new URL(globalThis.location.href).searchParams;
|
||||
if(urlParams.has('sqlite3.dir')){
|
||||
theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
|
||||
}
|
||||
}
|
||||
return new Worker(theJs + self.location.search);
|
||||
return new Worker(theJs + globalThis.location.search);
|
||||
//#endif
|
||||
}.bind({
|
||||
currentScript: self?.document?.currentScript
|
||||
}),
|
||||
}
|
||||
//#ifnot target=es6-module
|
||||
.bind({
|
||||
currentScript: globalThis?.document?.currentScript
|
||||
})
|
||||
//#endif
|
||||
,
|
||||
onerror: (...args)=>console.error('worker1 promiser error',...args)
|
||||
};
|
||||
}/*defaultConfig*/;
|
||||
|
||||
/**
|
||||
sqlite3Worker1Promiser.v2(), added in 3.46, works identically to
|
||||
sqlite3Worker1Promiser() except that it returns a Promise instead
|
||||
of relying an an onready callback in the config object. The Promise
|
||||
resolves to the same factory function which
|
||||
sqlite3Worker1Promiser() returns.
|
||||
|
||||
If config is-a function or is an object which contains an onready
|
||||
function, that function is replaced by a proxy which will resolve
|
||||
after calling the original function and will reject if that
|
||||
function throws.
|
||||
*/
|
||||
sqlite3Worker1Promiser.v2 = function(config){
|
||||
let oldFunc;
|
||||
if( 'function' == typeof config ){
|
||||
oldFunc = config;
|
||||
config = {};
|
||||
}else if('function'===typeof config?.onready){
|
||||
oldFunc = config.onready;
|
||||
delete config.onready;
|
||||
}
|
||||
const promiseProxy = Object.create(null);
|
||||
config = Object.assign((config || Object.create(null)),{
|
||||
onready: async function(func){
|
||||
try {
|
||||
if( oldFunc ) await oldFunc(func);
|
||||
promiseProxy.resolve(func);
|
||||
}
|
||||
catch(e){promiseProxy.reject(e)}
|
||||
}
|
||||
});
|
||||
const p = new Promise(function(resolve,reject){
|
||||
promiseProxy.resolve = resolve;
|
||||
promiseProxy.reject = reject;
|
||||
});
|
||||
try{
|
||||
this.original(config);
|
||||
}catch(e){
|
||||
promiseProxy.reject(e);
|
||||
}
|
||||
return p;
|
||||
}.bind({
|
||||
/* We do this because clients are
|
||||
recommended to delete globalThis.sqlite3Worker1Promiser. */
|
||||
original: sqlite3Worker1Promiser
|
||||
});
|
||||
|
||||
//#if target=es6-module
|
||||
/**
|
||||
When built as a module, we export sqlite3Worker1Promiser.v2()
|
||||
instead of sqlite3Worker1Promise() because (A) its interface is more
|
||||
conventional for ESM usage and (B) the ESM export option for this
|
||||
API did not exist until v2 was created, so there's no backwards
|
||||
incompatibility.
|
||||
*/
|
||||
export default sqlite3Worker1Promiser.v2;
|
||||
//#endif /* target=es6-module */
|
||||
//#else
|
||||
/* Built with the omit-oo1 flag. */
|
||||
//#endif ifnot omit-oo1
|
||||
|
||||
@@ -115,6 +115,7 @@ delete globalThis.sqlite3Worker1Promiser;
|
||||
"insert into t(a,b) values(1,2),(3,4),(5,6)"
|
||||
].join(';'),
|
||||
resultRows: [], columnNames: [],
|
||||
lastInsertRowId: true,
|
||||
countChanges: sqConfig.bigIntEnabled ? 64 : true
|
||||
}, function(ev){
|
||||
ev = ev.result;
|
||||
@@ -122,7 +123,9 @@ delete globalThis.sqlite3Worker1Promiser;
|
||||
.assert(0===ev.columnNames.length)
|
||||
.assert(sqConfig.bigIntEnabled
|
||||
? (3n===ev.changeCount)
|
||||
: (3===ev.changeCount));
|
||||
: (3===ev.changeCount))
|
||||
.assert('bigint'===typeof ev.lastInsertRowId)
|
||||
.assert(ev.lastInsertRowId>=3);
|
||||
});
|
||||
|
||||
await wtest('exec',{
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>SQLite3 Fiddle</title>
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<!-- to add a togglable terminal-style view, uncomment the following
|
||||
<!-- to add a toggleable terminal-style view, uncomment the following
|
||||
two lines and ensure that these files are on the web server. -->
|
||||
<!--script src="jqterm/jqterm-bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="jqterm/jquery.terminal.min.css"/-->
|
||||
<link rel="stylesheet" href="emscripten.css"/>
|
||||
<style>
|
||||
/* The following styles are for app-level use. */
|
||||
:root {
|
||||
@@ -171,6 +170,31 @@
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
/* emcscript-related styling, used during the module load/intialization processes... */
|
||||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { border: 1px solid black; }
|
||||
#module-spinner { overflow: visible; }
|
||||
#module-spinner > * {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.spinner {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin: 0px auto;
|
||||
animation: rotation 0.8s linear infinite;
|
||||
border-left: 10px solid rgb(0,150,240);
|
||||
border-right: 10px solid rgb(0,150,240);
|
||||
border-bottom: 10px solid rgb(0,150,240);
|
||||
border-top: 10px solid rgb(100,0,200);
|
||||
border-radius: 100%;
|
||||
background-color: rgb(200,100,250);
|
||||
}
|
||||
@keyframes rotation {
|
||||
from {transform: rotate(0deg);}
|
||||
to {transform: rotate(360deg);}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -273,11 +297,6 @@
|
||||
</fieldset>
|
||||
</div>
|
||||
</div> <!-- #view-split -->
|
||||
<!-- Maintenance notes:
|
||||
|
||||
... TODO... currently being refactored...
|
||||
|
||||
-->
|
||||
<script src="fiddle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3506,7 +3506,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
});
|
||||
db.exec([
|
||||
"create table t(a);",
|
||||
"insert into t(a) values(1),(2),(3);",
|
||||
"insert into t(a) values(1),(2),(1);",
|
||||
"select auxtest(1,a), auxtest(1,a) from t order by a"
|
||||
]);
|
||||
}finally{
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
2025-01-31
|
||||
|
||||
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 is part of sahpool-pausing.js's demonstration of the
|
||||
pause/unpause feature of the opfs-sahpool VFS.
|
||||
*/
|
||||
const clog = console.log.bind(console);
|
||||
const wPost = (type,...args)=>postMessage({type, payload:args});
|
||||
const log = (...args)=>{
|
||||
clog("Worker:",...args);
|
||||
wPost('log',...args);
|
||||
}
|
||||
|
||||
const hasOpfs = ()=>{
|
||||
return globalThis.FileSystemHandle
|
||||
&& globalThis.FileSystemDirectoryHandle
|
||||
&& globalThis.FileSystemFileHandle
|
||||
&& globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle
|
||||
&& navigator?.storage?.getDirectory;
|
||||
};
|
||||
if( !hasOpfs() ){
|
||||
wPost('error',"OPFS not detected");
|
||||
throw new Error("OPFS not detected");
|
||||
}
|
||||
|
||||
clog("Importing sqlite3...");
|
||||
const searchParams = new URL(self.location.href).searchParams;
|
||||
importScripts(searchParams.get('sqlite3.dir') + '/sqlite3.js');
|
||||
|
||||
const runTests = function(sqlite3, poolUtil){
|
||||
const fname = '/my.db';
|
||||
let db = new poolUtil.OpfsSAHPoolDb(fname);
|
||||
let n = (new Date()).valueOf();
|
||||
try {
|
||||
db.exec([
|
||||
"create table if not exists t(a);"
|
||||
]);
|
||||
db.exec({
|
||||
sql: "insert into t(a) values(?)",
|
||||
bind: n++
|
||||
});
|
||||
log(fname,"record count: ",db.selectValue("select count(*) from t"));
|
||||
}finally{
|
||||
db.close();
|
||||
}
|
||||
|
||||
db = new poolUtil.OpfsSAHPoolDb(fname);
|
||||
try {
|
||||
db.exec({
|
||||
sql: "insert into t(a) values(?)",
|
||||
bind: n++
|
||||
});
|
||||
log(fname,"record count: ",db.selectValue("select count(*) from t"));
|
||||
}finally{
|
||||
db.close();
|
||||
}
|
||||
|
||||
const fname2 = '/my2.db';
|
||||
db = new poolUtil.OpfsSAHPoolDb(fname2);
|
||||
try {
|
||||
db.exec([
|
||||
"create table if not exists t(a);"
|
||||
]);
|
||||
db.exec({
|
||||
sql: "insert into t(a) values(?)",
|
||||
bind: n++
|
||||
});
|
||||
log(fname2,"record count: ",db.selectValue("select count(*) from t"));
|
||||
}finally{
|
||||
db.close();
|
||||
}
|
||||
};
|
||||
|
||||
globalThis.sqlite3InitModule().then(async function(sqlite3){
|
||||
log("sqlite3 version:",sqlite3.version);
|
||||
const sahPoolConfig = {
|
||||
name: 'opfs-sahpool-digest',
|
||||
clearOnInit: false,
|
||||
initialCapacity: 6
|
||||
};
|
||||
return sqlite3.installOpfsSAHPoolVfs(sahPoolConfig).then(poolUtil=>{
|
||||
log('vfs acquired');
|
||||
runTests(sqlite3, poolUtil);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,141 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||
<link rel="stylesheet" href="../../../common/emscripten.css"/>
|
||||
<link rel="stylesheet" href="../../../common/testing.css"/>
|
||||
<title>sqlite3 tester: OpfsSAHPool Digest</title>
|
||||
<style></style>
|
||||
</head>
|
||||
<body><h1 id='color-target'></h1>
|
||||
|
||||
<p>
|
||||
This is a test app for the digest calculation of the OPFS
|
||||
SAHPool VFS. It requires running it with a new database created using
|
||||
v3.49.0 or older, then running it again with a newer version, then
|
||||
again with 3.49.0 or older.
|
||||
</p>
|
||||
<div class='input-wrapper'>
|
||||
<input type='checkbox' id='cb-log-reverse'>
|
||||
<label for='cb-log-reverse'>Reverse log order?</label>
|
||||
</div>
|
||||
<div id='test-output'></div>
|
||||
<script>
|
||||
/*
|
||||
2025-02-03
|
||||
|
||||
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 is a bugfix test for the OPFS SAHPool VFS. It requires setting up
|
||||
a database created using v3.49.0 or older, then running it again with
|
||||
a newer version.
|
||||
*/
|
||||
(function(){
|
||||
'use strict';
|
||||
document.querySelector('h1').innerHTML =
|
||||
document.querySelector('title').innerHTML;
|
||||
const mapToString = (v)=>{
|
||||
switch(typeof v){
|
||||
case 'number': case 'string': case 'boolean':
|
||||
case 'undefined': case 'bigint':
|
||||
return ''+v;
|
||||
default: break;
|
||||
}
|
||||
if(null===v) return 'null';
|
||||
if(v instanceof Error){
|
||||
v = {
|
||||
message: v.message,
|
||||
stack: v.stack,
|
||||
errorClass: v.name
|
||||
};
|
||||
}
|
||||
return JSON.stringify(v,undefined,2);
|
||||
};
|
||||
const normalizeArgs = (args)=>args.map(mapToString);
|
||||
const logTarget = document.querySelector('#test-output');
|
||||
const logClass = function(cssClass,...args){
|
||||
const ln = document.createElement('div');
|
||||
if(cssClass){
|
||||
for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
|
||||
ln.classList.add(c);
|
||||
}
|
||||
}
|
||||
ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
|
||||
logTarget.append(ln);
|
||||
};
|
||||
const cbReverse = document.querySelector('#cb-log-reverse');
|
||||
//cbReverse.setAttribute('checked','checked');
|
||||
const cbReverseKey = 'tester1:cb-log-reverse';
|
||||
const cbReverseIt = ()=>{
|
||||
logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
|
||||
//localStorage.setItem(cbReverseKey, cbReverse.checked ? 1 : 0);
|
||||
};
|
||||
cbReverse.addEventListener('change', cbReverseIt, true);
|
||||
/*if(localStorage.getItem(cbReverseKey)){
|
||||
cbReverse.checked = !!(+localStorage.getItem(cbReverseKey));
|
||||
}*/
|
||||
cbReverseIt();
|
||||
|
||||
const log = (...args)=>{
|
||||
//console.log(...args);
|
||||
logClass('',...args);
|
||||
}
|
||||
const warn = (...args)=>{
|
||||
console.warn(...args);
|
||||
logClass('warning',...args);
|
||||
}
|
||||
const error = (...args)=>{
|
||||
console.error(...args);
|
||||
logClass('error',...args);
|
||||
};
|
||||
|
||||
const toss = (...args)=>{
|
||||
error(...args);
|
||||
throw new Error(args.join(' '));
|
||||
};
|
||||
|
||||
const endOfWork = (passed=true)=>{
|
||||
const eH = document.querySelector('#color-target');
|
||||
const eT = document.querySelector('title');
|
||||
if(passed){
|
||||
log("End of work chain. If you made it this far, you win.");
|
||||
eH.innerText = 'PASS: '+eH.innerText;
|
||||
eH.classList.add('tests-pass');
|
||||
eT.innerText = 'PASS: '+eT.innerText;
|
||||
}else{
|
||||
eH.innerText = 'FAIL: '+eH.innerText;
|
||||
eH.classList.add('tests-fail');
|
||||
eT.innerText = 'FAIL: '+eT.innerText;
|
||||
}
|
||||
};
|
||||
|
||||
log("Running opfs-sahpool digest tests...");
|
||||
const W1 = new Worker('digest-worker.js?sqlite3.dir=../../../jswasm');
|
||||
W1.onmessage = function({data}){
|
||||
//log("onmessage:",data);
|
||||
switch(data.type){
|
||||
case 'log':
|
||||
log('worker says:', ...data.payload);
|
||||
break;
|
||||
case 'error':
|
||||
error('worker says:', ...data.payload);
|
||||
endOfWork(false);
|
||||
break;
|
||||
case 'initialized':
|
||||
log(data.workerId, ': Worker initialized',...data.payload);
|
||||
break;
|
||||
}
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -22,10 +22,10 @@ all:
|
||||
#
|
||||
# $(TOP) =
|
||||
#
|
||||
# The toplevel directory of the source tree. For canonical builds
|
||||
# The top-level directory of the source tree. For canonical builds
|
||||
# this is the directory that contains this "Makefile.in" and the
|
||||
# "configure.in" script. For out-of-tree builds, this will differ
|
||||
# from $(PWD).
|
||||
# "auto.def" script. For out-of-tree builds, this will differ from
|
||||
# $(PWD).
|
||||
#
|
||||
TOP ?= $(PWD)
|
||||
#
|
||||
@@ -115,8 +115,8 @@ JIMSH ?= ./jimsh$(T.exe)
|
||||
#
|
||||
# The TCL interpreter for in-tree code generation. May be either the
|
||||
# in-tree JimTCL ($(JIMSH)) or the canonical TCL ($(TCLSH_CMD). If
|
||||
# it's JimTCL, it must be compiled with -DHAVE_REALPATH or
|
||||
# -DHAVE__FULLPATH.
|
||||
# it's JimTCL, it must be compiled with -DHAVE_REALPATH (Unix) or
|
||||
# -DHAVE__FULLPATH (Windows).
|
||||
#
|
||||
B.tclsh ?= $(JIMSH)
|
||||
|
||||
@@ -231,6 +231,13 @@ LINK_TOOLS_DYNAMICALLY ?= 0
|
||||
# Optional flags for the amalgamation generator.
|
||||
#
|
||||
AMALGAMATION_GEN_FLAGS ?= --linemacros=0
|
||||
#
|
||||
# EXTRA_SRC = list of C files to append as-is to the generated
|
||||
# amalgamation. It should arguably be called AMALGAMATION_EXTRA_SRC
|
||||
# but this older name is already in use by clients.
|
||||
#
|
||||
EXTRA_SRC ?=
|
||||
|
||||
#
|
||||
# $(OPT_FEATURE_FLAGS) =
|
||||
#
|
||||
@@ -448,8 +455,9 @@ $(install-dir.all):
|
||||
# to an empty string.
|
||||
#
|
||||
# 2) Ensure that it is built with -DJIM_COMPAT (which may be
|
||||
# hard-coded into jimsh0.c). Without this, the [expr] command
|
||||
# accepts only a single argument.
|
||||
# hard-coded into jimsh0.c). Without this, the [expr] command accepts
|
||||
# only a single argument. (That said: the real fix for that is to
|
||||
# update any scripts which still pass multiple arguments to [expr].)
|
||||
#
|
||||
$(JIMSH): $(TOP)/autosetup/jimsh0.c
|
||||
$(B.cc) -o $@ $(CFLAGS.jimsh) $(TOP)/autosetup/jimsh0.c
|
||||
@@ -725,7 +733,6 @@ TESTSRC = \
|
||||
$(TOP)/src/test_quota.c \
|
||||
$(TOP)/src/test_rtree.c \
|
||||
$(TOP)/src/test_schema.c \
|
||||
$(TOP)/src/test_schemapool.c \
|
||||
$(TOP)/src/test_superlock.c \
|
||||
$(TOP)/src/test_syscall.c \
|
||||
$(TOP)/src/test_tclsh.c \
|
||||
@@ -793,8 +800,6 @@ TESTSRC2 = \
|
||||
$(TOP)/src/bitvec.c \
|
||||
$(TOP)/src/btree.c \
|
||||
$(TOP)/src/build.c \
|
||||
$(TOP)/src/callback.c \
|
||||
$(TOP)/src/ctime.c \
|
||||
ctime.c \
|
||||
$(TOP)/src/date.c \
|
||||
$(TOP)/src/dbpage.c \
|
||||
@@ -2336,6 +2341,9 @@ stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON)
|
||||
#
|
||||
# Windows section
|
||||
#
|
||||
# 2025-03-03: sqlite3.def and sqlite3.dll might no longer be relevant
|
||||
# in this particular build, but that's difficult to verify.
|
||||
#
|
||||
dll: sqlite3.dll
|
||||
sqlite3.def: $(LIBOBJ)
|
||||
echo 'EXPORTS' >sqlite3.def
|
||||
@@ -2348,6 +2356,7 @@ sqlite3.dll: $(LIBOBJ) sqlite3.def
|
||||
|
||||
#
|
||||
# Emit a list of commonly-used targets
|
||||
#
|
||||
help:
|
||||
@echo; echo "Frequently-used high-level make targets:"; echo; \
|
||||
echo " - all [default] = builds most components"; \
|
||||
@@ -2370,14 +2379,15 @@ help:
|
||||
echo
|
||||
|
||||
|
||||
#
|
||||
# Remove build products sufficient so that subsequent makes will recompile
|
||||
# everything from scratch. Do not remove:
|
||||
#
|
||||
# * test results and test logs
|
||||
# * output from ./configure
|
||||
#
|
||||
tidy-.:
|
||||
tidy: tidy-.
|
||||
#
|
||||
tidy:
|
||||
rm -f *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(T.exe)
|
||||
rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
|
||||
rm -rf .libs .deps tsrc .target_source
|
||||
@@ -2409,16 +2419,23 @@ tidy: tidy-.
|
||||
#
|
||||
# Removes build products and test logs. Retains ./configure outputs.
|
||||
#
|
||||
clean-.:
|
||||
clean: clean-. tidy
|
||||
clean: tidy
|
||||
rm -rf omittest* testrunner* testdir*
|
||||
|
||||
# Clean up everything. No exceptions.
|
||||
distclean-.:
|
||||
distclean: distclean-. clean
|
||||
#
|
||||
# Clean up everything. No exceptions. From an out-of-tree build which
|
||||
# starts in an empty directory, this should result in an empty
|
||||
# directory (assuming the user does not create new files in this
|
||||
# directory).
|
||||
#
|
||||
# The main distclean rules are in Makefile.in.
|
||||
#
|
||||
distclean: clean
|
||||
|
||||
|
||||
#
|
||||
# Show important variable settings.
|
||||
#
|
||||
show-variables:
|
||||
@echo "CC = $(CC)"
|
||||
@echo "B.cc = $(B.cc)"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
C Improvement\soutput\sfor\s".schema\s--indent"\sin\sthe\sCLI\swhen\sthe\sschema\scontains\npartial\sindexes\swith\slong\sand\scomplicated\sWHERE\sclauses.
|
||||
D 2025-03-05T16:30:36.389
|
||||
C Minor\sdoc\scorrections\sfor\sthe\ssahpool-digest\sfix\sand\smerge\sin\scurrent\strunk.
|
||||
D 2025-03-14T11:14:52.385
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
|
||||
F Makefile.in 4ff9b301b59c66ef9d11c8d133cc62e09173bad4abc7d5eb801e45d5527f8fe6
|
||||
F Makefile.in 88f74a1b9fcd903fe3414fe9f8484f8491dc403615dbf1c28c6f415f5220b8b2
|
||||
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
|
||||
F Makefile.msc 40a852813c2c84efd579f34b881f9169020284ac80d3d56463b88158e2f1c00e
|
||||
F Makefile.msc ef04498c7e227a0f459b105bb4952f26cc985d1d6340a367e62d5a79c4689dfb
|
||||
F README.md a953c0cffd6e4f2501a306c00ee2b6e1e6630c25031e094629307fe99dd003d1
|
||||
F VERSION 001dea55eb8304ec9130b6b44a32d3fc349f279d45a7e224fc0730c3cb8e2372
|
||||
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
|
||||
@@ -14,9 +14,9 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531
|
||||
F auto.def f39c4f3e58c8c2853555c7ec65c20701f8a42554d23dcb175a346a4f5ee5a36d
|
||||
F auto.def 0612f87776956cff7ba1585ad3ca7ab7d2e88735da0e9b4321dbacb05479cb94
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.in c9a7007181df2a07d08bd63c6ba395ed38705aa218789726951aabebec32ee27
|
||||
F autoconf/Makefile.in 6c98c82f52aa27a5c586080cf7c61c811174c2b6d8b8de33fd657d78d541dd7d
|
||||
F autoconf/Makefile.msc 5bc67d3912444c40c6f96d003e5c90663e51abb83d204a520110b1b2038dcd8b
|
||||
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
|
||||
F autoconf/README.txt 1a32296d8bbdd67110c79d224c92c05545a0b5bd0c272950025fe3c7c7b49580
|
||||
@@ -50,7 +50,7 @@ F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e
|
||||
F autosetup/jimsh0.c a57c16e65dcffc9c76e496757cb3f7fb47e01ecbd1631a0a5e01751fc856f049
|
||||
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
|
||||
F autosetup/proj.tcl e69b91f814ea510057ce7663845de703c3746d71cff9a0db6b2563ee3e7fd25e
|
||||
F autosetup/sqlite-config.tcl 1d0c70f372c464c9849dde898b5e778f73c72d8183c6e62634a45ee123e37f89
|
||||
F autosetup/sqlite-config.tcl 831985320d98002fcd5ea064cae8a49f8afcd9685d83178ef1ebb79189b5045c
|
||||
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
|
||||
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
|
||||
F contrib/sqlitecon.tcl eb4c6578e08dd353263958da0dc620f8400b869a50d06e271ab0be85a51a08d3
|
||||
@@ -59,9 +59,8 @@ F doc/compile-for-unix.md c9dce1ddd4bf0d25efccc5c63eb047e78c01ce06a6ff29c73e0a8a
|
||||
F doc/compile-for-windows.md 5141661e783c9ca9e3fd30e813345898712f5c311d71316f183db87038fa28a6
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
F doc/jsonb.md ede3238186e3a90bb79d20b2a6a06d0f9429a38e069e9da0efbad0f2ed48b924
|
||||
F doc/lemon.html 6aa6b6a75890bc71a6ad2b94e0723c273818b8b5e43b591eb483a6db0838441f
|
||||
F doc/lemon.html 7504a6dc9b56dd376a046833ea9cc8b08def93f19bfad6eab9f1a365a4b5f49a
|
||||
F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
|
||||
F doc/shared_schema.md 759fc374709fccf4e5d2d0cbd05f8fedd38fb022bdd8a6c5b5f492684c7023b9
|
||||
F doc/tcl-extension-testing.md 864875c3b672db79e7d42348dd726f9a4fbd852b1d8e5efcf09fe3d1ff6bf2a2
|
||||
F doc/testrunner.md 15583cf8c7d8a1c3378fd5d4319ca769a14c4d950a5df9b015d01d5be290dc69
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
@@ -76,7 +75,7 @@ F ext/expert/sqlite3expert.c cf4b1e5584862f486a4c6014ddb081831f1c512065dcf356446
|
||||
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
|
||||
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
|
||||
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
|
||||
F ext/fts3/README.syntax 6d0cbd8caa7ea34ecb0f0ae8278217180a8b7f24a1ea50ddf765383669f494a9
|
||||
F ext/fts3/README.syntax b72477722e9b4fe43f8403227d790a1c94221bfad15c27863a4b36d1052e892b
|
||||
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c fd2a8642fa4701ef5dd6bce7947ecb3c7ae472e1d44022772454a8b74a13155d
|
||||
@@ -410,11 +409,11 @@ F ext/misc/carray.c 34fac63770971611c5285de0a9f0ac67d504eaf66be891f637add9290f1c
|
||||
F ext/misc/carray.h 503209952ccf2431c7fd899ebb92bf46bf7635b38aace42ec8aa1b8d7b6e98a5
|
||||
F ext/misc/cksumvfs.c 3a7931dd30667be6348af919f3f9e6188dfd7646b42af8e399a499b327f5bd63
|
||||
F ext/misc/closure.c 87e0967772e0087e709887ce7ca9cf13aa32d2096e33b5d3382c8b8d477c6cb1
|
||||
F ext/misc/completion.c cb978c88d5577821323617a8ea775ce1b920e02dcdb593858f02044a4d008eea
|
||||
F ext/misc/completion.c c3c8b3cc1293c34f04f8746a3adfbfedb43f00d113f8c984a1ed09433317e507
|
||||
F ext/misc/compress.c 2c79a74330e0e0ba6cb3f7397f8ba5af12d46377ef5d3ee075e12dd8a6ed57f0
|
||||
F ext/misc/csv.c 7cae8c2666a058a58fb8994ed2457339a06c97d31c251d9a8445cdd966629890
|
||||
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
|
||||
F ext/misc/decimal.c 0e6edab8b055230e0ad0787d2e4b84b01f302168c7621042f7e6d7a3c1d98230
|
||||
F ext/misc/decimal.c 228d47e9ef4de60daf5851da19e3ac9ac1eda9e94432816914469501db6a1129
|
||||
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
|
||||
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
|
||||
F ext/misc/fileio.c 07cf3109ec6452789e3a989a010234e2a17b599ce82ea29212c948572456abac
|
||||
@@ -437,7 +436,7 @@ F ext/misc/regexp.c 388e7f237307c7dfbfb8dde44e097946f6c437801d63f0d7ad63f3320d4e
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
|
||||
F ext/misc/series.c 13c13768db923313c561851c7feb0adf5c456a40d01bf7c57051895f3e4b81c7
|
||||
F ext/misc/series.c 69e0d2b5d193c67bdfee5baf79c10ec24a61a40212c7ca9c219edf7afa24305f
|
||||
F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
|
||||
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
@@ -522,9 +521,9 @@ F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539c
|
||||
F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
|
||||
F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52bf293434305e2b1
|
||||
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
|
||||
F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
|
||||
F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
|
||||
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
|
||||
F ext/recover/sqlite3recover.c 788438a6735108d14ca82cf39c59abf8cde2ee384b962fb93e975eb24f2732fe
|
||||
F ext/recover/sqlite3recover.c 0ecdcb4df8967c84aa4dfe786816998bf2ef5cce55f4ac85ad4079e76f271027
|
||||
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
|
||||
F ext/recover/test_recover.c 072260d7452a3b81aba995b2b3269e7ec2aa7f06725544ba4c25b1b0a1dbc61a
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
@@ -619,7 +618,7 @@ F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009e
|
||||
F ext/session/sqlite3session.c 8011b9531c7dd8dce55226def022f3303ce40d0b45966877f2c35185f4b1c3fc
|
||||
F ext/session/sqlite3session.h aa5de3ec8ef0e5313e9f65dafd69e8ba292d170f07b57da9200c040068dab061
|
||||
F ext/session/test_session.c 12e0a2c15fd60f92da4bb29c697c9177ff0c0dbcdc5129a54c47e999f147937a
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
|
||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
|
||||
F ext/wasm/GNUmakefile 24d7e6f446528fa67f5ade6c3c7d7e46e1ac52649d6264cbe24539c1dab608e1
|
||||
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
|
||||
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
|
||||
@@ -628,7 +627,7 @@ F ext/wasm/SQLTester/SQLTester.mjs 66e1adc3d79467b68e3e40614fd42c1a577c7e219ec09
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs 57f2adb33f43f2784abbf8026c1bfd049d8013af1998e7dcb8b50c89ffc332e0
|
||||
F ext/wasm/SQLTester/index.html 64f3435084c7d6139b08d1f2a713828a73f68de2ae6a3112cbb5980d991ba06f
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c5eaceabb9e759aaae7d3101a4a3e542f96ab2c99d89a80ce20ec18c23115f33
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-core 2bcbbfe3b95c043ed6037e2708a2ee078d212dd1612c364f93588d8dc97300fe
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-extras fe40d6d758646e38f8b15f709044951e10884214f5453d35502100179c388c13
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||
@@ -646,11 +645,11 @@ F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644
|
||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 9654b565b346dc609b75d15337f20acfa7af7d9d558da1afeb9b6d8eaa404966
|
||||
F ext/wasm/api/sqlite3-vfs-helper.c-pp.js 3f828cc66758acb40e9c5b4dcfd87fd478a14c8fb7f0630264e6c7fa0e57515d
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 16d80af915bfd2529824b999b304425503094eedf34fb113d0791e002b13e5cf
|
||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 25d51a69084931c909a11e6850761ee156d9e243f733a42b221f3f90d70bd5ee
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4ab0704ee198de7d1059eccedc7703c931510b588d10af0ee36ea5b3ebbac284
|
||||
F ext/wasm/api/sqlite3-vtab-helper.c-pp.js e809739d71e8b35dfe1b55d24d91f02d04239e6aef7ca1ea92a15a29e704f616
|
||||
F ext/wasm/api/sqlite3-wasm.c 6a4cd40267eaf08400895c5b9de39c56976c3b97b3c1bbe53fc2e80fa074e9c7
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js c5ac33e39f21a3481812d7333ca6e18853640d423a01960ca8dbc6e7c5c3c21c
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc65debfe43b81fc39fb25c40ad0cc1946bd82580fbf644351107b544d6177ee
|
||||
F ext/wasm/api/sqlite3-worker1.c-pp.js 5e8706c2c4af2a57fbcdc02f4e7ef79869971bc21bb8ede777687786ce1c92d5
|
||||
F ext/wasm/batch-runner-sahpool.html e9a38fdeb36a13eac7b50241dfe7ae066fe3f51f5c0b0151e7baee5fce0d07a7
|
||||
F ext/wasm/batch-runner-sahpool.js 54a3ac228e6c4703fe72fb65c897e19156263a51fe9b7e21d2834a45e876aabd
|
||||
@@ -668,15 +667,15 @@ F ext/wasm/demo-123.js c7b3cca50c55841c381a9ca4f9396e5bbdc6114273d0b10a43e378e32
|
||||
F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
|
||||
F ext/wasm/demo-jsstorage.js 42131ddfa18e817d0e39ac63745e9ea31553980a5ebd2222e04d4fac60c19837
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.html 635cf90685805e21772a5f7a35d1ace80f98a9ef7c42ff04d7a125ddca7e5db8
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.js fcc628cb42fcfaf07d250477801de1e6deb1e319d003976612a0db8d76b9fccc
|
||||
F ext/wasm/demo-worker1-promiser.c-pp.js af168699d3cab1c27ad2364ebe06cd49db300bdbf404e23b00d5742ed52816ba
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js 08720227e98fa5b44761cf6e219269cee3e9dd0421d8d91459535da776950314
|
||||
F ext/wasm/dist.make 92ef4ffe33022a50f92d602acabad10bd8dd91759f3eb7df27fc6d7d37072b96
|
||||
F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
|
||||
F ext/wasm/fiddle.make c6d7a3d6cc03bb5f21acb295c1233820d0dbf5c6a89b28dc2e093edcc001c45a
|
||||
F ext/wasm/fiddle/fiddle-worker.js 850e66fce39b89d59e161d1abac43a181a4caa89ddeea162765d660277cd84ce
|
||||
F ext/wasm/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
|
||||
F ext/wasm/fiddle/fiddle.js 2a2f27b4be2674f501fff61c4a09e44dcf2295731a26b5c28e439f3a573bd269
|
||||
F ext/wasm/fiddle/index.html 7fcfb221165183bef0e05d5af9ceb79b527e799b1708ab05de0ec0eaebd5b7bf
|
||||
F ext/wasm/index-dist.html 56132399702b15d70c474c3f1952541e25cb0922942868f70daf188f024b3730
|
||||
F ext/wasm/index.html bcaa00eca521b372a6a62c7e7b17a870b0fcdf3e418a5921df1fd61e5344080d
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 6e4f26d0edb5c2e7d381b7eff1924832a040a12274afab2d1e1789027e9f6c5c
|
||||
@@ -697,16 +696,18 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
|
||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||
F ext/wasm/tester1.c-pp.js f3a3cbf0207287c4caa9f84b4e2934804e4b5720c71eaf143f33c8122bd3c9f2
|
||||
F ext/wasm/tester1.c-pp.js 419717b16e12703487a7ccf3ea4e63d693bdfbf7657e55a7e6c559bbccf027d3
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
|
||||
F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
F ext/wasm/tests/opfs/sahpool/digest-worker.js f8320caaf6368ee8c59f259de5bebe68232f678390dc773ee61c466e171881dc
|
||||
F ext/wasm/tests/opfs/sahpool/digest.html 08122dabf8ef56ac7d40f43660e178811166842bb47b37cbb11003030bb9ce09
|
||||
F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca01385e2732294b53f4c842328
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
|
||||
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
|
||||
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
|
||||
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
|
||||
F main.mk 178381be0b2cdcb14f49af1e0b0b679b6626089df9da097563333a265c67db32
|
||||
F main.mk f2f6af216cf14ec010d317e2f75ed5dc2134a2f9d6be7df3a96ee11149598ca1
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -716,9 +717,9 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
|
||||
F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
|
||||
F src/alter.c 4b855e10b66524fe39f3cc0fc19500593e0a0d7e9c77c17a5a8ad689356230e4
|
||||
F src/analyze.c b8662a13798064f01eef20d3f59e83f9f5b1860de131b526aec298180601f2de
|
||||
F src/attach.c 82a709d96b7043d9c9c52589e77ee5420415809d765405b0cc2f35894dd3fb13
|
||||
F src/alter.c 6a21a487290ed0990a0fac9db6b0b09c63de4b1cdaa6ba3fa3872e6f26b87768
|
||||
F src/analyze.c 13895d4da6ac857d95d3291dc607d492eba3ea1cbc3bc04baaa0383fbc1bb3d4
|
||||
F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
|
||||
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 782cc29b42b47e7ec6348eb0aaf9ffe60063f498387e7249f458d445af4b53e9
|
||||
@@ -726,8 +727,8 @@ F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
|
||||
F src/btree.c 00fcee37947641f48d4b529d96143e74d056b7afa8f26d61292c90ee59c056b2
|
||||
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
|
||||
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
|
||||
F src/build.c 259abd6d09b8692553bfa7670ff807091af1219d44d3ee467e283b99656878e0
|
||||
F src/callback.c dd68d54c81989e9ba846464ffc5cc122ac83fe6686fabc6cf38d9e0f480c6879
|
||||
F src/build.c 20793695ef64d2d0c147501e37f344f828f09f16d346a987b516316186030996
|
||||
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
|
||||
F src/dbpage.c 2e677acb658a29965e55398bbc61161cb7819da538057c8032adac7ab8e4a8c0
|
||||
@@ -746,7 +747,7 @@ F src/insert.c a5f0366266be993ebf533808f22cb7a788624805b55bc45424ceed3f48c54a16
|
||||
F src/json.c 81e2012796a0e139b18c50ee3444c8ef86a020ab360511882216f5b610657e0c
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 65ffb80350bf390245de6222bade5fcc69a4a93b8b70b880ec68b7776dd21ca0
|
||||
F src/main.c 5102588cbe7668d5ee19fd9945546e4f1fd99e41815432decf5dd29f01f55597
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -768,30 +769,30 @@ F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 410185df4900817c218c0efdb8064b3481af88cb3f7cea7392f820b6eebc7889
|
||||
F src/os_win.c 18a345cad65013f625bc8e1d7efdea40e7be5462c7bc38e84ca5fa8b125cef5d
|
||||
F src/os_win.c ab9912a2c1cb39a6429b8de919a5b63ad1c7775e511d748391c57bf9ad03bd29
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 9a40b9f6b1a4530905ac78914baba69e34f4f80ce86f53b010192df644adedc2
|
||||
F src/pager.c 9fbb541b46125dfa8914827575e6bb4d15048caa008073b1709112d495d7983b
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y e426d7323311554c75b0aebc426d0fe3c88d9777ffefed236f343ad9e661dc4c
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 78d4935e510f7bed0fdd1a3f742c0e663b36a795f9dc7411161dc22bdae1245e
|
||||
F src/pragma.c 22c184ba97a2d5880aae074edbcf3f862a0198b9d8f5ef1ee7ee96d883858f88
|
||||
F src/prepare.c 64fb8aaf3c0ad0a5a12472bd7f5ec8d2e569f186c555e6ad4bf962d751e30325
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
F src/pragma.c 30b535d0a66348df844ee36f890617b4cf45e9a22dcbc47ec3ca92909c50aaf1
|
||||
F src/prepare.c 1832be043fce7d489959aae6f994c452d023914714c4d5457beaed51c0f3d126
|
||||
F src/printf.c 33fc0d7643c848a098afdcb6e1db6de12379d47084b1cd0912cfce1d09345e44
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c a076f7db3a0fcbd9f710d7746cfc07e0b3baadee45eb3136bedc29c598ef8f1c
|
||||
F src/shell.c.in 5366b2a071d41784ce9bc87891c0d04cb469b122cdb632bafca3fad8d26a0b80
|
||||
F src/sqlite.h.in 7c58f9f9f7ed6d30d0783162f7d9f12ede11e833bac77b176aaa28aeca77bb12
|
||||
F src/select.c df63f64ef91c132dd12d37c876653f8b5493d2d5cf330a27158912ee5a065451
|
||||
F src/shell.c.in 248050551cad788f8bb4b4728e00d8e36a10130d2d101e55cd51cfee03df91ff
|
||||
F src/sqlite.h.in fd70afd92948cf7cc93f687ac960bad1b0b6fbc436752419eff2fd65a1809380
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h b6c47ecbe197adb620ce3d43415ff2d2519e53a5d634ec9c055ee193df72776c
|
||||
F src/sqliteInt.h 130217107c0425ab43d098c6eadf8aa2e1a037e26d79384127e2d950b27eec77
|
||||
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
|
||||
F src/status.c 9adeef15f9b2bd4a72ccd22b1f29e34dea6ca898baf420016332ba7e63f55539
|
||||
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 09d33ad9a35929f997d7152e9aa1d4d62757ce6e73d237dbe33f11261e4778ae
|
||||
F src/tclsqlite.c 254e69d6b4bc185ca2a3b186a92bda186aec9038063ebb9247b9b3181d4b4d4f
|
||||
F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395
|
||||
F src/test1.c ba7b93478a6a7a3f48ec5507f28bc662636ac5d9f9791700d3648a8e788f0bb2
|
||||
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
|
||||
@@ -806,7 +807,7 @@ F src/test_backup.c bd901e3c116c7f3b3bbbd4aae4ce87d99b400c9cbb0a9e7b4610af451d97
|
||||
F src/test_bestindex.c 3401bee51665cbf7f9ed2552b5795452a8b86365e4c9ece745b54155a55670c6
|
||||
F src/test_blob.c bcdf6a6c22d0bcc13c41479d63692ef413add2a4d30e1e26b9f74ab85b9fb4d5
|
||||
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
|
||||
F src/test_config.c 8b48024b0f240f1824ba801b72048c9a6344109292ee33a8eb7339d1a3689956
|
||||
F src/test_config.c 7f412406592794636d6226268e26d413850a9f799bc5f3c01afc2820b165fca8
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
|
||||
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
|
||||
@@ -830,11 +831,10 @@ F src/test_quota.c 744552848d9c5c5de3920d1c44b03d425a4123a223310567a199c7e0d3fe8
|
||||
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
F src/test_rtree.c d844d746a3cc027247318b970025a927f14772339c991f40e7911583ea5ed0d9
|
||||
F src/test_schema.c b06d3ddc3edc173c143878f3edb869dd200d57d918ae2f38820534f9a5e3d7d9
|
||||
F src/test_schemapool.c fc6c14f7a20fcf4fb76e56c7ce3a3bc7056e105efeb11a6476172d5d576b920d
|
||||
F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
|
||||
F src/test_superlock.c 18355ca274746aa6909e3744163e5deb1196a85d5bc64b9cd377273cef626da7
|
||||
F src/test_syscall.c 9ad7ab39910c16d29411678d91b0d27a7a996a718df5ee93dcd635e846d0275c
|
||||
F src/test_tclsh.c b2f529c87674301eb7ce168c6dd2d0a9030a0c75a0d88d85bcb0677195114249
|
||||
F src/test_tclsh.c c01706ac60bd3176754d3ccd37da74c6ad97c2e14489f8ed71b497c1c0ac0dd4
|
||||
F src/test_tclvar.c ae873248a0188459b1c16ca7cc431265dacce524399e8b46725c2b3b7e048424
|
||||
F src/test_thread.c d7a8bcea7445f37cc2a1f7f81dd6059634f45e0c61bfe80182b02872fb0328bb
|
||||
F src/test_vdbecov.c 5c426d9cd2b351f5f9ceb30cabf8c64a63bfcad644c507e0bd9ce2f6ae1a3bf3
|
||||
@@ -844,30 +844,30 @@ F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb7
|
||||
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 375a772e2342274f4bf73605a70633237da09deed00a9bf4c4816a56777ea7c9
|
||||
F src/tokenize.c 3e37ac2b6cbb9b0abe33827b0153c27595269afd7152b48019808974481aca2c
|
||||
F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc62279
|
||||
F src/trigger.c 24e5859e35eb5214ccea0da6924f0f90d41095091b0fc7247b6803e7d9a700f1
|
||||
F src/trigger.c da3c25786870d8bf97cd46b493374c2375d1abaf20a9b0f5f8629a3f2f2ce383
|
||||
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
|
||||
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
|
||||
F src/utf.c d4d55ca95106a2029ec1cdbd2497a34e69ea1d338f1a9d80ef15ebf4ff01690d
|
||||
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
|
||||
F src/vacuum.c 38577d6f45e10a984720b5219be09ca8649a0e600c2e5c11993900446caca609
|
||||
F src/vdbe.c dac8b4bf8e0a2451690aeb3a8384202e6498c8ec45477be0d0440b23fb52bce2
|
||||
F src/vdbe.h e56df3f84b08dfb60120796591af7d36fba8513a7df2605425189253f5a76d5f
|
||||
F src/vacuum.c fbfc3e074c865d2b5b10b8a65a3783275b80c152653590690747a102bb6cc770
|
||||
F src/vdbe.c 014769c8f7e528d59f5a8e25d0035258396cc2c755673dee29885b6049725ee6
|
||||
F src/vdbe.h 3d26d5c7660c5c7bd33ffb0d8784615072d8b23c81f8110870efe2631136bc89
|
||||
F src/vdbeInt.h 078b1c15b26587b54c1c1879d0d2f4dec812b9de4c337fed9faf73fbcc3bf091
|
||||
F src/vdbeapi.c cb8eb9e41a16f5fa3ce5b8f3910edfbba336d10156cfb7a79f92cf7bf443977b
|
||||
F src/vdbeaux.c 57b1ec1862d5d081294e3f266a20128837f21774215134b96a883b5d3cf8a70f
|
||||
F src/vdbeblob.c e14d9eca0cce3ec4fbef69cea8cc4caefb9f8d642cc4703123a56c43dfa470d3
|
||||
F src/vdbeaux.c d7ef1a0a7233589d789eda1ba9ffa4b0ea61fca9651e4f47fb4250d03d62bcaf
|
||||
F src/vdbeblob.c b1b4032cac46b41e44b957c4d00aee9851f862dfd85ecb68116ba49884b03dfd
|
||||
F src/vdbemem.c 571ae3116dbf840a62c4aaa6bc09d577dfef8ad4d3978cf37275bb5f9653217b
|
||||
F src/vdbesort.c f7ce6eb4c0e8b0273329d2f43b8b6e5ebe8f2d853fc323d5787dada702ea0b66
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
|
||||
F src/vtab.c 0c2567d6caa2f1df28362eedcd29a2fbc9f4d7a7ff6b13086cc23f4e6ab239c5
|
||||
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 2c69a5f92270429db72d853691b0640c76c671d5b2465396dadb9d9873e1efce
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
|
||||
F src/where.c 4ef72b4d791fb1b6725d6fbebd17e5a9487105864c7828a7b0311136c08786ce
|
||||
F src/where.c 12cca5dfbe96e2589f951c43c0720fc58e52611787c37d85a0d9c10376202e8b
|
||||
F src/whereInt.h d20cddddb1d61b18d5cb1fcfa9b77fbeebbc4afe44d996e603452a23b3009ee1
|
||||
F src/wherecode.c 5baa06f0daae7d38aca1d4814030b82ad4f127fe6bad18f0644776a474f6088b
|
||||
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
|
||||
@@ -1487,7 +1487,7 @@ F test/mutex1.test 42cb5e244c3a77bb0ef2b967e06fa5e7ba7d32d90a9b20bed98f6f5ede185
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test 73ea63ab43668313e2f8cc9ef9e9a966672c7934f3ce76926fbe991235d07d91
|
||||
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
|
||||
F test/nolock.test 284c72c2b752cf3ffbfd224dfa868bd524e624d3ab5c5ef181fc49ad9df0b444
|
||||
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
|
||||
F test/normalize.test f23b6c5926c59548635fcf39678ac613e726121e073dd902a3062fbb83903b72
|
||||
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
@@ -1560,9 +1560,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
|
||||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/readonly.test 69a7ccec846cad2e000b3539d56360d02f327061dc5e41f7f9a3e01f19719952
|
||||
F test/readonly2.test 4f4c451adf06e314c3eeed5c5e01e5df8fa10fb3cd5f537a77a48ef50ed97b84
|
||||
F test/readonlyfault.test 2b9c98ed3ac47e3f3cb00db3850b4d7fc7c857be1502a7b74985fecf50837b1e
|
||||
F test/recover.test a163a156ea9f2beea63fa83c4dcd8dea6e57b8a569fc647155e3d2754eaac1b5
|
||||
F test/recover.test c76d05f33f0271fba0f0752170e03b0ab5952dc61dcea7ab3ba40df03c4c42de
|
||||
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
|
||||
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
|
||||
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
|
||||
@@ -1570,13 +1568,6 @@ F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/returning1.test 212cd4111bb941a60abf608f20250db666c21eb1bc4d49217e96c87ff3ab9d1a
|
||||
F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
|
||||
F test/reuse1.test b5359932592b25d2178cd1ce0cd837abb25b68aaf69c4812eb83efa490c2dd19
|
||||
F test/reuse2.test 4012db85142e2abe3d8a1186756a71ea6e7078091f7448ac2145ca7b8c18cc51
|
||||
F test/reuse3.test 890074bbfc31f71762d583ee23a22c647870b2c2e91eb1eb60c2b5a5d3d8986b
|
||||
F test/reuse4.test bf36ee3848534f64234f84389fe8f2289da353cc0535cfe62b9287e32786f755
|
||||
F test/reuse5.test bbe6cf7384ef90f134392edd93d626385ef0bf6f40eefc3d993535cd0861d83b
|
||||
F test/reuse6.test f4674f9967aee2a0b49c02832120b8b495291c0d87aae084c54e6c0cc18132fe
|
||||
F test/reusefault.test 545a21be1b80b8ccab02c3695137ab2bb1fc58ac78738b5bf33348a618ee3b2e
|
||||
F test/rollback.test 952c4d805bca96adc2be76f621ea22115fe40b330015af36fcc8028c8547fcee
|
||||
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
|
||||
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
@@ -1637,7 +1628,7 @@ F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b787
|
||||
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
|
||||
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
|
||||
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
|
||||
F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
|
||||
F test/shared.test c99510b83a6ad650d7335e4733568b9d7b4f5ee88f4f2167b6138950a795b537
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
|
||||
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
|
||||
@@ -1657,7 +1648,7 @@ F test/shell5.test 0e5f8ce08206b9998a778cfe1989e20e47839153c05af2da29198150172e2
|
||||
F test/shell6.test e3b883b61d4916b6906678a35f9d19054861123ad91b856461e0a456273bdbb8
|
||||
F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d5c3
|
||||
F test/shell8.test aea51ecbcd4494c746b096aeff51d841d04d5f0dc4b62eb42427f16109b87acd
|
||||
F test/shell9.test 8030c6246e1ca474c65eb0e955324586bfbf3448289c99ca247fc7f62006ac2c
|
||||
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
|
||||
F test/shellA.test 079c05c11947ade4ea8d51053d3abb687ec96a3dce6680d01838519b705190c5
|
||||
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
@@ -1728,11 +1719,11 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test 7be82bd50c7ede7f01b2dd17cd1b84f352c516078222d0b067d858f081e3f9a7
|
||||
F test/tabfunc01.test 66d1ea27289c19317bf111744a4d5fda901759945d22ddb5bc964641fc38c185
|
||||
F test/table.test 7862a00b58b5541511a26757ea9c5c7c3f8298766e98aa099deec703d9c0a8e0
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 350536a4233914aa437b6735e3e8e683e921a71ced8fa9fb5396057a04dbea33
|
||||
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
@@ -1740,9 +1731,9 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl d067f95c685087f9e66efa2c4cefa5d99cd72ebeab2a7dceae89cba100ad61f7
|
||||
F test/testrunner.tcl fafc60461c165a6b53a879f090423eef7005d95f9692c7df798651b55e339fe6 x
|
||||
F test/testrunner_data.tcl 6aea1cb5865f005986037c9dad4dfe48a5281ec7aa214104e8ada3199332242b
|
||||
F test/tester.tcl 2244752d5dd5135c03370fa09fec3d02c87440521ca600c09c635b1c2cded9ef
|
||||
F test/testrunner.tcl 0ffa67806e75aa2c186c63d7d00b16bb45adb91ed6560461fda6dbe3e18c885e x
|
||||
F test/testrunner_data.tcl 6d7e7824bb36278ea65c33f7da6dd3ca101fc7d6f7a765b807dce0aa68c52521
|
||||
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
|
||||
F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1754,7 +1745,7 @@ F test/thread3.test a12656a56cdf67acb6a2ff7638826c6d6a645f79909d86df521045ad31cf
|
||||
F test/thread_common.tcl b3b19a769fe30ef5537cdfa60acd49b78f771301627720d1add2d3bac77d9039
|
||||
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
|
||||
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
|
||||
F test/threadtest3.c 25cb92accb4fa6d53e708d6006ed2db7a7533ef7b838ef1306455c6fe57e978a
|
||||
F test/threadtest3.c 655bff6c0895ec03f014126aa65e808fac9aae8c5a7a7da58a510cbe8b43b781
|
||||
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
|
||||
F test/threadtest5.c 9b4d782c58d8915d7e955ff8051f3d03628bda0d33b82971ea8c0f2f2808c421
|
||||
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
|
||||
@@ -1929,13 +1920,12 @@ F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123
|
||||
F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
|
||||
F test/triggerupfrom.test d1f9e56090408115c522bee626cc33a2f3370f627a5e341d832589d72e3aa271
|
||||
F test/trustschema1.test d2996bb284859c99956ac706160eab9f086919da738d19bfef3ac431cce8fd47
|
||||
F test/tt3_checkpoint.c 69214e2ce81bbbd3c1b82c31e103607fd2e6790818aef4792957fc9cc88d067e
|
||||
F test/tt3_index.c 95592839426dc85ce5a7a57b41be2cbf3c2ec3457b9cd841a06ed5877f712c7c
|
||||
F test/tt3_lookaside1.c 2ddd99bfffeef288f0786827ef68f912f6f47ce3d3184e62f05808d8e13b920e
|
||||
F test/tt3_reuseschema.c 4d52e141f89f009028d8ab0bd1f0697d0edffa94bafc1fff0f7ad4d9d9baa549
|
||||
F test/tt3_checkpoint.c ac7ca661d739280c89d9c253897df64a59a49369bd1247207ac0f655b622579d
|
||||
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
|
||||
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
|
||||
F test/tt3_shared.c b37d22defc944a2ac4c91c927fd06c1d48cd51e2ce9d004fe868625bd2399f93
|
||||
F test/tt3_stress.c 077e817ac1168443b075fedb44e92db84bb4dc5bd3b6fe1aba25c94ac280b231
|
||||
F test/tt3_vacuum.c 727bfda1299b18435eeba80dee8e6ff43462146d7c1e2096cc809f01db568391
|
||||
F test/tt3_stress.c f9a769ca8b026ecc76ee93ca8c9700a5619f8e51c581107c4053ba6ac97f616f
|
||||
F test/tt3_vacuum.c 71b254cde1fc49d6c8c44efd54f4668f3e57d7b3a8f4601ade069f75a999ba39
|
||||
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
|
||||
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
|
||||
F test/types3.test c60e89c4d6babe44b23a2ea0090f3044e549403b20648b1c6bb65a69fea5f1ed
|
||||
@@ -2040,7 +2030,7 @@ F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c
|
||||
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
|
||||
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
|
||||
F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533442b
|
||||
F test/walsetlk.test 9c5b92f9a20252540fedf9ffa6ee3d1b8af08ea4b80d0144d9b88e6c0c1de80d
|
||||
F test/walsetlk.test aaa418dc2c11002b3e270f8128235a3bbb846796907095a0a02bf0f0bbf8512e
|
||||
F test/walsetlk2.test 9097083633cdf55bf1098b694fb8651d0356d38fef28b869481d18029d7ceaf4
|
||||
F test/walsetlk3.test 1b82bd92dea7e58f498b4399b0b3d26773dd8ac5c74205ce4a23c207cb8e85fe
|
||||
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
|
||||
@@ -2152,7 +2142,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 5f999ac3801e8b585149a5fd5c7c2bbdde3baca98985ebe68e1a41b8e19d19a4
|
||||
F tool/lemon.c f51a488369046cd4f4212d755a214a57673ded400cbeb01e298cbf63539e1d8c
|
||||
F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
@@ -2168,7 +2158,7 @@ F tool/mkmsvcmin.tcl d76c45efda1cce2d4005bcea7b8a22bb752e3256009f331120fb4fecb14
|
||||
F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
|
||||
F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 7650ca1297ef7530179c149db50311e9c533c6accd8df3505275529a10e82137
|
||||
F tool/mkpragmatab.tcl 3801ce32f8c55fe63a3b279f231fb26c2c1a2ea9a09d2dd599239d87a609acec
|
||||
F tool/mkshellc.tcl 9ce74de0fa904a2c56a96f8d8b5261246bacb0eaa8d7e184f9e18ff94145ebbc
|
||||
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
@@ -2205,7 +2195,7 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
|
||||
F tool/split-sqlite3c.tcl 07e18a1d8cc3f6b3a4a1f3528e63c9b29a5c8a7bca0b8d394b231da464ce1247
|
||||
F tool/sqldiff.c 134be7866be19f8beb32043d5aea5657f01aaeae2df8d33d758ff722c78666b9
|
||||
F tool/sqlite3_analyzer.c.in fc7735c499d226a49d843d8209b2543e4e5229eeb71a674c331323a2217b65b4
|
||||
F tool/sqlite3_analyzer.c.in 5a2984ac457a49c7ad4f0924c738df55aafdc97661e912fd99c5cfcdfd4725fd
|
||||
F tool/sqlite3_rsync.c 9a1cca2ab1271c59b37a6493c15dc1bcd0ab9149197a9125926bc08dd26b83fb
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
@@ -2225,8 +2215,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 52b97a7ad5d944e44240f624b30a76398d10ef945d8edc4b7d7b36ed2e515327
|
||||
R 8f505da43903c156f4ae84ef87ecfc5e
|
||||
U drh
|
||||
Z 684998f2296e83c5d595e837037d9498
|
||||
P fc1eeb7d1f2880907b0fe71a8c572dd7cd74a5d65ec0177332976ad2f8c2b216 f786de8d1873cd27b1bf83273a1e100e9d481144674888ccf65974e003a3caad
|
||||
R 1281ce5a1bf5b175e155c185d7f4bb6f
|
||||
U stephan
|
||||
Z f4da5ec6a61829129290a8d77df27ca0
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
94c6e8d97158fde5c8200206cf21e8acc9de8d1b4cbaf7db8d9c6a56ad6762e4
|
||||
500f2e6ec74b4c0e4ac0365ba4e0d81ed6df8dd09dc0f8af65d294c3453f8865
|
||||
|
||||
+8
-3
@@ -112,8 +112,8 @@ static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
if( v ){
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb, 0, p5);
|
||||
if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse, 1, 0, p5);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);
|
||||
if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,6 +1136,7 @@ static int renameParseSql(
|
||||
int bTemp /* True if SQL is from temp schema */
|
||||
){
|
||||
int rc;
|
||||
u64 flags;
|
||||
|
||||
sqlite3ParseObjectInit(p, db);
|
||||
if( zSql==0 ){
|
||||
@@ -1154,7 +1155,11 @@ static int renameParseSql(
|
||||
p->eParseMode = PARSE_MODE_RENAME;
|
||||
p->db = db;
|
||||
p->nQueryLoop = 1;
|
||||
flags = db->flags;
|
||||
testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );
|
||||
db->flags |= SQLITE_Comments;
|
||||
rc = sqlite3RunParser(p, zSql);
|
||||
db->flags = flags;
|
||||
if( db->mallocFailed ) rc = SQLITE_NOMEM;
|
||||
if( rc==SQLITE_OK
|
||||
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
|
||||
@@ -2050,7 +2055,7 @@ static void renameTableTest(
|
||||
u64 flags = db->flags;
|
||||
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
|
||||
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
|
||||
db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
|
||||
db->flags = flags;
|
||||
if( rc==SQLITE_OK ){
|
||||
if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
|
||||
NameContext sNC;
|
||||
|
||||
@@ -212,7 +212,6 @@ static void openStatTable(
|
||||
** side-effect of the CREATE TABLE statement is to leave the rootpage
|
||||
** of the new table in register pParse->regRoot. This is important
|
||||
** because the OpenWrite opcode below will be needing it. */
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
sqlite3NestedParse(pParse,
|
||||
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
|
||||
);
|
||||
|
||||
+5
-8
@@ -224,6 +224,7 @@ static void attachFunc(
|
||||
** way we found it.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3BtreeEnterAll(db);
|
||||
db->init.iDb = 0;
|
||||
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
|
||||
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
||||
@@ -233,12 +234,11 @@ static void attachFunc(
|
||||
sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val);
|
||||
}
|
||||
#endif
|
||||
if( !IsSharedSchema(db) && !REOPEN_AS_MEMDB(db) ){
|
||||
sqlite3BtreeEnterAll(db);
|
||||
if( !REOPEN_AS_MEMDB(db) ){
|
||||
rc = sqlite3Init(db, &zErrDyn);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
assert( zErrDyn==0 || rc!=SQLITE_OK );
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
assert( zErrDyn==0 || rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc ){
|
||||
if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){
|
||||
@@ -329,7 +329,6 @@ static void detachFunc(
|
||||
pEntry = sqliteHashNext(pEntry);
|
||||
}
|
||||
|
||||
(void)sqlite3SchemaDisconnect(db, i, 0);
|
||||
sqlite3BtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
pDb->pSchema = 0;
|
||||
@@ -359,9 +358,7 @@ static void codeAttach(
|
||||
sqlite3* db = pParse->db;
|
||||
int regArgs;
|
||||
|
||||
if( (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end;
|
||||
}
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end;
|
||||
|
||||
if( pParse->nErr ) goto attach_end;
|
||||
memset(&sName, 0, sizeof(NameContext));
|
||||
|
||||
+61
-89
@@ -322,39 +322,6 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
pParse->nested--;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
/*
|
||||
** If this database connection was opened with the SQLITE_OPEN_SHARED_SCHEMA
|
||||
** flag specified, then ensure that the database schema for database iDb
|
||||
** is loaded. Either by obtaining a Schema object from the schema-pool, or
|
||||
** by reading the contents of the sqlite_master table. Unless it is NULL,
|
||||
** the location indicated by parameter pbUnload is set to 1 if a shared-schema
|
||||
** is loaded.
|
||||
**
|
||||
** If the database handle was not opened with SQLITE_OPEN_SHARED_SCHEMA, or
|
||||
** if the schema for database iDb is already loaded, this function is a no-op.
|
||||
**
|
||||
** SQLITE_OK is returned if successful, or an SQLite error code otherwise. If
|
||||
** an error code is returned, (*pzErr) may be set to point to a buffer
|
||||
** containing an error message. It is the responsibility of the caller to
|
||||
** eventually free this buffer using sqlite3_free().
|
||||
*/
|
||||
int sqlite3SchemaLoad(sqlite3 *db, int iDb, int *pbUnload, char **pzErr){
|
||||
int rc = SQLITE_OK;
|
||||
if( IsSharedSchema(db)
|
||||
&& DbHasProperty(db, iDb, DB_SchemaLoaded)==0
|
||||
&& (db->init.busy==0 || (iDb!=1 && db->init.iDb==1))
|
||||
){
|
||||
struct sqlite3InitInfo sv = db->init;
|
||||
memset(&db->init, 0, sizeof(struct sqlite3InitInfo));
|
||||
rc = sqlite3InitOne(db, iDb, pzErr, 0);
|
||||
db->init = sv;
|
||||
if( pbUnload && rc==SQLITE_OK && iDb!=1 ) *pbUnload = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Locate the in-memory structure that describes a particular database
|
||||
** table given the name of that table and (optionally) the name of the
|
||||
@@ -373,41 +340,59 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
|
||||
|
||||
/* All mutexes are required for schema access. Make sure we hold them. */
|
||||
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
while(1){
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDatabase==0 || sqlite3DbIsNamed(db, j, zDatabase) ){
|
||||
int bUnload = 0;
|
||||
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
||||
if( IsSharedSchema(db) ){
|
||||
Parse *pParse = db->pParse;
|
||||
if( pParse && pParse->nErr==0 ){
|
||||
pParse->rc = sqlite3SchemaLoad(db, j, &bUnload, &pParse->zErrMsg);
|
||||
if( pParse->rc ) pParse->nErr++;
|
||||
}
|
||||
if( zDatabase ){
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
|
||||
}
|
||||
if( i>=db->nDb ){
|
||||
/* No match against the official names. But always match "main"
|
||||
** to schema 0 as a legacy fallback. */
|
||||
if( sqlite3StrICmp(zDatabase,"main")==0 ){
|
||||
i = 0;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
|
||||
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
|
||||
if( i==1 ){
|
||||
if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0
|
||||
|| sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0
|
||||
|| sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0
|
||||
){
|
||||
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
|
||||
LEGACY_TEMP_SCHEMA_TABLE);
|
||||
}
|
||||
p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
|
||||
if( p ) return p;
|
||||
if( bUnload ){
|
||||
sqlite3SchemaRelease(db, j);
|
||||
}else{
|
||||
if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
|
||||
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
|
||||
LEGACY_SCHEMA_TABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Not found. If the name we were looking for was temp.sqlite_master
|
||||
** then change the name to sqlite_temp_master and try again. */
|
||||
if( sqlite3StrICmp(zName, PREFERRED_SCHEMA_TABLE)==0 ){
|
||||
zName = LEGACY_SCHEMA_TABLE;
|
||||
continue;
|
||||
}else{
|
||||
/* Match against TEMP first */
|
||||
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
|
||||
if( p ) return p;
|
||||
/* The main database is second */
|
||||
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
|
||||
if( p ) return p;
|
||||
/* Attached databases are in order of attachment */
|
||||
for(i=2; i<db->nDb; i++){
|
||||
assert( sqlite3SchemaMutexHeld(db, i, 0) );
|
||||
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
|
||||
if( p ) break;
|
||||
}
|
||||
if( sqlite3StrICmp(zName, PREFERRED_TEMP_SCHEMA_TABLE)==0 ){
|
||||
zName = LEGACY_TEMP_SCHEMA_TABLE;
|
||||
continue;
|
||||
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
|
||||
if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
|
||||
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE);
|
||||
}else if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
|
||||
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
|
||||
LEGACY_TEMP_SCHEMA_TABLE);
|
||||
}
|
||||
}
|
||||
if( sqlite3StrICmp(zName, LEGACY_SCHEMA_TABLE)!=0 ) break;
|
||||
if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
|
||||
zName = LEGACY_TEMP_SCHEMA_TABLE;
|
||||
}
|
||||
return 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -432,7 +417,6 @@ Table *sqlite3LocateTable(
|
||||
/* Read the database schema. If an error occurs, leave an error message
|
||||
** and code in pParse and return NULL. */
|
||||
if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
|
||||
&& !IsSharedSchema(db)
|
||||
&& SQLITE_OK!=sqlite3ReadSchema(pParse)
|
||||
){
|
||||
return 0;
|
||||
@@ -449,21 +433,9 @@ Table *sqlite3LocateTable(
|
||||
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
|
||||
pMod = sqlite3PragmaVtabRegister(db, zName);
|
||||
}
|
||||
if( pMod ){
|
||||
if( IsSharedSchema(db) && pParse->nErr==0 ){
|
||||
int bDummy = 0;
|
||||
pParse->rc = sqlite3SchemaLoad(db, 0, &bDummy, &pParse->zErrMsg);
|
||||
if( pParse->rc ) pParse->nErr++;
|
||||
(void)bDummy;
|
||||
}
|
||||
if( sqlite3VtabEponymousTableInit(pParse, pMod) ){
|
||||
Table *pEpoTab = pMod->pEpoTab;
|
||||
if( pEpoTab ){
|
||||
assert( IsSharedSchema(db)||pEpoTab->pSchema==db->aDb[0].pSchema );
|
||||
pEpoTab->pSchema = db->aDb[0].pSchema; /* For SHARED_SCHEMA mode */
|
||||
}
|
||||
return pEpoTab;
|
||||
}
|
||||
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
|
||||
testcase( pMod->pEpoTab==0 );
|
||||
return pMod->pEpoTab;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -473,13 +445,15 @@ Table *sqlite3LocateTable(
|
||||
p = 0;
|
||||
}
|
||||
|
||||
if( p==0 && (!IsSharedSchema(db) || pParse->nErr==0) ){
|
||||
if( p==0 ){
|
||||
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
|
||||
if( zDbase ){
|
||||
sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
|
||||
}else{
|
||||
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
|
||||
}
|
||||
}else{
|
||||
assert( HasRowid(p) || p->iPKey<0 );
|
||||
}
|
||||
|
||||
return p;
|
||||
@@ -648,10 +622,11 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
|
||||
DbSetProperty(db, 1, DB_ResetWanted);
|
||||
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
|
||||
}
|
||||
|
||||
if( db->nSchemaLock==0 ){
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( DbHasProperty(db, i, DB_ResetWanted) ){
|
||||
sqlite3SchemaClearOrDisconnect(db, i);
|
||||
sqlite3SchemaClear(db->aDb[i].pSchema);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -664,17 +639,16 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
|
||||
void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
|
||||
int i;
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; i<db->nDb; i=(i?i+1:2)){
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Db *pDb = &db->aDb[i];
|
||||
if( pDb->pSchema ){
|
||||
if( db->nSchemaLock==0 ){
|
||||
sqlite3SchemaClearOrDisconnect(db, i);
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}else{
|
||||
DbSetProperty(db, i, DB_ResetWanted);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3SchemaClear(db->aDb[1].pSchema);
|
||||
db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
|
||||
sqlite3VtabUnlockList(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
@@ -1291,7 +1265,7 @@ void sqlite3StartTable(
|
||||
*/
|
||||
if( !IN_SPECIAL_PARSE ){
|
||||
char *zDb = db->aDb[iDb].zDbSName;
|
||||
if( !IsSharedSchema(db) && SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
goto begin_table_error;
|
||||
}
|
||||
pTable = sqlite3FindTable(db, zName, zDb);
|
||||
@@ -2941,7 +2915,7 @@ void sqlite3EndTable(
|
||||
#endif
|
||||
|
||||
/* Reparse everything to update our internal data structures */
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb,
|
||||
sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
|
||||
|
||||
/* Test for cycles in generated columns and illegal expressions
|
||||
@@ -3513,7 +3487,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
assert( pName->nSrc==1 );
|
||||
assert( pName->a[0].fg.fixedSchema==0 );
|
||||
assert( pName->a[0].fg.isSubquery==0 );
|
||||
if( !IsSharedSchema(db) && sqlite3ReadSchema(pParse) ) goto exit_drop_table;
|
||||
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
|
||||
if( noErr ) db->suppressErr++;
|
||||
assert( isView==0 || isView==LOCATE_VIEW );
|
||||
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
|
||||
@@ -3528,7 +3502,6 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
|
||||
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
|
||||
** it is initialized.
|
||||
@@ -3985,7 +3958,7 @@ void sqlite3CreateIndex(
|
||||
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( !IsSharedSchema(db) && SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( sqlite3HasExplicitNulls(pParse, pList) ){
|
||||
@@ -4482,7 +4455,7 @@ void sqlite3CreateIndex(
|
||||
if( pTblName ){
|
||||
sqlite3RefillIndex(pParse, pIndex, iMem);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb,
|
||||
sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
|
||||
}
|
||||
@@ -4634,7 +4607,6 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code = SQLITE_DROP_INDEX;
|
||||
|
||||
+6
-365
@@ -16,63 +16,6 @@
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Connections opened with the SQLITE_OPEN_SHARED_SCHEMA flag specified
|
||||
** may use SchemaPool objects for any database that is not the temp db
|
||||
** (iDb==1). For such databases (type "struct Db") there are three states
|
||||
** the Schema/SchemaPool object may be in.
|
||||
**
|
||||
** 1) pSPool==0, pSchema points to an empty object allocated by
|
||||
** sqlite3_malloc(). DB_SchemaLoaded flag is clear.
|
||||
**
|
||||
** 2) pSPool!=0, pSchema points to a populated object owned by the
|
||||
** SchemaPool. DB_SchemaLoaded flag is set.
|
||||
**
|
||||
** 3) pSPool!=0, pSchema points to the SchemaPool's static object
|
||||
** (SchemaPool.sSchema).
|
||||
*/
|
||||
struct SchemaPool {
|
||||
int nRef; /* Number of pointers to this object */
|
||||
int nDelete; /* Schema objects deleted by ReleaseAll() */
|
||||
u64 cksum; /* Checksum for this Schema contents */
|
||||
Schema *pSchema; /* Linked list of Schema objects */
|
||||
Schema sSchema; /* The single dummy schema object */
|
||||
SchemaPool *pNext; /* Next element in schemaPoolList */
|
||||
};
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
#ifdef SQLITE_DEBUG
|
||||
static void assert_schema_state_ok(sqlite3 *db){
|
||||
if( IsSharedSchema(db) && db->eOpenState!=SQLITE_STATE_ZOMBIE ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( i!=1 ){
|
||||
Db *pDb = &db->aDb[i];
|
||||
Btree *pBt = pDb->pBt;
|
||||
if( pBt==0 ) continue;
|
||||
assert( sqlite3BtreeSchema(pBt, 0, 0)==0 );
|
||||
assert( pDb->pSchema );
|
||||
if( pDb->pSPool ){
|
||||
if( DbHasProperty(db, i, DB_SchemaLoaded)==0 ){
|
||||
assert( pDb->pSchema->tblHash.count==0 );
|
||||
assert( pDb->pSchema==&pDb->pSPool->sSchema );
|
||||
}else{
|
||||
assert( pDb->pSchema!=&pDb->pSPool->sSchema );
|
||||
}
|
||||
}else{
|
||||
assert( DbHasProperty(db, i, DB_SchemaLoaded)==0 );
|
||||
assert( pDb->pSchema->tblHash.count==0 );
|
||||
assert( pDb->pSchema!=&pDb->pSPool->sSchema );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define assert_schema_state_ok(x)
|
||||
#endif
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
|
||||
/*
|
||||
** Invoke the 'collation needed' callback to request a collation sequence
|
||||
** in the encoding enc of name zName, length nName.
|
||||
@@ -580,317 +523,15 @@ void sqlite3SchemaClear(void *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** If this database was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
|
||||
** and iDb!=1, then disconnect from the schema-pool associated with
|
||||
** database iDb. Otherwise, clear the Schema object belonging to
|
||||
** database iDb.
|
||||
**
|
||||
** If an OOM error occurs while disconnecting from a schema-pool,
|
||||
** the db->mallocFailed flag is set.
|
||||
*/
|
||||
void sqlite3SchemaClearOrDisconnect(sqlite3 *db, int iDb){
|
||||
Db *pDb = &db->aDb[iDb];
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) && iDb!=1 && pDb->pSPool ){
|
||||
sqlite3SchemaDisconnect(db, iDb, 1);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
/*
|
||||
** Global linked list of SchemaPool objects. Read and write access must
|
||||
** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex.
|
||||
*/
|
||||
static SchemaPool *SQLITE_WSD schemaPoolList = 0;
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
/*
|
||||
** Return a pointer to the head of the linked list of SchemaPool objects.
|
||||
** This is used by the virtual table in file test_schemapool.c.
|
||||
*/
|
||||
SchemaPool *sqlite3SchemaPoolList(void){ return schemaPoolList; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Database handle db was opened with the SHARED_SCHEMA flag, and database
|
||||
** iDb is currently connected to a schema-pool. When this function is called,
|
||||
** (*pnByte) is set to nInit plus the amount of memory used to store a
|
||||
** single instance of the Schema objects managed by the schema-pool.
|
||||
** This function adjusts (*pnByte) sot hat it is set to nInit plus
|
||||
** (nSchema/nRef) of the amount of memory used by a single Schema object,
|
||||
** where nSchema is the number of Schema objects allocated by this pool,
|
||||
** and nRef is the number of connections to the schema-pool.
|
||||
*/
|
||||
void sqlite3SchemaAdjustUsed(sqlite3 *db, int iDb, int nInit, int *pnByte){
|
||||
SchemaPool *pSPool = db->aDb[iDb].pSPool;
|
||||
int nSchema = 0;
|
||||
Schema *p;
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
for(p=pSPool->pSchema; p; p=p->pNext){
|
||||
nSchema++;
|
||||
}
|
||||
*pnByte = nInit + ((*pnByte - nInit) * nSchema) / pSPool->nRef;
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
}
|
||||
|
||||
/*
|
||||
** Check that the schema of db iDb is writable (either because it is the
|
||||
** temp db schema or because the db handle was opened without
|
||||
** SQLITE_OPEN_SHARED_SCHEMA). If so, do nothing. Otherwise, leave an
|
||||
** error in the Parse object.
|
||||
*/
|
||||
void sqlite3SchemaWritable(Parse *pParse, int iDb){
|
||||
if( iDb!=1 && IsSharedSchema(pParse->db) && IN_DECLARE_VTAB==0 ){
|
||||
sqlite3ErrorMsg(pParse, "attempt to modify read-only schema");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The schema object passed as the only argument was allocated using
|
||||
** sqlite3_malloc() and then populated using the usual mechanism. This
|
||||
** function frees both the Schema object and its contents.
|
||||
*/
|
||||
static void schemaDelete(Schema *pSchema){
|
||||
sqlite3SchemaClear((void*)pSchema);
|
||||
sqlite3_free(pSchema);
|
||||
}
|
||||
|
||||
/*
|
||||
** When this function is called, the database connection Db must be
|
||||
** using a schema-pool (Db.pSPool!=0) and must currently have Db.pSchema
|
||||
** set to point to a populated schema object checked out from the
|
||||
** schema-pool. It is also assumed that the STATIC_MASTER mutex is held.
|
||||
** This function returns the Schema object to the schema-pool and sets
|
||||
** Db.pSchema to point to the schema-pool's static, empty, Schema object.
|
||||
*/
|
||||
static void schemaRelease(sqlite3 *db, Db *pDb){
|
||||
Schema *pRelease = pDb->pSchema;
|
||||
SchemaPool *pSPool = pDb->pSPool;
|
||||
|
||||
assert( pDb->pSchema->iGeneration==pSPool->sSchema.iGeneration );
|
||||
pDb->pSchema = &pSPool->sSchema;
|
||||
|
||||
assert( pDb->pSPool && pRelease );
|
||||
assert( pRelease->schemaFlags & DB_SchemaLoaded );
|
||||
assert( (pDb->pSchema->schemaFlags & DB_SchemaLoaded)==0 );
|
||||
assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
|
||||
|
||||
/* If the DBFLAG_FreeSchema flag is set and the database connection holds
|
||||
** at least one other copy of the schema being released, delete it instead
|
||||
** of returning it to the schema-pool. */
|
||||
if( db->mDbFlags & DBFLAG_FreeSchema ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Db *p = &db->aDb[i];
|
||||
if( p!=pDb && p->pSchema!=&pSPool->sSchema && pDb->pSPool==p->pSPool ){
|
||||
pSPool->nDelete++;
|
||||
schemaDelete(pRelease);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pRelease->pNext = pDb->pSPool->pSchema;
|
||||
pDb->pSPool->pSchema = pRelease;
|
||||
}
|
||||
|
||||
/*
|
||||
** The schema for database iDb of database handle db, which was opened
|
||||
** with SQLITE_OPEN_SHARED_SCHEMA, has just been parsed. This function either
|
||||
** finds a matching SchemaPool object on the global list (schemaPoolList) or
|
||||
** else allocates a new one and sets the Db.pSPool variable accordingly.
|
||||
**
|
||||
** SQLITE_OK is returned if no error occurs, or an SQLite error code
|
||||
** (SQLITE_NOMEM) otherwise.
|
||||
*/
|
||||
int sqlite3SchemaConnect(sqlite3 *db, int iDb, u64 cksum){
|
||||
Schema *pSchema = db->aDb[iDb].pSchema;
|
||||
SchemaPool *p;
|
||||
|
||||
assert( pSchema && iDb!=1 && db->aDb[iDb].pSPool==0 );
|
||||
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
|
||||
/* Search for a matching SchemaPool object */
|
||||
for(p=schemaPoolList; p; p=p->pNext){
|
||||
if( p->cksum==cksum && p->sSchema.schema_cookie==pSchema->schema_cookie ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !p ){
|
||||
/* No SchemaPool object found. Allocate a new one. */
|
||||
p = (SchemaPool*)sqlite3_malloc(sizeof(SchemaPool));
|
||||
if( p ){
|
||||
memset(p, 0, sizeof(SchemaPool));
|
||||
p->cksum = cksum;
|
||||
p->pNext = schemaPoolList;
|
||||
schemaPoolList = p;
|
||||
|
||||
p->sSchema.schema_cookie = pSchema->schema_cookie;
|
||||
p->sSchema.iGeneration = pSchema->iGeneration;
|
||||
p->sSchema.file_format = pSchema->file_format;
|
||||
p->sSchema.enc = pSchema->enc;
|
||||
p->sSchema.cache_size = pSchema->cache_size;
|
||||
}
|
||||
}
|
||||
|
||||
if( p ) p->nRef++;
|
||||
|
||||
/* If the SchemaPool contains one or more free schemas at the moment,
|
||||
** delete one of them. */
|
||||
if( p && p->pSchema ){
|
||||
Schema *pDel = p->pSchema;
|
||||
p->pSchema = pDel->pNext;
|
||||
schemaDelete(pDel);
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
|
||||
db->aDb[iDb].pSPool = p;
|
||||
return (p ? SQLITE_OK : SQLITE_NOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
** If parameter iDb is 1 (the temp db), or if connection handle db was not
|
||||
** opened with the SQLITE_OPEN_SHARED_SCHEMA flag, this function is a no-op.
|
||||
** Otherwise, it disconnects from the schema-pool associated with database
|
||||
** iDb, assuming it is connected.
|
||||
**
|
||||
** If parameter bNew is true, then Db.pSchema is set to point to a new, empty,
|
||||
** Schema object obtained from sqlite3_malloc(). Or, if bNew is false, then
|
||||
** Db.pSchema is set to NULL before returning.
|
||||
**
|
||||
** If the bNew parameter is true, then this function may allocate memory.
|
||||
** If the allocation attempt fails, then SQLITE_NOMEM is returned and the
|
||||
** schema-pool is not disconnected from. Or, if no OOM error occurs,
|
||||
** SQLITE_OK is returned.
|
||||
*/
|
||||
int sqlite3SchemaDisconnect(sqlite3 *db, int iDb, int bNew){
|
||||
int rc = SQLITE_OK;
|
||||
if( IsSharedSchema(db) ){
|
||||
Db *pDb = &db->aDb[iDb];
|
||||
SchemaPool *pSPool = pDb->pSPool;
|
||||
assert_schema_state_ok(db);
|
||||
assert( pDb->pSchema );
|
||||
|
||||
if( pSPool==0 ){
|
||||
assert( pDb->pVTable==0 );
|
||||
assert( bNew==0 );
|
||||
schemaDelete(pDb->pSchema);
|
||||
pDb->pSchema = 0;
|
||||
}else{
|
||||
VTable *p;
|
||||
VTable *pNext;
|
||||
for(p=pDb->pVTable; p; p=pNext){
|
||||
pNext = p->pNext;
|
||||
sqlite3VtabUnlock(p);
|
||||
}
|
||||
pDb->pVTable = 0;
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){
|
||||
schemaRelease(db, pDb);
|
||||
}
|
||||
if( bNew ){
|
||||
Schema *pNew = sqlite3SchemaGet(db, 0);
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pDb->pSchema = pNew;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pSPool->nRef>=1 );
|
||||
pDb->pSPool = 0;
|
||||
pSPool->nRef--;
|
||||
if( pSPool->nRef<=0 ){
|
||||
SchemaPool **pp;
|
||||
while( pSPool->pSchema ){
|
||||
Schema *pNext = pSPool->pSchema->pNext;
|
||||
schemaDelete(pSPool->pSchema);
|
||||
pSPool->pSchema = pNext;
|
||||
}
|
||||
for(pp=&schemaPoolList; (*pp)!=pSPool; pp=&((*pp)->pNext));
|
||||
*pp = pSPool->pNext;
|
||||
sqlite3_free(pSPool);
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract and return a pointer to a schema object from the SchemaPool passed
|
||||
** as the only argument, if one is available. If one is not available, return
|
||||
** NULL.
|
||||
*/
|
||||
Schema *sqlite3SchemaExtract(SchemaPool *pSPool){
|
||||
Schema *pRet = 0;
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
if( pSPool->pSchema ){
|
||||
pRet = pSPool->pSchema;
|
||||
pSPool->pSchema = pRet->pNext;
|
||||
pRet->pNext = 0;
|
||||
}
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return all sharable schemas held by database handle db back to their
|
||||
** respective schema-pools. Db.pSchema variables are left pointing to
|
||||
** the static, empty, Schema object owned by each schema-pool.
|
||||
*/
|
||||
void sqlite3SchemaReleaseAll(sqlite3 *db){
|
||||
int i;
|
||||
assert_schema_state_ok(db);
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( i!=1 ){
|
||||
Db *pDb = &db->aDb[i];
|
||||
if( pDb->pSPool && DbHasProperty(db,i,DB_SchemaLoaded) ){
|
||||
schemaRelease(db, pDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
db->mDbFlags &= ~DBFLAG_FreeSchema;
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
}
|
||||
|
||||
/*
|
||||
** Release any sharable schema held by connection iDb of database handle
|
||||
** db. Db.pSchema is left pointing to the static, empty, Schema object
|
||||
** owned by the schema-pool.
|
||||
*/
|
||||
void sqlite3SchemaRelease(sqlite3 *db, int iDb){
|
||||
Db *pDb = &db->aDb[iDb];
|
||||
assert( iDb!=1 );
|
||||
assert_schema_state_ok(db);
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
schemaRelease(db, pDb);
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
}
|
||||
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
|
||||
/*
|
||||
** In most cases, this function finds and returns the schema associated
|
||||
** with BTree handle pBt, creating a new one if necessary. However, if
|
||||
** the database handle was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
|
||||
** specified, a new, empty, Schema object in memory obtained by
|
||||
** sqlite3_malloc() is always returned.
|
||||
** Find and return the schema associated with a BTree. Create
|
||||
** a new one if necessary.
|
||||
*/
|
||||
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
|
||||
Schema *p;
|
||||
if( pBt && IsSharedSchema(db)==0 ){
|
||||
p = (Schema*)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
|
||||
Schema * p;
|
||||
if( pBt ){
|
||||
p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
|
||||
}else{
|
||||
p = (Schema*)sqlite3DbMallocZero(0, sizeof(Schema));
|
||||
p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
|
||||
}
|
||||
if( !p ){
|
||||
sqlite3OomFault(db);
|
||||
|
||||
+6
-34
@@ -1214,17 +1214,6 @@ static void disconnectAllVtab(sqlite3 *db){
|
||||
if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) && i!=1 ){
|
||||
VTable *pVTable;
|
||||
VTable *pNext;
|
||||
for(pVTable=db->aDb[i].pVTable; pVTable; pVTable=pNext){
|
||||
pNext = pVTable->pNext;
|
||||
sqlite3VtabUnlock(pVTable);
|
||||
}
|
||||
db->aDb[i].pVTable = 0;
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
}
|
||||
for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){
|
||||
Module *pMod = (Module *)sqliteHashData(p);
|
||||
@@ -1401,7 +1390,6 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
sqlite3BtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
if( j!=1 ){
|
||||
(void)sqlite3SchemaDisconnect(db, j, 0);
|
||||
pDb->pSchema = 0;
|
||||
}
|
||||
}
|
||||
@@ -3974,7 +3962,7 @@ int sqlite3_table_column_metadata(
|
||||
int *pPrimaryKey, /* OUTPUT: True if column part of PK */
|
||||
int *pAutoinc /* OUTPUT: True if column is auto-increment */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int rc;
|
||||
char *zErrMsg = 0;
|
||||
Table *pTab = 0;
|
||||
Column *pCol = 0;
|
||||
@@ -3984,7 +3972,7 @@ int sqlite3_table_column_metadata(
|
||||
int notnull = 0;
|
||||
int primarykey = 0;
|
||||
int autoinc = 0;
|
||||
int bUnlock;
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){
|
||||
@@ -3994,29 +3982,14 @@ int sqlite3_table_column_metadata(
|
||||
|
||||
/* Ensure the database schema has been loaded */
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
bUnlock = sqlite3LockReusableSchema(db);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
if( IsSharedSchema(db)==0 ){
|
||||
rc = sqlite3Init(db, &zErrMsg);
|
||||
rc = sqlite3Init(db, &zErrMsg);
|
||||
if( SQLITE_OK!=rc ){
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* Locate the table in question */
|
||||
if( rc==SQLITE_OK ){
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
Parse sParse; /* Fake Parse object for FindTable */
|
||||
Parse *pSaved = db->pParse;
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
db->pParse = &sParse;
|
||||
#endif
|
||||
pTab = sqlite3FindTable(db, zTableName, zDbName);
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
sqlite3_free(sParse.zErrMsg);
|
||||
rc = sParse.rc;
|
||||
db->pParse = pSaved;
|
||||
#endif
|
||||
}
|
||||
if( SQLITE_OK!=rc ) goto error_out;
|
||||
|
||||
pTab = sqlite3FindTable(db, zTableName, zDbName);
|
||||
if( !pTab || IsView(pTab) ){
|
||||
pTab = 0;
|
||||
goto error_out;
|
||||
@@ -4086,7 +4059,6 @@ error_out:
|
||||
sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg);
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3UnlockReusableSchema(db, bUnlock);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
+1
-1
@@ -5311,7 +5311,7 @@ static int winOpen(
|
||||
|
||||
int rc = SQLITE_OK; /* Function Return Code */
|
||||
#if !defined(NDEBUG) || SQLITE_OS_WINCE
|
||||
int eType = flags&0x0FFF00; /* Type of file to open */
|
||||
int eType = flags&0x0FFF00; /* Type of file to open */
|
||||
#endif
|
||||
|
||||
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
|
||||
|
||||
+7
-123
@@ -5080,115 +5080,6 @@ sqlite3_file *sqlite3_database_file_object(const char *zName){
|
||||
}
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_READONLY_WALJOURNAL
|
||||
/*
|
||||
** This is used by a read-only database connection in cases where there
|
||||
** is a hot journal which cannot be rolled back, but the hot journal was
|
||||
** created by an aborted "PRAGMA journal_mode = wal" statement. In this
|
||||
** case we can proceed, but must set bytes 18 and 19 of page 1 of the
|
||||
** db file to indicate that this is not a wal mode database.
|
||||
*/
|
||||
static int getPageOneNoWal(
|
||||
Pager *pPager, /* The pager open on the database file */
|
||||
Pgno pgno, /* Page number to fetch */
|
||||
DbPage **ppPage, /* Write a pointer to the page here */
|
||||
int flags /* PAGER_GET_XXX flags */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( pgno==1 );
|
||||
assert( pPager->readOnly );
|
||||
assert( !isOpen(pPager->jfd) );
|
||||
|
||||
rc = getPageNormal(pPager, pgno, ppPage, flags);
|
||||
if( rc==SQLITE_OK ){
|
||||
int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
|
||||
u8 *aPg = (u8*)(*ppPage)->pData;
|
||||
u8 aHdr[28];
|
||||
rc = sqlite3OsOpen(pPager->pVfs, pPager->zJournal, pPager->jfd, f, &f);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsRead(pPager->jfd, (void*)aHdr, sizeof(aHdr), 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
u32 off = sqlite3Get4byte(&aHdr[20]);
|
||||
rc = sqlite3OsRead(pPager->jfd, (void*)aPg, pPager->pageSize, off+4);
|
||||
}
|
||||
sqlite3OsClose(pPager->jfd);
|
||||
}
|
||||
setGetterMethod(pPager);
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_READONLY_WALJOURNAL */
|
||||
|
||||
/*
|
||||
** This function is called after a potentially hot journal has been opened
|
||||
** to inspect its contents and determine whether or not it really is a
|
||||
** hot journal. The journal is not a hot journal in two cases:
|
||||
**
|
||||
** * The first byte of the journal is 0x00, or,
|
||||
**
|
||||
** * The connection is opened read-only, the journal consist of page 1
|
||||
** of the db only, and the contents of page 1 differs from the contents
|
||||
** of the db only in bytes 18 and 19 (the wal mode setting).
|
||||
**
|
||||
** If the journal is not hot, then output variable (*pbHot) is set to 0
|
||||
** before this function returns. Otherwise, if the journal is hot, (*pbHot)
|
||||
** is set to 1.
|
||||
*/
|
||||
static int checkHotJournal(Pager *pPager, int *pbHot){
|
||||
char aHdr[28];
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
*pbHot = 1;
|
||||
rc = sqlite3OsRead(pPager->jfd, (void *)aHdr, sizeof(aHdr), 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( aHdr[0]==0 ){
|
||||
*pbHot = 0;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_READONLY_WALJOURNAL
|
||||
else if( pPager->readOnly ){
|
||||
u32 nPg = sqlite3Get4byte(&aHdr[8]);
|
||||
u32 off = sqlite3Get4byte(&aHdr[20]);
|
||||
u32 pgsz = sqlite3Get4byte(&aHdr[24]);
|
||||
|
||||
if( nPg==0xFFFFFFFF ){
|
||||
i64 sz = 0;
|
||||
rc = sqlite3OsFileSize(pPager->jfd, &sz);
|
||||
nPg = ((sz-off) / pgsz);
|
||||
}
|
||||
if( nPg==1 ){
|
||||
u8 *a1 = 0;
|
||||
a1 = sqlite3_malloc(pgsz*2);
|
||||
if( a1==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
u8 *a2 = &a1[pgsz];
|
||||
rc = sqlite3OsRead(pPager->jfd, a1, pgsz, off+4);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsRead(pPager->fd, a2, pgsz, 0);
|
||||
memcpy(&a2[18], &a1[18], 2);
|
||||
memcpy(&a2[24], &a1[24], 4);
|
||||
memcpy(&a2[92], &a1[92], 8);
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
memcpy(&a2[176], &a1[176], 4);
|
||||
#endif
|
||||
}
|
||||
if( rc==SQLITE_OK && memcmp(a1, a2, pgsz)==0 ){
|
||||
*pbHot = 0;
|
||||
pPager->xGet = getPageOneNoWal;
|
||||
}
|
||||
sqlite3_free(a1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_READONLY_WALJOURNAL */
|
||||
}
|
||||
if( rc==SQLITE_IOERR_SHORT_READ ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called after transitioning from PAGER_UNLOCK to
|
||||
** PAGER_SHARED state. It tests if there is a hot journal present in
|
||||
@@ -5283,10 +5174,15 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = checkHotJournal(pPager, pExists);
|
||||
u8 first = 0;
|
||||
rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
|
||||
if( rc==SQLITE_IOERR_SHORT_READ ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
if( !jrnlOpen ){
|
||||
sqlite3OsClose(pPager->jfd);
|
||||
}
|
||||
*pExists = (first!=0);
|
||||
}else if( rc==SQLITE_CANTOPEN ){
|
||||
/* If we cannot open the rollback journal file in order to see if
|
||||
** it has a zero header, that might be due to an I/O error, or
|
||||
@@ -5537,10 +5433,6 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
assert( !MEMDB );
|
||||
pager_unlock(pPager);
|
||||
assert( pPager->eState==PAGER_OPEN );
|
||||
#ifdef SQLITE_ENABLE_READONLY_WALJOURNAL
|
||||
testcase( pPager->xGet==getPageOneNoWal );
|
||||
setGetterMethod(pPager);
|
||||
#endif /* SQLITE_ENABLE_READONLY_WALJOURNAL */
|
||||
}else{
|
||||
pPager->eState = PAGER_READER;
|
||||
pPager->hasHeldSharedLock = 1;
|
||||
@@ -5808,6 +5700,7 @@ static int getPageError(
|
||||
return pPager->errCode;
|
||||
}
|
||||
|
||||
|
||||
/* Dispatch all page fetch requests to the appropriate getter method.
|
||||
*/
|
||||
int sqlite3PagerGet(
|
||||
@@ -7508,15 +7401,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
|
||||
assert( state==PAGER_OPEN || state==PAGER_READER );
|
||||
if( state==PAGER_OPEN ){
|
||||
rc = sqlite3PagerSharedLock(pPager);
|
||||
|
||||
#ifdef SQLITE_ENABLE_READONLY_WALJOURNAL
|
||||
/* If this is a read-only connection, and there is a hot-journal
|
||||
** created by "PRAGMA journal_mode = wal" in the file-system, then
|
||||
** the Pager.xGet method may have been set to getPageOneNoWal. Call
|
||||
** setGetterMethod() here to ensure it is set properly. */
|
||||
testcase( pPager->xGet==getPageOneNoWal );
|
||||
setGetterMethod(pPager);
|
||||
#endif /* SQLITE_ENABLE_READONLY_WALJOURNAL */
|
||||
}
|
||||
if( pPager->eState==PAGER_READER ){
|
||||
assert( rc==SQLITE_OK );
|
||||
|
||||
+4
-8
@@ -232,10 +232,6 @@ static SQLITE_WSD struct PCacheGlobal {
|
||||
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
|
||||
PgFreeslot *pFree; /* Free page blocks */
|
||||
int nFreeSlot; /* Number of unused pcache slots */
|
||||
/* The following value requires a mutex to change. We skip the mutex on
|
||||
** reading because (1) most platforms read a 32-bit integer atomically and
|
||||
** (2) even if an incorrect value is read, no great harm is done since this
|
||||
** is really just an optimization. */
|
||||
int bUnderPressure; /* True if low on PAGECACHE memory */
|
||||
} pcache1_g;
|
||||
|
||||
@@ -283,7 +279,7 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
|
||||
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
|
||||
pcache1.pStart = pBuf;
|
||||
pcache1.pFree = 0;
|
||||
pcache1.bUnderPressure = 0;
|
||||
AtomicStore(&pcache1.bUnderPressure,0);
|
||||
while( n-- ){
|
||||
p = (PgFreeslot*)pBuf;
|
||||
p->pNext = pcache1.pFree;
|
||||
@@ -351,7 +347,7 @@ static void *pcache1Alloc(int nByte){
|
||||
if( p ){
|
||||
pcache1.pFree = pcache1.pFree->pNext;
|
||||
pcache1.nFreeSlot--;
|
||||
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
||||
AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
|
||||
assert( pcache1.nFreeSlot>=0 );
|
||||
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
@@ -390,7 +386,7 @@ static void pcache1Free(void *p){
|
||||
pSlot->pNext = pcache1.pFree;
|
||||
pcache1.pFree = pSlot;
|
||||
pcache1.nFreeSlot++;
|
||||
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
||||
AtomicStore(&pcache1.bUnderPressure,pcache1.nFreeSlot<pcache1.nReserve);
|
||||
assert( pcache1.nFreeSlot<=pcache1.nSlot );
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}else{
|
||||
@@ -521,7 +517,7 @@ void sqlite3PageFree(void *p){
|
||||
*/
|
||||
static int pcache1UnderMemoryPressure(PCache1 *pCache){
|
||||
if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
|
||||
return pcache1.bUnderPressure;
|
||||
return AtomicLoad(&pcache1.bUnderPressure);
|
||||
}else{
|
||||
return sqlite3HeapNearlyFull();
|
||||
}
|
||||
|
||||
+3
-10
@@ -504,13 +504,7 @@ void sqlite3Pragma(
|
||||
|
||||
/* Make sure the database schema is loaded if the pragma requires that */
|
||||
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
|
||||
if( IsSharedSchema(db) && (zDb || (pPragma->mPragFlg & PragFlg_OneSchema)) ){
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
pParse->rc = sqlite3SchemaLoad(db, iDb, 0, &pParse->zErrMsg);
|
||||
if( pParse->rc ) goto pragma_out;
|
||||
}else{
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
}
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
}
|
||||
|
||||
/* Register the result column names for pragmas that return results */
|
||||
@@ -2300,10 +2294,9 @@ void sqlite3Pragma(
|
||||
** applications for any purpose.
|
||||
*/
|
||||
case PragTyp_HEADER_VALUE: {
|
||||
int iCookie; /* Which cookie to read or write */
|
||||
iCookie = pPragma->iArg & PRAGMA_HEADER_VALUE_MASK;
|
||||
int iCookie = pPragma->iArg; /* Which cookie to read or write */
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
if( zRight && (pPragma->iArg & PRAGMA_HEADER_VALUE_READONLY)==0 ){
|
||||
if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){
|
||||
/* Write the specified cookie value */
|
||||
static const VdbeOpList setCookie[] = {
|
||||
{ OP_Transaction, 0, 1, 0}, /* 0 */
|
||||
|
||||
+10
-125
@@ -43,11 +43,6 @@ static void corruptSchema(
|
||||
pData->rc = SQLITE_ERROR;
|
||||
}else if( db->flags & SQLITE_WriteSchema ){
|
||||
pData->rc = SQLITE_CORRUPT_BKPT;
|
||||
}else if( IsSharedSchema(db)
|
||||
&& 0==sqlite3StrNICmp(zExtra, "malformed database schema", 17)
|
||||
){
|
||||
pData->rc = SQLITE_CORRUPT_BKPT;
|
||||
*pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
|
||||
}else{
|
||||
char *z;
|
||||
const char *zObj = azObj[1] ? azObj[1] : "?";
|
||||
@@ -58,28 +53,6 @@ static void corruptSchema(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
/*
|
||||
** Update the Schema.cksum checksum to account for the database object
|
||||
** specified by the three arguments following the first.
|
||||
*/
|
||||
static void schemaUpdateChecksum(
|
||||
InitData *pData, /* Schema parse context */
|
||||
const char *zName, /* Name of new database object */
|
||||
const char *zRoot, /* Root page of new database object */
|
||||
const char *zSql /* SQL used to create new database object */
|
||||
){
|
||||
int i;
|
||||
u64 cksum = pData->cksum;
|
||||
if( zName ){
|
||||
for(i=0; zName[i]; i++) cksum += (cksum<<3) + zName[i];
|
||||
}
|
||||
if( zRoot ) for(i=0; zRoot[i]; i++) cksum += (cksum<<3) + zRoot[i];
|
||||
if( zSql ) for(i=0; zSql[i]; i++) cksum += (cksum<<3) + zSql[i];
|
||||
pData->cksum = cksum;
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
|
||||
/*
|
||||
** Check to see if any sibling index (another index on the same table)
|
||||
** of pIndex has the same root page number, and if it does, return true.
|
||||
@@ -103,15 +76,6 @@ static int sqlite3Prepare(
|
||||
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
);
|
||||
static int sqlite3LockAndPrepare(
|
||||
sqlite3 *db, /* Database handle. */
|
||||
const char *zSql, /* UTF-8 encoded SQL statement. */
|
||||
int nBytes, /* Length of zSql in bytes. */
|
||||
u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
|
||||
Vdbe *pReprepare, /* VM being reprepared */
|
||||
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
@@ -177,11 +141,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
db->init.orphanTrigger = 0;
|
||||
db->init.azInit = (const char**)argv;
|
||||
pStmt = 0;
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
TESTONLY(rcp = ) sqlite3LockAndPrepare(db, argv[4], -1, 0, 0, &pStmt, 0);
|
||||
#else
|
||||
TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
|
||||
#endif
|
||||
rc = db->errCode;
|
||||
assert( (rc&0xFF)==(rcp&0xFF) );
|
||||
db->init.iDb = saved_iDb;
|
||||
@@ -193,11 +153,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
if( rc > pData->rc ) pData->rc = rc;
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
&& (rc&0xFF)!=SQLITE_IOERR
|
||||
#endif
|
||||
){
|
||||
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
|
||||
corruptSchema(pData, argv, sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
@@ -228,12 +184,6 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) && iDb!=1 ){
|
||||
schemaUpdateChecksum(pData, argv[0], argv[1], argv[2]);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -261,28 +211,10 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
|
||||
assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pSchema || (IsSharedSchema(db) && iDb!=1) );
|
||||
assert( db->aDb[iDb].pSchema );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
||||
|
||||
pDb = &db->aDb[iDb];
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
assert( pDb->pSPool==0 || IsSharedSchema(db) );
|
||||
if( pDb->pSPool ){
|
||||
/* See if there is a free schema object in the schema-pool. If not,
|
||||
** disconnect from said schema pool and continue. This function will
|
||||
** connect to a (possibly different) schema-pool before returning. */
|
||||
Schema *pNew = sqlite3SchemaExtract(pDb->pSPool);
|
||||
if( pNew ){
|
||||
pDb->pSchema = pNew;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
rc = sqlite3SchemaDisconnect(db, iDb, 1);
|
||||
if( rc!=SQLITE_OK ) goto error_out;
|
||||
assert( pDb->pSchema && pDb->pSPool==0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
db->init.busy = 1;
|
||||
|
||||
/* Construct the in-memory representation schema tables (sqlite_schema or
|
||||
@@ -303,7 +235,6 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
initData.pzErrMsg = pzErrMsg;
|
||||
initData.mInitFlags = mFlags;
|
||||
initData.nInitRow = 0;
|
||||
initData.cksum = 0;
|
||||
initData.mxPage = 0;
|
||||
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
|
||||
db->mDbFlags &= mask;
|
||||
@@ -314,6 +245,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
|
||||
/* Create a cursor to hold the database open
|
||||
*/
|
||||
pDb = &db->aDb[iDb];
|
||||
if( pDb->pBt==0 ){
|
||||
assert( iDb==1 );
|
||||
DbSetProperty(db, 1, DB_SchemaLoaded);
|
||||
@@ -472,10 +404,6 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && iDb!=1 && IsSharedSchema(db) ){
|
||||
rc = sqlite3SchemaConnect(db, iDb, initData.cksum);
|
||||
}
|
||||
|
||||
/* Jump here for an error that occurs after successfully allocating
|
||||
** curMain and calling sqlite3BtreeEnter(). For an error that occurs
|
||||
** before that point, jump to error_out.
|
||||
@@ -497,35 +425,6 @@ error_out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
/*
|
||||
** If this is a SHARED_SCHEMA connection and the DBFLAG_SchemaInUse flag
|
||||
** is not currently set, set it and return non-zero. Otherwise, return 0.
|
||||
*/
|
||||
int sqlite3LockReusableSchema(sqlite3 *db){
|
||||
if( IsSharedSchema(db) && (db->mDbFlags & DBFLAG_SchemaInuse)==0 ){
|
||||
db->mDbFlags |= DBFLAG_SchemaInuse;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
/*
|
||||
** This function is a no-op for non-SHARED_SCHEMA connections, or if bRelease
|
||||
** is zero. Otherwise, clear the DBFLAG_SchemaInuse flag and release all
|
||||
** schema references currently held.
|
||||
*/
|
||||
void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease){
|
||||
if( bRelease ){
|
||||
db->mDbFlags &= ~DBFLAG_SchemaInuse;
|
||||
sqlite3SchemaReleaseAll(db);
|
||||
}
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
|
||||
/*
|
||||
** Initialize all database files - the main database file, the file
|
||||
** used to store temporary tables, and any additional database files
|
||||
@@ -536,12 +435,8 @@ void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease){
|
||||
** bit is set in the flags field of the Db structure.
|
||||
*/
|
||||
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
int rc = SQLITE_OK;
|
||||
int bReleaseSchema;
|
||||
int i;
|
||||
int i, rc;
|
||||
int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
|
||||
|
||||
bReleaseSchema = sqlite3LockReusableSchema(db);
|
||||
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
|
||||
@@ -551,19 +446,20 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
/* Do the main schema first */
|
||||
if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, 0, pzErrMsg, 0);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
/* All other schemas after the main schema. The "temp" schema must be last */
|
||||
for(i=db->nDb-1; rc==SQLITE_OK && i>0; i--){
|
||||
for(i=db->nDb-1; i>0; i--){
|
||||
assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
|
||||
if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, i, pzErrMsg, 0);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && commit_internal ){
|
||||
if( commit_internal ){
|
||||
sqlite3CommitInternalChanges(db);
|
||||
}
|
||||
sqlite3UnlockReusableSchema(db, bReleaseSchema);
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -575,12 +471,11 @@ int sqlite3ReadSchema(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( !db->init.busy ){
|
||||
db->mDbFlags |= DBFLAG_FreeSchema; /* For sharable-schema mode */
|
||||
rc = sqlite3Init(db, &pParse->zErrMsg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pParse->rc = rc;
|
||||
pParse->nErr++;
|
||||
}else if( db->noSharedCache && !IsSharedSchema(db) ){
|
||||
}else if( db->noSharedCache ){
|
||||
db->mDbFlags |= DBFLAG_SchemaKnownOk;
|
||||
}
|
||||
}
|
||||
@@ -606,10 +501,6 @@ static void schemaIsValid(Parse *pParse){
|
||||
Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */
|
||||
if( pBt==0 ) continue;
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) && iDb!=1 && db->aDb[iDb].pSPool==0 ) continue;
|
||||
#endif
|
||||
|
||||
/* If there is not already a read-only (or read-write) transaction opened
|
||||
** on the b-tree database, open one now. If a transaction is opened, it
|
||||
** will be closed immediately after reading the meta-value. */
|
||||
@@ -952,7 +843,6 @@ static int sqlite3LockAndPrepare(
|
||||
){
|
||||
int rc;
|
||||
int cnt = 0;
|
||||
int bReleaseSchema = 0;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
|
||||
@@ -962,7 +852,6 @@ static int sqlite3LockAndPrepare(
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
bReleaseSchema = sqlite3LockReusableSchema(db);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
do{
|
||||
/* Make multiple attempts to compile the SQL, until it either succeeds
|
||||
@@ -973,11 +862,7 @@ static int sqlite3LockAndPrepare(
|
||||
if( rc==SQLITE_OK || db->mallocFailed ) break;
|
||||
}while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|
||||
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
|
||||
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
|
||||
sqlite3UnlockReusableSchema(db, bReleaseSchema);
|
||||
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
assert( (rc&db->errMask)==rc );
|
||||
db->busyHandler.nBusy = 0;
|
||||
|
||||
+6
-1
@@ -7201,6 +7201,7 @@ static void agginfoFree(sqlite3 *db, void *pArg){
|
||||
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
|
||||
** * The outer query is a simple count(*) with no WHERE clause or other
|
||||
** extraneous syntax.
|
||||
** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10)
|
||||
**
|
||||
** Return TRUE if the optimization is undertaken.
|
||||
*/
|
||||
@@ -7233,7 +7234,11 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
|
||||
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
|
||||
if( pSub->pWhere ) return 0; /* No WHERE clause */
|
||||
if( pSub->pLimit ) return 0; /* No LIMIT clause */
|
||||
if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
|
||||
if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){
|
||||
testcase( pSub->selFlags & SF_Aggregate );
|
||||
testcase( pSub->selFlags & SF_Distinct );
|
||||
return 0; /* Not an aggregate nor DISTINCT */
|
||||
}
|
||||
assert( pSub->pHaving==0 ); /* Due to the previous */
|
||||
pSub = pSub->pPrior; /* Repeat over compound */
|
||||
}while( pSub );
|
||||
|
||||
+13
-304
@@ -1528,14 +1528,13 @@ static ShellState shellState;
|
||||
|
||||
/* Allowed values for ShellState.openMode
|
||||
*/
|
||||
#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
|
||||
#define SHELL_OPEN_NORMAL 1 /* Normal database file */
|
||||
#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
|
||||
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
|
||||
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
|
||||
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
|
||||
#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
|
||||
#define SHELL_OPEN_SHAREDSCHEMA 7 /* Open for schema reuse */
|
||||
#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
|
||||
#define SHELL_OPEN_NORMAL 1 /* Normal database file */
|
||||
#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
|
||||
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
|
||||
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
|
||||
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
|
||||
#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
|
||||
|
||||
/* Allowed values for ShellState.eTraceType
|
||||
*/
|
||||
@@ -2790,12 +2789,12 @@ static int shell_callback(
|
||||
}else if( (c=='w' || c=='W')
|
||||
&& nParen==0 && isIndex
|
||||
&& sqlite3_strnicmp("WHERE",&z[i],5)==0
|
||||
&& !isalnum(z[i+5]) && z[i+5]!='_' ){
|
||||
&& !IsAlnum(z[i+5]) && z[i+5]!='_' ){
|
||||
isWhere = 1;
|
||||
}else if( isWhere && (c=='A' || c=='a')
|
||||
&& nParen==0
|
||||
&& sqlite3_strnicmp("AND",&z[i],3)==0
|
||||
&& !isalnum(z[i+3]) && z[i+3]!='_' ){
|
||||
&& !IsAlnum(z[i+3]) && z[i+3]!='_' ){
|
||||
printSchemaLineN(p->out, z, j, "\n ");
|
||||
j = 0;
|
||||
}
|
||||
@@ -5278,12 +5277,6 @@ static const char *(azHelp[]) = {
|
||||
" --sha3-384 Use the sha3-384 algorithm",
|
||||
" --sha3-512 Use the sha3-512 algorithm",
|
||||
" Any other argument is a LIKE pattern for tables to hash",
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
||||
".shared-schema CMD DB1 DB2 ...",
|
||||
" Commands:",
|
||||
" check Determine if DB1, DB2, etc have identical schemas",
|
||||
" fix Attempt to make DB1, DB2, etc compatible",
|
||||
#endif
|
||||
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
|
||||
".shell CMD ARGS... Run CMD ARGS... in a system shell",
|
||||
#endif
|
||||
@@ -5731,11 +5724,6 @@ static void open_db(ShellState *p, int openFlags){
|
||||
SQLITE_OPEN_READONLY|p->openFlags, 0);
|
||||
break;
|
||||
}
|
||||
case SHELL_OPEN_SHAREDSCHEMA: {
|
||||
sqlite3_open_v2(p->pAuxDb->zDbFilename, &p->db,
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SHARED_SCHEMA,0);
|
||||
break;
|
||||
}
|
||||
case SHELL_OPEN_UNSPEC:
|
||||
case SHELL_OPEN_NORMAL: {
|
||||
sqlite3_open_v2(zDbFilename, &p->db,
|
||||
@@ -8129,277 +8117,8 @@ end_ar_command:
|
||||
*******************************************************************************/
|
||||
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
|
||||
|
||||
/*
|
||||
** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
|
||||
** Otherwise, the SQL statement or statements in zSql are executed using
|
||||
** database connection db and the error code written to *pRc before
|
||||
** this function returns.
|
||||
*/
|
||||
static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
|
||||
int rc = *pRc;
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zErr = 0;
|
||||
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_fprintf(stderr, "SQL error: %s\n", zErr);
|
||||
}
|
||||
sqlite3_free(zErr);
|
||||
*pRc = rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Like shellExec(), except that zFmt is a printf() style format string.
|
||||
*/
|
||||
static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
|
||||
char *z = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
z = sqlite3_vmprintf(zFmt, ap);
|
||||
va_end(ap);
|
||||
if( z==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}else{
|
||||
shellExec(db, pRc, z);
|
||||
}
|
||||
sqlite3_free(z);
|
||||
}
|
||||
}
|
||||
|
||||
static int sharedSchemaFix(ShellState *pState, const char *zDb){
|
||||
int rc = SQLITE_OK;
|
||||
i64 iLast = 0;
|
||||
int iCookie = 0;
|
||||
int iAutoVacuum = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
|
||||
shellExecPrintf(pState->db, &rc, "ATTACH '%q' AS _shared_schema_tmp", zDb);
|
||||
shellExecPrintf(pState->db, &rc, "PRAGMA writable_schema = 1");
|
||||
shellExecPrintf(pState->db, &rc, "BEGIN");
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"SELECT max(rowid) FROM _shared_schema_tmp.sqlite_master"
|
||||
);
|
||||
sqlite3_step(pStmt);
|
||||
iLast = sqlite3_column_int64(pStmt, 0);
|
||||
shellFinalize(&rc, pStmt);
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"INSERT INTO _shared_schema_tmp.sqlite_master SELECT "
|
||||
" type, name, tbl_name, ("
|
||||
" SELECT rootpage FROM _shared_schema_tmp.sqlite_master WHERE "
|
||||
" type IS o.type AND name IS o.name AND rowid<=?"
|
||||
" ), sql FROM main.sqlite_master AS o"
|
||||
);
|
||||
sqlite3_bind_int64(pStmt, 1, iLast);
|
||||
sqlite3_step(pStmt);
|
||||
shellFinalize(&rc, pStmt);
|
||||
|
||||
shellExecPrintf(pState->db, &rc,
|
||||
"DELETE FROM _shared_schema_tmp.sqlite_master WHERE rowid<=%lld",
|
||||
iLast
|
||||
);
|
||||
shellExecPrintf(pState->db, &rc, "COMMIT");
|
||||
sqlite3_exec(pState->db, "PRAGMA writable_schema = 0", 0, 0, 0);
|
||||
|
||||
/* Copy the auto-vacuum setting from main to the target db */
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt, "PRAGMA main.auto_vacuum");
|
||||
sqlite3_step(pStmt);
|
||||
iAutoVacuum = sqlite3_column_int(pStmt, 0);
|
||||
shellFinalize(&rc, pStmt);
|
||||
shellExecPrintf(pState->db, &rc,
|
||||
"PRAGMA _shared_schema_tmp.auto_vacuum = %d", iAutoVacuum
|
||||
);
|
||||
|
||||
/* Vacuum the db in order to standardize the rootpage numbers. */
|
||||
shellExecPrintf(pState->db, &rc, "VACUUM _shared_schema_tmp");
|
||||
|
||||
/* Set the schema-cookie value to the same as database "main" */
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt, "PRAGMA main.schema_version");
|
||||
sqlite3_step(pStmt);
|
||||
iCookie = sqlite3_column_int(pStmt, 0);
|
||||
shellFinalize(&rc, pStmt);
|
||||
shellExecPrintf(pState->db, &rc,
|
||||
"PRAGMA _shared_schema_tmp.schema_version = %d", iCookie
|
||||
);
|
||||
|
||||
sqlite3_exec(pState->db, "DETACH _shared_schema_tmp", 0, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sharedSchemaCheck(ShellState *pState, const char *zDb, int *peFix){
|
||||
int rc = SQLITE_OK;
|
||||
int bFailed = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
|
||||
if( peFix ) *peFix = 0;
|
||||
shellExecPrintf(pState->db, &rc, "ATTACH '%q' AS _shared_schema_tmp", zDb);
|
||||
|
||||
/* Check if this database has the same set of objects as the current db */
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"SELECT type, name FROM _shared_schema_tmp.sqlite_master AS o "
|
||||
"WHERE NOT EXISTS ("
|
||||
" SELECT 1 FROM main.sqlite_master "
|
||||
" WHERE name IS o.name AND type IS o.type"
|
||||
")"
|
||||
" UNION ALL "
|
||||
"SELECT type, name FROM main.sqlite_master AS o "
|
||||
"WHERE NOT EXISTS ("
|
||||
" SELECT 1 FROM _shared_schema_tmp.sqlite_master "
|
||||
" WHERE name IS o.name AND type IS o.type"
|
||||
")"
|
||||
);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
sqlite3_fprintf(pState->out, "%s is NOT compatible (objects)\n", zDb);
|
||||
bFailed = 1;
|
||||
}
|
||||
shellFinalize(&rc, pStmt);
|
||||
|
||||
/* Check if this database has the same set of SQL statements as the
|
||||
** current db. */
|
||||
if( bFailed==0 ){
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"SELECT 1 FROM _shared_schema_tmp.sqlite_master AS o "
|
||||
"WHERE sql IS NOT ("
|
||||
" SELECT sql FROM main.sqlite_master "
|
||||
" WHERE name IS o.name AND type IS o.type"
|
||||
")"
|
||||
);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
sqlite3_fprintf(pState->out, "%s is NOT compatible (SQL)\n", zDb);
|
||||
bFailed = 1;
|
||||
}
|
||||
shellFinalize(&rc, pStmt);
|
||||
}
|
||||
|
||||
/* Check if this database has the same set of root pages as the current
|
||||
** db. */
|
||||
if( bFailed==0 ){
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"SELECT 1 FROM _shared_schema_tmp.sqlite_master AS o "
|
||||
"WHERE rootpage IS NOT ("
|
||||
" SELECT rootpage FROM main.sqlite_master "
|
||||
" WHERE name IS o.name AND type IS o.type"
|
||||
")"
|
||||
);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( peFix==0 ){
|
||||
sqlite3_fprintf(pState->out, "%s is NOT compatible (root pages)\n", zDb);
|
||||
}
|
||||
bFailed = 1;
|
||||
if( peFix ) *peFix = 1;
|
||||
}
|
||||
shellFinalize(&rc, pStmt);
|
||||
}
|
||||
|
||||
if( bFailed==0 ){
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"SELECT 1 WHERE ("
|
||||
" SELECT group_concat(rootpage || '.' || name || '.' || sql, '.') "
|
||||
" FROM _shared_schema_tmp.sqlite_master"
|
||||
") IS NOT ("
|
||||
" SELECT group_concat(rootpage || '.' || name || '.' || sql, '.') "
|
||||
" FROM main.sqlite_master"
|
||||
")"
|
||||
);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( peFix==0 ){
|
||||
sqlite3_fprintf(pState->out,
|
||||
"%s is NOT compatible (order of sqlite_master rows)\n", zDb
|
||||
);
|
||||
}
|
||||
bFailed = 1;
|
||||
if( peFix ) *peFix = 2;
|
||||
}
|
||||
shellFinalize(&rc, pStmt);
|
||||
}
|
||||
|
||||
if( bFailed==0 ){
|
||||
int iMain = -1;
|
||||
int iNew = +1;
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"PRAGMA main.schema_version"
|
||||
);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
iMain = sqlite3_column_int(pStmt, 0);
|
||||
}
|
||||
shellFinalize(&rc, pStmt);
|
||||
shellPreparePrintf(pState->db, &rc, &pStmt,
|
||||
"PRAGMA _shared_schema_tmp.schema_version"
|
||||
);
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
iNew = sqlite3_column_int(pStmt, 0);
|
||||
}
|
||||
shellFinalize(&rc, pStmt);
|
||||
if( rc==SQLITE_OK && iMain!=iNew ){
|
||||
if( peFix==0 ){
|
||||
sqlite3_fprintf(pState->out,
|
||||
"%s is NOT compatible (schema cookie)\n", zDb
|
||||
);
|
||||
}
|
||||
bFailed = 1;
|
||||
if( peFix ) *peFix = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && bFailed==0 ){
|
||||
sqlite3_fprintf(pState->out, "%s is compatible\n", zDb);
|
||||
}
|
||||
|
||||
sqlite3_exec(pState->db, "DETACH _shared_schema_tmp", 0, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** .shared-schema check|fix DB1 DB2...
|
||||
*/
|
||||
static int sharedSchemaDotCommand(
|
||||
ShellState *pState, /* Current shell tool state */
|
||||
char **azArg, /* Array of arguments passed to dot command */
|
||||
int nArg /* Number of entries in azArg[] */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int bFix = 0; /* Fix databases if possible */
|
||||
int n1;
|
||||
int i;
|
||||
if( nArg<3 ){
|
||||
goto shared_schema_usage;
|
||||
}
|
||||
|
||||
n1 = (int)strlen(azArg[1]);
|
||||
if( n1>0 && n1<=3 && memcmp("fix", azArg[1], n1)==0 ){
|
||||
bFix = 1;
|
||||
}else if( n1==0 || n1>5 || memcmp("check", azArg[1], n1) ){
|
||||
goto shared_schema_usage;
|
||||
}
|
||||
|
||||
for(i=2; rc==SQLITE_OK && i<nArg; i++){
|
||||
int eFix = 0;
|
||||
rc = sharedSchemaCheck(pState, azArg[i], bFix ? &eFix : 0);
|
||||
if( rc==SQLITE_OK && bFix && eFix ){
|
||||
sqlite3_fprintf(pState->out, "Fixing %s... ", azArg[i]);
|
||||
fflush(pState->out);
|
||||
rc = sharedSchemaFix(pState, azArg[i]);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sharedSchemaCheck(pState, azArg[i], &eFix);
|
||||
if( rc==SQLITE_OK && eFix ){
|
||||
sqlite3_fprintf(pState->out, "VACUUMing main... ");
|
||||
fflush(pState->out);
|
||||
rc = sqlite3_exec(pState->db, "VACUUM main", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sharedSchemaCheck(pState, azArg[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
shared_schema_usage:
|
||||
sqlite3_fprintf(stderr, "usage: .shared-schema check|fix DB1 DB2...\n");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
#if SQLITE_SHELL_HAVE_RECOVER
|
||||
|
||||
/*
|
||||
** This function is used as a callback by the recover extension. Simply
|
||||
** print the supplied SQL statement to stdout.
|
||||
@@ -8464,6 +8183,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
|
||||
sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
|
||||
sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
|
||||
|
||||
sqlite3_fprintf(pState->out, ".dbconfig defensive off\n");
|
||||
sqlite3_recover_run(p);
|
||||
if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
|
||||
const char *zErr = sqlite3_recover_errmsg(p);
|
||||
@@ -11581,13 +11301,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(zSql);
|
||||
}else
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
||||
if( c=='s' && strncmp(azArg[0], "shared-schema", n)==0 ){
|
||||
open_db(p, 0);
|
||||
sharedSchemaDotCommand(p, azArg, nArg);
|
||||
}else
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
|
||||
if( c=='s'
|
||||
&& (cli_strncmp(azArg[0], "shell", n)==0
|
||||
@@ -12562,7 +12275,7 @@ static int line_is_command_terminator(char *zLine){
|
||||
** out of the build if compiling with SQLITE_OMIT_COMPLETE.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_COMPLETE
|
||||
# error the CLI application is incompatable with SQLITE_OMIT_COMPLETE.
|
||||
# error the CLI application is incompatible with SQLITE_OMIT_COMPLETE.
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -13459,8 +13172,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#endif
|
||||
}else if( cli_strcmp(z,"-readonly")==0 ){
|
||||
data.openMode = SHELL_OPEN_READONLY;
|
||||
}else if( strcmp(z,"-sharedschema")==0 ){
|
||||
data.openMode = SHELL_OPEN_SHAREDSCHEMA;
|
||||
}else if( cli_strcmp(z,"-nofollow")==0 ){
|
||||
data.openFlags = SQLITE_OPEN_NOFOLLOW;
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
||||
@@ -13617,8 +13328,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#endif
|
||||
}else if( cli_strcmp(z,"-readonly")==0 ){
|
||||
data.openMode = SHELL_OPEN_READONLY;
|
||||
}else if( strcmp(z,"-sharedschema")==0 ){
|
||||
data.openMode = SHELL_OPEN_SHAREDSCHEMA;
|
||||
}else if( cli_strcmp(z,"-nofollow")==0 ){
|
||||
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
|
||||
}else if( cli_strcmp(z,"-ascii")==0 ){
|
||||
@@ -13766,6 +13475,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
** the database filename.
|
||||
*/
|
||||
for(i=0; i<nCmd; i++){
|
||||
echo_group_input(&data, azCmd[i]);
|
||||
if( azCmd[i][0]=='.' ){
|
||||
rc = do_meta_command(azCmd[i], &data);
|
||||
if( rc ){
|
||||
@@ -13774,7 +13484,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
}
|
||||
}else{
|
||||
open_db(&data, 0);
|
||||
echo_group_input(&data, azCmd[i]);
|
||||
rc = shell_exec(&data, azCmd[i], &zErrMsg);
|
||||
if( zErrMsg || rc ){
|
||||
if( zErrMsg!=0 ){
|
||||
|
||||
+3
-2
@@ -616,11 +616,10 @@ int sqlite3_exec(
|
||||
#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
|
||||
|
||||
/* Reserved: 0x00F00000 */
|
||||
#define SQLITE_OPEN_SHARED_SCHEMA 0x01000000 /* Ok for sqlite3_open_v2() */
|
||||
|
||||
/* Legacy compatibility: */
|
||||
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Device Characteristics
|
||||
**
|
||||
@@ -7072,6 +7071,8 @@ int sqlite3_autovacuum_pages(
|
||||
**
|
||||
** ^The second argument is a pointer to the function to invoke when a
|
||||
** row is updated, inserted or deleted in a rowid table.
|
||||
** ^The update hook is disabled by invoking sqlite3_update_hook()
|
||||
** with a NULL pointer as the second parameter.
|
||||
** ^The first argument to the callback is a copy of the third argument
|
||||
** to sqlite3_update_hook().
|
||||
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
|
||||
|
||||
@@ -1321,7 +1321,6 @@ typedef struct Db Db;
|
||||
typedef struct DbClientData DbClientData;
|
||||
typedef struct DbFixer DbFixer;
|
||||
typedef struct Schema Schema;
|
||||
typedef struct SchemaPool SchemaPool;
|
||||
typedef struct Expr Expr;
|
||||
typedef struct ExprList ExprList;
|
||||
typedef struct FKey FKey;
|
||||
@@ -1465,10 +1464,6 @@ struct Db {
|
||||
u8 safety_level; /* How aggressive at syncing data to disk */
|
||||
u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
|
||||
Schema *pSchema; /* Pointer to database schema (possibly shared) */
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
SchemaPool *pSPool; /* For REUSE_SCHEMA mode */
|
||||
VTable *pVTable; /* List of all VTable objects (REUSE_SCHEMA mode only) */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1500,9 +1495,6 @@ struct Schema {
|
||||
u8 enc; /* Text encoding used by this database */
|
||||
u16 schemaFlags; /* Flags associated with this schema */
|
||||
int cache_size; /* Number of pages to use in the cache */
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
Schema *pNext; /* Next Schema object SchemaPool (REUSE_SCHEMA) */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1798,12 +1790,6 @@ struct sqlite3 {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
# define IsSharedSchema(db) (((db)->openFlags & SQLITE_OPEN_SHARED_SCHEMA)!=0)
|
||||
#else
|
||||
# define IsSharedSchema(db) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A macro to discover the encoding of a database.
|
||||
*/
|
||||
@@ -1890,9 +1876,6 @@ struct sqlite3 {
|
||||
#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
|
||||
#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */
|
||||
|
||||
#define DBFLAG_SchemaInuse 0x0080 /* Do not release sharable schemas */
|
||||
#define DBFLAG_FreeSchema 0x0100 /* Free extra shared schemas on release */
|
||||
|
||||
/*
|
||||
** Bits of the sqlite3.dbOptFlags field that are used by the
|
||||
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
|
||||
@@ -2410,9 +2393,6 @@ struct VTable {
|
||||
u8 eVtabRisk; /* Riskiness of allowing hacker access */
|
||||
int iSavepoint; /* Depth of the SAVEPOINT stack */
|
||||
VTable *pNext; /* Next in linked list (see above) */
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
char *zName; /* Table name (REUSE_SCHEMA mode) */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Allowed values for VTable.eVtabRisk
|
||||
@@ -4086,9 +4066,6 @@ struct Trigger {
|
||||
Schema *pTabSchema; /* Schema containing the table */
|
||||
TriggerStep *step_list; /* Link list of trigger program steps */
|
||||
Trigger *pNext; /* Next trigger associated with the table */
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
char *zTabSchema; /* Temp triggers in IsSharedSchema() dbs only */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -4228,7 +4205,6 @@ typedef struct {
|
||||
int rc; /* Result code stored here */
|
||||
u32 mInitFlags; /* Flags controlling error messages */
|
||||
u32 nInitRow; /* Number of rows processed */
|
||||
u64 cksum; /* Schema checksum for REUSE_SCHEMA mode */
|
||||
Pgno mxPage; /* Maximum page number. 0 for no limit. */
|
||||
} InitData;
|
||||
|
||||
@@ -5446,29 +5422,6 @@ void sqlite3DefaultRowEst(Index*);
|
||||
void sqlite3RegisterLikeFunctions(sqlite3*, int);
|
||||
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
|
||||
void sqlite3SchemaClear(void *);
|
||||
void sqlite3SchemaClearOrDisconnect(sqlite3*, int);
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
int sqlite3SchemaConnect(sqlite3*, int, u64);
|
||||
int sqlite3SchemaDisconnect(sqlite3 *, int, int);
|
||||
Schema *sqlite3SchemaExtract(SchemaPool*);
|
||||
int sqlite3SchemaLoad(sqlite3*, int, int*, char**);
|
||||
void sqlite3SchemaReleaseAll(sqlite3*);
|
||||
void sqlite3SchemaRelease(sqlite3*, int);
|
||||
void sqlite3SchemaAdjustUsed(sqlite3*, int, int, int*);
|
||||
void sqlite3SchemaWritable(Parse*, int);
|
||||
void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease);
|
||||
int sqlite3LockReusableSchema(sqlite3 *db);
|
||||
#else
|
||||
# define sqlite3SchemaWritable(x,y)
|
||||
# define sqlite3UnlockReusableSchema(x,y) (void)(y)
|
||||
# define sqlite3LockReusableSchema(x) 0
|
||||
# define sqlite3SchemaDisconnect(x,y,z) SQLITE_OK
|
||||
# define sqlite3SchemaLoad(w,x,y,z) SQLITE_OK
|
||||
# define sqlite3SchemaRelease(y,z)
|
||||
# define sqlite3SchemaConnect(x,y,z) SQLITE_OK
|
||||
#endif
|
||||
|
||||
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
|
||||
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
|
||||
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
|
||||
|
||||
+1
-21
@@ -289,26 +289,13 @@ int sqlite3_db_status(
|
||||
case SQLITE_DBSTATUS_SCHEMA_USED: {
|
||||
int i; /* Used to iterate through schemas */
|
||||
int nByte = 0; /* Used to accumulate return value */
|
||||
int bReleaseSchema;
|
||||
|
||||
sqlite3BtreeEnterAll(db);
|
||||
bReleaseSchema = sqlite3LockReusableSchema(db);
|
||||
db->pnBytesFreed = &nByte;
|
||||
assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
|
||||
db->lookaside.pEnd = db->lookaside.pStart;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Schema *pSchema;
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
int bUnload = 0;
|
||||
int nUsed = nByte;
|
||||
if( db->aDb[i].pSPool ){
|
||||
char *zDummy = 0;
|
||||
rc = sqlite3SchemaLoad(db, i, &bUnload, &zDummy);
|
||||
sqlite3_free(zDummy);
|
||||
if( rc ) break;
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
pSchema = db->aDb[i].pSchema;
|
||||
Schema *pSchema = db->aDb[i].pSchema;
|
||||
if( ALWAYS(pSchema!=0) ){
|
||||
HashElem *p;
|
||||
|
||||
@@ -330,14 +317,7 @@ int sqlite3_db_status(
|
||||
sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( db->aDb[i].pSPool ){
|
||||
if( bUnload ) sqlite3SchemaRelease(db, i);
|
||||
sqlite3SchemaAdjustUsed(db, i, nUsed, &nByte);
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
}
|
||||
sqlite3UnlockReusableSchema(db, bReleaseSchema);
|
||||
db->pnBytesFreed = 0;
|
||||
db->lookaside.pEnd = db->lookaside.pTrueEnd;
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
|
||||
+13
-21
@@ -1232,6 +1232,7 @@ static int auth_callback(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTHORIZATION */
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** This routine reads a line of text from FILE in, stores
|
||||
** the text in memory obtained from malloc() and returns a pointer
|
||||
@@ -1276,6 +1277,7 @@ static char *local_getline(char *zPrompt, FILE *in){
|
||||
zLine = realloc( zLine, n+1 );
|
||||
return zLine;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -2057,7 +2059,7 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
** (4) Name of the database (ex: "main", "temp")
|
||||
** (5) Name of trigger that is doing the access
|
||||
**
|
||||
** The callback should return on of the following strings: SQLITE_OK,
|
||||
** The callback should return one of the following strings: SQLITE_OK,
|
||||
** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error.
|
||||
**
|
||||
** If this method is invoked with no arguments, the current authorization
|
||||
@@ -2520,9 +2522,10 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
char *zLine; /* A single line of input from the file */
|
||||
char **azCol; /* zLine[] broken up into columns */
|
||||
const char *zCommit; /* How to commit changes */
|
||||
FILE *in; /* The input file */
|
||||
Tcl_Channel in; /* The input file */
|
||||
int lineno = 0; /* Line number of input file */
|
||||
char zLineNum[80]; /* Line number print buffer */
|
||||
Tcl_DString str;
|
||||
Tcl_Obj *pResult; /* interp result */
|
||||
|
||||
const char *zSep;
|
||||
@@ -2601,23 +2604,24 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
sqlite3_finalize(pStmt);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
in = fopen(zFile, "rb");
|
||||
in = Tcl_OpenFileChannel(interp, zFile, "rb", 0666);
|
||||
if( in==0 ){
|
||||
Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, (char*)0);
|
||||
sqlite3_finalize(pStmt);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
azCol = malloc( sizeof(azCol[0])*(nCol+1) );
|
||||
if( azCol==0 ) {
|
||||
Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
|
||||
fclose(in);
|
||||
Tcl_Close(interp, in);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DStringInit(&str);
|
||||
(void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
|
||||
zCommit = "COMMIT";
|
||||
while( (zLine = local_getline(0, in))!=0 ){
|
||||
while( Tcl_Gets(in, &str)>=0 ) {
|
||||
char *z;
|
||||
lineno++;
|
||||
zLine = Tcl_DStringValue(&str);
|
||||
azCol[0] = zLine;
|
||||
for(i=0, z=zLine; *z; z++){
|
||||
if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
|
||||
@@ -2655,15 +2659,16 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
}
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_reset(pStmt);
|
||||
free(zLine);
|
||||
Tcl_DStringSetLength(&str, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);
|
||||
zCommit = "ROLLBACK";
|
||||
break;
|
||||
}
|
||||
}
|
||||
Tcl_DStringFree(&str);
|
||||
free(azCol);
|
||||
fclose(in);
|
||||
Tcl_Close(interp, in);
|
||||
sqlite3_finalize(pStmt);
|
||||
(void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
|
||||
|
||||
@@ -3772,9 +3777,6 @@ static int sqliteCmdUsage(
|
||||
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
||||
" ?-nofollow BOOLEAN?"
|
||||
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
" ?-shared-schema BOOLEAN?"
|
||||
#endif
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -3906,16 +3908,6 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}else{
|
||||
flags &= ~SQLITE_OPEN_URI;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
}else if( strcmp(zArg, "-shared-schema")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b ){
|
||||
flags |= SQLITE_OPEN_SHARED_SCHEMA;
|
||||
}else{
|
||||
flags &= ~SQLITE_OPEN_SHARED_SCHEMA;
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
}else if( strcmp(zArg, "-translatefilename")==0 ){
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &bTranslateFileName) ){
|
||||
return TCL_ERROR;
|
||||
|
||||
@@ -569,14 +569,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_READONLY_WALJOURNAL
|
||||
Tcl_SetVar2(
|
||||
interp, "sqlite_options", "readonly_waljournal", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(
|
||||
interp, "sqlite_options", "readonly_waljournal", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_REINDEX
|
||||
Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -795,13 +787,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
|
||||
Tcl_SetVar2(interp, "sqlite_options", "setlk_timeout", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
** 2006 June 10
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
*************************************************************************
|
||||
** Code for testing the virtual table interfaces. This code
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
*/
|
||||
|
||||
/*
|
||||
** None of this works unless we have virtual tables.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST)
|
||||
|
||||
#include "tclsqlite.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/* The code in this file defines a sqlite3 virtual-table module with
|
||||
** the following schema.
|
||||
*/
|
||||
#define SCHEMAPOOL_SCHEMA \
|
||||
"CREATE TABLE x(" \
|
||||
" cksum INTEGER, " \
|
||||
" nref INTEGER, " \
|
||||
" nschema INTEGER, " \
|
||||
" ndelete INTEGER " \
|
||||
")"
|
||||
|
||||
#define SCHEMAPOOL_NFIELD 4
|
||||
|
||||
typedef struct schemapool_vtab schemapool_vtab;
|
||||
typedef struct schemapool_cursor schemapool_cursor;
|
||||
|
||||
/* A schema table object */
|
||||
struct schemapool_vtab {
|
||||
sqlite3_vtab base;
|
||||
};
|
||||
|
||||
/* A schema table cursor object */
|
||||
struct schemapool_cursor {
|
||||
sqlite3_vtab_cursor base;
|
||||
sqlite3_int64 *aData;
|
||||
int iRow;
|
||||
int nRow;
|
||||
};
|
||||
|
||||
/*
|
||||
** Table destructor for the schema module.
|
||||
*/
|
||||
static int schemaPoolDestroy(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Table constructor for the schema module.
|
||||
*/
|
||||
static int schemaPoolCreate(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
int rc = SQLITE_NOMEM;
|
||||
schemapool_vtab *pVtab = sqlite3_malloc(sizeof(schemapool_vtab));
|
||||
if( pVtab ){
|
||||
memset(pVtab, 0, sizeof(schemapool_vtab));
|
||||
rc = sqlite3_declare_vtab(db, SCHEMAPOOL_SCHEMA);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(pVtab);
|
||||
pVtab = 0;
|
||||
}
|
||||
}
|
||||
*ppVtab = (sqlite3_vtab *)pVtab;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a new cursor on the schema table.
|
||||
*/
|
||||
static int schemaPoolOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
int rc = SQLITE_NOMEM;
|
||||
schemapool_cursor *pCur;
|
||||
pCur = sqlite3_malloc(sizeof(schemapool_cursor));
|
||||
if( pCur ){
|
||||
memset(pCur, 0, sizeof(schemapool_cursor));
|
||||
*ppCursor = (sqlite3_vtab_cursor*)pCur;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a schema table cursor.
|
||||
*/
|
||||
static int schemaPoolClose(sqlite3_vtab_cursor *cur){
|
||||
schemapool_cursor *pCur = (schemapool_cursor*)cur;
|
||||
sqlite3_free(pCur->aData);
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Retrieve a column of data.
|
||||
*/
|
||||
static int schemaPoolColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
schemapool_cursor *pCur = (schemapool_cursor*)cur;
|
||||
assert( i==0 || i==1 || i==2 || i==3 );
|
||||
sqlite3_result_int64(ctx, pCur->aData[pCur->iRow*SCHEMAPOOL_NFIELD + i]);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Retrieve the current rowid.
|
||||
*/
|
||||
static int schemaPoolRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
schemapool_cursor *pCur = (schemapool_cursor*)cur;
|
||||
*pRowid = pCur->iRow + 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int schemaPoolEof(sqlite3_vtab_cursor *cur){
|
||||
schemapool_cursor *pCur = (schemapool_cursor*)cur;
|
||||
return pCur->iRow>=pCur->nRow;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the cursor to the next row.
|
||||
*/
|
||||
static int schemaPoolNext(sqlite3_vtab_cursor *cur){
|
||||
schemapool_cursor *pCur = (schemapool_cursor*)cur;
|
||||
pCur->iRow++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
struct SchemaPool {
|
||||
int nRef; /* Number of pointers to this object */
|
||||
int nDelete; /* Schema objects deleted by ReleaseAll() */
|
||||
u64 cksum; /* Checksum for this Schema contents */
|
||||
Schema *pSchema; /* Linked list of Schema objects */
|
||||
Schema sSchema; /* The single dummy schema object */
|
||||
SchemaPool *pNext; /* Next element in schemaPoolList */
|
||||
};
|
||||
extern SchemaPool *sqlite3SchemaPoolList(void);
|
||||
|
||||
/*
|
||||
** Reset a schemaPool table cursor.
|
||||
*/
|
||||
static int schemaPoolFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
SchemaPool *pSPool;
|
||||
schemapool_cursor *pCur = (schemapool_cursor*)pVtabCursor;
|
||||
|
||||
sqlite3_free(pCur->aData);
|
||||
pCur->aData = 0;
|
||||
pCur->nRow = 0;
|
||||
pCur->iRow = 0;
|
||||
|
||||
for(pSPool = sqlite3SchemaPoolList(); pSPool; pSPool=pSPool->pNext){
|
||||
pCur->nRow++;
|
||||
}
|
||||
|
||||
if( pCur->nRow ){
|
||||
int iRow = 0;
|
||||
int nByte = SCHEMAPOOL_NFIELD * pCur->nRow * sizeof(i64);
|
||||
pCur->aData = (i64*)sqlite3_malloc(nByte);
|
||||
if( pCur->aData==0 ) return SQLITE_NOMEM;
|
||||
for(pSPool = sqlite3SchemaPoolList(); pSPool; pSPool=pSPool->pNext){
|
||||
Schema *p;
|
||||
i64 nSchema = 0;
|
||||
for(p=pSPool->pSchema; p; p=p->pNext){
|
||||
nSchema++;
|
||||
}
|
||||
pCur->aData[0 + iRow*SCHEMAPOOL_NFIELD] = pSPool->cksum;
|
||||
pCur->aData[1 + iRow*SCHEMAPOOL_NFIELD] = (i64)pSPool->nRef;
|
||||
pCur->aData[2 + iRow*SCHEMAPOOL_NFIELD] = nSchema;
|
||||
pCur->aData[3 + iRow*SCHEMAPOOL_NFIELD] = (i64)pSPool->nDelete;
|
||||
iRow++;
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Analyse the WHERE condition.
|
||||
*/
|
||||
static int schemaPoolBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** A virtual table module that merely echos method calls into TCL
|
||||
** variables.
|
||||
*/
|
||||
static sqlite3_module schemaPoolModule = {
|
||||
0, /* iVersion */
|
||||
schemaPoolCreate,
|
||||
schemaPoolCreate,
|
||||
schemaPoolBestIndex,
|
||||
schemaPoolDestroy,
|
||||
schemaPoolDestroy,
|
||||
schemaPoolOpen, /* xOpen - open a cursor */
|
||||
schemaPoolClose, /* xClose - close a cursor */
|
||||
schemaPoolFilter, /* xFilter - configure scan constraints */
|
||||
schemaPoolNext, /* xNext - advance a cursor */
|
||||
schemaPoolEof, /* xEof */
|
||||
schemaPoolColumn, /* xColumn - read data */
|
||||
schemaPoolRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
};
|
||||
|
||||
/*
|
||||
** Decode a pointer to an sqlite3 object.
|
||||
*/
|
||||
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
|
||||
|
||||
/*
|
||||
** Register the schema virtual table module.
|
||||
*/
|
||||
static int SQLITE_TCLAPI register_schemapool_module(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_create_module(db, "schemapool", &schemaPoolModule, 0);
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST) */
|
||||
|
||||
/*
|
||||
** Register commands with the TCL interpreter.
|
||||
*/
|
||||
int Sqlitetestschemapool_Init(Tcl_Interp *interp){
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
static struct {
|
||||
char *zName;
|
||||
Tcl_ObjCmdProc *xProc;
|
||||
void *clientData;
|
||||
} aObjCmd[] = {
|
||||
{ "register_schemapool_module", register_schemapool_module, 0 },
|
||||
};
|
||||
int i;
|
||||
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
|
||||
Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
|
||||
aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -68,7 +68,6 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
|
||||
extern int Sqlitetest_malloc_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_mutex_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestschema_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestschemapool_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestsse_Init(Tcl_Interp*);
|
||||
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestfs_Init(Tcl_Interp*);
|
||||
@@ -140,7 +139,6 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
|
||||
Sqlitetest_malloc_Init(interp);
|
||||
Sqlitetest_mutex_Init(interp);
|
||||
Sqlitetestschema_Init(interp);
|
||||
Sqlitetestschemapool_Init(interp);
|
||||
Sqlitetesttclvar_Init(interp);
|
||||
Sqlitetestfs_Init(interp);
|
||||
SqlitetestThread_Init(interp);
|
||||
|
||||
+5
-1
@@ -692,7 +692,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql){
|
||||
assert( n==6 );
|
||||
tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
}else if( tokenType==TK_COMMENT && (db->flags & SQLITE_Comments)!=0 ){
|
||||
}else if( tokenType==TK_COMMENT
|
||||
&& (db->init.busy || (db->flags & SQLITE_Comments)!=0)
|
||||
){
|
||||
/* Ignore SQL comments if either (1) we are reparsing the schema or
|
||||
** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */
|
||||
zSql += n;
|
||||
continue;
|
||||
}else if( tokenType!=TK_QNUMBER ){
|
||||
|
||||
+5
-40
@@ -52,34 +52,13 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
|
||||
Trigger *pList; /* List of triggers to return */
|
||||
HashElem *p; /* Loop variable for TEMP triggers */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
char *zSchema = 0;
|
||||
sqlite3 *db = pParse->db;
|
||||
if( IsSharedSchema(db) ){
|
||||
zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert( pParse->disableTriggers==0 );
|
||||
pTmpSchema = pParse->db->aDb[1].pSchema;
|
||||
p = sqliteHashFirst(&pTmpSchema->trigHash);
|
||||
pList = pTab->pTrigger;
|
||||
while( p ){
|
||||
Trigger *pTrig = (Trigger *)sqliteHashData(p);
|
||||
|
||||
int bSchemaMatch;
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( zSchema ){
|
||||
/* Shared-schema */
|
||||
bSchemaMatch = (0==sqlite3StrICmp(pTrig->zTabSchema, zSchema));
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
/* Non-shared-schema */
|
||||
bSchemaMatch = (pTrig->pTabSchema==pTab->pSchema);
|
||||
}
|
||||
|
||||
if( bSchemaMatch
|
||||
if( pTrig->pTabSchema==pTab->pSchema
|
||||
&& pTrig->table
|
||||
&& 0==sqlite3StrICmp(pTrig->table, pTab->zName)
|
||||
&& (pTrig->pTabSchema!=pTmpSchema || pTrig->bReturning)
|
||||
@@ -89,7 +68,7 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
|
||||
}else if( pTrig->op==TK_RETURNING ){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
assert( pParse->db->pVtabCtx==0 );
|
||||
#endif
|
||||
#endif
|
||||
assert( pParse->bReturning );
|
||||
assert( !pParse->isCreate );
|
||||
assert( &(pParse->u1.d.pReturning->retTrig) == pTrig );
|
||||
@@ -287,12 +266,6 @@ void sqlite3BeginTrigger(
|
||||
pTrigger->zName = zName;
|
||||
zName = 0;
|
||||
pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) && iDb==1 ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
pTrigger->zTabSchema = sqlite3DbStrDup(db, db->aDb[iTabDb].zDbSName);
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
pTrigger->pSchema = db->aDb[iDb].pSchema;
|
||||
pTrigger->pTabSchema = pTab->pSchema;
|
||||
pTrigger->op = (u8)op;
|
||||
@@ -416,7 +389,7 @@ void sqlite3FinishTrigger(
|
||||
pTrig->table, z);
|
||||
sqlite3DbFree(db, z);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb,
|
||||
sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
|
||||
}
|
||||
|
||||
@@ -635,9 +608,6 @@ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
|
||||
sqlite3DeleteTriggerStep(db, pTrigger->step_list);
|
||||
sqlite3DbFree(db, pTrigger->zName);
|
||||
sqlite3DbFree(db, pTrigger->table);
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
sqlite3DbFree(db, pTrigger->zTabSchema);
|
||||
#endif
|
||||
sqlite3ExprDelete(db, pTrigger->pWhen);
|
||||
sqlite3IdListDelete(db, pTrigger->pColumns);
|
||||
sqlite3DbFree(db, pTrigger);
|
||||
@@ -710,7 +680,6 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
pTable = tableOfTrigger(pTrigger);
|
||||
assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
@@ -1281,9 +1250,7 @@ static TriggerPrg *codeRowTrigger(
|
||||
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
|
||||
Parse sSubParse; /* Parse context for sub-vdbe */
|
||||
|
||||
assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
|
||||
|| pTab==tableOfTrigger(pTrigger)
|
||||
);
|
||||
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
|
||||
assert( pTop->pVdbe );
|
||||
|
||||
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
|
||||
@@ -1392,9 +1359,7 @@ static TriggerPrg *getRowTrigger(
|
||||
Parse *pRoot = sqlite3ParseToplevel(pParse);
|
||||
TriggerPrg *pPrg;
|
||||
|
||||
assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
|
||||
|| pTab==tableOfTrigger(pTrigger)
|
||||
);
|
||||
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
|
||||
|
||||
/* It may be that this trigger has already been coded (or is in the
|
||||
** process of being coded). If this is the case, then an entry with
|
||||
|
||||
+1
-2
@@ -125,7 +125,6 @@ void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
|
||||
}
|
||||
if( iDb!=1 ){
|
||||
int iIntoReg = 0;
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){
|
||||
iIntoReg = ++pParse->nMem;
|
||||
sqlite3ExprCode(pParse, pInto, iIntoReg);
|
||||
@@ -196,7 +195,7 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
|
||||
saved_nChange = db->nChange;
|
||||
saved_nTotalChange = db->nTotalChange;
|
||||
saved_mTrace = db->mTrace;
|
||||
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
|
||||
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
|
||||
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
|
||||
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
|
||||
| SQLITE_Defensive | SQLITE_CountRows);
|
||||
|
||||
+8
-8
@@ -4101,6 +4101,13 @@ case OP_Transaction: {
|
||||
&& pOp->p5
|
||||
&& (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i)
|
||||
){
|
||||
/*
|
||||
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
|
||||
** version is checked to ensure that the schema has not changed since the
|
||||
** SQL statement was prepared.
|
||||
*/
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
|
||||
/* If the schema-cookie from the database file matches the cookie
|
||||
** stored with the in-memory representation of the schema, do
|
||||
** not reload the schema from the database file.
|
||||
@@ -4117,13 +4124,6 @@ case OP_Transaction: {
|
||||
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
|
||||
sqlite3ResetOneSchema(db, pOp->p1);
|
||||
}
|
||||
/*
|
||||
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
|
||||
** version is checked to ensure that the schema has not changed since the
|
||||
** SQL statement was prepared.
|
||||
*/
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
|
||||
p->expired = 1;
|
||||
rc = SQLITE_SCHEMA;
|
||||
|
||||
@@ -6056,7 +6056,7 @@ case OP_RowData: {
|
||||
/* The OP_RowData opcodes always follow OP_NotExists or
|
||||
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
|
||||
** that might invalidate the cursor.
|
||||
** If this where not the case, on of the following assert()s
|
||||
** If this were not the case, one of the following assert()s
|
||||
** would fail. Should this ever change (because of changes in the code
|
||||
** generator) then the fix would be to insert a call to
|
||||
** sqlite3VdbeCursorMoveto().
|
||||
|
||||
+1
-1
@@ -245,7 +245,7 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
|
||||
#else
|
||||
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
|
||||
#endif
|
||||
void sqlite3VdbeAddParseSchemaOp(Parse*,int,char*,u16);
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
|
||||
void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
|
||||
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
|
||||
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
|
||||
|
||||
+1
-3
@@ -561,10 +561,8 @@ void sqlite3VdbeExplainPop(Parse *pParse){
|
||||
** The zWhere string must have been obtained from sqlite3_malloc().
|
||||
** This routine will take ownership of the allocated memory.
|
||||
*/
|
||||
void sqlite3VdbeAddParseSchemaOp(Parse *pParse, int iDb, char *zWhere, u16 p5){
|
||||
Vdbe *p = pParse->pVdbe;
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
|
||||
int j;
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
|
||||
sqlite3VdbeChangeP5(p, p5);
|
||||
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
|
||||
|
||||
+6
-6
@@ -133,8 +133,8 @@ int sqlite3_blob_open(
|
||||
char *zErr = 0;
|
||||
Table *pTab;
|
||||
Incrblob *pBlob = 0;
|
||||
int iDb;
|
||||
Parse sParse;
|
||||
int bUnlock; /* True to unlock reusable schemas before returning */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppBlob==0 ){
|
||||
@@ -151,7 +151,6 @@ int sqlite3_blob_open(
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
bUnlock = sqlite3LockReusableSchema(db);
|
||||
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
|
||||
while(1){
|
||||
sqlite3ParseObjectInit(&sParse,db);
|
||||
@@ -180,7 +179,10 @@ int sqlite3_blob_open(
|
||||
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
|
||||
}
|
||||
#endif
|
||||
if( !pTab ){
|
||||
if( pTab==0
|
||||
|| ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 &&
|
||||
sqlite3OpenTempDatabase(&sParse))
|
||||
){
|
||||
if( sParse.zErrMsg ){
|
||||
sqlite3DbFree(db, zErr);
|
||||
zErr = sParse.zErrMsg;
|
||||
@@ -191,7 +193,7 @@ int sqlite3_blob_open(
|
||||
goto blob_open_out;
|
||||
}
|
||||
pBlob->pTab = pTab;
|
||||
pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
|
||||
pBlob->zDb = db->aDb[iDb].zDbSName;
|
||||
|
||||
/* Now search pTab for the exact column. */
|
||||
iCol = sqlite3ColumnIndex(pTab, zColumn);
|
||||
@@ -275,7 +277,6 @@ int sqlite3_blob_open(
|
||||
{OP_Halt, 0, 0, 0}, /* 5 */
|
||||
};
|
||||
Vdbe *v = (Vdbe *)pBlob->pStmt;
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
VdbeOp *aOp;
|
||||
|
||||
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
|
||||
@@ -338,7 +339,6 @@ int sqlite3_blob_open(
|
||||
}
|
||||
|
||||
blob_open_out:
|
||||
sqlite3UnlockReusableSchema(db, bUnlock);
|
||||
if( rc==SQLITE_OK && db->mallocFailed==0 ){
|
||||
*ppBlob = (sqlite3_blob *)pBlob;
|
||||
}else{
|
||||
|
||||
+8
-47
@@ -192,24 +192,6 @@ void sqlite3VtabLock(VTable *pVTab){
|
||||
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
|
||||
VTable *pVtab;
|
||||
assert( IsVirtual(pTab) );
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
if( iDb!=1 ){
|
||||
VTable **pp;
|
||||
for(pp=&db->aDb[iDb].pVTable; *pp; pp=&(*pp)->pNext){
|
||||
if( sqlite3StrICmp(pTab->zName, (*pp)->zName)==0 ) break;
|
||||
}
|
||||
pVtab = *pp;
|
||||
if( pVtab && pTab->nCol<=0 ){
|
||||
*pp = pVtab->pNext;
|
||||
sqlite3VtabUnlock(pVtab);
|
||||
pVtab = 0;
|
||||
}
|
||||
return pVtab;
|
||||
}
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
|
||||
return pVtab;
|
||||
}
|
||||
@@ -518,7 +500,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
||||
|
||||
sqlite3VdbeAddOp0(v, OP_Expire);
|
||||
zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb, zWhere, 0);
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
|
||||
sqlite3DbFree(db, zStmt);
|
||||
|
||||
iReg = ++pParse->nMem;
|
||||
@@ -588,7 +570,6 @@ static int vtabCallConstructor(
|
||||
char *zModuleName;
|
||||
int iDb;
|
||||
VtabCtx *pCtx;
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
|
||||
assert( IsVirtual(pTab) );
|
||||
azArg = (const char *const*)pTab->u.vtab.azArg;
|
||||
@@ -608,11 +589,7 @@ static int vtabCallConstructor(
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
nByte = sizeof(VTable);
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
nByte += sqlite3Strlen30(pTab->zName) + 1;
|
||||
#endif
|
||||
pVTable = (VTable*)sqlite3MallocZero(nByte);
|
||||
pVTable = sqlite3MallocZero(sizeof(VTable));
|
||||
if( !pVTable ){
|
||||
sqlite3OomFault(db);
|
||||
sqlite3DbFree(db, zModuleName);
|
||||
@@ -620,10 +597,6 @@ static int vtabCallConstructor(
|
||||
}
|
||||
pVTable->db = db;
|
||||
pVTable->pMod = pMod;
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
pVTable->zName = (char*)&pVTable[1];
|
||||
memcpy(pVTable->zName, pTab->zName, nByte-sizeof(VTable));
|
||||
#endif
|
||||
pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
@@ -670,23 +643,12 @@ static int vtabCallConstructor(
|
||||
int iCol;
|
||||
u16 oooHidden = 0;
|
||||
/* If everything went according to plan, link the new VTable structure
|
||||
** into the linked list headed by pTab->u.vtab.p. Or, if this is a
|
||||
** reusable schema, into the linked list headed by Db.pVTable.
|
||||
**
|
||||
** Then loop through the columns of the table to see if any of them
|
||||
** contain the token "hidden". If so, set the Column COLFLAG_HIDDEN flag
|
||||
** and remove the token from the type string. */
|
||||
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
|
||||
if( IsSharedSchema(db) && iDb!=1 ){
|
||||
pVTable->pNext = db->aDb[iDb].pVTable;
|
||||
db->aDb[iDb].pVTable = pVTable;
|
||||
}else
|
||||
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
|
||||
{
|
||||
assert( IsVirtual(pTab) );
|
||||
pVTable->pNext = pTab->u.vtab.p;
|
||||
pTab->u.vtab.p = pVTable;
|
||||
}
|
||||
** into the linked list headed by pTab->u.vtab.p. Then loop through the
|
||||
** columns of the table to see if any of them contain the token "hidden".
|
||||
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
|
||||
** the type string. */
|
||||
pVTable->pNext = pTab->u.vtab.p;
|
||||
pTab->u.vtab.p = pVTable;
|
||||
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
|
||||
@@ -741,7 +703,6 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
|
||||
assert( pTab );
|
||||
assert( IsVirtual(pTab) );
|
||||
if( sqlite3GetVTable(db, pTab) ){
|
||||
assert( !IsVirtual(pTab) || pTab->nCol>0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1679,7 +1679,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
|
||||
}
|
||||
}
|
||||
if( pTab->u.vtab.p && pTab->u.vtab.p->bAllSchemas ){
|
||||
if( pTab->u.vtab.p->bAllSchemas ){
|
||||
sqlite3VtabUsesAllSchemas(pParse);
|
||||
}
|
||||
sqlite3_free(pVtab->zErrMsg);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix nolock
|
||||
|
||||
unset -nocomplain tvfs_calls
|
||||
proc tvfs_reset {} {
|
||||
@@ -218,31 +217,4 @@ if {[permutation]!="inmemory_journal"} {
|
||||
} {1 {unable to open database file}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
|
||||
INSERT INTO t2 VALUES(1, 2), (3, 4), (5, 6);
|
||||
PRAGMA cache_size = 0;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t2 VALUES(7, 8);
|
||||
}
|
||||
|
||||
do_test 5.1 {
|
||||
forcecopy test.db test.db2
|
||||
forcecopy test.db-journal test.db2-journal
|
||||
sqlite3 db2 file:test.db2?immutable=0 -uri 1 -readonly 1
|
||||
|
||||
list [catch {
|
||||
db2 eval {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} msg] $msg
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
# 2024 October 30
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test that readonly database connections may ignore a hot journal
|
||||
# created by an aborted "PRAGMA journal_mode = wal" statement.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !readonly_waljournal {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set ::testprefix readonly2
|
||||
|
||||
testvfs tvfs -default 1
|
||||
tvfs script at_vfs_callback
|
||||
tvfs filter {xDelete}
|
||||
|
||||
set ::delete_shall_fail 0
|
||||
proc at_vfs_callback {method file z args} {
|
||||
if {$::delete_shall_fail} {
|
||||
return "SQLITE_IOERR"
|
||||
}
|
||||
return "SQLITE_OK"
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 1.0 {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
set ::delete_shall_fail 1
|
||||
do_catchsql_test 1.1 {
|
||||
PRAGMA journal_mode = wal;
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
do_test 1.2 {
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
|
||||
do_test 1.3 {
|
||||
sqlite3 db2 test.db -readonly 1
|
||||
db2 eval {
|
||||
SELECT * FROM t1
|
||||
}
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
do_test 1.4 {
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
|
||||
set ::delete_shall_fail 0
|
||||
do_execsql_test 1.5 {
|
||||
SELECT * FROM t1
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
set ::delete_shall_fail 1
|
||||
do_catchsql_test 1.6 {
|
||||
PRAGMA user_version = 444;
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
do_test 1.7 {
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
|
||||
do_test 1.8 {
|
||||
list [catch { db2 eval { SELECT * FROM t1 } } msg] $msg
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
do_test 1.9 {
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
|
||||
set ::delete_shall_fail 0
|
||||
do_execsql_test 1.10 {
|
||||
SELECT * FROM t1
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
#---------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES('abc', 'def');
|
||||
}
|
||||
|
||||
set ::delete_shall_fail 1
|
||||
do_catchsql_test 2.2 {
|
||||
PRAGMA journal_mode = wal;
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
do_test 2.3 {
|
||||
sqlite3 db2 test.db -readonly 1
|
||||
breakpoint
|
||||
db2 eval {
|
||||
PRAGMA journal_mode = persist;
|
||||
PRAGMA journal_mode = off;
|
||||
}
|
||||
} {persist off}
|
||||
|
||||
do_test 2.4 {
|
||||
db2 eval {
|
||||
SELECT * FROM t1
|
||||
}
|
||||
} {abc def}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
# 2024 October 30
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !readonly_waljournal {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set ::testprefix readonlyfault
|
||||
|
||||
testvfs tvfs -default 1
|
||||
tvfs script at_vfs_callback
|
||||
tvfs filter {xDelete}
|
||||
|
||||
set ::delete_shall_fail 0
|
||||
proc at_vfs_callback {method file z args} {
|
||||
if {$::delete_shall_fail} {
|
||||
return "SQLITE_IOERR"
|
||||
}
|
||||
return "SQLITE_OK"
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 1.0 {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
set ::delete_shall_fail 1
|
||||
do_catchsql_test 1.1 {
|
||||
PRAGMA journal_mode = wal;
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
do_test 1.2 {
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
|
||||
db_save_and_close
|
||||
|
||||
# Injecting CANTOPEN errors doesn't work here. If such an error occurs
|
||||
# while trying to open a potentially hot journal to inspect its contents,
|
||||
# the error is ignored and the journal assumed to be hot. Leading to an
|
||||
# SQLITE_READONLY error. So only the other types of fault-injection are
|
||||
# tested here.
|
||||
#
|
||||
do_faultsim_test readonlyfault-1 -faults {oom* ioerr* inter* full*} -prep {
|
||||
catch { db close }
|
||||
db_restore
|
||||
sqlite3 db test.db -readonly 1
|
||||
} -body {
|
||||
execsql { SELECT count(*), sum(a), sum(b) FROM t1 }
|
||||
} -test {
|
||||
faultsim_test_result {0 {3 9 12}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -47,6 +47,9 @@ proc recover_with_opts {opts} {
|
||||
set sql [read $fd]
|
||||
close $fd
|
||||
|
||||
# Remove the ".dbconfig defensive off" line
|
||||
set sql [string map {".dbconfig defensive off" ""} $sql]
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
execsql $sql db2
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
# 2017 August 9
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reuse1
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
PRAGMA schema_version;
|
||||
} {2}
|
||||
|
||||
do_execsql_test -db db2 1.1 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
PRAGMA schema_version;
|
||||
} {2}
|
||||
|
||||
do_test 1.2 {
|
||||
db close
|
||||
db2 close
|
||||
sqlite3 db2 test.db2 -shared-schema 1
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 1.3.1 {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT * FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_execsql_test -db db2 1.3.3 {
|
||||
SELECT * FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {1 2 3 4 5 6 ok}
|
||||
|
||||
sqlite3 db3 test.db2
|
||||
do_execsql_test -db db3 1.4.1 {
|
||||
ALTER TABLE t1 ADD COLUMN a;
|
||||
}
|
||||
do_execsql_test -db db2 1.4.2 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3 {} 4 5 6 {}}
|
||||
do_execsql_test 1.4.3 {
|
||||
SELECT * FROM t1;
|
||||
} {}
|
||||
|
||||
db3 close
|
||||
sqlite3 db3 test.db
|
||||
do_execsql_test -db db3 1.5.0 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
SELECT 1, 2, 3;
|
||||
END;
|
||||
}
|
||||
|
||||
# Check that the schema cannot be modified if the db was opened with
|
||||
# SQLITE_OPEN_REUSE_SCHEMA.
|
||||
#
|
||||
foreach {tn sql} {
|
||||
1 { CREATE TABLE t2(x, y) }
|
||||
2 { CREATE INDEX i2 ON t1(z) }
|
||||
3 { CREATE VIEW v2 AS SELECT * FROM t2 }
|
||||
4 { ALTER TABLE t1 RENAME TO t3 }
|
||||
5 { ALTER TABLE t1 ADD COLUMN xyz }
|
||||
6 { VACUUM }
|
||||
7 { DROP INDEX i1 }
|
||||
8 { DROP TABLE t1 }
|
||||
9 { DROP TRIGGER tr1 }
|
||||
10 { ANALYZE }
|
||||
11 { ALTER TABLE t1 RENAME z TO zzz }
|
||||
} {
|
||||
do_catchsql_test 1.5.$tn $sql {1 {attempt to modify read-only schema}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
db2 close
|
||||
db3 close
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a);
|
||||
INSERT INTO ft VALUES('one'), ('two'), ('three');
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE VIRTUAL TABLE aux.ft USING fts5(a);
|
||||
INSERT INTO aux.ft VALUES('aux1'), ('aux2'), ('aux3');
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
SELECT * FROM main.ft;
|
||||
} {one two three}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM aux.ft;
|
||||
} {aux1 aux2 aux3}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM aux.ft_content;
|
||||
} {1 aux1 2 aux2 3 aux3}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE TRIGGER v1_ins INSTEAD OF INSERT ON v1 BEGIN
|
||||
INSERT INTO t1 VALUES(new.a, new.b, new.c);
|
||||
END;
|
||||
CREATE TRIGGER v1_del INSTEAD OF DELETE ON v1 BEGIN
|
||||
DELETE FROM t1 WHERE a=old.a;
|
||||
END;
|
||||
CREATE TRIGGER v1_up INSTEAD OF UPDATE ON v1 BEGIN
|
||||
UPDATE t1 SET a=new.a, b=new.b, c=new.c WHERE a=old.a;
|
||||
END;
|
||||
}
|
||||
forcecopy test.db test.db2
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3 db2 test.db2
|
||||
execsql { INSERT INTO t1 VALUES(1, 2, 3) } db
|
||||
execsql { INSERT INTO t1 VALUES(4, 5, 6) } db2
|
||||
db2 close
|
||||
execsql { ATTACH 'test.db2' AS aux; }
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM main.v1;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
SELECT * FROM aux.v1;
|
||||
} {4 5 6}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
|
||||
do_execsql_test 3.4 { ATTACH 'test.db2' AS aux } {}
|
||||
do_execsql_test 3.5 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.6 { SELECT * FROM aux.v1 } {4 5 6}
|
||||
|
||||
do_execsql_test 3.7.1 { INSERT INTO aux.t1 VALUES(8, 9, 10); }
|
||||
do_execsql_test 3.7.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.7.3 { SELECT * FROM aux.v1 } {4 5 6 8 9 10}
|
||||
|
||||
do_execsql_test 3.8.1 { DELETE FROM aux.t1 WHERE b=5 }
|
||||
do_execsql_test 3.8.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.8.3 { SELECT * FROM aux.v1 } {8 9 10}
|
||||
|
||||
do_execsql_test 3.9.1 { UPDATE aux.t1 SET b='abc' }
|
||||
do_execsql_test 3.9.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.9.3 { SELECT * FROM aux.v1 } {8 abc 10}
|
||||
|
||||
do_execsql_test 3.10.1 { INSERT INTO aux.v1 VALUES(11, 12, 13) }
|
||||
do_execsql_test 3.10.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.10.3 { SELECT * FROM aux.v1 } {8 abc 10 11 12 13}
|
||||
|
||||
do_execsql_test 3.11.1 { DELETE FROM aux.v1 WHERE b='abc' }
|
||||
do_execsql_test 3.11.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.11.3 { SELECT * FROM aux.v1 } {11 12 13}
|
||||
|
||||
do_execsql_test 3.12.1 { UPDATE aux.v1 SET b='def' }
|
||||
do_execsql_test 3.12.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.12.3 { SELECT * FROM aux.v1 } {11 def 13}
|
||||
|
||||
do_execsql_test 3.13.1 {
|
||||
CREATE TEMP TRIGGER xyz AFTER INSERT ON aux.t1 BEGIN
|
||||
INSERT INTO v1 VALUES(new.a, new.b, new.c);
|
||||
END
|
||||
}
|
||||
do_execsql_test 3.13.2 {
|
||||
INSERT INTO aux.v1 VALUES('x', 'y', 'z');
|
||||
}
|
||||
do_execsql_test 3.13.3 {
|
||||
SELECT * FROM v1;
|
||||
} {1 2 3 x y z}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
|
||||
CREATE TABLE del(a, b, c);
|
||||
CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN
|
||||
INSERT INTO del VALUES(old.a, old.b, old.c);
|
||||
END;
|
||||
}
|
||||
forcecopy test.db test.db2
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
execsql {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
PRAGMA recursive_triggers = 1;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
INSERT INTO main.t1 VALUES(1, 2, 3);
|
||||
INSERT INTO aux.t1 VALUES(4, 5, 6);
|
||||
}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
INSERT OR REPLACE INTO aux.t1 VALUES('a', 'b', 6);
|
||||
SELECT * FROM aux.t1;
|
||||
} {a b 6}
|
||||
do_execsql_test 4.2.2 { SELECT * FROM aux.del } {4 5 6}
|
||||
do_execsql_test 4.2.3 { SELECT * FROM main.del } {}
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
INSERT INTO aux.t1 VALUES('x', 'y', 'z');
|
||||
UPDATE OR REPLACE aux.t1 SET c='z' WHERE a='a';
|
||||
} {}
|
||||
do_execsql_test 4.3.2 { SELECT * FROM aux.del } {4 5 6 x y z}
|
||||
do_execsql_test 4.3.3 { SELECT * FROM main.del } {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
|
||||
ANALYZE;
|
||||
PRAGMA writable_schema = 1;
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
db close
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
execsql { ATTACH 'test.db2' AS aux }
|
||||
|
||||
foreach {tn sql} {
|
||||
1 { CREATE TABLE t3(x) }
|
||||
2 { DROP TABLE t2 }
|
||||
3 { CREATE INDEX i2 ON t2(b) }
|
||||
4 { DROP INDEX i1 }
|
||||
5 { ALTER TABLE t1 ADD COLUMN d }
|
||||
6 { ALTER TABLE t1 RENAME TO t3 }
|
||||
7 { ALTER TABLE t1 RENAME c TO d }
|
||||
} {
|
||||
do_catchsql_test 5.1.$tn $sql {1 {attempt to modify read-only schema}}
|
||||
}
|
||||
|
||||
do_execsql_test 5.2.1 { ANALYZE aux.t1 } {}
|
||||
do_execsql_test 5.2.2 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}}
|
||||
do_execsql_test 5.2.3 { SELECT * FROM main.sqlite_stat1 } {}
|
||||
|
||||
do_test 5.3.0 {
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval {
|
||||
PRAGMA writable_schema = 1;
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 5.3.1 { SELECT * FROM aux.sqlite_stat1 } {}
|
||||
do_execsql_test 5.3.2 { ANALYZE aux } {}
|
||||
do_execsql_test 5.3.3 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}}
|
||||
do_execsql_test 5.3.4 { SELECT * FROM main.sqlite_stat1 } {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Attempting to run ANALYZE when the required sqlite_statXX functions
|
||||
# are missing is an error (because it would modify the database schema).
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.4 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
foreach {tn sql} {
|
||||
1 { ANALYZE }
|
||||
2 { ANALYZE t1 }
|
||||
3 { ANALYZE i1 }
|
||||
4 { ANALYZE main }
|
||||
5 { ANALYZE main.t1 }
|
||||
6 { ANALYZE main.i1 }
|
||||
} {
|
||||
do_catchsql_test 5.4.$tn $sql {1 {attempt to modify read-only schema}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
}
|
||||
db close
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
execsql { ATTACH 'test.db2' AS aux }
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO main.t1(a) VALUES(1), (2), (3);
|
||||
INSERT INTO aux.t1(a) VALUES(4), (5), (6);
|
||||
CREATE TEMP TABLE t2(i,t);
|
||||
INSERT INTO t2 VALUES(2, 'two'), (5, 'five');
|
||||
}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.t1)
|
||||
} {five}
|
||||
do_execsql_test 6.3 {
|
||||
SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.v1)
|
||||
} {five}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE p1(a PRIMARY KEY, b);
|
||||
CREATE TABLE p2(a PRIMARY KEY, b);
|
||||
CREATE TABLE c1(x REFERENCES p1 ON UPDATE CASCADE ON DELETE CASCADE);
|
||||
}
|
||||
|
||||
db close
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
execsql { ATTACH 'test.db2' AS aux }
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
INSERT INTO aux.p1 VALUES(1, 'one');
|
||||
INSERT INTO aux.p1 VALUES(2, 'two');
|
||||
PRAGMA foreign_keys = on;
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO aux.c1 VALUES(2);
|
||||
}
|
||||
|
||||
do_execsql_test 7.3.1 {
|
||||
PRAGMA foreign_keys = off;
|
||||
INSERT INTO main.p2 SELECT * FROM aux.p1;
|
||||
}
|
||||
do_execsql_test 7.3.2 {
|
||||
SELECT * FROM main.p2;
|
||||
} {1 one 2 two}
|
||||
|
||||
do_execsql_test 7.3.3 {
|
||||
INSERT INTO aux.p2 VALUES(1, 2);
|
||||
}
|
||||
|
||||
do_execsql_test 7.3.4 {
|
||||
SELECT main.p2.a FROM main.p2, aux.p2;
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 7.3.5 {
|
||||
SELECT * FROM main.p2, aux.p2;
|
||||
} {1 one 1 2 2 two 1 2}
|
||||
|
||||
do_execsql_test 7.4 {
|
||||
SELECT count(*) FROM aux.p2;
|
||||
} {1}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -1,336 +0,0 @@
|
||||
# 2017 August 9
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reuse2
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
PRAGMA schema_version;
|
||||
} {2}
|
||||
|
||||
do_test 1.2 {
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 1.3.1 {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 1.3.2 {
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.3 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
db2 close
|
||||
reset_db
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(c);
|
||||
INSERT INTO ft VALUES('one two three');
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM ft
|
||||
} {{one two three}}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
PRAGMA schema_version;
|
||||
} {2}
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3 db1 test.db -shared-schema 1
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db1 3.2.1 { SELECT * FROM t1 }
|
||||
do_execsql_test -db db2 3.2.2 { SELECT * FROM t1 }
|
||||
|
||||
register_schemapool_module db
|
||||
do_execsql_test 3.3 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=2 nschema=1 ndelete=0}
|
||||
|
||||
sqlite3 db3 test.db -shared-schema 1
|
||||
register_schemapool_module db3
|
||||
|
||||
do_execsql_test 3.5 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=2 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test -db db3 3.6 {
|
||||
SELECT * FROM t1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=3 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 3.7 {
|
||||
CREATE TABLE t2(x);
|
||||
}
|
||||
|
||||
do_execsql_test 3.8 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=3 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test -db db1 3.9.1 { SELECT * FROM t1 }
|
||||
do_execsql_test 3.9.2 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=1 nschema=1 ndelete=0 nref=2 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test -db db2 3.10.1 { SELECT * FROM t1 }
|
||||
do_execsql_test 3.10.2 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool ORDER BY 1;
|
||||
} {nref=1 nschema=1 ndelete=0 nref=2 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test -db db3 3.11.1 { SELECT * FROM t1 }
|
||||
do_execsql_test 3.11.2 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=3 nschema=1 ndelete=0}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
catch {db1 close}
|
||||
catch {db2 close}
|
||||
catch {db3 close}
|
||||
reset_db
|
||||
do_execsql_test 4.0.1 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
CREATE INDEX x1a ON x1(a);
|
||||
CREATE INDEX x1b ON x1(b);
|
||||
}
|
||||
do_test 4.0.2 {
|
||||
db close
|
||||
for {set i 1} {$i < 6} {incr i} {
|
||||
forcedelete test.db${i}-journal test.db${i}-wal test.db${i}-wal2
|
||||
forcecopy test.db test.db${i}
|
||||
}
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
} {}
|
||||
|
||||
register_schemapool_module db
|
||||
do_execsql_test 4.0.3 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {}
|
||||
|
||||
do_test 4.1.1 {
|
||||
execsql {
|
||||
ATTACH 'test.db1' AS db1;
|
||||
ATTACH 'test.db2' AS db2;
|
||||
ATTACH 'test.db3' AS db3;
|
||||
ATTACH 'test.db4' AS db4;
|
||||
ATTACH 'test.db5' AS db5;
|
||||
} db2
|
||||
} {}
|
||||
do_execsql_test 4.1.2 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=1 nschema=1 ndelete=0}
|
||||
do_execsql_test -db db2 4.1.3 {
|
||||
SELECT * FROM db3.x1
|
||||
}
|
||||
do_execsql_test 4.1.4 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=2 nschema=1 ndelete=0}
|
||||
do_execsql_test -db db2 4.1.5 {
|
||||
SELECT * FROM db2.x1
|
||||
}
|
||||
do_execsql_test 4.1.6 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=3 nschema=1 ndelete=0}
|
||||
do_execsql_test -db db2 4.1.7 {
|
||||
SELECT * FROM x1
|
||||
}
|
||||
do_execsql_test 4.1.8 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=3 nschema=1 ndelete=0}
|
||||
|
||||
do_test 4.2.1 {
|
||||
catchsql { SELECT * FROM abc } db2
|
||||
} {1 {no such table: abc}}
|
||||
do_execsql_test 4.2.2 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=6 nschema=1 ndelete=0}
|
||||
|
||||
register_schemapool_module db2
|
||||
do_execsql_test -db db2 4.3.1 {
|
||||
INSERT INTO x1 VALUES(1, 2, 3);
|
||||
INSERT INTO db1.x1 VALUES(4, 5, 6);
|
||||
INSERT INTO db2.x1 VALUES(7, 8, 9);
|
||||
INSERT INTO db3.x1 VALUES(10, 11, 12);
|
||||
INSERT INTO db4.x1 VALUES(13, 14, 15);
|
||||
INSERT INTO db5.x1 VALUES(16, 17, 18);
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=6 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test -db db2 4.3.2 {
|
||||
SELECT * FROM db5.x1;
|
||||
SELECT * FROM db4.x1;
|
||||
SELECT * FROM db3.x1;
|
||||
SELECT * FROM db2.x1;
|
||||
SELECT * FROM db1.x1;
|
||||
SELECT * FROM x1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {
|
||||
16 17 18 13 14 15 10 11 12 7 8 9 4 5 6 1 2 3
|
||||
nref=6 nschema=1 ndelete=0
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3.3 {
|
||||
UPDATE x1 SET a=a+10;
|
||||
UPDATE db5.x1 SET a=a+10;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {
|
||||
nref=6 nschema=1 ndelete=0
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3.4 {
|
||||
SELECT * FROM db5.x1;
|
||||
SELECT * FROM db4.x1;
|
||||
SELECT * FROM db3.x1;
|
||||
SELECT * FROM db2.x1;
|
||||
SELECT * FROM db1.x1;
|
||||
SELECT * FROM x1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {
|
||||
26 17 18 13 14 15 10 11 12 7 8 9 4 5 6 11 2 3
|
||||
nref=6 nschema=1 ndelete=0
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3.5 {
|
||||
DELETE FROM db3.x1;
|
||||
DELETE FROM x1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {
|
||||
nref=6 nschema=1 ndelete=0
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3.6 {
|
||||
SELECT * FROM db5.x1;
|
||||
SELECT * FROM db4.x1;
|
||||
SELECT * FROM db3.x1;
|
||||
SELECT * FROM db2.x1;
|
||||
SELECT * FROM db1.x1;
|
||||
SELECT * FROM x1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {
|
||||
26 17 18 13 14 15 7 8 9 4 5 6
|
||||
nref=6 nschema=1 ndelete=0
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 4.3.6 {
|
||||
SELECT * FROM db5.x1, db4.x1, db1.x1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {26 17 18 13 14 15 4 5 6 nref=6 nschema=3 ndelete=0}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test the incremental-blob API with REUSE_SCHEMA connections.
|
||||
#
|
||||
catch {db1 close}
|
||||
catch {db2 close}
|
||||
catch {db3 close}
|
||||
reset_db
|
||||
do_execsql_test 5.0.1 {
|
||||
CREATE TABLE bbb(a INTEGER PRIMARY KEY, b);
|
||||
}
|
||||
db close
|
||||
do_test 5.0.2 {
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
register_schemapool_module db2
|
||||
for {set i 1} {$i<6} {incr i} {
|
||||
forcedelete test.db${i}-journal test.db${i}-wal test.db${i}-wal2
|
||||
forcecopy test.db test.db${i}
|
||||
sqlite3 db test.db${i}
|
||||
db eval { INSERT INTO bbb VALUES(123, 'database_' || $i) }
|
||||
db close
|
||||
db2 eval "ATTACH 'test.db${i}' AS db${i}"
|
||||
}
|
||||
execsql {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} db2
|
||||
} {nref=6 nschema=1 ndelete=0}
|
||||
|
||||
do_test 5.1.1 {
|
||||
set res [list]
|
||||
for {set i 1} {$i<6} {incr i} {
|
||||
set chan [db2 incrblob db${i} bbb b 123]
|
||||
lappend res [gets $chan]
|
||||
close $chan
|
||||
}
|
||||
set res
|
||||
} {database_1 database_2 database_3 database_4 database_5}
|
||||
|
||||
do_execsql_test -db db2 5.1.2 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=6 nschema=1 ndelete=0}
|
||||
|
||||
do_test 5.2.1 {
|
||||
sqlite3_table_column_metadata db2 main bbb a
|
||||
} {INTEGER BINARY 0 1 0}
|
||||
do_test 5.2.2 {
|
||||
sqlite3_table_column_metadata db2 main bbb b
|
||||
} {{} BINARY 0 0 0}
|
||||
|
||||
do_execsql_test -db db2 5.2.3 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=6 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test -db db2 5.2.4 {
|
||||
PRAGMA integrity_check;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {ok nref=6 nschema=1 ndelete=5}
|
||||
|
||||
finish_test
|
||||
@@ -1,356 +0,0 @@
|
||||
# 2019 February 12
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reuse3
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
CREATE TABLE t2(a);
|
||||
} {}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TEMP VIEW v1 AS SELECT * FROM t1;
|
||||
SELECT * FROM v1;
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
CREATE TEMP TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
INSERT INTO t2 VALUES(new.x);
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT * FROM t2
|
||||
} {1}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT * FROM v1
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
BEGIN;
|
||||
DROP TRIGGER tr1;
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
SELECT * FROM v1
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 1.8 {
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
SELECT * FROM t2
|
||||
} {1 4}
|
||||
|
||||
do_execsql_test 1.9 {
|
||||
SELECT * FROM v1
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test error messages when parsing the schema with a REUSE_SCHEMA
|
||||
# connection.
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
CREATE TABLE y1(d, e, f);
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = 'CREATE TBL y1(d, e, f)' WHERE name = 'y1';
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT * FROM x1;
|
||||
} {1 {malformed database schema (y1) - near "TBL": syntax error}}
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT * FROM x1;
|
||||
} {1 {malformed database schema (y1) - near "TBL": syntax error}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
CREATE INDEX i1 ON x1(a, b, c);
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON x1 BEGIN
|
||||
SELECT 1, 2, 3, 4, 5;
|
||||
END;
|
||||
INSERT INTO x1 VALUES(1, 2, 3);
|
||||
}
|
||||
sqlite3 db1 test.db -shared-schema 1
|
||||
|
||||
do_test 3.1 {
|
||||
execsql { SELECT * FROM x1 } db1
|
||||
set N [lindex [sqlite3_db_status db1 SCHEMA_USED 0] 1]
|
||||
expr $N==$N
|
||||
} 1
|
||||
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
do_test 3.2 {
|
||||
execsql { SELECT * FROM x1 } db2
|
||||
set N2 [lindex [sqlite3_db_status db2 SCHEMA_USED 0] 1]
|
||||
expr $N2>($N/2) && $N2<($N/2)+400
|
||||
} 1
|
||||
|
||||
sqlite3 db3 test.db -shared-schema 1
|
||||
sqlite3 db4 test.db -shared-schema 1
|
||||
do_test 3.3 {
|
||||
execsql { SELECT * FROM x1 } db3
|
||||
execsql { SELECT * FROM x1 } db4
|
||||
set N4 [lindex [sqlite3_db_status db2 SCHEMA_USED 0] 1]
|
||||
set M [expr 2*($N-$N2)]
|
||||
set {} {}
|
||||
} {}
|
||||
do_test 3.3.1 { expr {(($M / 4) + $N-$M)} } "#/$N4/"
|
||||
|
||||
catch { db1 close }
|
||||
catch { db2 close }
|
||||
catch { db3 close }
|
||||
catch { db4 close }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# 4.1 Test the REINDEX command.
|
||||
# 4.2 Test CREATE TEMP ... commands.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1.0 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
CREATE INDEX x1a ON x1(a);
|
||||
CREATE INDEX x1b ON x1(b);
|
||||
CREATE INDEX x1c ON x1(c);
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
|
||||
do_execsql_test 4.1.1 {
|
||||
REINDEX x1;
|
||||
REINDEX x1a;
|
||||
REINDEX x1b;
|
||||
REINDEX x1c;
|
||||
REINDEX;
|
||||
}
|
||||
|
||||
do_test 4.1.2 {
|
||||
for {set i 1} {$i < 5} {incr i} {
|
||||
forcedelete test.db${i} test.db${i}-wal test.db${i}-journal
|
||||
forcecopy test.db test.db${i}
|
||||
execsql "ATTACH 'test.db${i}' AS db${i}"
|
||||
}
|
||||
register_schemapool_module db
|
||||
set {} {}
|
||||
execsql {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool
|
||||
}
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.1.3 {
|
||||
REINDEX x1;
|
||||
REINDEX x1a;
|
||||
REINDEX x1b;
|
||||
REINDEX x1c;
|
||||
REINDEX db1.x1a;
|
||||
REINDEX db2.x1b;
|
||||
REINDEX db3.x1c;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1.4 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool
|
||||
} {nref=5 nschema=1 ndelete=28}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
register_schemapool_module db
|
||||
do_execsql_test 4.2.0 {
|
||||
ATTACH 'test.db1' AS db1;
|
||||
ATTACH 'test.db2' AS db2;
|
||||
ATTACH 'test.db3' AS db3;
|
||||
ATTACH 'test.db4' AS db4;
|
||||
|
||||
SELECT * FROM db1.x1;
|
||||
SELECT * FROM db2.x1;
|
||||
SELECT * FROM db3.x1;
|
||||
SELECT * FROM db4.x1;
|
||||
}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.2.2 {
|
||||
CREATE TEMP TABLE t1(a, b, c);
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.2.3 {
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.2.4 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
SELECT 1,2,3,4;
|
||||
END;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.2.5 {
|
||||
DROP TABLE t1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.2.6 {
|
||||
CREATE TEMP TRIGGER tr1 AFTER INSERT ON db2.x1 BEGIN
|
||||
SELECT 1,2,3,4;
|
||||
END;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=0}
|
||||
|
||||
do_execsql_test 4.2.7 {
|
||||
DROP TRIGGER tr1;
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema, 'ndelete=' || nDelete
|
||||
FROM schemapool;
|
||||
} {nref=5 nschema=1 ndelete=4}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE TABLE t3(a, b);
|
||||
}
|
||||
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
register_schemapool_module db2
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE t3 a,b' WHERE name = 't3';
|
||||
}
|
||||
|
||||
do_test 5.2 {
|
||||
catchsql { SELECT * FROM t1 } db2
|
||||
} {1 {malformed database schema (t3) - near "a": syntax error}}
|
||||
|
||||
do_test 5.3 {
|
||||
catchsql { SELECT nref,nschema FROM schemapool } db2
|
||||
} {1 {malformed database schema (t3) - near "a": syntax error}}
|
||||
|
||||
do_execsql_test 5.4 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE t3(a,b)' WHERE name = 't3';
|
||||
}
|
||||
|
||||
do_test 5.5 {
|
||||
catchsql { SELECT nref,nschema FROM schemapool } db2
|
||||
} {0 {1 1}}
|
||||
|
||||
db2 close
|
||||
db close
|
||||
do_test 5.6.1 {
|
||||
forcedelete test.db2 test.db2-wal test.db2-journal
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
sqlite3 db3 test.db2 -shared-schema 1
|
||||
register_schemapool_module db
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 5.6.2 { SELECT * FROM t1 }
|
||||
do_execsql_test -db db3 5.6.3 { SELECT * FROM t1 }
|
||||
do_execsql_test 5.6.4 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool;
|
||||
CREATE TABLE t4(x);
|
||||
DROP TABLE t4;
|
||||
} {nref=2 nschema=1}
|
||||
do_execsql_test -db db2 5.6.5 { SELECT * FROM t1 }
|
||||
do_execsql_test -db db3 5.6.6 { SELECT * FROM t1 }
|
||||
do_execsql_test 5.6.7 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool;
|
||||
ATTACH 'test.db2' AS db2;
|
||||
CREATE TABLE db2.t4(x);
|
||||
DROP TABLE db2.t4;
|
||||
} {nref=1 nschema=1 nref=1 nschema=1}
|
||||
do_execsql_test -db db2 5.6.8 { SELECT * FROM t1 }
|
||||
do_execsql_test -db db3 5.6.9 { SELECT * FROM t1 }
|
||||
do_execsql_test 5.6.10 {
|
||||
SELECT 'nref=' || nRef, 'nschema=' || nSchema FROM schemapool;
|
||||
} {nref=2 nschema=1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
db2 close
|
||||
db3 close
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE TABLE t3(a, b);
|
||||
}
|
||||
|
||||
do_test 6.1 {
|
||||
db close
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
for {set i 1} {$i < 5} {incr i} {
|
||||
set base "test.db$i"
|
||||
set nm "aux$i"
|
||||
forcedelete $base $base-wal $base-journal
|
||||
forcecopy test.db $base
|
||||
execsql "ATTACH '$base' AS $nm"
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 6.2 {
|
||||
set N1 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||
set N2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||
expr {$N1>0 && $N2>0 && $N1==$N2}
|
||||
} {1}
|
||||
|
||||
do_test 6.3 {
|
||||
execsql { SELECT * FROM main.t1 }
|
||||
set N1 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||
set N2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||
expr {$N1>0 && $N2>0 && $N1==$N2}
|
||||
} {1}
|
||||
|
||||
do_test 6.4 {
|
||||
execsql { SELECT * FROM aux1.t1 }
|
||||
set N3 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||
set N4 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||
list $N3 $N4
|
||||
} "#/$N1 $N1/"
|
||||
|
||||
finish_test
|
||||
@@ -1,174 +0,0 @@
|
||||
# 2019 February 12
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reuse4
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
foreach {tn sharedschema} {
|
||||
1 0
|
||||
2 1
|
||||
} {
|
||||
catch {db2 close}
|
||||
reset_db
|
||||
|
||||
do_execsql_test 1.$tn.0 {
|
||||
CREATE TABLE x1(a, b);
|
||||
CREATE INDEX x1a ON x1(a);
|
||||
CREATE INDEX x1b ON x1(b);
|
||||
CREATE TABLE x2(a, b);
|
||||
}
|
||||
db close
|
||||
|
||||
do_test 1.$tn.1 {
|
||||
for {set i 1} {$i<4} {incr i} {
|
||||
forcedelete test.db$i test.db$i-journal test.db$i-wal
|
||||
forcecopy test.db test.db$i
|
||||
}
|
||||
|
||||
sqlite3 db test.db -shared-schema $sharedschema
|
||||
for {set i 1} {$i<4} {incr i} {
|
||||
execsql " ATTACH 'test.db$i' AS db$i "
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10 )
|
||||
INSERT INTO x1 SELECT i, i FROM s;
|
||||
|
||||
INSERT INTO db3.x2 SELECT * FROM x1;
|
||||
INSERT INTO db2.x1 SELECT * FROM db3.x2;
|
||||
CREATE TEMP TRIGGER tr1 AFTER INSERT ON db2.x2 BEGIN
|
||||
INSERT INTO x1 VALUES(new.a, new.b);
|
||||
END;
|
||||
INSERT INTO db2.x2 SELECT * FROM x1 WHERE a%2;
|
||||
DELETE FROM x1 WHERE a<3;
|
||||
INSERT INTO db3.x1 SELECT * FROM db2.x2;
|
||||
|
||||
DETACH db3;
|
||||
ATTACH 'test.db3' AS db3;
|
||||
|
||||
UPDATE db3.x1 SET a=a-10 WHERE b NOT IN (SELECT b FROM db2.x2);
|
||||
|
||||
CREATE TEMP TABLE x1(a, b);
|
||||
INSERT INTO db2.x2 VALUES(50, 60), (60, 70), (80, 90);
|
||||
ALTER TABLE x1 RENAME TO x2;
|
||||
ALTER TABLE x2 ADD COLUMN c;
|
||||
ALTER TABLE x2 RENAME a TO aaa;
|
||||
DELETE FROM x1 WHERE b>8;
|
||||
UPDATE db3.x2 SET b=b*10;
|
||||
|
||||
BEGIN;
|
||||
CREATE TEMP TABLE x5(x);
|
||||
INSERT INTO x5 VALUES(1);
|
||||
ROLLBACK;
|
||||
|
||||
INSERT INTO main.x2 VALUES(123, 456);
|
||||
}
|
||||
|
||||
integrity_check 1.$tn.3
|
||||
|
||||
do_execsql_test 1.$tn.4 {
|
||||
SELECT * FROM main.x1; SELECT 'xxx';
|
||||
SELECT * FROM main.x2; SELECT 'xxx';
|
||||
SELECT * FROM temp.x2; SELECT 'xxx';
|
||||
|
||||
SELECT * FROM db1.x1; SELECT 'xxx';
|
||||
SELECT * FROM db1.x2; SELECT 'xxx';
|
||||
SELECT * FROM db2.x1; SELECT 'xxx';
|
||||
SELECT * FROM db2.x2; SELECT 'xxx';
|
||||
SELECT * FROM db3.x1; SELECT 'xxx';
|
||||
SELECT * FROM db3.x2; SELECT 'xxx';
|
||||
} {
|
||||
3 3 4 4 5 5 6 6 7 7 8 8 3 3 5 5 7 7 xxx
|
||||
123 456 xxx
|
||||
50 60 {} 60 70 {} 80 90 {} xxx
|
||||
xxx
|
||||
xxx
|
||||
1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 xxx
|
||||
1 1 3 3 5 5 7 7 9 9 50 60 60 70 80 90 xxx
|
||||
1 1 3 3 5 5 7 7 9 9 xxx
|
||||
1 10 2 20 3 30 4 40 5 50 6 60 7 70 8 80 9 90 10 100 xxx
|
||||
}
|
||||
|
||||
do_test 1.$tn.5.1 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval { CREATE TABLE x3(x) }
|
||||
} {}
|
||||
do_execsql_test 1.$tn.5.2 {
|
||||
SELECT * FROM main.x1; SELECT 'xxx';
|
||||
SELECT * FROM main.x2; SELECT 'xxx';
|
||||
SELECT * FROM main.x3; SELECT 'xxx';
|
||||
} {
|
||||
3 3 4 4 5 5 6 6 7 7 8 8 3 3 5 5 7 7 xxx
|
||||
123 456 xxx
|
||||
xxx
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test some PRAGMA statements with shared-schema connections.
|
||||
#
|
||||
db2 close
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX t1abc ON t1(a, b, c);
|
||||
}
|
||||
|
||||
foreach {tn pragma nSchema nDelete} {
|
||||
1 "PRAGMA synchronous = OFF" 1 0
|
||||
2 "PRAGMA cache_size = 200" 1 0
|
||||
3 "PRAGMA aux2.integrity_check" 1 0
|
||||
4 "PRAGMA integrity_check" 1 5
|
||||
5 "PRAGMA index_info=t1abc" 1 5
|
||||
6 "PRAGMA aux3.index_info=t1abc" 1 0
|
||||
7 "PRAGMA journal_mode" 1 0
|
||||
8 "PRAGMA aux2.wal_checkpoint" 1 0
|
||||
9 "PRAGMA wal_checkpoint" 1 0
|
||||
} {
|
||||
do_test 2.$tn.1 {
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
for {set i 1} {$i < 6} {incr i} {
|
||||
forcedelete "test.db$i" "test.db${i}-wal" "test.db${i}-journal"
|
||||
forcecopy test.db test.db$i
|
||||
}
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
for {set i 1} {$i < 6} {incr i} {
|
||||
execsql "ATTACH 'test.db$i' AS aux$i" db2
|
||||
}
|
||||
} {}
|
||||
|
||||
sqlite3 db test.db
|
||||
register_schemapool_module db
|
||||
|
||||
do_test 2.$tn.2 {
|
||||
execsql $pragma db2
|
||||
execsql { SELECT 'nschema='||nschema, 'ndelete='||nDelete FROM schemapool }
|
||||
} "nschema=$nSchema ndelete=$nDelete"
|
||||
|
||||
do_test 2.$tn.3 {
|
||||
execsql {
|
||||
SELECT * FROM main.t1,aux1.t1,aux2.t1,aux3.t1,aux4.t1,aux5.t1
|
||||
} db2
|
||||
execsql { SELECT 'nschema=' || nschema, 'nref=' || nref FROM schemapool }
|
||||
} "nschema=6 nref=6"
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -1,125 +0,0 @@
|
||||
# 2019 February 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reuse5
|
||||
set CLI [test_find_cli]
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
}
|
||||
|
||||
foreach {tn sql out1 out2} {
|
||||
1 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
} {
|
||||
test.db2 is compatible
|
||||
} {}
|
||||
|
||||
2 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
CREATE TABLE x1(x);
|
||||
DROP TABLE x1;
|
||||
} {
|
||||
test.db2 is NOT compatible (schema cookie)
|
||||
} {
|
||||
Fixing test.db2... test.db2 is compatible
|
||||
}
|
||||
|
||||
3 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
} {
|
||||
test.db2 is NOT compatible (objects)
|
||||
} {}
|
||||
|
||||
4 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1x ON t1(X);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
} {
|
||||
test.db2 is NOT compatible (SQL)
|
||||
} {}
|
||||
|
||||
5 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
} {
|
||||
test.db2 is NOT compatible (root pages)
|
||||
} {
|
||||
Fixing test.db2... test.db2 is compatible
|
||||
}
|
||||
|
||||
6 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
DROP INDEX t1x;
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
} {
|
||||
test.db2 is NOT compatible (order of sqlite_master rows)
|
||||
} {
|
||||
Fixing test.db2... test.db2 is compatible
|
||||
}
|
||||
|
||||
} {
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval $sql
|
||||
db2 close
|
||||
|
||||
if {$out2==""} {set out2 $out1}
|
||||
|
||||
do_test 1.$tn.1 {
|
||||
catchcmd test.db ".shared-schema check test.db2"
|
||||
} [list 0 [string trim $out1]]
|
||||
|
||||
do_test 1.$tn.2 {
|
||||
catchcmd test.db ".shared-schema fix test.db2"
|
||||
} [list 0 [string trim $out2]]
|
||||
|
||||
do_test 1.$tn.3 {
|
||||
catchcmd test.db2 "PRAGMA integrity_check"
|
||||
} [list 0 ok]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
# 2019 February 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reuse6
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t1x ON t1(x);
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
|
||||
INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6);
|
||||
INSERT INTO t2 VALUES('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i');
|
||||
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE t3(i, ii);
|
||||
INSERT INTO t3 VALUES(10, 20);
|
||||
}
|
||||
|
||||
sqlite3 db1 test.db -shared-schema 1
|
||||
sqlite3 db2 test.db -shared-schema 1
|
||||
|
||||
do_execsql_test -db db1 1.1 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
execsql {SELECT * FROM t3} db1
|
||||
} {10 20}
|
||||
|
||||
do_execsql_test -db db2 1.3 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
}
|
||||
|
||||
do_test 1.3 {
|
||||
execsql {SELECT * FROM t3} db1
|
||||
} {10 20}
|
||||
|
||||
do_execsql_test -db db2 1.5 {
|
||||
SELECT * FROM t3;
|
||||
} {10 20}
|
||||
|
||||
do_test 1.6 {
|
||||
execsql {SELECT * FROM t3} db1
|
||||
} {10 20}
|
||||
|
||||
db1 close
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
forcedelete test.db3
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
ATTACH 'test.db2' AS aux2;
|
||||
CREATE TABLE aux2.t2(x, y);
|
||||
ATTACH 'test.db3' AS aux3;
|
||||
CREATE TABLE aux3.t3(x, y);
|
||||
}
|
||||
|
||||
sqlite3 db1 test.db -shared-schema 1
|
||||
do_execsql_test -db db1 2.1 {
|
||||
ATTACH 'test.db2' AS aux2;
|
||||
ATTACH 'test.db3' AS aux3;
|
||||
}
|
||||
|
||||
do_test 2.2.1 {
|
||||
catchsql { SELECT * FROM aux2.nosuchtable } db1
|
||||
} {1 {no such table: aux2.nosuchtable}}
|
||||
do_test 2.2.2 {
|
||||
sqlite3_errcode db1
|
||||
} {SQLITE_ERROR}
|
||||
db1 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b);
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t1(x, y, z);
|
||||
}
|
||||
|
||||
sqlite3 db1 test.db -shared-schema 1
|
||||
do_execsql_test -db db1 3.1 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
}
|
||||
|
||||
do_execsql_test -db db1 3.2 {
|
||||
SELECT * FROM main.ft, aux.t1;
|
||||
}
|
||||
db1 close
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b);
|
||||
}
|
||||
forcecopy test.db test.db2
|
||||
|
||||
sqlite3 db1 test.db -shared-schema 1
|
||||
do_execsql_test -db db1 4.1 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
SELECT * FROM main.ft;
|
||||
SELECT * FROM aux.ft;
|
||||
}
|
||||
|
||||
do_execsql_test -db db1 4.2 {
|
||||
SELECT * FROM main.ft, aux.ft
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
# 2019 February 12
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix reusefault
|
||||
|
||||
ifcapable !sharedschema {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA cache_size = 10;
|
||||
CREATE TABLE t1(a UNIQUE, b UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, 2), (3, 4);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1.1 -prep {
|
||||
catch {db close}
|
||||
faultsim_restore
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
} -body {
|
||||
execsql { SELECT * FROM t1 }
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 2 3 4}}
|
||||
}
|
||||
|
||||
do_faultsim_test 1.2 -prep {
|
||||
catch {db close}
|
||||
catch {db2 close}
|
||||
faultsim_restore
|
||||
sqlite3 db test.db -shared-schema 1
|
||||
execsql { SELECT * FROM t1 }
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {CREATE TABLE a(a)}
|
||||
db2 close
|
||||
} -body {
|
||||
execsql { SELECT * FROM t1 }
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 2 3 4}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
+1
-1
@@ -312,7 +312,7 @@ do_test shared-$av.4.1.3 {
|
||||
} {2}
|
||||
|
||||
# Sanity check: Create a table in ./test.db via handle db, and test that handle
|
||||
# db2 can "see" the new table immediately. A handle using a seperate pager
|
||||
# db2 can "see" the new table immediately. A handle using a separate pager
|
||||
# cache would have to reload the database schema before this were possible.
|
||||
#
|
||||
do_test shared-$av.4.2.1 {
|
||||
|
||||
+3
-4
@@ -72,10 +72,9 @@ do_execsql_test 1.2.1 {
|
||||
CREATE TABLE t4(hello);
|
||||
}
|
||||
db close
|
||||
# This works ok on the reuse-schema branch
|
||||
# do_test 1.2.2 {
|
||||
# catchcmd test.db ".read testdump.txt"
|
||||
# } {1 {Parse error near line 5: table sqlite_master may not be modified}}
|
||||
do_test 1.2.2 {
|
||||
catchcmd test.db ".read testdump.txt"
|
||||
} {1 {Parse error near line 5: table sqlite_master may not be modified}}
|
||||
|
||||
# Check testdump.txt cannot be processed if the db is in safe mode
|
||||
#
|
||||
|
||||
@@ -181,6 +181,19 @@ do_execsql_test tabfunc01-4.4 {
|
||||
SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10;
|
||||
} {1 3 5}
|
||||
|
||||
# 2025-03-13 forum post bf2dc8e909983511
|
||||
#
|
||||
do_execsql_test tabfunc01-5.1 {
|
||||
SELECT value
|
||||
FROM generate_series(60,73,6)
|
||||
WHERE value=66;
|
||||
} 66
|
||||
do_execsql_test tabfunc01-5.2 {
|
||||
SELECT value
|
||||
FROM generate_series(73,60,-6)
|
||||
WHERE value=67;
|
||||
} 67
|
||||
|
||||
# The next series of tests is verifying that virtual table are able
|
||||
# to optimize the IN operator, even on terms that are not marked "omit".
|
||||
# When the generate_series virtual table is compiled for the testfixture,
|
||||
|
||||
+1
-1
@@ -230,7 +230,7 @@ ifcapable schema_pragmas {
|
||||
}
|
||||
|
||||
# do_malloc_test closes and deletes the usual db connections and files on
|
||||
# each iteration. $::dbx is a seperate connection, and on Windows, will
|
||||
# each iteration. $::dbx is a separate connection, and on Windows, will
|
||||
# cause the file deletion of test.db to fail, so we move the close of $::dbx
|
||||
# up to here before the do_malloc_test.
|
||||
do_test tableapi-99.0 {
|
||||
|
||||
@@ -26,9 +26,6 @@ set testprefix tcl
|
||||
# Check the error messages generated by tclsqlite
|
||||
#
|
||||
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nofollow BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
ifcapable sharedschema {
|
||||
append r " ?-shared-schema BOOLEAN?"
|
||||
}
|
||||
if {[sqlite3 -has-codec]} {
|
||||
append r " ?-key CODECKEY?"
|
||||
}
|
||||
|
||||
+2
-2
@@ -823,7 +823,7 @@ proc catchcmd {db {cmd ""}} {
|
||||
set out [open cmds.txt w]
|
||||
puts $out $cmd
|
||||
close $out
|
||||
set line "exec $CLI --unsafe-testing $db < cmds.txt"
|
||||
set line "exec $CLI $db < cmds.txt"
|
||||
set rc [catch { eval $line } msg]
|
||||
list $rc $msg
|
||||
}
|
||||
@@ -1724,7 +1724,7 @@ proc ifcapable {expr code {else ""} {elsecode ""}} {
|
||||
return -code $c $r
|
||||
}
|
||||
|
||||
# This proc execs a seperate process that crashes midway through executing
|
||||
# This proc execs a separate process that crashes midway through executing
|
||||
# the SQL script $sql on database test.db.
|
||||
#
|
||||
# The crash occurs during a sync() of file $crashfile. When the crash
|
||||
|
||||
+2
-3
@@ -1240,8 +1240,7 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
devtest -
|
||||
mdevtest {
|
||||
set config_set {
|
||||
ReuseSchema-O0
|
||||
ReuseSchema-Debug
|
||||
All-O0
|
||||
All-Debug
|
||||
}
|
||||
add_devtest_jobs $config_set [lrange $patternlist 1 end]
|
||||
@@ -1249,7 +1248,7 @@ proc add_jobs_from_cmdline {patternlist} {
|
||||
|
||||
sdevtest {
|
||||
set config_set {
|
||||
ReuseSchema-Sanitize
|
||||
All-Sanitize
|
||||
All-Debug
|
||||
}
|
||||
add_devtest_jobs $config_set [lrange $patternlist 1 end]
|
||||
|
||||
@@ -108,18 +108,6 @@ namespace eval trd {
|
||||
--enable-all -fsanitize=address,undefined -fno-sanitize-recover=undefined
|
||||
}
|
||||
|
||||
set build(ReuseSchema-Debug) {
|
||||
--enable-debug --enable-all -DSQLITE_ENABLE_SHARED_SCHEMA
|
||||
}
|
||||
set build(ReuseSchema-O0) {
|
||||
-O0 --enable-all -DSQLITE_ENABLE_SHARED_SCHEMA
|
||||
}
|
||||
set build(ReuseSchema-Sanitize) {
|
||||
-DSQLITE_OMIT_LOOKASIDE=1 -DSQLITE_ENABLE_SHARED_SCHEMA
|
||||
--enable-all -fsanitize=address,undefined -fno-sanitize-recover=undefined
|
||||
}
|
||||
|
||||
|
||||
set build(Sanitize) {
|
||||
CC=clang -fsanitize=address,undefined -fno-sanitize-recover=undefined
|
||||
-DSQLITE_ENABLE_STAT4
|
||||
@@ -490,10 +478,10 @@ proc make_sh_script {srcdir opts cflags makeOpts configOpts} {
|
||||
set myopts ""
|
||||
if {[info exists ::env(OPTS)]} {
|
||||
append myopts "# From environment variable:\n"
|
||||
append myopts "OPTIONS=$::env(OPTS)\n\n"
|
||||
append myopts "OPTS=$::env(OPTS)\n\n"
|
||||
}
|
||||
foreach o [lsort $opts] {
|
||||
append myopts "OPTIONS=\"\$OPTS $o\"\n"
|
||||
append myopts "OPTS=\"\$OPTS $o\"\n"
|
||||
}
|
||||
|
||||
return [trimscript [subst -nocommands {
|
||||
|
||||
+19
-24
@@ -38,7 +38,7 @@
|
||||
#define SEL(e) ((e)->iLine = ((e)->rc ? (e)->iLine : __LINE__))
|
||||
|
||||
/* Database functions */
|
||||
#define opendb(w,x,y,z,f) (SEL(w), opendb_x(w,x,y,z,f))
|
||||
#define opendb(w,x,y,z) (SEL(w), opendb_x(w,x,y,z))
|
||||
#define closedb(y,z) (SEL(y), closedb_x(y,z))
|
||||
|
||||
/* Functions to execute SQL */
|
||||
@@ -545,14 +545,11 @@ static void opendb_x(
|
||||
Error *pErr, /* IN/OUT: Error code */
|
||||
Sqlite *pDb, /* OUT: Database handle */
|
||||
const char *zFile, /* Database file name */
|
||||
int bDelete, /* True to delete db file before opening */
|
||||
int flags
|
||||
int bDelete /* True to delete db file before opening */
|
||||
){
|
||||
if( pErr->rc==SQLITE_OK ){
|
||||
int rc;
|
||||
if( flags==0 ){
|
||||
flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
|
||||
}
|
||||
int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
|
||||
if( bDelete ) unlink(zFile);
|
||||
rc = sqlite3_open_v2(zFile, &pDb->db, flags, 0);
|
||||
if( rc ){
|
||||
@@ -988,7 +985,7 @@ static char *walthread1_thread(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
int nIter = 0; /* Iterations so far */
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
const char *azSql[] = {
|
||||
"SELECT md5sum(x) FROM t1 WHERE rowid != (SELECT max(rowid) FROM t1)",
|
||||
@@ -1027,7 +1024,7 @@ static char *walthread1_ckpt_thread(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
int nCkpt = 0; /* Checkpoints so far */
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
sqlite3_sleep(500);
|
||||
execsql(&err, &db, "PRAGMA wal_checkpoint");
|
||||
@@ -1046,7 +1043,7 @@ static void walthread1(int nMs){
|
||||
Threadset threads = {0}; /* Test threads */
|
||||
int i; /* Iterator variable */
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA journal_mode = WAL;"
|
||||
"CREATE TABLE t1(x PRIMARY KEY);"
|
||||
@@ -1079,7 +1076,7 @@ static char *walthread2_thread(int iTid, void *pArg){
|
||||
int journal_exists = 0;
|
||||
int wal_exists = 0;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
|
||||
sql_script(&err, &db, zJournal);
|
||||
clear_error(&err, SQLITE_BUSY);
|
||||
@@ -1109,7 +1106,7 @@ static void walthread2(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db, "CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE)");
|
||||
closedb(&err, &db);
|
||||
|
||||
@@ -1129,7 +1126,7 @@ static char *walthread3_thread(int iTid, void *pArg){
|
||||
i64 iNextWrite; /* Next value this thread will write */
|
||||
int iArg = PTR2INT(pArg);
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
sql_script(&err, &db, "PRAGMA wal_autocheckpoint = 10");
|
||||
|
||||
iNextWrite = iArg+1;
|
||||
@@ -1166,7 +1163,7 @@ static void walthread3(int nMs){
|
||||
Threadset threads = {0};
|
||||
int i;
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA journal_mode = WAL;"
|
||||
"CREATE TABLE t1(cnt PRIMARY KEY, sum1, sum2);"
|
||||
@@ -1189,7 +1186,7 @@ static char *walthread4_reader_thread(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
integrity_check(&err, &db);
|
||||
}
|
||||
@@ -1204,7 +1201,7 @@ static char *walthread4_writer_thread(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
i64 iRow = 1;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
sql_script(&err, &db, "PRAGMA wal_autocheckpoint = 15;");
|
||||
while( !timetostop(&err) ){
|
||||
execsql_i64(
|
||||
@@ -1224,7 +1221,7 @@ static void walthread4(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA journal_mode = WAL;"
|
||||
"CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);"
|
||||
@@ -1244,7 +1241,7 @@ static char *walthread5_thread(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
i64 nRow;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
nRow = execsql_i64(&err, &db, "SELECT count(*) FROM t1");
|
||||
closedb(&err, &db);
|
||||
|
||||
@@ -1257,7 +1254,7 @@ static void walthread5(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA wal_autocheckpoint = 0;"
|
||||
"PRAGMA page_size = 1024;"
|
||||
@@ -1348,7 +1345,7 @@ static void cgt_pager_1(int nMs){
|
||||
Error err = {0};
|
||||
Sqlite db = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA cache_size = 2000;"
|
||||
"PRAGMA page_size = 1024;"
|
||||
@@ -1377,7 +1374,7 @@ static char *dynamic_triggers_1(int iTid, void *pArg){
|
||||
int nDrop = 0;
|
||||
int nCreate = 0;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
int i;
|
||||
|
||||
@@ -1430,7 +1427,7 @@ static char *dynamic_triggers_2(int iTid, void *pArg){
|
||||
int nInsert = 0;
|
||||
int nDelete = 0;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
do {
|
||||
iVal = (iVal+1)%100;
|
||||
@@ -1455,7 +1452,7 @@ static void dynamic_triggers(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA page_size = 1024;"
|
||||
"PRAGMA journal_mode = WAL;"
|
||||
@@ -1495,7 +1492,6 @@ static void dynamic_triggers(int nMs){
|
||||
#include "tt3_lookaside1.c"
|
||||
#include "tt3_vacuum.c"
|
||||
#include "tt3_stress.c"
|
||||
#include "tt3_reuseschema.c"
|
||||
#include "tt3_shared.c"
|
||||
|
||||
int main(int argc, char **argv){
|
||||
@@ -1521,7 +1517,6 @@ int main(int argc, char **argv){
|
||||
{ vacuum1, "vacuum1", 10000 },
|
||||
{ stress1, "stress1", 10000 },
|
||||
{ stress2, "stress2", 60000 },
|
||||
{ reuse_schema_1, "reuse_schema_1", 20000 },
|
||||
{ shared1, "shared1", 10000 },
|
||||
};
|
||||
static char *substArgv[] = { 0, "*", 0 };
|
||||
|
||||
@@ -70,7 +70,7 @@ static char *checkpoint_starvation_reader(int iTid, void *pArg){
|
||||
Error err = {0};
|
||||
Sqlite db = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
i64 iCount1, iCount2;
|
||||
sql_script(&err, &db, "BEGIN");
|
||||
@@ -96,7 +96,7 @@ static void checkpoint_starvation_main(int nMs, CheckpointStarvationCtx *p){
|
||||
int nInsert = 0;
|
||||
int i;
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"PRAGMA page_size = 1024;"
|
||||
"PRAGMA journal_mode = WAL;"
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ static char *create_drop_index_thread(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
|
||||
while( !timetostop(&err) ){
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
|
||||
sql_script(&err, &db,
|
||||
"DROP INDEX IF EXISTS i1;"
|
||||
@@ -51,7 +51,7 @@ static void create_drop_index_1(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"CREATE TABLE t11(a, b, c, d);"
|
||||
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
|
||||
|
||||
@@ -22,7 +22,7 @@ static char *lookaside1_thread_reader(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
|
||||
while( !timetostop(&err) ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
@@ -47,7 +47,7 @@ static char *lookaside1_thread_writer(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
|
||||
do{
|
||||
sql_script(&err, &db,
|
||||
@@ -68,7 +68,7 @@ static void lookaside1(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"CREATE TABLE t1(x PRIMARY KEY) WITHOUT ROWID;"
|
||||
"WITH data(x,y) AS ("
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
** 2014 December 9
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** reuse_schema_1
|
||||
*/
|
||||
|
||||
|
||||
static char *reuse_schema_thread(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
int iRep = 0;
|
||||
|
||||
while( !timetostop(&err) ){
|
||||
int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_SHARED_SCHEMA;
|
||||
opendb(&err, &db, "test.db", 0, f);
|
||||
|
||||
execsql_i64(&err, &db, "SELECT count(*) FROM t1");
|
||||
sql_script(&err, &db, "ATTACH 'test.db2' AS aux");
|
||||
execsql_i64(&err, &db, "SELECT count(*) FROM t1");
|
||||
|
||||
closedb(&err, &db);
|
||||
iRep++;
|
||||
}
|
||||
|
||||
print_and_free_err(&err);
|
||||
return sqlite3_mprintf("%d", iRep);
|
||||
}
|
||||
|
||||
static void reuse_schema_1(int nMs){
|
||||
Error err = {0};
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
sql_script(&err, &db,
|
||||
"CREATE TABLE t1(a, b, c, d);"
|
||||
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
|
||||
"INSERT INTO t1 SELECT x,x,x,x FROM data;"
|
||||
);
|
||||
closedb(&err, &db);
|
||||
opendb(&err, &db, "test.db2", 1, 0);
|
||||
sql_script(&err, &db,
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
"CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, d);"
|
||||
#else
|
||||
"CREATE TABLE t2(a, b, c, d);"
|
||||
#endif
|
||||
"WITH data(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM data WHERE x<100) "
|
||||
"INSERT INTO t2 SELECT x*2,x*2,x*2,x*2 FROM data;"
|
||||
);
|
||||
closedb(&err, &db);
|
||||
|
||||
setstoptime(&err, nMs);
|
||||
|
||||
launch_thread(&err, &threads, reuse_schema_thread, 0);
|
||||
launch_thread(&err, &threads, reuse_schema_thread, 0);
|
||||
launch_thread(&err, &threads, reuse_schema_thread, 0);
|
||||
launch_thread(&err, &threads, reuse_schema_thread, 0);
|
||||
launch_thread(&err, &threads, reuse_schema_thread, 0);
|
||||
|
||||
join_all_threads(&err, &threads);
|
||||
sqlite3_enable_shared_cache(0);
|
||||
print_and_free_err(&err);
|
||||
}
|
||||
+10
-10
@@ -21,7 +21,7 @@ static char *stress_thread_1(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
sql_script(&err, &db, "CREATE TABLE IF NOT EXISTS t1(a PRIMARY KEY, b)");
|
||||
clear_error(&err, SQLITE_LOCKED);
|
||||
@@ -40,7 +40,7 @@ static char *stress_thread_2(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
while( !timetostop(&err) ){
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
sql_script(&err, &db, "SELECT * FROM sqlite_schema;");
|
||||
clear_error(&err, SQLITE_LOCKED);
|
||||
closedb(&err, &db);
|
||||
@@ -59,7 +59,7 @@ static char *stress_thread_3(int iTid, void *pArg){
|
||||
int i1 = 0;
|
||||
int i2 = 0;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
sql_script(&err, &db, "SELECT * FROM t1 ORDER BY a;");
|
||||
i1++;
|
||||
@@ -82,11 +82,11 @@ static char *stress_thread_4(int iTid, void *pArg){
|
||||
int i2 = 0;
|
||||
int iArg = PTR2INT(pArg);
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
if( iArg ){
|
||||
closedb(&err, &db);
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
}
|
||||
sql_script(&err, &db,
|
||||
"WITH loop(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM loop LIMIT 200) "
|
||||
@@ -113,12 +113,12 @@ static char *stress_thread_5(int iTid, void *pArg){
|
||||
int i1 = 0;
|
||||
int i2 = 0;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
i64 i = (i1 % 4);
|
||||
if( iArg ){
|
||||
closedb(&err, &db);
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
}
|
||||
execsql(&err, &db, "DELETE FROM t1 WHERE (rowid % 4)==:i", &i);
|
||||
i1++;
|
||||
@@ -265,7 +265,7 @@ static char *stress2_workload19(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
const char *zDb = (const char*)pArg;
|
||||
while( !timetostop(&err) ){
|
||||
opendb(&err, &db, zDb, 0, 0);
|
||||
opendb(&err, &db, zDb, 0);
|
||||
sql_script(&err, &db, "SELECT * FROM sqlite_schema;");
|
||||
clear_error(&err, SQLITE_LOCKED);
|
||||
closedb(&err, &db);
|
||||
@@ -290,7 +290,7 @@ static char *stress2_thread_wrapper(int iTid, void *pArg){
|
||||
|
||||
while( !timetostop(&err) ){
|
||||
int cnt;
|
||||
opendb(&err, &db, pCtx->zDb, 0, 0);
|
||||
opendb(&err, &db, pCtx->zDb, 0);
|
||||
for(cnt=0; err.rc==SQLITE_OK && cnt<STRESS2_TABCNT; cnt++){
|
||||
pCtx->xProc(&err, &db, i1);
|
||||
i2 += (err.rc==SQLITE_OK);
|
||||
@@ -342,7 +342,7 @@ static void stress2(int nMs){
|
||||
Threadset threads = {0};
|
||||
|
||||
/* To make sure the db file is empty before commencing */
|
||||
opendb(&err, &db, zDb, 1, 0);
|
||||
opendb(&err, &db, zDb, 1);
|
||||
sql_script(&err, &db,
|
||||
"CREATE TABLE IF NOT EXISTS t0(x PRIMARY KEY, y, z);"
|
||||
"CREATE INDEX IF NOT EXISTS i0 ON t0(y);"
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@ static char *vacuum1_thread_writer(int iTid, void *pArg){
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
i64 i = 0;
|
||||
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
while( !timetostop(&err) ){
|
||||
i++;
|
||||
|
||||
@@ -52,7 +52,7 @@ static char *vacuum1_thread_writer(int iTid, void *pArg){
|
||||
static char *vacuum1_thread_vacuumer(int iTid, void *pArg){
|
||||
Error err = {0}; /* Error code and message */
|
||||
Sqlite db = {0}; /* SQLite database connection */
|
||||
opendb(&err, &db, "test.db", 0, 0);
|
||||
opendb(&err, &db, "test.db", 0);
|
||||
|
||||
do{
|
||||
sql_script(&err, &db, "VACUUM");
|
||||
@@ -69,7 +69,7 @@ static void vacuum1(int nMs){
|
||||
Sqlite db = {0};
|
||||
Threadset threads = {0};
|
||||
|
||||
opendb(&err, &db, "test.db", 1, 0);
|
||||
opendb(&err, &db, "test.db", 1);
|
||||
sql_script(&err, &db,
|
||||
"CREATE TABLE t1(x PRIMARY KEY, y BLOB);"
|
||||
"CREATE INDEX i1 ON t1(y);"
|
||||
|
||||
@@ -315,6 +315,7 @@ testfixture_nb done {
|
||||
db eval {
|
||||
COMMIT
|
||||
}
|
||||
db close
|
||||
}
|
||||
|
||||
after 500 {set ok 1}
|
||||
|
||||
+10
-97
@@ -88,7 +88,7 @@ static MemChunk *memChunkList = 0;
|
||||
*/
|
||||
static void *lemon_malloc(size_t nByte){
|
||||
MemChunk *p;
|
||||
/* if( nByte<0 ) return 0; -- size_t is unsigned */
|
||||
if( nByte<0 ) return 0;
|
||||
p = malloc( nByte + sizeof(MemChunk) );
|
||||
if( p==0 ){
|
||||
fprintf(stderr, "Out of memory. Failed to allocate %lld bytes.\n",
|
||||
@@ -2314,8 +2314,6 @@ void OptPrint(void){
|
||||
}
|
||||
}
|
||||
/*********************** From the file "parse.c" ****************************/
|
||||
|
||||
|
||||
/*
|
||||
** Input file parser for the LEMON parser generator.
|
||||
*/
|
||||
@@ -2371,60 +2369,6 @@ struct pstate {
|
||||
struct rule *lastrule; /* Pointer to the most recently parsed rule */
|
||||
};
|
||||
|
||||
/*
|
||||
** input x[] is a filename enclosed in <...>. This routine strives
|
||||
** to load the complete text of the named file into memory obtained
|
||||
** from lemon_malloc() and return that text. The complete filename
|
||||
** (without the enclosing <...>) is also written into memory obtained
|
||||
** from lemon_malloc() and written back into *pzFN.
|
||||
**
|
||||
** Except, if any error occurs, the error message is set on psp and
|
||||
** no memory is allocated and a NULL is returned.
|
||||
*/
|
||||
static char *load_file_content(
|
||||
struct pstate *psp, /* Parsing context */
|
||||
const char *x, /* Filename enclosed in <....> */
|
||||
char **pzFN /* Write true filename here */
|
||||
){
|
||||
char *zContent;
|
||||
char *zFN;
|
||||
int nFN;
|
||||
FILE *in;
|
||||
int nAlloc;
|
||||
int nContent;
|
||||
|
||||
*pzFN = 0;
|
||||
nFN = lemonStrlen(x);
|
||||
zFN = lemon_malloc( nFN );
|
||||
memcpy(zFN, x+1, nFN-1);
|
||||
zFN[nFN-1] = 0;
|
||||
in = fopen(zFN, "rb");
|
||||
if( in==0 ){
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Cannot read file \"%s\"", zFN);
|
||||
psp->errorcnt++;
|
||||
lemon_free(zFN);
|
||||
return 0;
|
||||
}
|
||||
*pzFN = zFN;
|
||||
nAlloc = 2000;
|
||||
zContent = lemon_malloc( nAlloc );
|
||||
nContent = 0;
|
||||
while( nContent<nAlloc-1 ){
|
||||
long got = fread(&zContent[nContent], 1, nAlloc-nContent-1, in);
|
||||
if( got<=0 ) break;
|
||||
nContent += got;
|
||||
if( nContent>=nAlloc-1 ){
|
||||
nAlloc *= 2;
|
||||
zContent = lemon_realloc(zContent, nAlloc);
|
||||
}
|
||||
}
|
||||
zContent[nContent] = 0;
|
||||
fclose(in);
|
||||
return zContent;
|
||||
}
|
||||
|
||||
|
||||
/* Parse a single token */
|
||||
static void parseonetoken(struct pstate *psp)
|
||||
{
|
||||
@@ -2802,30 +2746,14 @@ static void parseonetoken(struct pstate *psp)
|
||||
}
|
||||
break;
|
||||
case WAITING_FOR_DECL_ARG:
|
||||
if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0])
|
||||
|| (x[0]=='<' && psp->insertLineMacro)
|
||||
){
|
||||
if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){
|
||||
const char *zOld, *zNew;
|
||||
char *zBuf;
|
||||
const char *z;
|
||||
char *zBuf, *z;
|
||||
int nOld, n, nLine = 0, nNew, nBack;
|
||||
int addLineMacro;
|
||||
char zLine[50];
|
||||
char *zToFreeTxt = 0;
|
||||
char *zToFreeFN = 0;
|
||||
const char *zFN = psp->filename;
|
||||
int ln = psp->tokenlineno;
|
||||
|
||||
if( x[0]=='<' ){
|
||||
zToFreeTxt = load_file_content(psp,x,&zToFreeFN);
|
||||
if( psp->errorcnt ) break;
|
||||
zNew = zToFreeTxt;
|
||||
zFN = zToFreeFN;
|
||||
ln = 1;
|
||||
}else{
|
||||
zNew = x;
|
||||
if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
|
||||
}
|
||||
zNew = x;
|
||||
if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
|
||||
nNew = lemonStrlen(zNew);
|
||||
if( *psp->declargslot ){
|
||||
zOld = *psp->declargslot;
|
||||
@@ -2838,14 +2766,13 @@ static void parseonetoken(struct pstate *psp)
|
||||
&& psp->insertLineMacro
|
||||
&& psp->tokenlineno>1
|
||||
&& (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
|
||||
if( addLineMacro || x[0]=='<' ){
|
||||
addLineMacro = 1;
|
||||
for(z=zFN, nBack=0; *z; z++){
|
||||
if( addLineMacro ){
|
||||
for(z=psp->filename, nBack=0; *z; z++){
|
||||
if( *z=='\\' ) nBack++;
|
||||
}
|
||||
lemon_sprintf(zLine, "#line %d ", ln);
|
||||
lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
|
||||
nLine = lemonStrlen(zLine);
|
||||
n += nLine + lemonStrlen(zFN) + nBack;
|
||||
n += nLine + lemonStrlen(psp->filename) + nBack;
|
||||
}
|
||||
*psp->declargslot = (char *) lemon_realloc(*psp->declargslot, n);
|
||||
zBuf = *psp->declargslot + nOld;
|
||||
@@ -2856,7 +2783,7 @@ static void parseonetoken(struct pstate *psp)
|
||||
memcpy(zBuf, zLine, nLine);
|
||||
zBuf += nLine;
|
||||
*(zBuf++) = '"';
|
||||
for(z=zFN; *z; z++){
|
||||
for(z=psp->filename; *z; z++){
|
||||
if( *z=='\\' ){
|
||||
*(zBuf++) = '\\';
|
||||
}
|
||||
@@ -2872,8 +2799,6 @@ static void parseonetoken(struct pstate *psp)
|
||||
zBuf += nNew;
|
||||
*zBuf = 0;
|
||||
psp->state = WAITING_FOR_DECL_OR_RULE;
|
||||
lemon_free(zToFreeTxt);
|
||||
lemon_free(zToFreeFN);
|
||||
}else{
|
||||
ErrorMsg(psp->filename,psp->tokenlineno,
|
||||
"Illegal argument to %%%s: %s",psp->declkeyword,x);
|
||||
@@ -3241,18 +3166,6 @@ void Parse(struct lemon *gp)
|
||||
}else{
|
||||
nextcp = cp+1;
|
||||
}
|
||||
}else if( c=='<' ){ /* Pathname in <...> */
|
||||
cp++;
|
||||
while( (c= *cp)!=0 && c!='>' && (c&0xfc)!=0 ){ cp++; }
|
||||
if( (c&0xfc)==0 ){
|
||||
ErrorMsg(ps.filename,startline,
|
||||
c==0 ? "Unterminated filename"
|
||||
: "Control-character in filename");
|
||||
ps.errorcnt++;
|
||||
nextcp = cp;
|
||||
}else{
|
||||
nextcp = cp+1;
|
||||
}
|
||||
}else if( c=='{' ){ /* A block of C code */
|
||||
int level;
|
||||
cp++;
|
||||
|
||||
+16
-22
@@ -20,7 +20,7 @@
|
||||
|
||||
# Flag meanings:
|
||||
set flagMeaning(NeedSchema) {Force schema load before running}
|
||||
set flagMeaning(OneSchema) {Only a single schema required}
|
||||
set flagMeaning(ReadOnly) {Read-only HEADER_VALUE}
|
||||
set flagMeaning(Result0) {Acts as query when no argument}
|
||||
set flagMeaning(Result1) {Acts as query when has one argument}
|
||||
set flagMeaning(SchemaReq) {Schema required - "main" is default}
|
||||
@@ -158,7 +158,7 @@ set pragma_def {
|
||||
ARG: SQLITE_CellSizeCk
|
||||
|
||||
NAME: default_cache_size
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1
|
||||
COLS: cache_size
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
|
||||
|
||||
@@ -171,12 +171,12 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: page_count
|
||||
FLAG: NeedSchema Result0 SchemaReq OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: max_page_count
|
||||
TYPE: PAGE_COUNT
|
||||
FLAG: NeedSchema Result0 SchemaReq OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: locking_mode
|
||||
@@ -184,7 +184,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: journal_mode
|
||||
FLAG: NeedSchema Result0 SchemaReq OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: journal_size_limit
|
||||
@@ -192,18 +192,18 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: cache_size
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: mmap_size
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: auto_vacuum
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1
|
||||
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
|
||||
|
||||
NAME: incremental_vacuum
|
||||
FLAG: NeedSchema NoColumns OneSchema
|
||||
FLAG: NeedSchema NoColumns
|
||||
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
|
||||
|
||||
NAME: temp_store
|
||||
@@ -223,7 +223,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
|
||||
|
||||
NAME: synchronous
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1 OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq NoColumns1
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: table_info
|
||||
@@ -246,7 +246,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: stats
|
||||
FLAG: NeedSchema Result0 SchemaReq OneSchema
|
||||
FLAG: NeedSchema Result0 SchemaReq
|
||||
COLS: tbl idx wdth hght flgs
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
|
||||
|
||||
@@ -298,7 +298,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: foreign_key_list
|
||||
FLAG: NeedSchema Result1 SchemaOpt OneSchema
|
||||
FLAG: NeedSchema Result1 SchemaOpt
|
||||
COLS: id seq table from to on_update on_delete match
|
||||
IF: !defined(SQLITE_OMIT_FOREIGN_KEY)
|
||||
|
||||
@@ -344,14 +344,14 @@ set pragma_def {
|
||||
|
||||
NAME: data_version
|
||||
TYPE: HEADER_VALUE
|
||||
ARG: BTREE_DATA_VERSION|PRAGMA_HEADER_VALUE_READONLY
|
||||
FLAG: Result0
|
||||
ARG: BTREE_DATA_VERSION
|
||||
FLAG: ReadOnly Result0
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
|
||||
NAME: freelist_count
|
||||
TYPE: HEADER_VALUE
|
||||
ARG: BTREE_FREE_PAGE_COUNT|PRAGMA_HEADER_VALUE_READONLY
|
||||
FLAG: Result0
|
||||
ARG: BTREE_FREE_PAGE_COUNT
|
||||
FLAG: ReadOnly Result0
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
|
||||
NAME: application_id
|
||||
@@ -365,7 +365,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
|
||||
|
||||
NAME: wal_checkpoint
|
||||
FLAG: NeedSchema OneSchema
|
||||
FLAG: NeedSchema
|
||||
COLS: busy log checkpointed
|
||||
IF: !defined(SQLITE_OMIT_WAL)
|
||||
|
||||
@@ -528,12 +528,6 @@ foreach f [lsort [array names allflags]] {
|
||||
set fv [expr {$fv*2}]
|
||||
}
|
||||
|
||||
puts $fd "\n/* For PragTyp_HEADER_VALUE pragmas the Pragma.iArg value is set"
|
||||
puts $fd "** to the index of the header field to access (always 10 or less)."
|
||||
puts $fd "** Ored with HEADER_VALUE_READONLY if the field is read only. */"
|
||||
puts $fd "#define PRAGMA_HEADER_VALUE_READONLY 0x0100"
|
||||
puts $fd "#define PRAGMA_HEADER_VALUE_MASK 0x00FF\n"
|
||||
|
||||
# Sort the column lists so that longer column lists occur first.
|
||||
# In the event of a tie, sort column lists lexicographically.
|
||||
#
|
||||
|
||||
@@ -61,6 +61,7 @@ static int subst_puts(
|
||||
}
|
||||
sqlite3_fputs(zOut, pOut);
|
||||
if( addNewLine ) sqlite3_fputs("\n", pOut);
|
||||
fflush(pOut);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
Reference in New Issue
Block a user