diff --git a/pkg/migration/20221113170740.go b/pkg/migration/20221113170740.go new file mode 100644 index 000000000..ff3a60210 --- /dev/null +++ b/pkg/migration/20221113170740.go @@ -0,0 +1,432 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package migration + +import ( + "src.techknowlogick.com/xormigrate" + "xorm.io/xorm" + "xorm.io/xorm/schemas" +) + +const sqliteRename20221113170740 = ` +-- buckets +create table buckets_dg_tmp +( + id INTEGER not null + primary key autoincrement, + title TEXT not null, + project_id INTEGER not null, + "limit" INTEGER default 0, + is_done_bucket INTEGER, + position REAL, + created DATETIME not null, + updated DATETIME not null, + created_by_id INTEGER not null +); + +insert into buckets_dg_tmp(id, title, project_id, "limit", is_done_bucket, position, created, updated, created_by_id) +select id, + title, + list_id, + "limit", + is_done_bucket, + position, + created, + updated, + created_by_id +from buckets; + +drop table buckets; + +alter table buckets_dg_tmp + rename to buckets; + +create unique index UQE_buckets_id + on buckets (id); + +-- link shares +create table link_shares_dg_tmp +( + id INTEGER not null + primary key autoincrement, + hash TEXT not null, + name TEXT, + project_id INTEGER not null, + "right" INTEGER default 0 not null, + sharing_type INTEGER default 0 not null, + password TEXT, + shared_by_id INTEGER not null, + created DATETIME not null, + updated DATETIME not null +); + +insert into link_shares_dg_tmp(id, hash, name, project_id, "right", sharing_type, password, shared_by_id, created, + updated) +select id, + hash, + name, + list_id, + "right", + sharing_type, + password, + shared_by_id, + created, + updated +from link_shares; + +drop table link_shares; + +alter table link_shares_dg_tmp + rename to link_shares; + +create index IDX_link_shares_right + on link_shares ("right"); + +create index IDX_link_shares_shared_by_id + on link_shares (shared_by_id); + +create index IDX_link_shares_sharing_type + on link_shares (sharing_type); + +create unique index UQE_link_shares_hash + on link_shares (hash); + +create unique index UQE_link_shares_id + on link_shares (id); + +-- tasks +create table tasks_dg_tmp +( + id INTEGER not null + primary key autoincrement, + title TEXT not null, + description TEXT, + done INTEGER, + done_at DATETIME, + due_date DATETIME, + project_id INTEGER not null, + repeat_after INTEGER, + repeat_mode INTEGER default 0 not null, + priority INTEGER, + start_date DATETIME, + end_date DATETIME, + hex_color TEXT, + percent_done REAL, + "index" INTEGER default 0 not null, + uid TEXT, + cover_image_attachment_id INTEGER default 0, + created DATETIME not null, + updated DATETIME not null, + bucket_id INTEGER, + position REAL, + kanban_position REAL, + created_by_id INTEGER not null +); + +insert into tasks_dg_tmp(id, title, description, done, done_at, due_date, project_id, repeat_after, repeat_mode, + priority, start_date, end_date, hex_color, percent_done, "index", uid, + cover_image_attachment_id, created, updated, bucket_id, position, kanban_position, + created_by_id) +select id, + title, + description, + done, + done_at, + due_date, + list_id, + repeat_after, + repeat_mode, + priority, + start_date, + end_date, + hex_color, + percent_done, + "index", + uid, + cover_image_attachment_id, + created, + updated, + bucket_id, + position, + kanban_position, + created_by_id +from tasks; + +drop table tasks; + +alter table tasks_dg_tmp + rename to tasks; + +create index IDX_tasks_done + on tasks (done); + +create index IDX_tasks_done_at + on tasks (done_at); + +create index IDX_tasks_due_date + on tasks (due_date); + +create index IDX_tasks_end_date + on tasks (end_date); + +create index IDX_tasks_list_id + on tasks (project_id); + +create index IDX_tasks_repeat_after + on tasks (repeat_after); + +create index IDX_tasks_start_date + on tasks (start_date); + +create unique index UQE_tasks_id + on tasks (id); + +--- team_lists +create table team_lists_dg_tmp +( + id INTEGER not null + primary key autoincrement, + team_id INTEGER not null, + project_id INTEGER not null, + "right" INTEGER default 0 not null, + created DATETIME not null, + updated DATETIME not null +); + +insert into team_lists_dg_tmp(id, team_id, project_id, "right", created, updated) +select id, team_id, list_id, "right", created, updated +from team_lists; + +drop table team_lists; + +alter table team_lists_dg_tmp + rename to team_lists; + +create index IDX_team_lists_list_id + on team_lists (project_id); + +create index IDX_team_lists_right + on team_lists ("right"); + +create index IDX_team_lists_team_id + on team_lists (team_id); + +create unique index UQE_team_lists_id + on team_lists (id); + +--- users +create table users_dg_tmp +( + id INTEGER not null + primary key autoincrement, + name TEXT, + username TEXT not null, + password TEXT, + email TEXT, + status INTEGER default 0, + avatar_provider TEXT, + avatar_file_id INTEGER, + issuer TEXT, + subject TEXT, + email_reminders_enabled INTEGER default 1, + discoverable_by_name INTEGER default 0, + discoverable_by_email INTEGER default 0, + overdue_tasks_reminders_enabled INTEGER default 1, + overdue_tasks_reminders_time TEXT default '09:00' not null, + default_project_id INTEGER, + week_start INTEGER, + language TEXT, + timezone TEXT, + deletion_scheduled_at DATETIME, + deletion_last_reminder_sent DATETIME, + export_file_id INTEGER, + created DATETIME not null, + updated DATETIME not null +); + +insert into users_dg_tmp(id, name, username, password, email, status, avatar_provider, avatar_file_id, issuer, subject, + email_reminders_enabled, discoverable_by_name, discoverable_by_email, + overdue_tasks_reminders_enabled, overdue_tasks_reminders_time, default_project_id, week_start, + language, timezone, deletion_scheduled_at, deletion_last_reminder_sent, export_file_id, + created, updated) +select id, + name, + username, + password, + email, + status, + avatar_provider, + avatar_file_id, + issuer, + subject, + email_reminders_enabled, + discoverable_by_name, + discoverable_by_email, + overdue_tasks_reminders_enabled, + overdue_tasks_reminders_time, + default_list_id, + week_start, + language, + timezone, + deletion_scheduled_at, + deletion_last_reminder_sent, + export_file_id, + created, + updated +from users; + +drop table users; + +alter table users_dg_tmp + rename to users; + +create index IDX_users_default_list_id + on users (default_project_id); + +create index IDX_users_discoverable_by_email + on users (discoverable_by_email); + +create index IDX_users_discoverable_by_name + on users (discoverable_by_name); + +create index IDX_users_overdue_tasks_reminders_enabled + on users (overdue_tasks_reminders_enabled); + +create unique index UQE_users_id + on users (id); + +create unique index UQE_users_username + on users (username); + +--- users_list +create table users_lists_dg_tmp +( + id INTEGER not null + primary key autoincrement, + user_id INTEGER not null, + project_id INTEGER not null, + "right" INTEGER default 0 not null, + created DATETIME not null, + updated DATETIME not null +); + +insert into users_lists_dg_tmp(id, user_id, project_id, "right", created, updated) +select id, user_id, list_id, "right", created, updated +from users_lists; + +drop table users_lists; + +alter table users_lists_dg_tmp + rename to users_lists; + +create index IDX_users_lists_list_id + on users_lists (project_id); + +create index IDX_users_lists_right + on users_lists ("right"); + +create index IDX_users_lists_user_id + on users_lists (user_id); + +create unique index UQE_users_lists_id + on users_lists (id); +` + +type colToRename struct { + table string + oldName string + newName string +} + +func init() { + migrations = append(migrations, &xormigrate.Migration{ + ID: "20221113170740", + Description: "Rename lists to projects", + Migrate: func(tx *xorm.Engine) error { + // SQLite does not support renaming columns. Instead, we'll need to run manual sql. + if tx.Dialect().URI().DBType == schemas.SQLITE { + _, err := tx.Exec(sqliteRename20221113170740) + if err != nil { + return err + } + } else { + + colsToRename := []*colToRename{ + { + table: "buckets", + oldName: "list_id", + newName: "project_id", + }, + { + table: "link_shares", + oldName: "list_id", + newName: "project_id", + }, + { + table: "tasks", + oldName: "list_id", + newName: "project_id", + }, + { + table: "team_lists", + oldName: "list_id", + newName: "project_id", + }, + { + table: "users", + oldName: "default_list_id", + newName: "default_project_id", + }, + { + table: "users_list", + oldName: "list_id", + newName: "project_id", + }, + } + + for _, col := range colsToRename { + if tx.Dialect().URI().DBType == schemas.POSTGRES || tx.Dialect().URI().DBType == schemas.MYSQL { + _, err := tx.Exec("ALTER TABLE `" + col.table + "` RENAME COLUMN `" + col.oldName + "` TO `" + col.newName + "`") + if err != nil { + return err + } + } + } + } + + err := renameTable(tx, "lists", "projects") + if err != nil { + return err + } + + err = renameTable(tx, "team_lists", "team_projects") + if err != nil { + return err + } + + err = renameTable(tx, "users_lists", "users_projects") + if err != nil { + return err + } + + return nil + }, + Rollback: func(tx *xorm.Engine) error { + return nil + }, + }) +}