feat: 迁移订阅表字段,为用户认证方法添加软删除功能及索引,并调整 Docker Compose 中 MySQL 端口映射。
Build docker and publish / build (20.15.1) (push) Successful in 7m34s

This commit is contained in:
2026-03-15 01:47:01 -07:00
parent ad578883e4
commit 3db14ae472
4 changed files with 109 additions and 6 deletions
@@ -1,7 +1,53 @@
ALTER TABLE `subscribe`
ADD COLUMN `nodes` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Node IDs',
ADD COLUMN `node_tags` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Node Tags',
DROP COLUMN `server`,
DROP COLUMN `server_group`;
-- Add nodes column if not exists
SET @col_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'subscribe'
AND COLUMN_NAME = 'nodes');
SET @sql = IF(@col_exists = 0,
'ALTER TABLE `subscribe` ADD COLUMN `nodes` VARCHAR(255) NOT NULL DEFAULT '''' COMMENT ''Node IDs''',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Add node_tags column if not exists
SET @col_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'subscribe'
AND COLUMN_NAME = 'node_tags');
SET @sql = IF(@col_exists = 0,
'ALTER TABLE `subscribe` ADD COLUMN `node_tags` VARCHAR(255) NOT NULL DEFAULT '''' COMMENT ''Node Tags''',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop server column if exists
SET @col_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'subscribe'
AND COLUMN_NAME = 'server');
SET @sql = IF(@col_exists > 0,
'ALTER TABLE `subscribe` DROP COLUMN `server`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Drop server_group column if exists
SET @col_exists = (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'subscribe'
AND COLUMN_NAME = 'server_group');
SET @sql = IF(@col_exists > 0,
'ALTER TABLE `subscribe` DROP COLUMN `server_group`',
'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE IF EXISTS `server_rule_group`;
+53
View File
@@ -121,6 +121,25 @@ func EnsureSchemaCompatibility(ctx *svc.ServiceContext) error {
column: "status",
ddl: "ALTER TABLE `redemption_code` ADD COLUMN `status` TINYINT NOT NULL DEFAULT 1 COMMENT 'Status: 1=enabled, 0=disabled';",
},
{
table: "user_auth_methods",
column: "deleted_at",
ddl: "ALTER TABLE `user_auth_methods` ADD COLUMN `deleted_at` DATETIME(3) DEFAULT NULL COMMENT 'Deletion Time';",
},
}
// Index patches: ensure critical indexes exist
type schemaIndexPatch struct {
table string
index string
ddl string
}
indexPatches := []schemaIndexPatch{
{
table: "user_auth_methods",
index: "idx_user_deleted_at",
ddl: "CREATE INDEX `idx_user_deleted_at` ON `user_auth_methods` (`user_id`, `deleted_at`);",
},
}
for _, patch := range tablePatches {
@@ -159,6 +178,27 @@ func EnsureSchemaCompatibility(ctx *svc.ServiceContext) error {
logger.Infof("[SchemaCompat] added missing column: %s.%s", patch.table, patch.column)
}
for _, patch := range indexPatches {
tblExists, err := tableExists(ctx.DB, patch.table)
if err != nil {
return errors.Wrapf(err, "check table %s failed", patch.table)
}
if !tblExists {
continue
}
exists, err := indexExists(ctx.DB, patch.table, patch.index)
if err != nil {
return errors.Wrapf(err, "check index %s.%s failed", patch.table, patch.index)
}
if exists {
continue
}
if err = ctx.DB.Exec(patch.ddl).Error; err != nil {
return errors.Wrapf(err, "create index %s.%s failed", patch.table, patch.index)
}
logger.Infof("[SchemaCompat] created missing index: %s.%s", patch.table, patch.index)
}
return nil
}
@@ -184,6 +224,19 @@ func columnExists(db *gorm.DB, table, column string) (bool, error) {
return count > 0, nil
}
func indexExists(db *gorm.DB, table, index string) (bool, error) {
var count int64
err := db.Raw(
"SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND INDEX_NAME = ?",
table,
index,
).Scan(&count).Error
if err != nil {
return false, err
}
return count > 0, nil
}
func _schemaCompatDebug(table, column string) string {
if column == "" {
return table