3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
6 # May you do good and not evil.
7 # May you find forgiveness for yourself and forgive others.
8 # May you share freely, never taking more than you give.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this file is the "memdb" VFS
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
20 ifcapable !deserialize {
25 # Create a MEMDB and populate it with some dummy data.
26 # Then extract the database into the $::db1 variable.
27 # Verify that the size of $::db1 is the same as the size of
32 unset -nocomplain pgsz
36 INSERT INTO t1 VALUES(1,2);
38 set ::pgsz [db one {PRAGMA page_size}]
39 set ::sz1 [expr {$::pgsz*[db one {PRAGMA page_count}]}]
40 set ::db1 [db serialize]
41 expr {[string length $::db1]==$::sz1}
43 set fd [open db1.db wb]
44 puts -nonewline $fd $db1
47 # Create a new MEMDB and initialize it to the content of $::db1
48 # Verify that the content is the same.
57 # What happens when we try to VACUUM a MEMDB database?
60 PRAGMA auto_vacuum = off;
64 CREATE TABLE t2(x, y);
65 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
66 INSERT INTO t2(x, y) SELECT x, randomblob(1000) FROM c;
76 catch {db deserialize -unknown 1 $db1} msg
78 } {unknown option: -unknown}
80 db deserialize -readonly 1 $db1
81 db eval {SELECT * FROM t1}
84 catchsql {INSERT INTO t1 VALUES(3,4);}
85 } {1 {attempt to write a readonly database}}
88 db deserialize -maxsize 32768 $db1
89 db eval {SELECT * FROM t1}
92 db eval {INSERT INTO t1 VALUES(3,4); SELECT * FROM t1}
95 catchsql {INSERT INTO t1 VALUES(5,randomblob(100000))}
96 } {1 {database or disk is full}}
99 # Build a largish on-disk database and serialize it. Verify that the
100 # serialization works.
105 do_execsql_test 200 {
106 CREATE TABLE t3(x, y);
107 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<400)
108 INSERT INTO t3(x, y) SELECT x, randomblob(1000) FROM c;
111 set fd [open test.db rb]
112 unset -nocomplain direct
113 set direct [read $fd]
116 string length [db serialize]
117 } [string length $direct]
119 db eval {ATTACH ':memory:' AS aux1}
120 db deserialize aux1 $::direct
122 SELECT x, y FROM main.t3 EXCEPT SELECT x, y FROM aux1.t3;
125 unset -nocomplain direct
127 # Do the same with a :memory: database.
131 do_execsql_test 300 {
132 CREATE TABLE t3(x, y);
133 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<400)
134 INSERT INTO t3(x, y) SELECT x, randomblob(1000) FROM c;
138 db eval {ATTACH ':memory:' AS aux1}
139 db deserialize aux1 [db serialize main]
141 SELECT x, y FROM main.t3 EXCEPT SELECT x, y FROM aux1.t3;
145 # Deserialize an empty database
150 do_execsql_test 400 {
151 PRAGMA integrity_check;
153 do_execsql_test 410 {
154 CREATE TABLE t4(a,b);
155 INSERT INTO t4 VALUES('hello','world!');
156 PRAGMA integrity_check;
159 do_execsql_test 420 {
160 PRAGMA journal_mode=TRUNCATE;
161 PRAGMA journal_mode=OFF;
162 PRAGMA journal_mode=DELETE;
163 PRAGMA journal_mode=WAL;
164 PRAGMA journal_mode=PERSIST;
165 PRAGMA journal_mode=MEMORY;
166 PRAGMA journal_mode=OFF;
167 PRAGMA journal_mode=DELETE;
168 } {truncate off delete delete persist memory off delete}
170 # Deserialize something that is not a database.
175 set rc [catch {db deserialize not-a-database} msg]
178 do_catchsql_test 510 {
179 PRAGMA integrity_check;
180 } {1 {file is not a database}}
182 # Abuse the serialize and deserialize commands. Make sure errors are caught.
185 set rc [catch {db deserialize} msg]
187 } {1 {wrong # args: should be "db deserialize ?DATABASE? VALUE"}}
189 set rc [catch {db deserialize a b c} msg]
191 } {1 {unknown option: a}}
193 set rc [catch {db serialize a b} msg]
195 } {1 {wrong # args: should be "db serialize ?DATABASE?"}}
197 # 2021-07-19 https://sqlite.org/forum/forumpost/e1cbb5f450b98aa6
198 # The TEMP database cannot participate in serialization or
204 CREATE TEMP TABLE t0(a);
206 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
207 INSERT INTO t1(x) SELECT random() FROM c;
209 set rc [catch {db deserialize temp [db serialize main]} err]
213 #-------------------------------------------------------------------------
216 do_execsql_test 700 {
217 CREATE TABLE t1(a, b);
218 PRAGMA schema_version = 0;
221 set ser [db serialize main]
224 db deserialize main $ser
226 CREATE VIRTUAL TABLE t1 USING rtree(id, a, b, c, d);
228 } {1 {table t1 already exists}}
232 #-------------------------------------------------------------------------
233 # dbsqlfuzz 0a13dfb474d4f2f11a48a2ea57075c96fb456dd7
235 if {[wal_is_capable]} {
237 do_execsql_test 800 {
238 PRAGMA auto_vacuum = 0;
239 PRAGMA page_size = 8192;
240 PRAGMA journal_mode = wal;
241 CREATE TABLE t1(x, y);
242 INSERT INTO t1 VALUES(1, 2);
243 CREATE TABLE t2(x, y);
247 set fd [open test.db]
248 fconfigure $fd -translation binary -encoding binary
249 set data [read $fd [expr 20*1024]]
255 do_execsql_test 810 {
256 PRAGMA locking_mode = exclusive;
260 do_execsql_test 820 {
261 INSERT INTO t1 VALUES(3, 4);
265 do_catchsql_test 830 {
266 PRAGMA wal_checkpoint;
267 } {1 {database disk image is malformed}}
271 # https://sqlite.org/forum/forumpost/498777780e16880a
273 # Make sure a database is initialized before serializing it.
276 sqlite3 dbempty :memory:
278 set len [string length [dbempty serialize]]