diff --git a/migration/titles.5.cr b/migration/titles.5.cr new file mode 100644 index 0000000..fdf531f --- /dev/null +++ b/migration/titles.5.cr @@ -0,0 +1,59 @@ +class CreateTitles < MG::Base + def up : String + <<-SQL + -- create titles + CREATE TABLE titles ( + id TEXT NOT NULL, + path TEXT NOT NULL, + signature TEXT + ); + CREATE UNIQUE INDEX titles_id_idx on titles (id); + CREATE UNIQUE INDEX titles_path_idx on titles (path); + + -- migrate data from ids to titles + INSERT INTO titles + SELECT id, path, null + FROM ids + WHERE is_title = 1; + + DELETE FROM ids + WHERE is_title = 1; + + -- remove the is_title column from ids + ALTER TABLE ids RENAME TO tmp; + + CREATE TABLE ids ( + path TEXT NOT NULL, + id TEXT NOT NULL + ); + + INSERT INTO ids + SELECT path, id + FROM tmp; + + DROP TABLE tmp; + + -- recreate the indices + CREATE UNIQUE INDEX path_idx ON ids (path); + CREATE UNIQUE INDEX id_idx ON ids (id); + SQL + end + + def down : String + <<-SQL + -- insert the is_title column + ALTER TABLE ids ADD COLUMN is_title INTEGER NOT NULL; + + -- set is_title for all rows to 0 + UPDATE ids SET column = 0; + + -- migrate data from titles to ids + INSERT INTO ids + SELECT path, id, 1 + FROM titles; + + -- remove titles + DROP TABLE titles; + SQL + end +end diff --git a/src/storage.cr b/src/storage.cr index d2374f7..06ce534 100644 --- a/src/storage.cr +++ b/src/storage.cr @@ -15,9 +15,10 @@ def verify_password(hash, pw) end class Storage + @@insert_ids = [] of IDTuple + @path : String @db : DB::Database? - @insert_ids = [] of IDTuple alias IDTuple = NamedTuple(path: String, id: String, @@ -41,9 +42,10 @@ class Storage Log.setup "mg", severity MG::Migration.new(db).migrate rescue e + Logger.reset Logger.fatal "DB migration failed. #{e}" raise e - ensure + else Logger.reset end @@ -235,28 +237,38 @@ class Storage id = nil MainFiber.run do get_db do |db| - id = db.query_one? "select id from ids where path = (?)", path, - as: {String} + if is_title + id = db.query_one? "select id from titles where path = (?)", path, + as: String + else + id = db.query_one? "select id from ids where path = (?)", path, + as: String + end end end id end def insert_id(tp : IDTuple) - @insert_ids << tp + @@insert_ids << tp end def bulk_insert_ids MainFiber.run do get_db do |db| - db.transaction do |tx| - @insert_ids.each do |tp| - tx.connection.exec "insert into ids values (?, ?, ?)", tp[:path], - tp[:id], tp[:is_title] ? 1 : 0 + db.transaction do |tran| + conn = tran.connection + @@insert_ids.each do |tp| + if tp[:is_title] + conn.exec "insert into titles values (?, ?, null)", tp[:id], + tp[:path] + else + conn.exec "insert into ids values (?, ?)", tp[:path], tp[:id] + end end end end - @insert_ids.clear + @@insert_ids.clear end end