Files
MyGoNavi/internal/db/oracle_triggers_test.go
Syngnat 4b1cd1b727 🐛 fix(oracle): 修复触发器脚本显示为空
- 触发器列表查询补齐 OWNER、TABLE_NAME、TRIGGER_BODY 等 Oracle 元数据字段
- 优先使用 DBMS_METADATA.GET_DDL 返回完整 CREATE TRIGGER 脚本
- 在 DDL 不可用时基于 USER_TRIGGERS/ALL_TRIGGERS 重建可编辑触发器语句
- 补充 Oracle 触发器 DDL 获取与回退重建回归测试
2026-06-25 10:50:07 +08:00

101 lines
3.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package db
import (
"database/sql/driver"
"slices"
"strings"
"testing"
)
func TestOracleGetTriggersUsesDBMSMetadataDDL(t *testing.T) {
t.Parallel()
dbConn, state := openOracleRecordingDB(t)
triggerListQuery := buildOracleTriggersQuery("H2", "T_MEMCARD_CASH")
triggerDDLQuery := `SELECT DBMS_METADATA.GET_DDL('TRIGGER', 'TR_T_MEMCARD_CASH', 'H2') as ddl FROM DUAL`
metadataDDL := `CREATE OR REPLACE TRIGGER "H2"."TR_T_MEMCARD_CASH"
BEFORE INSERT ON "H2"."T_MEMCARD_CASH"
BEGIN
NULL;
END;`
state.mu.Lock()
state.queryResults[triggerListQuery] = oracleRecordingQueryResult{
columns: []string{"OWNER", "TABLE_OWNER", "TABLE_NAME", "TRIGGER_NAME", "TRIGGER_TYPE", "TRIGGERING_EVENT", "WHEN_CLAUSE", "TRIGGER_BODY"},
rows: [][]driver.Value{
{"H2", "H2", "T_MEMCARD_CASH", "TR_T_MEMCARD_CASH", "BEFORE EACH ROW", "INSERT", nil, "SOURCE HIDDEN"},
},
}
state.queryResults[triggerDDLQuery] = oracleRecordingQueryResult{
columns: []string{"DDL"},
rows: [][]driver.Value{
{metadataDDL},
},
}
state.mu.Unlock()
oracleDB := &OracleDB{conn: dbConn}
triggers, err := oracleDB.GetTriggers("H2", "T_MEMCARD_CASH")
if err != nil {
t.Fatalf("GetTriggers 返回错误: %v", err)
}
if len(triggers) != 1 {
t.Fatalf("期望返回 1 个触发器,实际 %#v", triggers)
}
if !strings.Contains(triggers[0].Statement, `CREATE OR REPLACE TRIGGER "H2"."TR_T_MEMCARD_CASH"`) {
t.Fatalf("期望返回 DBMS_METADATA 完整 DDL实际: %s", triggers[0].Statement)
}
if strings.Contains(triggers[0].Statement, "SOURCE HIDDEN") {
t.Fatalf("触发器语句不应继续返回 SOURCE HIDDEN: %s", triggers[0].Statement)
}
if queries := state.snapshotQueries(); !slices.Contains(queries, triggerDDLQuery) {
t.Fatalf("期望查询 DBMS_METADATA 获取触发器 DDL实际 queries=%v", queries)
}
}
func TestOracleGetTriggersRebuildsDDLFromTriggerBodyWhenMetadataDDLIsEmpty(t *testing.T) {
t.Parallel()
dbConn, state := openOracleRecordingDB(t)
triggerListQuery := buildOracleTriggersQuery("H2", "T_MEMCARD_CASH")
triggerDDLQuery := `SELECT DBMS_METADATA.GET_DDL('TRIGGER', 'TR_T_MEMCARD_CASH', 'H2') as ddl FROM DUAL`
state.mu.Lock()
state.queryResults[triggerListQuery] = oracleRecordingQueryResult{
columns: []string{"OWNER", "TABLE_OWNER", "TABLE_NAME", "TRIGGER_NAME", "TRIGGER_TYPE", "TRIGGERING_EVENT", "WHEN_CLAUSE", "TRIGGER_BODY"},
rows: [][]driver.Value{
{"H2", "H2", "T_MEMCARD_CASH", "TR_T_MEMCARD_CASH", "BEFORE EACH ROW", "INSERT OR UPDATE", "NEW.ID IS NOT NULL", "BEGIN\n :NEW.UPDATED_AT := SYSDATE;\nEND;"},
},
}
state.queryResults[triggerDDLQuery] = oracleRecordingQueryResult{
columns: []string{"DDL"},
rows: [][]driver.Value{},
}
state.mu.Unlock()
oracleDB := &OracleDB{conn: dbConn}
triggers, err := oracleDB.GetTriggers("H2", "T_MEMCARD_CASH")
if err != nil {
t.Fatalf("GetTriggers 返回错误: %v", err)
}
if len(triggers) != 1 {
t.Fatalf("期望返回 1 个触发器,实际 %#v", triggers)
}
statement := triggers[0].Statement
for _, want := range []string{
`CREATE OR REPLACE TRIGGER "H2"."TR_T_MEMCARD_CASH"`,
`BEFORE INSERT OR UPDATE ON "H2"."T_MEMCARD_CASH"`,
`FOR EACH ROW`,
`WHEN (NEW.ID IS NOT NULL)`,
`:NEW.UPDATED_AT := SYSDATE;`,
} {
if !strings.Contains(statement, want) {
t.Fatalf("期望重建后的触发器 DDL 包含 %q实际: %s", want, statement)
}
}
if strings.Contains(statement, "SOURCE HIDDEN") {
t.Fatalf("触发器语句不应继续返回 SOURCE HIDDEN: %s", statement)
}
}