20230521105850_emoji_empty_domain_fix.go (3960B)
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 "github.com/uptrace/bun/dialect" 26 ) 27 28 func init() { 29 up := func(ctx context.Context, db *bun.DB) error { 30 return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { 31 // SQLite doesn't mind creating multiple constraints with 32 // the same name, but Postgres balks at it, so remove 33 // constraints before we go editing the emoji tables. 34 if tx.Dialect().Name() == dialect.PG { 35 for _, constraint := range []string{ 36 "shortcodedomain", // initial constraint name 37 "domainshortcode", // later constraint name 38 } { 39 if _, err := tx.ExecContext( 40 ctx, 41 "ALTER TABLE ? DROP CONSTRAINT IF EXISTS ?", 42 bun.Ident("emojis"), 43 bun.Safe(constraint), 44 ); err != nil { 45 return err 46 } 47 } 48 } 49 50 // Set all existing emoji domains to null 51 // where domain is '', to fix the bug! 52 if _, err := tx. 53 NewUpdate(). 54 Table("emojis"). 55 Set("? = NULL", bun.Ident("domain")). 56 Where("? = ?", bun.Ident("domain"), ""). 57 Exec(ctx); err != nil { 58 return err 59 } 60 61 // Create the new emojis table. 62 if _, err := tx. 63 NewCreateTable(). 64 ModelTableExpr("new_emojis"). 65 Model(>smodel.Emoji{}). 66 Exec(ctx); err != nil { 67 return err 68 } 69 70 // Specify columns explicitly to 71 // avoid any Postgres shenanigans. 72 columns := []string{ 73 "id", 74 "created_at", 75 "updated_at", 76 "shortcode", 77 "domain", 78 "image_remote_url", 79 "image_static_remote_url", 80 "image_url", 81 "image_static_url", 82 "image_path", 83 "image_static_path", 84 "image_content_type", 85 "image_static_content_type", 86 "image_file_size", 87 "image_static_file_size", 88 "image_updated_at", 89 "disabled", 90 "uri", 91 "visible_in_picker", 92 "category_id", 93 } 94 95 // Copy existing emojis to the new table. 96 if _, err := tx. 97 NewInsert(). 98 Table("new_emojis"). 99 Table("emojis"). 100 Column(columns...). 101 Exec(ctx); err != nil { 102 return err 103 } 104 105 // Drop the old table. 106 if _, err := tx. 107 NewDropTable(). 108 Table("emojis"). 109 Exec(ctx); err != nil { 110 return err 111 } 112 113 // Rename new table to old table. 114 if _, err := tx. 115 ExecContext( 116 ctx, 117 "ALTER TABLE ? RENAME TO ?", 118 bun.Ident("new_emojis"), 119 bun.Ident("emojis"), 120 ); err != nil { 121 return err 122 } 123 124 // Add indexes to the new table. 125 for index, columns := range map[string][]string{ 126 "emojis_id_idx": {"id"}, 127 "emojis_available_custom_idx": {"visible_in_picker", "disabled", "shortcode"}, 128 "emojis_image_static_url_idx": {"image_static_url"}, 129 "emojis_uri_idx": {"uri"}, 130 } { 131 if _, err := tx. 132 NewCreateIndex(). 133 Table("emojis"). 134 Index(index). 135 Column(columns...). 136 Exec(ctx); err != nil { 137 return err 138 } 139 } 140 141 return nil 142 }) 143 } 144 145 down := func(ctx context.Context, db *bun.DB) error { 146 return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { 147 return nil 148 }) 149 } 150 151 if err := Migrations.Register(up, down); err != nil { 152 panic(err) 153 } 154 }