OLD | NEW |
| (Empty) |
1 /* | |
2 ** This program is used to generate and verify databases with hot journals. | |
3 ** Use this program to generate a hot journal on one machine and verify | |
4 ** that it rolls back correctly on another machine with a different | |
5 ** architecture. | |
6 ** | |
7 ** Usage: | |
8 ** | |
9 ** rollback-test new [-utf8] [-utf16le] [-utf16be] [-pagesize=N] DATABASE | |
10 ** rollback-test check DATABASE | |
11 ** rollback-test crash [-wal] [-rollback] DATABASE | |
12 */ | |
13 #include <stdio.h> | |
14 #include <stdlib.h> | |
15 #include <string.h> | |
16 #include "sqlite3.h" | |
17 | |
18 static void usage(char *argv0){ | |
19 fprintf(stderr, | |
20 "Usage: %s new [-utf8] [-utf16le] [-utf16be] [-pagesize=N] DATABASE\n" | |
21 " %s check DATABASE\n" | |
22 " %s crash [-wal] DATABASE\n", | |
23 argv0, argv0, argv0 | |
24 ); | |
25 exit(1); | |
26 } | |
27 | |
28 static sqlite3 *openDb(const char *zFilename){ | |
29 int rc; | |
30 sqlite3 *db; | |
31 rc = sqlite3_open(zFilename, &db); | |
32 if( rc ){ | |
33 fprintf(stderr, "Cannot open \"%s\": %s\n", | |
34 zFilename, sqlite3_errmsg(db)); | |
35 sqlite3_close(db); | |
36 exit(1); | |
37 } | |
38 return db; | |
39 } | |
40 | |
41 static int nReply = 0; | |
42 static char zReply[1000]; | |
43 | |
44 static int execCallback(void *NotUsed, int nArg, char **azArg, char **azCol){ | |
45 int i, n; | |
46 char *z; | |
47 for(i=0; i<nArg; i++){ | |
48 z = azArg[i]; | |
49 if( z==0 ) z = "NULL"; | |
50 if( nReply>0 && nReply<sizeof(zReply)-1 ) zReply[nReply++] = ' '; | |
51 n = strlen(z); | |
52 if( nReply+n>=sizeof(zReply)-1 ) n = sizeof(zReply) - nReply - 1; | |
53 memcpy(&zReply[nReply], z, n); | |
54 nReply += n; | |
55 zReply[nReply] = 0; | |
56 } | |
57 return 0; | |
58 } | |
59 | |
60 static void runSql(sqlite3 *db, const char *zSql){ | |
61 char *zErr = 0; | |
62 int rc; | |
63 nReply = 0; | |
64 rc = sqlite3_exec(db, zSql, execCallback, 0, &zErr); | |
65 if( zErr ){ | |
66 fprintf(stderr, "SQL error: %s\n", zErr); | |
67 exit(1); | |
68 } | |
69 if( rc ){ | |
70 fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); | |
71 exit(1); | |
72 } | |
73 } | |
74 | |
75 int main(int argc, char **argv){ | |
76 sqlite3 *db; | |
77 int i; | |
78 | |
79 if( argc<3 ) usage(argv[0]); | |
80 if( strcmp(argv[1], "new")==0 ){ | |
81 db = openDb(argv[argc-1]); | |
82 for(i=2; i<argc-1; i++){ | |
83 if( strcmp(argv[i],"-utf8")==0 ){ | |
84 runSql(db, "PRAGMA encoding=UTF8"); | |
85 }else if( strcmp(argv[i], "-utf16le")==0 ){ | |
86 runSql(db, "PRAGMA encoding=UTF16LE"); | |
87 }else if( strcmp(argv[i], "-utf16be")==0 ){ | |
88 runSql(db, "PRAGMA encoding=UTF16BE"); | |
89 }else if( strncmp(argv[i], "-pagesize=", 10)==0 ){ | |
90 int szPg = atoi(&argv[i][10]); | |
91 char zBuf[100]; | |
92 sprintf(zBuf, "PRAGMA pagesize=%d", szPg); | |
93 runSql(db, zBuf); | |
94 }else{ | |
95 fprintf(stderr, "unknown option %s\n", argv[i]); | |
96 usage(argv[0]); | |
97 } | |
98 } | |
99 runSql(db, | |
100 "BEGIN;" | |
101 "CREATE TABLE t1(x INTEGER PRIMARY KEY, y);" | |
102 "INSERT INTO t1(y) VALUES('abcdefghijklmnopqrstuvwxyz');" | |
103 "INSERT INTO t1(y) VALUES('abcdefghijklmnopqrstuvwxyz');" | |
104 "INSERT INTO t1(y) SELECT y FROM t1;" /* 4 */ | |
105 "INSERT INTO t1(y) SELECT y FROM t1;" /* 8 */ | |
106 "INSERT INTO t1(y) SELECT y FROM t1;" /* 16 */ | |
107 "INSERT INTO t1(y) SELECT y FROM t1;" /* 32 */ | |
108 "INSERT INTO t1(y) SELECT y FROM t1;" /* 64 */ | |
109 "INSERT INTO t1(y) SELECT y FROM t1;" /* 128 */ | |
110 "INSERT INTO t1(y) SELECT y FROM t1;" /* 256 */ | |
111 "INSERT INTO t1(y) SELECT y FROM t1;" /* 512 */ | |
112 "INSERT INTO t1(y) SELECT y FROM t1;" /* 1024 */ | |
113 "UPDATE t1 SET y=(y || x);" | |
114 "CREATE INDEX t1y ON t1(y);" | |
115 "COMMIT;" | |
116 ); | |
117 sqlite3_close(db); | |
118 }else if( strcmp(argv[1], "check")==0 ){ | |
119 db = openDb(argv[argc-1]); | |
120 runSql(db, "PRAGMA integrity_check"); | |
121 if( strcmp(zReply, "ok")!=0 ){ | |
122 fprintf(stderr, "Integrity check: %s\n", zReply); | |
123 exit(1); | |
124 } | |
125 runSql(db, | |
126 "SELECT count(*) FROM t1 WHERE y<>('abcdefghijklmnopqrstuvwxyz' || x)" | |
127 ); | |
128 if( strcmp(zReply, "0")!=0 ){ | |
129 fprintf(stderr, "Wrong content\n"); | |
130 exit(1); | |
131 } | |
132 printf("Ok\n"); | |
133 }else if( strcmp(argv[1], "crash")==0 ){ | |
134 db = openDb(argv[argc-1]); | |
135 for(i=2; i<argc-1; i++){ | |
136 if( strcmp(argv[i],"-wal")==0 ){ | |
137 runSql(db, "PRAGMA journal_mode=WAL"); | |
138 }else if( strcmp(argv[i], "-rollback")==0 ){ | |
139 runSql(db, "PRAGMA journal_mode=DELETE"); | |
140 }else{ | |
141 fprintf(stderr, "unknown option %s\n", argv[i]); | |
142 usage(argv[0]); | |
143 } | |
144 } | |
145 runSql(db, | |
146 "PRAGMA cache_size=10;" | |
147 "BEGIN;" | |
148 "UPDATE t1 SET y=(y || -x)" | |
149 ); | |
150 exit(0); | |
151 }else{ | |
152 usage(argv[0]); | |
153 } | |
154 return 0; | |
155 } | |
OLD | NEW |