mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
fix(oracle): list materialized views without table duplicates
Closes #6611
This commit is contained in:
@@ -103,13 +103,20 @@ SELECT t.TABLE_NAME AS OBJECT_NAME,
|
||||
FROM ALL_TABLES t
|
||||
WHERE t.OWNER = :1
|
||||
AND t.NESTED = 'NO'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM ALL_OBJECTS mv
|
||||
WHERE mv.OWNER = t.OWNER
|
||||
AND mv.OBJECT_NAME = t.TABLE_NAME
|
||||
AND mv.OBJECT_TYPE = 'MATERIALIZED VIEW'
|
||||
)
|
||||
UNION ALL
|
||||
SELECT o.OBJECT_NAME,
|
||||
'VIEW' AS TABLE_TYPE,
|
||||
CASE o.OBJECT_TYPE WHEN 'MATERIALIZED VIEW' THEN 'MATERIALIZED_VIEW' ELSE o.OBJECT_TYPE END AS TABLE_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM ALL_OBJECTS o
|
||||
WHERE o.OWNER = :2
|
||||
AND o.OBJECT_TYPE = 'VIEW'
|
||||
AND o.OBJECT_TYPE IN ('VIEW', 'MATERIALIZED VIEW')
|
||||
)`
|
||||
const oracleListTablesSessionUserBaseSQL = `
|
||||
SELECT OBJECT_NAME, TABLE_TYPE, COMMENTS
|
||||
@@ -119,12 +126,18 @@ SELECT t.TABLE_NAME AS OBJECT_NAME,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_TABLES t
|
||||
WHERE t.NESTED = 'NO'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM USER_OBJECTS mv
|
||||
WHERE mv.OBJECT_NAME = t.TABLE_NAME
|
||||
AND mv.OBJECT_TYPE = 'MATERIALIZED VIEW'
|
||||
)
|
||||
UNION ALL
|
||||
SELECT o.OBJECT_NAME,
|
||||
'VIEW' AS TABLE_TYPE,
|
||||
CASE o.OBJECT_TYPE WHEN 'MATERIALIZED VIEW' THEN 'MATERIALIZED_VIEW' ELSE o.OBJECT_TYPE END AS TABLE_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_OBJECTS o
|
||||
WHERE o.OBJECT_TYPE = 'VIEW'
|
||||
WHERE o.OBJECT_TYPE IN ('VIEW', 'MATERIALIZED VIEW')
|
||||
)`
|
||||
const oracleListTablesOrderSQL = `ORDER BY OBJECT_NAME`
|
||||
const oracleListTablesSQL = oracleListTablesBaseSQL + "\n" + oracleListTablesOrderSQL
|
||||
@@ -137,13 +150,24 @@ SELECT t.TABLE_NAME AS OBJECT_NAME,
|
||||
FROM ALL_TABLES t
|
||||
WHERE t.OWNER = :1
|
||||
AND t.NESTED = 'NO'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM ALL_OBJECTS mv
|
||||
WHERE mv.OWNER = t.OWNER
|
||||
AND mv.OBJECT_NAME = t.TABLE_NAME
|
||||
AND mv.OBJECT_TYPE = 'MATERIALIZED VIEW'
|
||||
)
|
||||
UNION ALL
|
||||
SELECT o.OBJECT_NAME,
|
||||
CASE o.OBJECT_TYPE WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY' ELSE o.OBJECT_TYPE END AS OBJECT_TYPE,
|
||||
CASE o.OBJECT_TYPE
|
||||
WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY'
|
||||
WHEN 'MATERIALIZED VIEW' THEN 'MATERIALIZED_VIEW'
|
||||
ELSE o.OBJECT_TYPE
|
||||
END AS OBJECT_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM ALL_OBJECTS o
|
||||
WHERE o.OWNER = :2
|
||||
AND o.OBJECT_TYPE IN ('VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY')
|
||||
AND o.OBJECT_TYPE IN ('VIEW', 'MATERIALIZED VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY')
|
||||
UNION ALL
|
||||
SELECT s.SYNONYM_NAME AS OBJECT_NAME,
|
||||
'SYNONYM' AS OBJECT_TYPE,
|
||||
@@ -159,12 +183,22 @@ SELECT t.TABLE_NAME AS OBJECT_NAME,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_TABLES t
|
||||
WHERE t.NESTED = 'NO'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM USER_OBJECTS mv
|
||||
WHERE mv.OBJECT_NAME = t.TABLE_NAME
|
||||
AND mv.OBJECT_TYPE = 'MATERIALIZED VIEW'
|
||||
)
|
||||
UNION ALL
|
||||
SELECT o.OBJECT_NAME,
|
||||
CASE o.OBJECT_TYPE WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY' ELSE o.OBJECT_TYPE END AS OBJECT_TYPE,
|
||||
CASE o.OBJECT_TYPE
|
||||
WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY'
|
||||
WHEN 'MATERIALIZED VIEW' THEN 'MATERIALIZED_VIEW'
|
||||
ELSE o.OBJECT_TYPE
|
||||
END AS OBJECT_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_OBJECTS o
|
||||
WHERE o.OBJECT_TYPE IN ('VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY')
|
||||
WHERE o.OBJECT_TYPE IN ('VIEW', 'MATERIALIZED VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY')
|
||||
UNION ALL
|
||||
SELECT s.SYNONYM_NAME AS OBJECT_NAME,
|
||||
'SYNONYM' AS OBJECT_TYPE,
|
||||
@@ -174,11 +208,12 @@ FROM USER_SYNONYMS s
|
||||
const oracleListObjectsOrderSQL = `ORDER BY CASE OBJECT_TYPE
|
||||
WHEN 'TABLE' THEN 0
|
||||
WHEN 'VIEW' THEN 1
|
||||
WHEN 'PROCEDURE' THEN 2
|
||||
WHEN 'FUNCTION' THEN 3
|
||||
WHEN 'SYNONYM' THEN 4
|
||||
WHEN 'PACKAGE' THEN 5
|
||||
ELSE 6
|
||||
WHEN 'MATERIALIZED_VIEW' THEN 2
|
||||
WHEN 'PROCEDURE' THEN 3
|
||||
WHEN 'FUNCTION' THEN 4
|
||||
WHEN 'SYNONYM' THEN 5
|
||||
WHEN 'PACKAGE' THEN 6
|
||||
ELSE 7
|
||||
END, OBJECT_NAME`
|
||||
const oracleListObjectsSQL = oracleListObjectsBaseSQL + "\n" + oracleListObjectsOrderSQL
|
||||
const oracleListTriggersSQL = `
|
||||
|
||||
@@ -1744,6 +1744,61 @@ func TestListTablesSQLUsesSplitDictionaryQuery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOracleMetadataQueriesClassifyMaterializedViews(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
sqlText string
|
||||
tableView string
|
||||
objectView string
|
||||
ownerMatch string
|
||||
}{
|
||||
{
|
||||
name: "all list tables",
|
||||
sqlText: oracleListTablesBaseSQL,
|
||||
tableView: "ALL_TABLES",
|
||||
objectView: "ALL_OBJECTS",
|
||||
ownerMatch: "MV.OWNER = T.OWNER",
|
||||
},
|
||||
{
|
||||
name: "user list tables",
|
||||
sqlText: oracleListTablesSessionUserBaseSQL,
|
||||
tableView: "USER_TABLES",
|
||||
objectView: "USER_OBJECTS",
|
||||
},
|
||||
{
|
||||
name: "all list objects",
|
||||
sqlText: oracleListObjectsBaseSQL,
|
||||
tableView: "ALL_TABLES",
|
||||
objectView: "ALL_OBJECTS",
|
||||
ownerMatch: "MV.OWNER = T.OWNER",
|
||||
},
|
||||
{
|
||||
name: "user list objects",
|
||||
sqlText: oracleListObjectsSessionUserBaseSQL,
|
||||
tableView: "USER_TABLES",
|
||||
objectView: "USER_OBJECTS",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
sqlText := strings.ToUpper(test.sqlText)
|
||||
if !strings.Contains(sqlText, "FROM "+test.tableView+" T") || !strings.Contains(sqlText, "FROM "+test.objectView+" MV") {
|
||||
t.Fatalf("metadata query should classify tables against materialized-view objects: %s", test.sqlText)
|
||||
}
|
||||
if !strings.Contains(sqlText, "NOT EXISTS") || !strings.Contains(sqlText, "MV.OBJECT_NAME = T.TABLE_NAME") || !strings.Contains(sqlText, "MV.OBJECT_TYPE = 'MATERIALIZED VIEW'") {
|
||||
t.Fatalf("metadata query should exclude materialized-view storage tables: %s", test.sqlText)
|
||||
}
|
||||
if test.ownerMatch != "" && !strings.Contains(sqlText, test.ownerMatch) {
|
||||
t.Fatalf("cross-schema metadata query should keep materialized-view classification owner-scoped: %s", test.sqlText)
|
||||
}
|
||||
if !strings.Contains(sqlText, "'MATERIALIZED_VIEW'") || !strings.Contains(sqlText, "'MATERIALIZED VIEW'") {
|
||||
t.Fatalf("metadata query should return the normalized materialized-view type: %s", test.sqlText)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListTablesQueryAppliesMetadataConstraints(t *testing.T) {
|
||||
query := oracleListTablesQuery("APP", metadataListConstraints{
|
||||
Filter: "u_r",
|
||||
|
||||
Reference in New Issue
Block a user