Fossil

Check-in [94f4c0aa]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:On-the-fly schema updates. No "fossil rebuild" needed when moving to Fossil 2.0.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fossil-2.0
Files: files | file ages | folders
SHA1:94f4c0aab5678f83f82e5ee44876acd606a48d7c
User & Date: drh 2017-02-28 14:14:32
Context
2017-02-28
16:25
Refactoring and cleanup of some of the hash name interfaces. check-in: 1c8768b0 user: drh tags: fossil-2.0
14:14
On-the-fly schema updates. No "fossil rebuild" needed when moving to Fossil 2.0. check-in: 94f4c0aa user: drh tags: fossil-2.0
10:12
Update the change log for version 2.0. check-in: 89077b05 user: drh tags: fossil-2.0
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/db.c.

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513


1514
1515
1516
1517
1518
1519
1520
  db_open_or_attach(g.zRepositoryName, "repository");
  g.repositoryOpen = 1;
  /* Cache "allow-symlinks" option, because we'll need it on every stat call */
  g.allowSymlinks = db_get_boolean("allow-symlinks",
                                   db_allow_symlinks_by_default());
  g.zAuxSchema = db_get("aux-schema","");

  /* Verify that the PLINK table has a new column added by the
  ** 2014-11-28 schema change.  Create it if necessary.  This code
  ** can be removed in the future, once all users have upgraded to the
  ** 2014-11-28 or later schema.
  */
  if( !db_table_has_column("repository","plink","baseid") ){
    db_multi_exec(
      "ALTER TABLE repository.plink ADD COLUMN baseid;"
    );
  }

  /* Verify that the MLINK table has the newer columns added by the
  ** 2015-01-24 schema change.  Create them if necessary.  This code
  ** can be removed in the future, once all users have upgraded to the
  ** 2015-01-24 or later schema.
  */
  if( !db_table_has_column("repository","mlink","isaux") ){
    db_begin_transaction();
    db_multi_exec(
      "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
      "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
    );
    db_end_transaction(0);


  }
}

/*
** Flags for the db_find_and_open_repository() function.
*/
#if INTERFACE







|
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>







1484
1485
1486
1487
1488
1489
1490
1491
1492


1493


















1494
1495
1496
1497
1498
1499
1500
1501
1502
  db_open_or_attach(g.zRepositoryName, "repository");
  g.repositoryOpen = 1;
  /* Cache "allow-symlinks" option, because we'll need it on every stat call */
  g.allowSymlinks = db_get_boolean("allow-symlinks",
                                   db_allow_symlinks_by_default());
  g.zAuxSchema = db_get("aux-schema","");

  /* If the ALIAS table is not present, then some on-the-fly schema
  ** updates might be required.


  */


















  if( !db_table_exists("repository","alias") ){
    rebuild_schema_update_2_0();   /* Do the Fossil-2.0 schema updates */
  }
}

/*
** Flags for the db_find_and_open_repository() function.
*/
#if INTERFACE

Changes to src/rebuild.c.

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
...
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
170
171
172
173

























174
175
176
177
178
179
180
181
182
183
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
** This file contains code used to rebuild the database.
*/
#include "config.h"
#include "rebuild.h"
#include <assert.h>
#include <errno.h>

/*
** Make changes to the stable part of the schema (the part that is not
** simply deleted and reconstructed on a rebuild) to bring the schema
** up to the latest.
*/


static const char zSchemaUpdates1[] =
@ -- Index on the delta table
@ --
@ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
@


@ -- Artifacts that should not be processed are identified in the
@ -- "shun" table.  Artifacts that are control-file forgeries or
@ -- spam or artifacts whose contents violate administrative policy
@ -- can be shunned in order to prevent them from contaminating
@ -- the repository.
@ --
@ -- Shunned artifacts do not exist in the blob table.  Hence they
@ -- have not artifact ID (rid) and we thus must store their full
@ -- UUID.
@ --
@ CREATE TABLE IF NOT EXISTS shun(
@   uuid UNIQUE,          -- UUID of artifact to be shunned. Canonical form
@   mtime INTEGER,        -- When added.  Seconds since 1970
@   scom TEXT             -- Optional text explaining why the shun occurred
@ );

