This is an automated email from the ASF dual-hosted git repository. klesh pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push: new e52ce1313 refactor(migrations): enhance file meta migration to check column existence and nullability before modification (#8565) e52ce1313 is described below commit e52ce13139c2e30ed0f40efe47ab6fdd239865fb Author: Bamboo <124539898+gosimplic...@users.noreply.github.com> AuthorDate: Mon Sep 22 11:10:01 2025 +0800 refactor(migrations): enhance file meta migration to check column existence and nullability before modification (#8565) * fix(jira): update epic collector to use new API endpoint and include all fields * fix(jira): enhance epic collector to dynamically select API endpoint based on JIRA version * fix(jira): update epic collector to use correct API endpoint for JIRA Cloud and Server versions * fix(jira): refactor epic collector to streamline API endpoint selection and enhance error handling * fix(jira): fix type for Jira issue descriptions * refactor(jira): update comment and worklog models to use FlexibleDescription type for comments * docs(jira): add ADF reference for FlexibleDescription type in issue model * refactor(migrations): enhance file meta migration to check column existence and nullability before modification --- .../migrationscripts/20250320_modify_file_meta.go | 77 ++++++++++++++++++++-- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/backend/plugins/q_dev/models/migrationscripts/20250320_modify_file_meta.go b/backend/plugins/q_dev/models/migrationscripts/20250320_modify_file_meta.go index d9d704273..9744f6d09 100644 --- a/backend/plugins/q_dev/models/migrationscripts/20250320_modify_file_meta.go +++ b/backend/plugins/q_dev/models/migrationscripts/20250320_modify_file_meta.go @@ -19,6 +19,7 @@ package migrationscripts import ( "github.com/apache/incubator-devlake/core/context" + "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" ) @@ -31,14 +32,78 @@ func (*modifyFileMetaTable) Name() string { func (*modifyFileMetaTable) Up(basicRes context.BasicRes) errors.Error { db := basicRes.GetDal() - // 修改 processed_time 列允许为 NULL - sql := "ALTER TABLE _tool_q_dev_s3_file_meta MODIFY processed_time DATETIME NULL" - err := db.Exec(sql) - if err != nil { - return errors.Default.Wrap(err, "failed to modify processed_time column") + // Target table and column + tableName := "_tool_q_dev_s3_file_meta" + columnName := "processed_time" + + // If column doesn't exist, no migration needed, idempotent + if !db.HasColumn(tableName, columnName) { + return nil } - return nil + // Read column metadata to check if already nullable, return idempotently if already nullable + var processedTimeNullable bool + { + cols, err := db.GetColumns(dal.DefaultTabler{Name: tableName}, func(cm dal.ColumnMeta) bool { + return cm.Name() == columnName + }) + if err != nil { + return errors.Default.Wrap(err, "failed to load column metadata for _tool_q_dev_s3_file_meta.processed_time") + } + if len(cols) == 0 { + // If column is not visible in metadata, treat as no processing needed + return nil + } + if nullable, ok := cols[0].Nullable(); ok { + processedTimeNullable = nullable + } + } + if processedTimeNullable { + return nil + } + + // Execute compatible SQL by dialect + switch db.Dialect() { + case "postgres": + // PostgreSQL makes column nullable via DROP NOT NULL, without changing data type + if err := db.Exec( + "ALTER TABLE ? ALTER COLUMN ? DROP NOT NULL", + dal.ClauseTable{Name: tableName}, + dal.ClauseColumn{Name: columnName}, + ); err != nil { + return errors.Default.Wrap(err, "failed to drop NOT NULL on processed_time for postgres") + } + return nil + case "mysql": + // MySQL requires MODIFY COLUMN with original type specification, preserve original type as much as possible + cols, err := db.GetColumns(dal.DefaultTabler{Name: tableName}, func(cm dal.ColumnMeta) bool { + return cm.Name() == columnName + }) + if err != nil { + return errors.Default.Wrap(err, "failed to load column metadata for mysql type preservation") + } + columnTypeSql := "DATETIME" + if len(cols) > 0 { + if ct, ok := cols[0].ColumnType(); ok && ct != "" { + columnTypeSql = ct + } else if dbt := cols[0].DatabaseTypeName(); dbt != "" { + // DatabaseTypeName may return DATETIME, TIMESTAMP etc + columnTypeSql = dbt + } + } + alterSql := "ALTER TABLE ? MODIFY COLUMN ? " + columnTypeSql + " NULL" + if err := db.Exec( + alterSql, + dal.ClauseTable{Name: tableName}, + dal.ClauseColumn{Name: columnName}, + ); err != nil { + return errors.Default.Wrap(err, "failed to modify processed_time to NULL for mysql") + } + return nil + default: + // Other dialects are not forced to migrate for now, return idempotently + return nil + } } func (*modifyFileMetaTable) Version() uint64 {