mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-02 19:16:23 -07:00
250 lines
7.5 KiB
Go
250 lines
7.5 KiB
Go
package gcupdate
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
|
|
"github.com/gochan-org/gochan/cmd/gochan-migration/internal/common"
|
|
"github.com/gochan-org/gochan/pkg/config"
|
|
"github.com/gochan-org/gochan/pkg/gcsql"
|
|
"github.com/gochan-org/gochan/pkg/gcutil"
|
|
)
|
|
|
|
func updateMysqlDB(ctx context.Context, db *gcsql.GCDB, tx *sql.Tx, sqlConfig *config.SQLConfig) error {
|
|
var query string
|
|
var dataType string
|
|
dbName := sqlConfig.DBname
|
|
|
|
wordfiltersTableExists, err := common.TableExists(ctx, db, tx, "DBPREFIXwordfilters", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if wordfiltersTableExists {
|
|
// wordfilters table is going to be migrated by the end of the update, but we want to make sure its legacy data is migrated first
|
|
// so it can be properly merged into the filter table
|
|
|
|
var numConstraints int
|
|
query = `SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
|
|
WHERE CONSTRAINT_NAME = 'wordfilters_board_id_fk'
|
|
AND TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'DBPREFIXwordfilters'`
|
|
|
|
if err = db.QueryRowContextSQL(ctx, tx, query, nil, []any{&numConstraints}); err != nil {
|
|
return err
|
|
}
|
|
if numConstraints > 0 {
|
|
query = `ALTER TABLE DBPREFIXwordfilters DROP FOREIGN KEY wordfilters_board_id_fk`
|
|
} else {
|
|
query = ""
|
|
}
|
|
dataType, err = common.ColumnType(ctx, db, tx, "board_dirs", "DBPREFIXwordfilters", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType == "" {
|
|
query = `ALTER TABLE DBPREFIXwordfilters ADD COLUMN board_dirs varchar(255) DEFAULT '*'`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
// Yay, collation! Everybody loves MySQL's default collation!
|
|
query = `ALTER DATABASE ` + dbName + ` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
query = `SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?`
|
|
rows, err := db.QueryContextSQL(ctx, tx, query, dbName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() {
|
|
rows.Close()
|
|
}()
|
|
var tableName string
|
|
for rows.Next() {
|
|
err = rows.Scan(&tableName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
query = `ALTER TABLE ` + tableName + ` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`
|
|
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err = rows.Close(); err != nil {
|
|
return err
|
|
}
|
|
dataType, err = common.ColumnType(ctx, db, tx, "ip", "DBPREFIXip_ban", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType != "" {
|
|
// add range_start and range_end columns
|
|
query = `ALTER TABLE DBPREFIXip_ban
|
|
ADD COLUMN IF NOT EXISTS range_start VARBINARY(16) NOT NULL,
|
|
ADD COLUMN IF NOT EXISTS range_end VARBINARY(16) NOT NULL`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
// convert ban IP string to IP range
|
|
if rows, err = db.QueryContextSQL(ctx, tx, `SELECT id, ip FROM DBPREFIXip_ban`); err != nil {
|
|
return err
|
|
}
|
|
var rangeStart, rangeEnd string
|
|
for rows.Next() {
|
|
var id int
|
|
var ipOrCIDR string
|
|
if err = rows.Scan(&id, &ipOrCIDR); err != nil {
|
|
return err
|
|
}
|
|
if rangeStart, rangeEnd, err = gcutil.ParseIPRange(ipOrCIDR); err != nil {
|
|
return err
|
|
}
|
|
query = `UPDATE DBPREFIXip_ban
|
|
SET range_start = INET6_ATON(?), range_end = INET6_ATON(?) WHERE id = ?`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query, rangeStart, rangeEnd, id); err != nil {
|
|
return err
|
|
}
|
|
query = `ALTER TABLE DBPREFIXip_ban DROP COLUMN IF EXISTS ip`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err = rows.Close(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Convert DBPREFIXposts.ip to from varchar to varbinary
|
|
dataType, err = common.ColumnType(ctx, db, tx, "ip", "DBPREFIXposts", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if common.IsStringType(dataType) {
|
|
// rename `ip` to a temporary column to then be removed
|
|
query = `ALTER TABLE DBPREFIXposts CHANGE ip ip_str varchar(45)`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
query = `ALTER TABLE DBPREFIXposts
|
|
ADD COLUMN IF NOT EXISTS ip VARBINARY(16) NOT NULL`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
// convert post IP VARCHAR(45) to VARBINARY(16)
|
|
query = `UPDATE DBPREFIXposts SET ip = INET6_ATON(ip_str)`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
query = `ALTER TABLE DBPREFIXposts DROP COLUMN IF EXISTS ip_str`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Convert DBPREFIXreports.ip to from varchar to varbinary
|
|
dataType, err = common.ColumnType(ctx, db, tx, "ip", "DBPREFIXreports", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if common.IsStringType(dataType) {
|
|
// rename `ip` to a temporary column to then be removed
|
|
query = `ALTER TABLE DBPREFIXreports CHANGE ip ip_str varchar(45)`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
query = `ALTER TABLE DBPREFIXreports
|
|
ADD COLUMN IF NOT EXISTS ip VARBINARY(16) NOT NULL`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
// convert report IP VARCHAR(45) to VARBINARY(16)
|
|
query = `UPDATE DBPREFIXreports SET ip = INET6_ATON(ip_str)`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
|
|
query = `ALTER TABLE DBPREFIXreports DROP COLUMN IF EXISTS ip_str`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// add flag column to DBPREFIXposts
|
|
dataType, err = common.ColumnType(ctx, db, tx, "flag", "DBPREFIXposts", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType == "" {
|
|
query = `ALTER TABLE DBPREFIXposts ADD COLUMN flag VARCHAR(45) NOT NULL DEFAULT ''`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// add country column to DBPREFIXposts
|
|
dataType, err = common.ColumnType(ctx, db, tx, "country", "DBPREFIXposts", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType == "" {
|
|
query = `ALTER TABLE DBPREFIXposts ADD COLUMN country VARCHAR(80) NOT NULL DEFAULT ''`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
fileBanTableExists, err := common.TableExists(ctx, db, tx, "DBPREFIXfile_ban", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if fileBanTableExists {
|
|
// file ban table is going to be migrated by the end of the update, but we want to make sure its legacy data is migrated first
|
|
// so it can be properly merged into the filter table
|
|
|
|
// add fingerprinter column to DBPREFIXfile_ban
|
|
dataType, err = common.ColumnType(ctx, db, tx, "fingerprinter", "DBPREFIXfile_ban", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType == "" {
|
|
query = `ALTER TABLE DBPREFIXfile_ban ADD COLUMN fingerprinter VARCHAR(64)`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// add ban_ip column to DBPREFIXfile_ban
|
|
dataType, err = common.ColumnType(ctx, db, tx, "ban_ip", "DBPREFIXfile_ban", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType == "" {
|
|
query = `ALTER TABLE DBPREFIXfile_ban ADD COLUMN ban_ip BOOL NOT NULL`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// add ban_ip_message column to DBPREFIXfile_ban
|
|
dataType, err = common.ColumnType(ctx, db, tx, "ban_ip_message", "DBPREFIXfile_ban", sqlConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if dataType == "" {
|
|
query = `ALTER TABLE DBPREFIXfile_ban ADD COLUMN ban_ip_message TEXT`
|
|
if _, err = db.ExecContextSQL(ctx, tx, query); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|