@
@ -- Artifacts that should not be pushed are stored in the "private"
@ -- table.
@ --
@ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
@
@ -- Some ticket content (such as the originators email address or contact
@ -- information) needs to be obscured to protect privacy.  This is achieved
@ -- by storing an SHA1 hash of the content.  For display, the hash is
@ -- mapped back into the original text using this table.
@ --
@ -- This table contains sensitive information and should not be shared
@ -- with unauthorized users.
@ --
@ CREATE TABLE IF NOT EXISTS concealed(
@   hash TEXT PRIMARY KEY,    -- The SHA1 hash of content
@   mtime INTEGER,            -- Time created.  Seconds since 1970
@   content TEXT              -- Content intended to be concealed










@ );
;
static const char zSchemaUpdates2[] =
@ -- An entry in this table describes a database query that generates a
@ -- table of tickets.
@ --
@ CREATE TABLE IF NOT EXISTS reportfmt(
@    rn INTEGER PRIMARY KEY,  -- Report number
@    owner TEXT,              -- Owner of this report format (not used)
@    title TEXT UNIQUE,       -- Title of this report
@    mtime INTEGER,           -- Time last modified.  Seconds since 1970
@    cols TEXT,               -- A color-key specification
@    sqlcode TEXT             -- An SQL SELECT statement for this report
@ );
;
static const char zSchemaUpdate3[] =
@ -- Make sure the alias table exists.
@ --
@ CREATE TABLE repository.alias(
@   hval TEXT,                      -- Hex-encoded hash value
@   htype ANY,                      -- Type of hash.
@   rid INTEGER REFERENCES blob,    -- Blob that this hash names
@   PRIMARY KEY(hval,htype,rid)
@ ) WITHOUT ROWID;
@ CREATE INDEX alias_rid ON alias(rid);
;


/*
** Update the schema as necessary
*/
static void rebuild_update_schema(void){
  int rc;
  char *z;
  db_multi_exec("%s", zSchemaUpdates1 /*safe-for-%s*/);
  db_multi_exec("%s", zSchemaUpdates2 /*safe-for-%s*/);

  /* Add the user.mtime column if it is missing.
  */
  if( !db_table_has_column("repository", "user", "mtime") ){
    db_multi_exec(
      "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
      "DROP TABLE user;"
      "CREATE TABLE user(\n"
      "  uid INTEGER PRIMARY KEY,\n"
................................................................................
      "INSERT OR IGNORE INTO user"
        " SELECT uid, login, pw, cap, cookie,"
               " ipaddr, cexpire, info, now(), photo FROM temp_user;"
      "DROP TABLE temp_user;"
    );
  }

  /* Add the config.mtime column if it is missing.
  */
  if( !db_table_has_column("repository", "config", "mtime") ){
    db_multi_exec(
      "ALTER TABLE config ADD COLUMN mtime INTEGER;"
      "UPDATE config SET mtime=now();"
    );
  }

  /* Add the shun.mtime and shun.scom columns if they are missing.

  */
  if( !db_table_has_column("repository", "shun", "mtime") ){
    db_multi_exec(
      "ALTER TABLE shun ADD COLUMN mtime INTEGER;"
      "ALTER TABLE shun ADD COLUMN scom TEXT;"
      "UPDATE shun SET mtime=now();"
    );
  }

  /* Add the reportfmt.mtime column if it is missing.
  */
  if( !db_table_has_column("repository", "reportfmt", "mtime") ){













    db_multi_exec(
      "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
      "DROP TABLE reportfmt;"
    );
    db_multi_exec("%s", zSchemaUpdates2/*safe-for-%s*/);
    db_multi_exec(
      "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
        " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
      "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
        " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
        "   FROM old_fmt;"
    );
  }

  /* Add the concealed.mtime column if it is missing.
  */
  if( !db_table_has_column("repository", "concealed", "mtime") ){
    db_multi_exec(
      "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
      "UPDATE concealed SET mtime=now();"
    );
  }


























  /* If the alias table is missing, create it. */
  if( !db_table_exists("repository", "alias") ){
    db_multi_exec("%s", zSchemaUpdate3/*safe-for-%s*/);
  }

  /* Make sure the CHECK constraint on the BLOB table says "length(uuid)>=40"
  ** instead of "length(uuid)==40". */
  z = db_text(0, "SELECT sql FROM repository.sqlite_master WHERE"
                 " name LIKE 'blob' AND sql LIKE '%%length(uuid)==40%%'");
  if( z ){
................................................................................
           z
        );
        break;
      }
    }
    fossil_free(z);
  }
      
}

/*
** Variables used to store state information about an on-going "rebuild"
** or "deconstruct".
*/
static int totalSize;       /* Total number of artifacts to process */








|
<
<

>
>
|
|
|
<
<
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
<
<
<
<
<
<
<
<

|







 







|









>









|


>
>
>
>
>
>
>
>
>
>
>
>
>




|









|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







 







<







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
..
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
170
171
172
...
183
184
185
186
187
188
189

190
191
192
193
194
195
196
** This file contains code used to rebuild the database.
*/
#include "config.h"
#include "rebuild.h"
#include <assert.h>
#include <errno.h>

