Skip to content

Commit e52ce13

Browse files
authored
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
1 parent 6e224fa commit e52ce13

1 file changed

Lines changed: 71 additions & 6 deletions

File tree

backend/plugins/q_dev/models/migrationscripts/20250320_modify_file_meta.go

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package migrationscripts
1919

2020
import (
2121
"github.com/apache/incubator-devlake/core/context"
22+
"github.com/apache/incubator-devlake/core/dal"
2223
"github.com/apache/incubator-devlake/core/errors"
2324
)
2425

@@ -31,14 +32,78 @@ func (*modifyFileMetaTable) Name() string {
3132
func (*modifyFileMetaTable) Up(basicRes context.BasicRes) errors.Error {
3233
db := basicRes.GetDal()
3334

34-
// 修改 processed_time 列允许为 NULL
35-
sql := "ALTER TABLE _tool_q_dev_s3_file_meta MODIFY processed_time DATETIME NULL"
36-
err := db.Exec(sql)
37-
if err != nil {
38-
return errors.Default.Wrap(err, "failed to modify processed_time column")
35+
// Target table and column
36+
tableName := "_tool_q_dev_s3_file_meta"
37+
columnName := "processed_time"
38+
39+
// If column doesn't exist, no migration needed, idempotent
40+
if !db.HasColumn(tableName, columnName) {
41+
return nil
3942
}
4043

41-
return nil
44+
// Read column metadata to check if already nullable, return idempotently if already nullable
45+
var processedTimeNullable bool
46+
{
47+
cols, err := db.GetColumns(dal.DefaultTabler{Name: tableName}, func(cm dal.ColumnMeta) bool {
48+
return cm.Name() == columnName
49+
})
50+
if err != nil {
51+
return errors.Default.Wrap(err, "failed to load column metadata for _tool_q_dev_s3_file_meta.processed_time")
52+
}
53+
if len(cols) == 0 {
54+
// If column is not visible in metadata, treat as no processing needed
55+
return nil
56+
}
57+
if nullable, ok := cols[0].Nullable(); ok {
58+
processedTimeNullable = nullable
59+
}
60+
}
61+
if processedTimeNullable {
62+
return nil
63+
}
64+
65+
// Execute compatible SQL by dialect
66+
switch db.Dialect() {
67+
case "postgres":
68+
// PostgreSQL makes column nullable via DROP NOT NULL, without changing data type
69+
if err := db.Exec(
70+
"ALTER TABLE ? ALTER COLUMN ? DROP NOT NULL",
71+
dal.ClauseTable{Name: tableName},
72+
dal.ClauseColumn{Name: columnName},
73+
); err != nil {
74+
return errors.Default.Wrap(err, "failed to drop NOT NULL on processed_time for postgres")
75+
}
76+
return nil
77+
case "mysql":
78+
// MySQL requires MODIFY COLUMN with original type specification, preserve original type as much as possible
79+
cols, err := db.GetColumns(dal.DefaultTabler{Name: tableName}, func(cm dal.ColumnMeta) bool {
80+
return cm.Name() == columnName
81+
})
82+
if err != nil {
83+
return errors.Default.Wrap(err, "failed to load column metadata for mysql type preservation")
84+
}
85+
columnTypeSql := "DATETIME"
86+
if len(cols) > 0 {
87+
if ct, ok := cols[0].ColumnType(); ok && ct != "" {
88+
columnTypeSql = ct
89+
} else if dbt := cols[0].DatabaseTypeName(); dbt != "" {
90+
// DatabaseTypeName may return DATETIME, TIMESTAMP etc
91+
columnTypeSql = dbt
92+
}
93+
}
94+
alterSql := "ALTER TABLE ? MODIFY COLUMN ? " + columnTypeSql + " NULL"
95+
if err := db.Exec(
96+
alterSql,
97+
dal.ClauseTable{Name: tableName},
98+
dal.ClauseColumn{Name: columnName},
99+
); err != nil {
100+
return errors.Default.Wrap(err, "failed to modify processed_time to NULL for mysql")
101+
}
102+
return nil
103+
default:
104+
// Other dialects are not forced to migrate for now, return idempotently
105+
return nil
106+
}
42107
}
43108

44109
func (*modifyFileMetaTable) Version() uint64 {

0 commit comments

Comments
 (0)