all repos — honk @ 4e677416490459a50a90d3254867b208a2ef0164

my fork of honk

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
 23	"humungus.tedunangst.com/r/webs/htfilter"
 24)
 25
 26var myVersion = 48 // chat keys
 27
 28type dbexecer interface {
 29	Exec(query string, args ...interface{}) (sql.Result, error)
 30}
 31
 32func doordie(db dbexecer, s string, args ...interface{}) {
 33	_, err := db.Exec(s, args...)
 34	if err != nil {
 35		elog.Fatalf("can't run %s: %s", s, err)
 36	}
 37}
 38
 39func upgradedb() {
 40	db := opendatabase()
 41	dbversion := 0
 42	getconfig("dbversion", &dbversion)
 43	getconfig("servername", &serverName)
 44
 45	if dbversion < 40 {
 46		elog.Fatal("database is too old to upgrade")
 47	}
 48	var err error
 49	var tx *sql.Tx
 50	try := func(s string, args ...interface{}) *sql.Rows {
 51		var rows *sql.Rows
 52		if strings.HasPrefix(s, "select") {
 53			if tx != nil {
 54				rows, err = tx.Query(s, args...)
 55			} else {
 56				rows, err = db.Query(s, args...)
 57			}
 58		} else {
 59			if tx != nil {
 60				_, err = tx.Exec(s, args...)
 61			} else {
 62				_, err = db.Exec(s, args...)
 63			}
 64		}
 65		if err != nil {
 66			elog.Fatalf("can't run %s: %s", s, err)
 67		}
 68		return rows
 69	}
 70	setV := func(ver int64) {
 71		try("update config set value = ? where key = 'dbversion'", ver)
 72	}
 73
 74	switch dbversion {
 75	case 41:
 76		tx, err := db.Begin()
 77		if err != nil {
 78			elog.Fatal(err)
 79		}
 80		rows, err := tx.Query("select honkid, noise from honks where format = 'markdown' and precis <> ''")
 81		if err != nil {
 82			elog.Fatal(err)
 83		}
 84		m := make(map[int64]string)
 85		var dummy Honk
 86		for rows.Next() {
 87			err = rows.Scan(&dummy.ID, &dummy.Noise)
 88			if err != nil {
 89				elog.Fatal(err)
 90			}
 91			precipitate(&dummy)
 92			m[dummy.ID] = dummy.Noise
 93		}
 94		rows.Close()
 95		for id, noise := range m {
 96			_, err = tx.Exec("update honks set noise = ? where honkid = ?", noise, id)
 97			if err != nil {
 98				elog.Fatal(err)
 99			}
100		}
101		err = tx.Commit()
102		if err != nil {
103			elog.Fatal(err)
104		}
105		doordie(db, "update config set value = 42 where key = 'dbversion'")
106		fallthrough
107	case 42:
108		doordie(db, "update honks set what = 'honk', flags = flags & ~ 32 where what = 'tonk' or what = 'wonk'")
109		doordie(db, "delete from honkmeta where genus = 'wonkles' or genus = 'guesses'")
110		doordie(db, "update config set value = 43 where key = 'dbversion'")
111		fallthrough
112	case 43:
113		try("alter table honks add column plain text")
114		try("update honks set plain = ''")
115		setV(44)
116		fallthrough
117	case 44:
118		makeplain := func(noise, precis, format string) []string {
119			var plain []string
120			var filt htfilter.Filter
121			filt.WithLinks = true
122			if precis != "" {
123				t, _ := filt.TextOnly(precis)
124				plain = append(plain, t)
125			}
126			if format == "html" {
127				t, _ := filt.TextOnly(noise)
128				plain = append(plain, t)
129			} else {
130				plain = append(plain, noise)
131			}
132			return plain
133		}
134		tx, err = db.Begin()
135		if err != nil {
136			elog.Fatal(err)
137		}
138		plainmap := make(map[int64][]string)
139		rows, err := tx.Query("select honkid, noise, precis, format from honks")
140		if err != nil {
141			elog.Fatal(err)
142		}
143		for rows.Next() {
144			var honkid int64
145			var noise, precis, format string
146			err = rows.Scan(&honkid, &noise, &precis, &format)
147			if err != nil {
148				elog.Fatal(err)
149			}
150			plainmap[honkid] = makeplain(noise, precis, format)
151		}
152		rows.Close()
153		rows, err = tx.Query("select honkid, name, description from donks join filemeta on donks.fileid = filemeta.fileid")
154		if err != nil {
155			elog.Fatal(err)
156		}
157		for rows.Next() {
158			var honkid int64
159			var name, desc string
160			err = rows.Scan(&honkid, &name, &desc)
161			if err != nil {
162				elog.Fatal(err)
163			}
164			plainmap[honkid] = append(plainmap[honkid], name)
165			plainmap[honkid] = append(plainmap[honkid], desc)
166		}
167		rows.Close()
168		for honkid, plain := range plainmap {
169			try("update honks set plain = ? where honkid = ?", strings.Join(plain, " "), honkid)
170		}
171		setV(45)
172		err = tx.Commit()
173		if err != nil {
174			elog.Fatal(err)
175		}
176		tx = nil
177		fallthrough
178	case 45:
179		try("create index idx_honkswhotwo on honks(whofore) where whofore = 2")
180		setV(46)
181		fallthrough
182	case 46:
183		try("create index idx_honksforme on honks(whofore) where whofore = 1")
184		setV(47)
185		fallthrough
186	case 47:
187		rows := try("select userid, options from users where userid > 0")
188		var users []*WhatAbout
189		for rows.Next() {
190			var user WhatAbout
191			var jopt string
192			err = rows.Scan(&user.ID, &jopt)
193			if err != nil {
194				elog.Fatal(err)
195			}
196			err = unjsonify(jopt, &user.Options)
197			if err != nil {
198				elog.Fatal(err)
199			}
200			users = append(users, &user)
201		}
202		rows.Close()
203		for _, user := range users {
204			chatpubkey, chatseckey := newChatKeys()
205			user.Options.ChatPubKey = tob64(chatpubkey.key[:])
206			user.Options.ChatSecKey = tob64(chatseckey.key[:])
207			jopt, _ := jsonify(user.Options)
208			try("update users set options = ? where userid = ?", jopt, user.ID)
209		}
210		setV(48)
211		fallthrough
212	case 48:
213		try("analyze")
214		closedatabases()
215
216	default:
217		elog.Fatalf("can't upgrade unknown version %d", dbversion)
218	}
219	os.Exit(0)
220}