20230328203024_migration_fix.go (4442B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package migrations 19 20 import ( 21 "context" 22 23 "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 24 "github.com/uptrace/bun" 25 ) 26 27 func init() { 28 up := func(ctx context.Context, db *bun.DB) error { 29 // To update not null constraint on public key, we need to migrate accounts into a new table. 30 // See section 7 here: https://www.sqlite.org/lang_altertable.html 31 32 return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { 33 // Create the new accounts table. 34 if _, err := tx. 35 NewCreateTable(). 36 ModelTableExpr("new_accounts"). 37 Model(>smodel.Account{}). 38 Exec(ctx); err != nil { 39 return err 40 } 41 42 // If we don't specify columns explicitly, 43 // Postgres gives the following error when 44 // transferring accounts to new_accounts: 45 // 46 // ERROR: column "fetched_at" is of type timestamp with time zone but expression is of type character varying at character 35 47 // HINT: You will need to rewrite or cast the expression. 48 // 49 // Rather than do funky casting to fix this, 50 // it's simpler to just specify all columns. 51 columns := []string{ 52 "id", 53 "created_at", 54 "updated_at", 55 "fetched_at", 56 "username", 57 "domain", 58 "avatar_media_attachment_id", 59 "avatar_remote_url", 60 "header_media_attachment_id", 61 "header_remote_url", 62 "display_name", 63 "emojis", 64 "fields", 65 "note", 66 "note_raw", 67 "memorial", 68 "also_known_as", 69 "moved_to_account_id", 70 "bot", 71 "reason", 72 "locked", 73 "discoverable", 74 "privacy", 75 "sensitive", 76 "language", 77 "status_content_type", 78 "custom_css", 79 "uri", 80 "url", 81 "inbox_uri", 82 "shared_inbox_uri", 83 "outbox_uri", 84 "following_uri", 85 "followers_uri", 86 "featured_collection_uri", 87 "actor_type", 88 "private_key", 89 "public_key", 90 "public_key_uri", 91 "sensitized_at", 92 "silenced_at", 93 "suspended_at", 94 "hide_collections", 95 "suspension_origin", 96 "enable_rss", 97 } 98 99 // Copy all accounts to the new table. 100 if _, err := tx. 101 NewInsert(). 102 Table("new_accounts"). 103 Table("accounts"). 104 Column(columns...). 105 Exec(ctx); err != nil { 106 return err 107 } 108 109 // Drop the old table. 110 if _, err := tx. 111 NewDropTable(). 112 Table("accounts"). 113 Exec(ctx); err != nil { 114 return err 115 } 116 117 // Rename new table to old table. 118 if _, err := tx. 119 ExecContext( 120 ctx, 121 "ALTER TABLE ? RENAME TO ?", 122 bun.Ident("new_accounts"), 123 bun.Ident("accounts"), 124 ); err != nil { 125 return err 126 } 127 128 // Add all account indexes to the new table. 129 for index, columns := range map[string][]string{ 130 // Standard indices. 131 "accounts_id_idx": {"id"}, 132 "accounts_suspended_at_idx": {"suspended_at"}, 133 "accounts_domain_idx": {"domain"}, 134 "accounts_username_domain_idx": {"username", "domain"}, 135 // URI indices. 136 "accounts_uri_idx": {"uri"}, 137 "accounts_url_idx": {"url"}, 138 "accounts_inbox_uri_idx": {"inbox_uri"}, 139 "accounts_outbox_uri_idx": {"outbox_uri"}, 140 "accounts_followers_uri_idx": {"followers_uri"}, 141 "accounts_following_uri_idx": {"following_uri"}, 142 "accounts_public_key_uri_idx": {"public_key_uri"}, 143 } { 144 if _, err := tx. 145 NewCreateIndex(). 146 Table("accounts"). 147 Index(index). 148 Column(columns...). 149 Exec(ctx); err != nil { 150 return err 151 } 152 } 153 154 return nil 155 }) 156 } 157 158 down := func(ctx context.Context, db *bun.DB) error { 159 return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { 160 return nil 161 }) 162 } 163 164 if err := Migrations.Register(up, down); err != nil { 165 panic(err) 166 } 167 }