From deba5db2fd7e5b086108ff1a0956767ace510ac9 Mon Sep 17 00:00:00 2001 From: onenewcode Date: Mon, 10 Aug 2026 18:27:04 +0800 Subject: [PATCH] fix(oracle): preserve cloned table index and trigger metadata --- agents/drivers/oracle-go/main.go | 6 +-- agents/drivers/oracle-go/main_test.go | 77 +++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/agents/drivers/oracle-go/main.go b/agents/drivers/oracle-go/main.go index 7280940a9a..0eb5c8e871 100644 --- a/agents/drivers/oracle-go/main.go +++ b/agents/drivers/oracle-go/main.go @@ -2414,7 +2414,7 @@ func (s *server) listIndexes(schema, table string) ([]indexInfo, error) { if err != nil { return nil, err } - table = strings.ToUpper(strings.TrimSpace(table)) + table = strings.TrimSpace(table) rows, err := s.queryRows(` SELECT i.INDEX_NAME, ic.COLUMN_NAME, @@ -2474,7 +2474,7 @@ func (s *server) listForeignKeys(schema, table string) ([]foreignKeyInfo, error) if err != nil { return nil, err } - table = strings.ToUpper(strings.TrimSpace(table)) + table = strings.TrimSpace(table) rows, err := s.queryRows(` SELECT ac.CONSTRAINT_NAME, acc.COLUMN_NAME, @@ -2510,7 +2510,7 @@ func (s *server) listTriggers(schema, table string) ([]triggerInfo, error) { if err != nil { return nil, err } - table = strings.ToUpper(strings.TrimSpace(table)) + table = strings.TrimSpace(table) rows, err := s.queryRows(oracleListTriggersSQL, []any{schema, table}) if err != nil { return nil, err diff --git a/agents/drivers/oracle-go/main_test.go b/agents/drivers/oracle-go/main_test.go index ff0e49babd..0d6115de8d 100644 --- a/agents/drivers/oracle-go/main_test.go +++ b/agents/drivers/oracle-go/main_test.go @@ -618,6 +618,44 @@ func TestGetTableDDLAppendsIndexesTriggersAndComments(t *testing.T) { } } +func TestListIndexesSeparatesQuotedCloneTableNamesByCase(t *testing.T) { + const schema = "HR" + db, scripted := openOracleViewSourceTestDB(t, []oracleViewSourceQueryStep{ + { + queryContains: "FROM ALL_INDEXES", + args: []driver.Value{schema, "ORDERS_COPY"}, + columns: []string{"INDEX_NAME", "COLUMN_NAME", "UNIQUENESS", "IS_PRIMARY", "INDEX_TYPE", "COLUMN_POSITION"}, + rows: [][]driver.Value{{"ORDERS_COPY_IDX1", "STATUS", "NONUNIQUE", int64(0), "NORMAL", int64(1)}}, + }, + { + queryContains: "FROM ALL_INDEXES", + args: []driver.Value{schema, "ORDERS_copy"}, + columns: []string{"INDEX_NAME", "COLUMN_NAME", "UNIQUENESS", "IS_PRIMARY", "INDEX_TYPE", "COLUMN_POSITION"}, + rows: [][]driver.Value{{"ORDERS_copy_IDX1", "STATUS", "NONUNIQUE", int64(0), "NORMAL", int64(1)}}, + }, + }) + s := newServer() + s.db = db + + uppercaseIndexes, err := s.listIndexes(schema, "ORDERS_COPY") + if err != nil { + t.Fatal(err) + } + mixedCaseIndexes, err := s.listIndexes(schema, "ORDERS_copy") + if err != nil { + t.Fatal(err) + } + if len(uppercaseIndexes) != 1 || uppercaseIndexes[0].Name != "ORDERS_COPY_IDX1" { + t.Fatalf("listIndexes(ORDERS_COPY) = %#v, want uppercase table index", uppercaseIndexes) + } + if len(mixedCaseIndexes) != 1 || mixedCaseIndexes[0].Name != "ORDERS_copy_IDX1" || !reflect.DeepEqual(mixedCaseIndexes[0].Columns, []string{"STATUS"}) { + t.Fatalf("listIndexes(ORDERS_copy) = %#v, want quoted clone index", mixedCaseIndexes) + } + if scripted.next != len(scripted.steps) { + t.Fatalf("expected %d queries, got %d", len(scripted.steps), scripted.next) + } +} + func TestGetTableCommentPreservesQuotedObjectName(t *testing.T) { const schema = "HR" const table = "OrderDetails" @@ -708,6 +746,45 @@ func TestListForeignKeysIncludesReferencedSchemaAndDeleteRule(t *testing.T) { } } +func TestListForeignKeysAndTriggersPreserveQuotedCloneTableName(t *testing.T) { + const schema = "HR" + const table = "ORDERS_copy" + db, scripted := openOracleViewSourceTestDB(t, []oracleViewSourceQueryStep{ + { + queryContains: "FROM ALL_CONSTRAINTS ac", + args: []driver.Value{schema, table}, + columns: []string{"CONSTRAINT_NAME", "COLUMN_NAME", "REF_SCHEMA", "REF_TABLE", "REF_COLUMN", "DELETE_RULE"}, + rows: [][]driver.Value{{"ORDERS_copy_FK1", "CUSTOMER_ID", "CRM", "CUSTOMERS", "ID", "CASCADE"}}, + }, + { + queryContains: "FROM ALL_TRIGGERS", + args: []driver.Value{schema, table}, + columns: []string{"TRIGGER_NAME", "TRIGGERING_EVENT", "TRIGGER_TYPE", "DESCRIPTION", "LINE", "TEXT"}, + rows: [][]driver.Value{{"ORDERS_copy_TRG1", "INSERT", "BEFORE EACH ROW", nil, nil, nil}}, + }, + }) + s := newServer() + s.db = db + + foreignKeys, err := s.listForeignKeys(schema, table) + if err != nil { + t.Fatal(err) + } + triggers, err := s.listTriggers(schema, table) + if err != nil { + t.Fatal(err) + } + if len(foreignKeys) != 1 || foreignKeys[0].Name != "ORDERS_copy_FK1" { + t.Fatalf("listForeignKeys(%q) = %#v, want quoted clone foreign key", table, foreignKeys) + } + if len(triggers) != 1 || triggers[0].Name != "ORDERS_copy_TRG1" { + t.Fatalf("listTriggers(%q) = %#v, want quoted clone trigger", table, triggers) + } + if scripted.next != len(scripted.steps) { + t.Fatalf("expected %d queries, got %d", len(scripted.steps), scripted.next) + } +} + func TestIsQuerySQLSkipsLeadingComments(t *testing.T) { tests := []string{ "-- 测试\nSELECT * FROM (SELECT * FROM \"DBX_TEST\".\"ORDERS_10K\") WHERE ROWNUM <= 100",