mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 00:17:44 +00:00
fix(oracle): include system schemas in schema list
This commit is contained in:
@@ -63,6 +63,17 @@ ORDER BY CASE
|
||||
WHEN username = SYS_CONTEXT('USERENV', 'SESSION_USER') THEN 1
|
||||
ELSE 2
|
||||
END, username`
|
||||
|
||||
// Oracle schemas are users, so expose every user visible through ALL_USERS; system filtering remains database-picker behavior.
|
||||
const oracleListSchemasSQL = `
|
||||
SELECT username AS owner
|
||||
FROM all_users
|
||||
WHERE username IS NOT NULL
|
||||
ORDER BY CASE
|
||||
WHEN username = SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') THEN 0
|
||||
WHEN username = SYS_CONTEXT('USERENV', 'SESSION_USER') THEN 1
|
||||
ELSE 2
|
||||
END, username`
|
||||
const oracleListTablesBaseSQL = `
|
||||
SELECT OBJECT_NAME, TABLE_TYPE, COMMENTS
|
||||
FROM (
|
||||
@@ -1062,13 +1073,44 @@ func (s *server) listSchemas(visibleSchemas []string) ([]string, error) {
|
||||
if visibleSchemas != nil && len(visibleSchemas) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
databases, err := s.listDatabasesFiltered(visibleSchemas)
|
||||
sqlText, args := oracleListSchemasSQLWithVisibleSchemas(visibleSchemas)
|
||||
rows, err := s.queryRows(sqlText, args)
|
||||
if err != nil {
|
||||
if isOraclePGALimitError(err) {
|
||||
databases, fallbackErr := s.currentSchemaDatabase()
|
||||
if fallbackErr != nil {
|
||||
return nil, fallbackErr
|
||||
}
|
||||
result := make([]string, 0, len(databases))
|
||||
for _, database := range databases {
|
||||
result = append(result, database.Name)
|
||||
}
|
||||
return emptyIfNil(result), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
result := make([]string, 0, len(databases))
|
||||
for _, database := range databases {
|
||||
result = append(result, database.Name)
|
||||
defer s.closeRows(rows)
|
||||
var result []string
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, name)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
if isOraclePGALimitError(err) {
|
||||
databases, fallbackErr := s.currentSchemaDatabase()
|
||||
if fallbackErr != nil {
|
||||
return nil, fallbackErr
|
||||
}
|
||||
result = result[:0]
|
||||
for _, database := range databases {
|
||||
result = append(result, database.Name)
|
||||
}
|
||||
return emptyIfNil(result), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return emptyIfNil(result), nil
|
||||
}
|
||||
@@ -1104,8 +1146,16 @@ func (s *server) listDatabasesFiltered(visibleSchemas []string) ([]databaseInfo,
|
||||
}
|
||||
|
||||
func oracleListDatabasesSQLWithVisibleSchemas(visibleSchemas []string) (string, []any) {
|
||||
return oracleListSQLWithVisibleSchemas(oracleListDatabasesSQL, visibleSchemas)
|
||||
}
|
||||
|
||||
func oracleListSchemasSQLWithVisibleSchemas(visibleSchemas []string) (string, []any) {
|
||||
return oracleListSQLWithVisibleSchemas(oracleListSchemasSQL, visibleSchemas)
|
||||
}
|
||||
|
||||
func oracleListSQLWithVisibleSchemas(baseSQL string, visibleSchemas []string) (string, []any) {
|
||||
if len(visibleSchemas) == 0 {
|
||||
return oracleListDatabasesSQL, nil
|
||||
return baseSQL, nil
|
||||
}
|
||||
placeholders := make([]string, 0, len(visibleSchemas))
|
||||
args := make([]any, 0, len(visibleSchemas))
|
||||
@@ -1114,7 +1164,7 @@ func oracleListDatabasesSQLWithVisibleSchemas(visibleSchemas []string) (string,
|
||||
args = append(args, schema)
|
||||
}
|
||||
sqlText := strings.Replace(
|
||||
oracleListDatabasesSQL,
|
||||
baseSQL,
|
||||
"\nORDER BY CASE",
|
||||
"\n AND username IN ("+strings.Join(placeholders, ",")+")\nORDER BY CASE",
|
||||
1,
|
||||
|
||||
@@ -677,13 +677,16 @@ func TestListDatabasesSQLUsesUserDictionaryInsteadOfObjectDictionary(t *testing.
|
||||
sqlText := strings.ToUpper(oracleListDatabasesSQL)
|
||||
|
||||
if !strings.Contains(sqlText, "ALL_USERS") {
|
||||
t.Fatalf("schema listing should query ALL_USERS, got: %s", oracleListDatabasesSQL)
|
||||
t.Fatalf("database listing should query ALL_USERS, got: %s", oracleListDatabasesSQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "ALL_TABLES") || strings.Contains(sqlText, "ALL_VIEWS") {
|
||||
t.Fatalf("schema listing should not scan object dictionaries, got: %s", oracleListDatabasesSQL)
|
||||
t.Fatalf("database listing should not scan object dictionaries, got: %s", oracleListDatabasesSQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "'DIP'") {
|
||||
t.Fatalf("schema listing should not hide an existing user named DIP, got: %s", oracleListDatabasesSQL)
|
||||
t.Fatalf("database listing should not hide an existing user named DIP, got: %s", oracleListDatabasesSQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "'SYS','SYSTEM'") || !strings.Contains(sqlText, "USERNAME NOT LIKE 'APEX_%'") {
|
||||
t.Fatalf("database listing should retain system schema filtering, got: %s", oracleListDatabasesSQL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -692,16 +695,54 @@ func TestListDatabasesSQLCanApplyVisibleSchemaFilter(t *testing.T) {
|
||||
upperSQL := strings.ToUpper(sqlText)
|
||||
|
||||
if !strings.Contains(upperSQL, "ALL_USERS") {
|
||||
t.Fatalf("schema listing should query ALL_USERS, got: %s", sqlText)
|
||||
t.Fatalf("database listing should query ALL_USERS, got: %s", sqlText)
|
||||
}
|
||||
if !strings.Contains(upperSQL, "USERNAME IN (:1,:2)") {
|
||||
t.Fatalf("schema listing should apply visible schema filter, got: %s", sqlText)
|
||||
t.Fatalf("database listing should apply visible schema filter, got: %s", sqlText)
|
||||
}
|
||||
if len(args) != 2 || args[0] != "APP" || args[1] != "REPORTING" {
|
||||
t.Fatalf("visible schema args were not preserved: %#v", args)
|
||||
}
|
||||
if strings.Contains(upperSQL, "ALL_TABLES") || strings.Contains(upperSQL, "ALL_VIEWS") {
|
||||
t.Fatalf("schema listing should not scan object dictionaries, got: %s", sqlText)
|
||||
t.Fatalf("database listing should not scan object dictionaries, got: %s", sqlText)
|
||||
}
|
||||
if !strings.Contains(upperSQL, "'SYS','SYSTEM'") {
|
||||
t.Fatalf("database visible-schema filtering should retain system exclusions, got: %s", sqlText)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSchemasSQLIncludesSystemUsersWithoutSynthesizingPublic(t *testing.T) {
|
||||
sqlText := strings.ToUpper(oracleListSchemasSQL)
|
||||
|
||||
if !strings.Contains(sqlText, "FROM ALL_USERS") {
|
||||
t.Fatalf("schema listing should query ALL_USERS, got: %s", oracleListSchemasSQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "NOT IN") || strings.Contains(sqlText, "'SYS'") || strings.Contains(sqlText, "'SYSTEM'") {
|
||||
t.Fatalf("schema listing should not hard-exclude SYS or SYSTEM, got: %s", oracleListSchemasSQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "PUBLIC") || strings.Contains(sqlText, "UNION") {
|
||||
t.Fatalf("schema listing should not synthesize PUBLIC, got: %s", oracleListSchemasSQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "CURRENT_SCHEMA') THEN 0") || !strings.Contains(sqlText, "SESSION_USER') THEN 1") {
|
||||
t.Fatalf("schema listing should prioritize CURRENT_SCHEMA then SESSION_USER, got: %s", oracleListSchemasSQL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSchemasSQLCanApplyVisibleSchemaFilter(t *testing.T) {
|
||||
sqlText, args := oracleListSchemasSQLWithVisibleSchemas([]string{"SYS", "SYSTEM"})
|
||||
upperSQL := strings.ToUpper(sqlText)
|
||||
|
||||
if !strings.Contains(upperSQL, "USERNAME IN (:1,:2)") {
|
||||
t.Fatalf("schema listing should parameterize visible schemas, got: %s", sqlText)
|
||||
}
|
||||
if len(args) != 2 || args[0] != "SYS" || args[1] != "SYSTEM" {
|
||||
t.Fatalf("visible schema args were not preserved: %#v", args)
|
||||
}
|
||||
if strings.Contains(upperSQL, "NOT IN") || strings.Contains(upperSQL, "'SYS'") || strings.Contains(upperSQL, "'SYSTEM'") {
|
||||
t.Fatalf("visible schema query should not hard-exclude SYS or SYSTEM, got: %s", sqlText)
|
||||
}
|
||||
if !strings.Contains(upperSQL, "CURRENT_SCHEMA') THEN 0") || !strings.Contains(upperSQL, "SESSION_USER') THEN 1") {
|
||||
t.Fatalf("visible schema query should preserve schema ordering, got: %s", sqlText)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user