SQLite

Check-in [0493e39c1c]
Login

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: 0493e39c1cbbe4a38e990a2370181a79606af222
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
Unified Diff Ignore Whitespace Patch
Changes to src/main.c.
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.87 2002/07/18 00:34:12 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the







|







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
244
245
246
247
248
249
250
251
  */
  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);
    rc = SQLITE_ERROR;
  }

  /* Read the schema information out of the schema tables
  */
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.pBe = db->pBe;







|







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