7718c866e1
FossilOrigin-Name: 6cd70b71df5c0d45412081590316bced302ec4403d565250b56e611882204821
284 lines
6.6 KiB
Plaintext
284 lines
6.6 KiB
Plaintext
# 2018-01-02
|
|
#
|
|
# The author disclaims copyright to this source code. In place of
|
|
# a legal notice, here is a blessing:
|
|
#
|
|
# May you do good and not evil.
|
|
# May you find forgiveness for yourself and forgive others.
|
|
# May you share freely, never taking more than you give.
|
|
#
|
|
#***********************************************************************
|
|
# This file implements regression tests for SQLite library. The
|
|
# focus of this file is the "memdb" VFS
|
|
#
|
|
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
set testprefix memdb1
|
|
do_not_use_codec
|
|
|
|
ifcapable !deserialize {
|
|
finish_test
|
|
return
|
|
}
|
|
|
|
# Create a MEMDB and populate it with some dummy data.
|
|
# Then extract the database into the $::db1 variable.
|
|
# Verify that the size of $::db1 is the same as the size of
|
|
# the database.
|
|
#
|
|
unset -nocomplain db1
|
|
unset -nocomplain sz1
|
|
unset -nocomplain pgsz
|
|
do_test 100 {
|
|
db eval {
|
|
CREATE TABLE t1(a,b);
|
|
INSERT INTO t1 VALUES(1,2);
|
|
}
|
|
set ::pgsz [db one {PRAGMA page_size}]
|
|
set ::sz1 [expr {$::pgsz*[db one {PRAGMA page_count}]}]
|
|
set ::db1 [db serialize]
|
|
expr {[string length $::db1]==$::sz1}
|
|
} 1
|
|
set fd [open db1.db wb]
|
|
puts -nonewline $fd $db1
|
|
close $fd
|
|
|
|
# Create a new MEMDB and initialize it to the content of $::db1
|
|
# Verify that the content is the same.
|
|
#
|
|
db close
|
|
sqlite3 db
|
|
db deserialize $db1
|
|
do_execsql_test 110 {
|
|
SELECT * FROM t1;
|
|
} {1 2}
|
|
|
|
# What happens when we try to VACUUM a MEMDB database?
|
|
#
|
|
do_execsql_test 120 {
|
|
PRAGMA auto_vacuum = off;
|
|
VACUUM;
|
|
} {}
|
|
do_execsql_test 130 {
|
|
CREATE TABLE t2(x, y);
|
|
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
|
|
INSERT INTO t2(x, y) SELECT x, randomblob(1000) FROM c;
|
|
DROP TABLE t2;
|
|
PRAGMA page_count;
|
|
} {116}
|
|
do_execsql_test 140 {
|
|
VACUUM;
|
|
PRAGMA page_count;
|
|
} {2}
|
|
|
|
do_test 150 {
|
|
catch {db deserialize -unknown 1 $db1} msg
|
|
set msg
|
|
} {unknown option: -unknown}
|
|
do_test 151 {
|
|
db deserialize -readonly 1 $db1
|
|
db eval {SELECT * FROM t1}
|
|
} {1 2}
|
|
do_test 152 {
|
|
catchsql {INSERT INTO t1 VALUES(3,4);}
|
|
} {1 {attempt to write a readonly database}}
|
|
|
|
do_test 160 {
|
|
db deserialize -maxsize 32768 $db1
|
|
db eval {SELECT * FROM t1}
|
|
} {1 2}
|
|
do_test 161 {
|
|
db eval {INSERT INTO t1 VALUES(3,4); SELECT * FROM t1}
|
|
} {1 2 3 4}
|
|
do_test 162 {
|
|
catchsql {INSERT INTO t1 VALUES(5,randomblob(100000))}
|
|
} {1 {database or disk is full}}
|
|
|
|
|
|
# Build a largish on-disk database and serialize it. Verify that the
|
|
# serialization works.
|
|
#
|
|
db close
|
|
forcedelete test.db
|
|
sqlite3 db test.db
|
|
do_execsql_test 200 {
|
|
CREATE TABLE t3(x, y);
|
|
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<400)
|
|
INSERT INTO t3(x, y) SELECT x, randomblob(1000) FROM c;
|
|
PRAGMA quick_check;
|
|
} {ok}
|
|
set fd [open test.db rb]
|
|
unset -nocomplain direct
|
|
set direct [read $fd]
|
|
close $fd
|
|
do_test 210 {
|
|
string length [db serialize]
|
|
} [string length $direct]
|
|
do_test 220 {
|
|
db eval {ATTACH ':memory:' AS aux1}
|
|
db deserialize aux1 $::direct
|
|
db eval {
|
|
SELECT x, y FROM main.t3 EXCEPT SELECT x, y FROM aux1.t3;
|
|
}
|
|
} {}
|
|
unset -nocomplain direct
|
|
|
|
# Do the same with a :memory: database.
|
|
#
|
|
db close
|
|
sqlite3 db :memory:
|
|
do_execsql_test 300 {
|
|
CREATE TABLE t3(x, y);
|
|
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<400)
|
|
INSERT INTO t3(x, y) SELECT x, randomblob(1000) FROM c;
|
|
PRAGMA quick_check;
|
|
} {ok}
|
|
do_test 310 {
|
|
db eval {ATTACH ':memory:' AS aux1}
|
|
db deserialize aux1 [db serialize main]
|
|
db eval {
|
|
SELECT x, y FROM main.t3 EXCEPT SELECT x, y FROM aux1.t3;
|
|
}
|
|
} {}
|
|
|
|
# Deserialize an empty database
|
|
#
|
|
db close
|
|
sqlite3 db
|
|
db deserialize {}
|
|
do_execsql_test 400 {
|
|
PRAGMA integrity_check;
|
|
} {ok}
|
|
do_execsql_test 410 {
|
|
CREATE TABLE t4(a,b);
|
|
INSERT INTO t4 VALUES('hello','world!');
|
|
PRAGMA integrity_check;
|
|
SELECT * FROM t4;
|
|
} {ok hello world!}
|
|
do_execsql_test 420 {
|
|
PRAGMA journal_mode=TRUNCATE;
|
|
PRAGMA journal_mode=OFF;
|
|
PRAGMA journal_mode=DELETE;
|
|
PRAGMA journal_mode=WAL;
|
|
PRAGMA journal_mode=PERSIST;
|
|
PRAGMA journal_mode=MEMORY;
|
|
PRAGMA journal_mode=OFF;
|
|
PRAGMA journal_mode=DELETE;
|
|
} {truncate off delete delete persist memory off delete}
|
|
|
|
# Deserialize something that is not a database.
|
|
#
|
|
db close
|
|
sqlite3 db
|
|
do_test 500 {
|
|
set rc [catch {db deserialize not-a-database} msg]
|
|
lappend rc $msg
|
|
} {0 {}}
|
|
do_catchsql_test 510 {
|
|
PRAGMA integrity_check;
|
|
} {1 {file is not a database}}
|
|
|
|
# Abuse the serialize and deserialize commands. Make sure errors are caught.
|
|
#
|
|
do_test 600 {
|
|
set rc [catch {db deserialize} msg]
|
|
lappend rc $msg
|
|
} {1 {wrong # args: should be "db deserialize ?DATABASE? VALUE"}}
|
|
do_test 610 {
|
|
set rc [catch {db deserialize a b c} msg]
|
|
lappend rc $msg
|
|
} {1 {unknown option: a}}
|
|
do_test 620 {
|
|
set rc [catch {db serialize a b} msg]
|
|
lappend rc $msg
|
|
} {1 {wrong # args: should be "db serialize ?DATABASE?"}}
|
|
|
|
# 2021-07-19 https://sqlite.org/forum/forumpost/e1cbb5f450b98aa6
|
|
# The TEMP database cannot participate in serialization or
|
|
# deserialization.
|
|
#
|
|
reset_db
|
|
do_test 650 {
|
|
db eval {
|
|
CREATE TEMP TABLE t0(a);
|
|
CREATE TABLE t1(x);
|
|
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
|
|
INSERT INTO t1(x) SELECT random() FROM c;
|
|
}
|
|
set rc [catch {db deserialize temp [db serialize main]} err]
|
|
lappend rc err
|
|
} {1 err}
|
|
|
|
#-------------------------------------------------------------------------
|
|
ifcapable vtab {
|
|
reset_db
|
|
do_execsql_test 700 {
|
|
CREATE TABLE t1(a, b);
|
|
PRAGMA schema_version = 0;
|
|
}
|
|
do_test 710 {
|
|
set ser [db serialize main]
|
|
db close
|
|
sqlite3 db
|
|
db deserialize main $ser
|
|
catchsql {
|
|
CREATE VIRTUAL TABLE t1 USING rtree(id, a, b, c, d);
|
|
}
|
|
} {1 {table t1 already exists}}
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
# dbsqlfuzz 0a13dfb474d4f2f11a48a2ea57075c96fb456dd7
|
|
#
|
|
if {[wal_is_capable]} {
|
|
reset_db
|
|
do_execsql_test 800 {
|
|
PRAGMA auto_vacuum = 0;
|
|
PRAGMA page_size = 8192;
|
|
PRAGMA journal_mode = wal;
|
|
CREATE TABLE t1(x, y);
|
|
INSERT INTO t1 VALUES(1, 2);
|
|
CREATE TABLE t2(x, y);
|
|
} {wal}
|
|
db close
|
|
|
|
set fd [open test.db]
|
|
fconfigure $fd -translation binary -encoding binary
|
|
set data [read $fd [expr 20*1024]]
|
|
close $fd
|
|
|
|
sqlite3 db ""
|
|
db deserialize $data
|
|
|
|
do_execsql_test 810 {
|
|
PRAGMA locking_mode = exclusive;
|
|
SELECT * FROM t1
|
|
} {exclusive 1 2}
|
|
|
|
do_execsql_test 820 {
|
|
INSERT INTO t1 VALUES(3, 4);
|
|
SELECT * FROM t1;
|
|
} {1 2 3 4}
|
|
|
|
do_catchsql_test 830 {
|
|
PRAGMA wal_checkpoint;
|
|
} {1 {database disk image is malformed}}
|
|
}
|
|
|
|
# 2024-01-20
|
|
# https://sqlite.org/forum/forumpost/498777780e16880a
|
|
#
|
|
# Make sure a database is initialized before serializing it.
|
|
#
|
|
reset_db
|
|
sqlite3 dbempty :memory:
|
|
do_test 900 {
|
|
set len [string length [dbempty serialize]]
|
|
expr {$len>0}
|
|
} 1
|
|
dbempty close
|
|
|
|
finish_test
|