/*
** Update the schema as necessary


*/
static void rebuild_update_schema(void){
  /* Verify that the PLINK table has a new column added by the
  ** 2014-11-28 schema change.  Create it if necessary.  This code
  ** can be removed in the future, once all users have upgraded to the
  ** 2014-11-28 or later schema.


  */
  if( !db_table_has_column("repository","plink","baseid") ){
    db_multi_exec(
      "ALTER TABLE repository.plink ADD COLUMN baseid;"












    );
  }


















  /* Verify that the MLINK table has the newer columns added by the
  ** 2015-01-24 schema change.  Create them if necessary.  This code
  ** can be removed in the future, once all users have upgraded to the
  ** 2015-01-24 or later schema.
  */
  if( !db_table_has_column("repository","mlink","isaux") ){
    db_begin_transaction();
    db_multi_exec(
      "ALTER TABLE repository.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
      "ALTER TABLE repository.mlink ADD COLUMN isaux BOOLEAN DEFAULT 0;"
    );

























    db_end_transaction(0);
  }









  /* Add the user.mtime column if it is missing. (2011-04-27)
  */
  if( !db_table_has_column("repository", "user", "mtime") ){
    db_multi_exec(
      "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
      "DROP TABLE user;"
      "CREATE TABLE user(\n"
      "  uid INTEGER PRIMARY KEY,\n"
................................................................................
      "INSERT OR IGNORE INTO user"
        " SELECT uid, login, pw, cap, cookie,"
               " ipaddr, cexpire, info, now(), photo FROM temp_user;"
      "DROP TABLE temp_user;"
    );
  }

  /* Add the config.mtime column if it is missing.  (2011-04-27)
  */
  if( !db_table_has_column("repository", "config", "mtime") ){
    db_multi_exec(
      "ALTER TABLE config ADD COLUMN mtime INTEGER;"
      "UPDATE config SET mtime=now();"
    );
  }

  /* Add the shun.mtime and shun.scom columns if they are missing.
  ** (2011-04-27)
  */
  if( !db_table_has_column("repository", "shun", "mtime") ){
    db_multi_exec(
      "ALTER TABLE shun ADD COLUMN mtime INTEGER;"
      "ALTER TABLE shun ADD COLUMN scom TEXT;"
      "UPDATE shun SET mtime=now();"
    );
  }

  /* Add the reportfmt.mtime column if it is missing. (2011-04-27)
  */
  if( !db_table_has_column("repository", "reportfmt", "mtime") ){
    static const char zCreateReportFmtTable[] =
    @ -- An entry in this table describes a database query that generates a
    @ -- table of tickets.
    @ --
    @ CREATE TABLE IF NOT EXISTS reportfmt(
    @    rn INTEGER PRIMARY KEY,  -- Report number
    @    owner TEXT,              -- Owner of this report format (not used)
    @    title TEXT UNIQUE,       -- Title of this report
    @    mtime INTEGER,           -- Time last modified.  Seconds since 1970
    @    cols TEXT,               -- A color-key specification
    @    sqlcode TEXT             -- An SQL SELECT statement for this report
    @ );
    ;
    db_multi_exec(
      "CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
      "DROP TABLE reportfmt;"
    );
    db_multi_exec("%s", zCreateReportFmtTable/*safe-for-%s*/);
    db_multi_exec(
      "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
        " SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
      "INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
        " SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
        "   FROM old_fmt;"
    );
  }

  /* Add the concealed.mtime column if it is missing. (2011-04-27)
  */
  if( !db_table_has_column("repository", "concealed", "mtime") ){
    db_multi_exec(
      "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
      "UPDATE concealed SET mtime=now();"
    );
  }

  /* Do the fossil-2.0 updates to the schema.  (2017-02-28)
  */
  rebuild_schema_update_2_0();
}

/*
** Update the repository schema for Fossil version 2.0.  (2017-02-28)
**   (1) Create the ALIAS table
**   (2) Change the CHECK constraint on BLOB.UUID so that the length
**       is greater than or equal to 40, not exactly equal to 40.
*/
void rebuild_schema_update_2_0(void){
  static const char zCreateAliasTable[] =
  @ -- Make sure the alias table exists.
  @ --
  @ CREATE TABLE repository.alias(
  @   hval TEXT,                      -- Hex-encoded hash value
  @   htype ANY,                      -- Type of hash.
  @   rid INTEGER REFERENCES blob,    -- Blob that this hash names
  @   PRIMARY KEY(hval,htype,rid)
  @ ) WITHOUT ROWID;
  @ CREATE INDEX repository.alias_rid ON alias(rid);
  ;
  char *z;
   
  /* If the alias table is missing, create it. */
  if( !db_table_exists("repository", "alias") ){
    db_multi_exec("%s", zCreateAliasTable/*safe-for-%s*/);
  }

  /* Make sure the CHECK constraint on the BLOB table says "length(uuid)>=40"
  ** instead of "length(uuid)==40". */
  z = db_text(0, "SELECT sql FROM repository.sqlite_master WHERE"
                 " name LIKE 'blob' AND sql LIKE '%%length(uuid)==40%%'");
  if( z ){
................................................................................
           z
        );
        break;
      }
    }
    fossil_free(z);
  }

}

/*
** Variables used to store state information about an on-going "rebuild"
** or "deconstruct".
*/
static int totalSize;       /* Total number of artifacts to process */