# 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 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