fix(oracle): apply visible schema filter
This commit is contained in:
1 parent
1ded7e8332
commit
b2edf7cad6
20 files changed
+469
-102
No files matched your search
@@ -323,7 +323,7 @@ func (s *server) dispatch(method string, params map[string]json.RawMessage) (any
|
||||
result, err := s.listDatabases()
|
||||
return result, false, err
|
||||
case "list_schemas":
|
||||
result, err := s.listSchemas()
|
||||
result, err := s.listSchemas(stringSliceParam(params, "visible_schemas"))
|
||||
return result, false, err
|
||||
case "list_tables":
|
||||
schema := stringParam(params, "schema")
|
||||
@@ -570,8 +570,11 @@ func (s *server) currentSchemaDatabase() ([]databaseInfo, error) {
|
||||
return []databaseInfo{{Name: schema}}, nil
|
||||
}
|
||||
|
||||
func (s *server) listSchemas() ([]string, error) {
|
||||
databases, err := s.listDatabases()
|
||||
func (s *server) listSchemas(visibleSchemas []string) ([]string, error) {
|
||||
if visibleSchemas != nil && len(visibleSchemas) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
databases, err := s.listDatabasesFiltered(visibleSchemas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -582,6 +585,55 @@ func (s *server) listSchemas() ([]string, error) {
|
||||
return emptyIfNil(result), nil
|
||||
}
|
||||
|
||||
func (s *server) listDatabasesFiltered(visibleSchemas []string) ([]databaseInfo, error) {
|
||||
if visibleSchemas == nil {
|
||||
return s.listDatabases()
|
||||
}
|
||||
sqlText, args := oracleListDatabasesSQLWithVisibleSchemas(visibleSchemas)
|
||||
rows, err := s.queryRows(sqlText, args)
|
||||
if err != nil {
|
||||
if isOraclePGALimitError(err) {
|
||||
return s.currentSchemaDatabase()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var result []databaseInfo
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, databaseInfo{Name: name})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
if isOraclePGALimitError(err) {
|
||||
return s.currentSchemaDatabase()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return emptyIfNil(result), nil
|
||||
}
|
||||
|
||||
func oracleListDatabasesSQLWithVisibleSchemas(visibleSchemas []string) (string, []any) {
|
||||
if len(visibleSchemas) == 0 {
|
||||
return oracleListDatabasesSQL, nil
|
||||
}
|
||||
placeholders := make([]string, 0, len(visibleSchemas))
|
||||
args := make([]any, 0, len(visibleSchemas))
|
||||
for i, schema := range visibleSchemas {
|
||||
placeholders = append(placeholders, fmt.Sprintf(":%d", i+1))
|
||||
args = append(args, schema)
|
||||
}
|
||||
sqlText := strings.Replace(
|
||||
oracleListDatabasesSQL,
|
||||
"\nORDER BY CASE",
|
||||
"\n AND username IN ("+strings.Join(placeholders, ",")+")\nORDER BY CASE",
|
||||
1,
|
||||
)
|
||||
return sqlText, args
|
||||
}
|
||||
|
||||
func (s *server) currentSchema() (string, error) {
|
||||
db, err := s.requireDB()
|
||||
if err != nil {
|
||||
@@ -1352,6 +1404,17 @@ func stringParam(params map[string]json.RawMessage, key string) string {
|
||||
return value
|
||||
}
|
||||
|
||||
func stringSliceParam(params map[string]json.RawMessage, key string) []string {
|
||||
if params == nil || len(params[key]) == 0 {
|
||||
return nil
|
||||
}
|
||||
var value []string
|
||||
if err := json.Unmarshal(params[key], &value); err != nil {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func intParam(params map[string]json.RawMessage, key string) int {
|
||||
if params == nil || len(params[key]) == 0 {
|
||||
return 0
|
||||
|
||||
@@ -265,6 +265,24 @@ func TestListDatabasesSQLUsesUserDictionaryInsteadOfObjectDictionary(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestListDatabasesSQLCanApplyVisibleSchemaFilter(t *testing.T) {
|
||||
sqlText, args := oracleListDatabasesSQLWithVisibleSchemas([]string{"APP", "REPORTING"})
|
||||
upperSQL := strings.ToUpper(sqlText)
|
||||
|
||||
if !strings.Contains(upperSQL, "ALL_USERS") {
|
||||
t.Fatalf("schema 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListTablesSQLUsesSplitDictionaryQuery(t *testing.T) {
|
||||
sqlText := strings.ToUpper(oracleListTablesSQL)
|
||||
|
||||
|
||||
Reference in new issue
Block a user