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