all repos — honk @ v1.1.0

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 = 45
 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{}) {
 51		if tx != nil {
 52			_, err = tx.Exec(s, args...)
 53		} else {
 54			_, err = db.Exec(s, args...)
 55		}
 56		if err != nil {
 57			elog.Fatalf("can't run %s: %s", s, err)
 58		}
 59	}
 60	setV := func(ver int64) {
 61		try("update config set value = ? where key = 'dbversion'", ver)
 62	}
 63
 64	switch dbversion {
 65	case 40:
 66		doordie(db, "PRAGMA journal_mode=WAL")
 67		blobdb := openblobdb()
 68		doordie(blobdb, "PRAGMA journal_mode=WAL")
 69		doordie(db, "update config set value = 41 where key = 'dbversion'")
 70		fallthrough
 71	case 41:
 72		tx, err := db.Begin()
 73		if err != nil {
 74			elog.Fatal(err)
 75		}
 76		rows, err := tx.Query("select honkid, noise from honks where format = 'markdown' and precis <> ''")
 77		if err != nil {
 78			elog.Fatal(err)
 79		}
 80		m := make(map[int64]string)
 81		var dummy Honk
 82		for rows.Next() {
 83			err = rows.Scan(&dummy.ID, &dummy.Noise)
 84			if err != nil {
 85				elog.Fatal(err)
 86			}
 87			precipitate(&dummy)
 88			m[dummy.ID] = dummy.Noise
 89		}
 90		rows.Close()
 91		for id, noise := range m {
 92			_, err = tx.Exec("update honks set noise = ? where honkid = ?", noise, id)
 93			if err != nil {
 94				elog.Fatal(err)
 95			}
 96		}
 97		err = tx.Commit()
 98		if err != nil {
 99			elog.Fatal(err)
100		}
101		doordie(db, "update config set value = 42 where key = 'dbversion'")
102		fallthrough
103	case 42:
104		doordie(db, "update honks set what = 'honk', flags = flags & ~ 32 where what = 'tonk' or what = 'wonk'")
105		doordie(db, "delete from honkmeta where genus = 'wonkles' or genus = 'guesses'")
106		doordie(db, "update config set value = 43 where key = 'dbversion'")
107		fallthrough
108	case 43:
109		try("alter table honks add column plain text")
110		try("update honks set plain = ''")
111		setV(44)
112		fallthrough
113	case 44:
114		makeplain := func(noise, precis, format string) []string {
115			var plain []string
116			var filt htfilter.Filter
117			filt.WithLinks = true
118			if precis != "" {
119				t, _ := filt.TextOnly(precis)
120				plain = append(plain, t)
121			}
122			if format == "html" {
123				t, _ := filt.TextOnly(noise)
124				plain = append(plain, t)
125			} else {
126				plain = append(plain, noise)
127			}
128			return plain
129		}
130		tx, err = db.Begin()
131		if err != nil {
132			elog.Fatal(err)
133		}
134		plainmap := make(map[int64][]string)
135		rows, err := tx.Query("select honkid, noise, precis, format from honks")
136		if err != nil {
137			elog.Fatal(err)
138		}
139		for rows.Next() {
140			var honkid int64
141			var noise, precis, format string
142			err = rows.Scan(&honkid, &noise, &precis, &format)
143			if err != nil {
144				elog.Fatal(err)
145			}
146			plainmap[honkid] = makeplain(noise, precis, format)
147		}
148		rows.Close()
149		rows, err = tx.Query("select honkid, name, description from donks join filemeta on donks.fileid = filemeta.fileid")
150		if err != nil {
151			elog.Fatal(err)
152		}
153		for rows.Next() {
154			var honkid int64
155			var name, desc string
156			err = rows.Scan(&honkid, &name, &desc)
157			if err != nil {
158				elog.Fatal(err)
159			}
160			plainmap[honkid] = append(plainmap[honkid], name)
161			plainmap[honkid] = append(plainmap[honkid], desc)
162		}
163		rows.Close()
164		for honkid, plain := range plainmap {
165			try("update honks set plain = ? where honkid = ?", strings.Join(plain, " "), honkid)
166		}
167		setV(45)
168		err = tx.Commit()
169		if err != nil {
170			elog.Fatal(err)
171		}
172		tx = nil
173		fallthrough
174	case 45:
175		try("analyze")
176
177	default:
178		elog.Fatalf("can't upgrade unknown version %d", dbversion)
179	}
180	os.Exit(0)
181}