upgradedb.go (view raw)
1//
2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
3//
4// Permission to use, copy, modify, and distribute this software for any
5// purpose with or without fee is hereby granted, provided that the above
6// copyright notice and this permission notice appear in all copies.
7//
8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16package main
17
18import (
19 "database/sql"
20 "os"
21 "strings"
22 "time"
23)
24
25var myVersion = 42
26
27type dbexecer interface {
28 Exec(query string, args ...interface{}) (sql.Result, error)
29}
30
31func doordie(db dbexecer, s string, args ...interface{}) {
32 _, err := db.Exec(s, args...)
33 if err != nil {
34 elog.Fatalf("can't run %s: %s", s, err)
35 }
36}
37
38func upgradedb() {
39 db := opendatabase()
40 dbversion := 0
41 getconfig("dbversion", &dbversion)
42 getconfig("servername", &serverName)
43
44 if dbversion < 13 {
45 elog.Fatal("database is too old to upgrade")
46 }
47 switch dbversion {
48 case 25:
49 doordie(db, "delete from auth")
50 doordie(db, "alter table auth add column expiry text")
51 doordie(db, "update config set value = 26 where key = 'dbversion'")
52 fallthrough
53 case 26:
54 s := ""
55 getconfig("servermsg", &s)
56 if s == "" {
57 setconfig("servermsg", "<h2>Things happen.</h2>")
58 }
59 s = ""
60 getconfig("aboutmsg", &s)
61 if s == "" {
62 setconfig("aboutmsg", "<h3>What is honk?</h3><p>Honk is amazing!")
63 }
64 s = ""
65 getconfig("loginmsg", &s)
66 if s == "" {
67 setconfig("loginmsg", "<h2>login</h2>")
68 }
69 d := -1
70 getconfig("devel", &d)
71 if d == -1 {
72 setconfig("devel", 0)
73 }
74 doordie(db, "update config set value = 27 where key = 'dbversion'")
75 fallthrough
76 case 27:
77 createserveruser(db)
78 doordie(db, "update config set value = 28 where key = 'dbversion'")
79 fallthrough
80 case 28:
81 doordie(db, "drop table doovers")
82 doordie(db, "create table doovers(dooverid integer primary key, dt text, tries integer, userid integer, rcpt text, msg blob)")
83 doordie(db, "update config set value = 29 where key = 'dbversion'")
84 fallthrough
85 case 29:
86 doordie(db, "alter table honkers add column owner text")
87 doordie(db, "update honkers set owner = xid")
88 doordie(db, "update config set value = 30 where key = 'dbversion'")
89 fallthrough
90 case 30:
91 tx, err := db.Begin()
92 if err != nil {
93 elog.Fatal(err)
94 }
95 rows, err := tx.Query("select userid, options from users")
96 if err != nil {
97 elog.Fatal(err)
98 }
99 m := make(map[int64]string)
100 for rows.Next() {
101 var userid int64
102 var options string
103 err = rows.Scan(&userid, &options)
104 if err != nil {
105 elog.Fatal(err)
106 }
107 var uo UserOptions
108 uo.SkinnyCSS = strings.Contains(options, " skinny ")
109 m[userid], err = jsonify(uo)
110 if err != nil {
111 elog.Fatal(err)
112 }
113 }
114 rows.Close()
115 for u, o := range m {
116 _, err = tx.Exec("update users set options = ? where userid = ?", o, u)
117 if err != nil {
118 elog.Fatal(err)
119 }
120 }
121 err = tx.Commit()
122 if err != nil {
123 elog.Fatal(err)
124 }
125 doordie(db, "update config set value = 31 where key = 'dbversion'")
126 fallthrough
127 case 31:
128 doordie(db, "create table tracks (xid text, fetches text)")
129 doordie(db, "create index idx_trackhonkid on tracks(xid)")
130 doordie(db, "update config set value = 32 where key = 'dbversion'")
131 fallthrough
132 case 32:
133 doordie(db, "alter table xonkers add column dt text")
134 doordie(db, "update xonkers set dt = ?", time.Now().UTC().Format(dbtimeformat))
135 doordie(db, "update config set value = 33 where key = 'dbversion'")
136 fallthrough
137 case 33:
138 doordie(db, "alter table honkers add column meta text")
139 doordie(db, "update honkers set meta = '{}'")
140 doordie(db, "update config set value = 34 where key = 'dbversion'")
141 fallthrough
142 case 34:
143 doordie(db, "create table chonks (chonkid integer primary key, userid integer, xid text, who txt, target text, dt text, noise text, format text)")
144 doordie(db, "update config set value = 35 where key = 'dbversion'")
145 fallthrough
146 case 35:
147 doordie(db, "alter table donks add column chonkid integer")
148 doordie(db, "update donks set chonkid = -1")
149 doordie(db, "create index idx_donkshonk on donks(honkid)")
150 doordie(db, "create index idx_donkschonk on donks(chonkid)")
151 doordie(db, "update config set value = 36 where key = 'dbversion'")
152 fallthrough
153 case 36:
154 doordie(db, "alter table honkers add column folxid text")
155 doordie(db, "update honkers set folxid = 'lostdata'")
156 doordie(db, "update config set value = 37 where key = 'dbversion'")
157 fallthrough
158 case 37:
159 doordie(db, "update honkers set combos = '' where combos is null")
160 doordie(db, "update honkers set owner = '' where owner is null")
161 doordie(db, "update honkers set meta = '' where meta is null")
162 doordie(db, "update honkers set folxid = '' where folxid is null")
163 doordie(db, "update config set value = 38 where key = 'dbversion'")
164 fallthrough
165 case 38:
166 doordie(db, "update honkers set folxid = abs(random())")
167 doordie(db, "update config set value = 39 where key = 'dbversion'")
168 fallthrough
169 case 39:
170 blobdb := openblobdb()
171 doordie(blobdb, "alter table filedata add column hash text")
172 doordie(blobdb, "create index idx_filehash on filedata(hash)")
173 rows, err := blobdb.Query("select xid, content from filedata")
174 if err != nil {
175 elog.Fatal(err)
176 }
177 m := make(map[string]string)
178 for rows.Next() {
179 var xid string
180 var data sql.RawBytes
181 err := rows.Scan(&xid, &data)
182 if err != nil {
183 elog.Fatal(err)
184 }
185 hash := hashfiledata(data)
186 m[xid] = hash
187 }
188 rows.Close()
189 tx, err := blobdb.Begin()
190 if err != nil {
191 elog.Fatal(err)
192 }
193 for xid, hash := range m {
194 doordie(tx, "update filedata set hash = ? where xid = ?", hash, xid)
195 }
196 err = tx.Commit()
197 if err != nil {
198 elog.Fatal(err)
199 }
200 doordie(db, "update config set value = 40 where key = 'dbversion'")
201 fallthrough
202 case 40:
203 doordie(db, "PRAGMA journal_mode=WAL")
204 blobdb := openblobdb()
205 doordie(blobdb, "PRAGMA journal_mode=WAL")
206 doordie(db, "update config set value = 41 where key = 'dbversion'")
207 fallthrough
208 case 41:
209 tx, err := db.Begin()
210 if err != nil {
211 elog.Fatal(err)
212 }
213 rows, err := tx.Query("select honkid, noise from honks where format = 'markdown' and precis <> ''")
214 if err != nil {
215 elog.Fatal(err)
216 }
217 m := make(map[int64]string)
218 var dummy Honk
219 for rows.Next() {
220 err = rows.Scan(&dummy.ID, &dummy.Noise)
221 if err != nil {
222 elog.Fatal(err)
223 }
224 precipitate(&dummy)
225 m[dummy.ID] = dummy.Noise
226 }
227 rows.Close()
228 for id, noise := range m {
229 _, err = tx.Exec("update honks set noise = ? where honkid = ?", noise, id)
230 if err != nil {
231 elog.Fatal(err)
232 }
233 }
234 err = tx.Commit()
235 if err != nil {
236 elog.Fatal(err)
237 }
238 doordie(db, "update config set value = 42 where key = 'dbversion'")
239 fallthrough
240 case 42:
241
242 default:
243 elog.Fatalf("can't upgrade unknown version %d", dbversion)
244 }
245 os.Exit(0)
246}