Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Make the automatic database upgrade work even if there are triggers. Add tests for automatic upgrade and for failing if reading a more advanced version of the database. Ticket #107. (CVS 682) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0493e39c1cbbe4a38e990a2370181a79 |
User & Date: | drh 2002-07-18 01:27:18.000 |
Context
2002-07-18
| ||
02:07 | Update documentation prior to the release of 2.6.0. (CVS 683) (check-in: f2d9191381 user: drh tags: trunk) | |
01:27 | Make the automatic database upgrade work even if there are triggers. Add tests for automatic upgrade and for failing if reading a more advanced version of the database. Ticket #107. (CVS 682) (check-in: 0493e39c1c user: drh tags: trunk) | |
00:34 | Fix for ticket #107: Fix a design defect in indices that was causing queries to fail when using an index on a column containing an empty string. This fix is an incompatible file-format change. (CVS 681) (check-in: 20d152fcdd user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.88 2002/07/18 01:27:18 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** This is the callback routine for the code that initializes the |
︙ | ︙ | |||
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | ** this routine relys on the fact that no indices are used when ** copying a table out to a temporary file. */ static int upgrade_3_callback(void *pDb, int argc, char **argv, char **NotUsed){ sqlite *db = (sqlite*)pDb; int rc; rc = sqlite_exec_printf(db, "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; " "DELETE FROM '%q'; " "INSERT INTO '%q' SELECT * FROM sqlite_x; " "DROP TABLE sqlite_x;", 0, 0, 0, argv[0], argv[0], argv[0]); return rc!=SQLITE_OK; } /* ** Attempt to read the database schema and initialize internal | > > > > > > > > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | ** this routine relys on the fact that no indices are used when ** copying a table out to a temporary file. */ static int upgrade_3_callback(void *pDb, int argc, char **argv, char **NotUsed){ sqlite *db = (sqlite*)pDb; int rc; Table *pTab; Trigger *pTrig; pTab = sqliteFindTable(db, argv[0]); if( pTab ){ pTrig = pTab->pTrigger; pTab->pTrigger = 0; /* Disable all triggers before rebuilding the table */ } rc = sqlite_exec_printf(db, "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; " "DELETE FROM '%q'; " "INSERT INTO '%q' SELECT * FROM sqlite_x; " "DROP TABLE sqlite_x;", 0, 0, 0, argv[0], argv[0], argv[0]); if( pTab ) pTab->pTrigger = pTrig; /* Re-enable triggers */ return rc!=SQLITE_OK; } /* ** Attempt to read the database schema and initialize internal |
︙ | ︙ | |||
237 238 239 240 241 242 243 | */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 3; }else if( db->file_format>3 ){ sqliteBtreeCloseCursor(curMain); sqliteSetString(pzErrMsg, "unsupported file format", 0); | | | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 3; }else if( db->file_format>3 ){ sqliteBtreeCloseCursor(curMain); sqliteSetString(pzErrMsg, "unsupported file format", 0); return SQLITE_ERROR; } /* Read the schema information out of the schema tables */ memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.pBe = db->pBe; |
︙ | ︙ |
Added test/version.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | # 2002 July 17 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the ability of the library to detect # past or future file format version numbers and respond appropriately. # # $Id: version.test,v 1.1 2002/07/18 01:27:19 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Current file format version set VX 3 # Create a new database # do_test version-1.1 { execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 SELECT x+1 FROM t1; INSERT INTO t1 SELECT x+2 FROM t1; INSERT INTO t1 SELECT x+4 FROM t1; SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} # Make sure the version number is set correctly # do_test version-1.2 { db close set ::bt [btree_open test.db] set ::meta [btree_get_meta $::bt] lindex $::meta 2 } $VX # Increase the file_format number by one. Verify that the # file will refuse to open. # do_test version-1.3 { set m2 [lreplace $::meta 2 2 [expr {$::VX+1}]] btree_begin_transaction $::bt eval btree_update_meta $::bt $m2 btree_commit $::bt set rc [catch {sqlite db test.db} msg] lappend rc $msg } {1 {unsupported file format}} # Decrease the file_format number by one. Verify that the # file will open correctly. # do_test version-1.4 { set m2 [lreplace $::meta 2 2 [expr {$::VX-1}]] btree_begin_transaction $::bt eval btree_update_meta $::bt $m2 btree_commit $::bt sqlite db test.db execsql { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} # Set the file_format number to 2. This should cause the automatic # upgrade processing to run. # do_test version-1.5 { set m2 [lreplace $::meta 2 2 2] btree_begin_transaction $::bt eval btree_update_meta $::bt $m2 btree_commit $::bt sqlite db test.db execsql { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test version-1.6 { set ::meta [btree_get_meta $::bt] lindex $::meta 2 } $VX # Add some triggers, views, and indices to the schema and make sure the # automatic upgrade still works. # do_test version-1.7 { execsql { CREATE INDEX i1 ON t1(x); DELETE FROM t1; CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE, c); CREATE TABLE cnt(name,ins, del); INSERT INTO cnt VALUES('t1',0,0); INSERT INTO cnt VALUES('t2',0,0); CREATE TRIGGER r1 AFTER INSERT ON t1 FOR EACH ROW BEGIN UPDATE cnt SET ins=ins+1 WHERE name='t1'; END; CREATE TRIGGER r2 AFTER DELETE ON t1 FOR EACH ROW BEGIN UPDATE cnt SET del=del+1 WHERE name='t1'; END; CREATE TRIGGER r3 AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE cnt SET ins=ins+1 WHERE name='t2'; END; CREATE TRIGGER r4 AFTER DELETE ON t2 FOR EACH ROW BEGIN UPDATE cnt SET del=del+1 WHERE name='t2'; END; CREATE VIEW v1 AS SELECT x+100 FROM t1; CREATE VIEW v2 AS SELECT sum(ins), sum(del) FROM cnt; INSERT INTO t1 VALUES(1); INSERT INTO t1 SELECT x+1 FROM t1; INSERT INTO t1 SELECT x+2 FROM t1; INSERT INTO t1 SELECT x+4 FROM t1; SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test version-1.8 { execsql { SELECT * FROM v2; } } {8 0} do_test version-1.9 { execsql { SELECT * FROM cnt; } } {t1 8 0 t2 0 0} do_test version-1.10 { execsql { INSERT INTO t2 SELECT x*3, x*2, x FROM t1; SELECT * FROM t2; } } {3 2 1 6 4 2 9 6 3 12 8 4 15 10 5 18 12 6 21 14 7 24 16 8} do_test version-1.11 { execsql { SELECT * FROM cnt; } } {t1 8 0 t2 8 0} # Here we do the upgrade test. # do_test version-1.12 { db close set m2 [lreplace $::meta 2 2 2] btree_begin_transaction $::bt eval btree_update_meta $::bt $m2 btree_commit $::bt sqlite db test.db execsql { SELECT * FROM cnt; } } {t1 8 0 t2 8 0} do_test version-1.13 { execsql { SELECT * FROM v1; } } {101 102 103 104 105 106 107 108} do_test version-1.14 { execsql { SELECT * FROM v2; } } {16 0} finish_test |