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 |