xref: /sqlite-3.40.0/tool/rollback-test.c (revision bce7365c)
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