fix(oracle): use USER views for current schema objects
This commit is contained in:
parent
9319efb9e5
commit
ac6b2f6cb5
|
|
@ -75,6 +75,21 @@ FROM ALL_OBJECTS o
|
|||
WHERE o.OWNER = :2
|
||||
AND o.OBJECT_TYPE = 'VIEW'
|
||||
)`
|
||||
const oracleListTablesSessionUserBaseSQL = `
|
||||
SELECT OBJECT_NAME, TABLE_TYPE, COMMENTS
|
||||
FROM (
|
||||
SELECT t.TABLE_NAME AS OBJECT_NAME,
|
||||
'TABLE' AS TABLE_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_TABLES t
|
||||
WHERE t.NESTED = 'NO'
|
||||
UNION ALL
|
||||
SELECT o.OBJECT_NAME,
|
||||
'VIEW' AS TABLE_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_OBJECTS o
|
||||
WHERE o.OBJECT_TYPE = 'VIEW'
|
||||
)`
|
||||
const oracleListTablesOrderSQL = `ORDER BY OBJECT_NAME`
|
||||
const oracleListTablesSQL = oracleListTablesBaseSQL + "\n" + oracleListTablesOrderSQL
|
||||
const oracleListObjectsBaseSQL = `
|
||||
|
|
@ -94,6 +109,21 @@ FROM ALL_OBJECTS o
|
|||
WHERE o.OWNER = :2
|
||||
AND o.OBJECT_TYPE IN ('VIEW', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY')
|
||||
)`
|
||||
const oracleListObjectsSessionUserBaseSQL = `
|
||||
SELECT OBJECT_NAME, OBJECT_TYPE, COMMENTS
|
||||
FROM (
|
||||
SELECT t.TABLE_NAME AS OBJECT_NAME,
|
||||
'TABLE' AS OBJECT_TYPE,
|
||||
CAST(NULL AS VARCHAR2(4000)) AS COMMENTS
|
||||
FROM USER_TABLES t
|
||||
WHERE t.NESTED = 'NO'
|
||||
UNION ALL
|
||||
SELECT o.OBJECT_NAME,
|
||||
CASE o.OBJECT_TYPE WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY' 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')
|
||||
)`
|
||||
const oracleListObjectsOrderSQL = `ORDER BY CASE OBJECT_TYPE
|
||||
WHEN 'TABLE' THEN 0
|
||||
WHEN 'VIEW' THEN 1
|
||||
|
|
@ -785,6 +815,23 @@ func (s *server) normalizeSchema(schema string) (string, error) {
|
|||
return strings.ToUpper(schema), nil
|
||||
}
|
||||
|
||||
func (s *server) sessionUser() (string, error) {
|
||||
db, err := s.requireDB()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var username string
|
||||
if err := db.QueryRow("SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') FROM DUAL").Scan(&username); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.ToUpper(username), nil
|
||||
}
|
||||
|
||||
func (s *server) schemaIsSessionUser(schema string) bool {
|
||||
username, err := s.sessionUser()
|
||||
return err == nil && strings.EqualFold(schema, username)
|
||||
}
|
||||
|
||||
type oracleMetadataListQuery struct {
|
||||
SQL string
|
||||
Args []any
|
||||
|
|
@ -822,6 +869,17 @@ func oracleListTablesQuery(schema string, constraints metadataListConstraints) o
|
|||
)
|
||||
}
|
||||
|
||||
func oracleListSessionUserTablesQuery(constraints metadataListConstraints) oracleMetadataListQuery {
|
||||
return oracleConstrainedMetadataListQuery(
|
||||
oracleListTablesSessionUserBaseSQL,
|
||||
"OBJECT_NAME, TABLE_TYPE, COMMENTS",
|
||||
"TABLE_TYPE",
|
||||
oracleListTablesOrderSQL,
|
||||
nil,
|
||||
constraints,
|
||||
)
|
||||
}
|
||||
|
||||
func oracleListObjectsQuery(schema string, constraints metadataListConstraints) oracleMetadataListQuery {
|
||||
return oracleConstrainedMetadataListQuery(
|
||||
oracleListObjectsBaseSQL,
|
||||
|
|
@ -833,6 +891,17 @@ func oracleListObjectsQuery(schema string, constraints metadataListConstraints)
|
|||
)
|
||||
}
|
||||
|
||||
func oracleListSessionUserObjectsQuery(constraints metadataListConstraints) oracleMetadataListQuery {
|
||||
return oracleConstrainedMetadataListQuery(
|
||||
oracleListObjectsSessionUserBaseSQL,
|
||||
"OBJECT_NAME, OBJECT_TYPE, COMMENTS",
|
||||
"OBJECT_TYPE",
|
||||
oracleListObjectsOrderSQL,
|
||||
nil,
|
||||
constraints,
|
||||
)
|
||||
}
|
||||
|
||||
func oracleConstrainedMetadataListQuery(baseSQL, selectList, typeColumn, orderSQL string, baseArgs []any, constraints metadataListConstraints) oracleMetadataListQuery {
|
||||
args := append([]any{}, baseArgs...)
|
||||
where := make([]string, 0, 2)
|
||||
|
|
@ -923,6 +992,9 @@ func (s *server) listTables(schema string, constraints metadataListConstraints)
|
|||
return nil, err
|
||||
}
|
||||
query := oracleListTablesQuery(schema, constraints)
|
||||
if s.schemaIsSessionUser(schema) {
|
||||
query = oracleListSessionUserTablesQuery(constraints)
|
||||
}
|
||||
rows, err := s.queryRows(query.SQL, query.Args)
|
||||
if err != nil {
|
||||
if isOraclePGALimitError(err) {
|
||||
|
|
@ -948,6 +1020,9 @@ func (s *server) listObjects(schema string, constraints metadataListConstraints)
|
|||
return nil, err
|
||||
}
|
||||
query := oracleListObjectsQuery(schema, constraints)
|
||||
if s.schemaIsSessionUser(schema) {
|
||||
query = oracleListSessionUserObjectsQuery(constraints)
|
||||
}
|
||||
rows, err := s.queryRows(query.SQL, query.Args)
|
||||
if err != nil {
|
||||
if isOraclePGALimitError(err) {
|
||||
|
|
|
|||
|
|
@ -474,6 +474,41 @@ func TestListTablesQueryAppliesMetadataConstraints(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestListSessionUserTablesQueryUsesUserDictionary(t *testing.T) {
|
||||
query := oracleListSessionUserTablesQuery(metadataListConstraints{
|
||||
Filter: "u_r",
|
||||
Limit: 501,
|
||||
Offset: 10,
|
||||
ObjectTypes: []string{"view", "TABLE", "TABLE"},
|
||||
})
|
||||
sqlText := strings.ToUpper(query.SQL)
|
||||
|
||||
if !strings.Contains(sqlText, "USER_TABLES") || !strings.Contains(sqlText, "USER_OBJECTS") {
|
||||
t.Fatalf("session-user table listing should use USER_* dictionaries, got: %s", query.SQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "ALL_TABLES") || strings.Contains(sqlText, "ALL_OBJECTS") {
|
||||
t.Fatalf("session-user table listing should avoid ALL_* dictionaries, got: %s", query.SQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "OWNER =") {
|
||||
t.Fatalf("session-user table listing should not add owner predicates, got: %s", query.SQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "UPPER(OBJECT_NAME) LIKE :1 ESCAPE '\\'") {
|
||||
t.Fatalf("table listing should push filter predicate, got: %s", query.SQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "TABLE_TYPE IN (:2,:3)") {
|
||||
t.Fatalf("table listing should push table type predicate, got: %s", query.SQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "ROWNUM <= :4") || !strings.Contains(sqlText, "DBX_RN > :5") {
|
||||
t.Fatalf("table listing should use rownum pagination, got: %s", query.SQL)
|
||||
}
|
||||
if len(query.Args) != 5 {
|
||||
t.Fatalf("unexpected args: %#v", query.Args)
|
||||
}
|
||||
if query.Args[0] != "%U%\\_%R%" || query.Args[1] != "TABLE" || query.Args[2] != "VIEW" || query.Args[3] != 511 || query.Args[4] != 10 {
|
||||
t.Fatalf("constraints args were not normalized: %#v", query.Args)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListObjectsSQLUsesSplitDictionaryQuery(t *testing.T) {
|
||||
sqlText := strings.ToUpper(oracleListObjectsSQL)
|
||||
|
||||
|
|
@ -516,6 +551,40 @@ func TestListObjectsQueryAppliesMetadataConstraints(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestListSessionUserObjectsQueryUsesUserDictionary(t *testing.T) {
|
||||
query := oracleListSessionUserObjectsQuery(metadataListConstraints{
|
||||
Filter: "pkg%",
|
||||
Limit: 25,
|
||||
ObjectTypes: []string{"FUNCTION", "package"},
|
||||
})
|
||||
sqlText := strings.ToUpper(query.SQL)
|
||||
|
||||
if !strings.Contains(sqlText, "USER_TABLES") || !strings.Contains(sqlText, "USER_OBJECTS") {
|
||||
t.Fatalf("session-user object listing should use USER_* dictionaries, got: %s", query.SQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "ALL_TABLES") || strings.Contains(sqlText, "ALL_OBJECTS") {
|
||||
t.Fatalf("session-user object listing should avoid ALL_* dictionaries, got: %s", query.SQL)
|
||||
}
|
||||
if strings.Contains(sqlText, "OWNER =") {
|
||||
t.Fatalf("session-user object listing should not add owner predicates, got: %s", query.SQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "UPPER(OBJECT_NAME) LIKE :1 ESCAPE '\\'") {
|
||||
t.Fatalf("object listing should push filter predicate, got: %s", query.SQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "OBJECT_TYPE IN (:2,:3)") {
|
||||
t.Fatalf("object listing should push object type predicate, got: %s", query.SQL)
|
||||
}
|
||||
if !strings.Contains(sqlText, "ROWNUM <= :4") || !strings.Contains(sqlText, "DBX_RN > :5") {
|
||||
t.Fatalf("object listing should use rownum pagination, got: %s", query.SQL)
|
||||
}
|
||||
if len(query.Args) != 5 {
|
||||
t.Fatalf("unexpected args: %#v", query.Args)
|
||||
}
|
||||
if query.Args[0] != "%P%K%G%\\%%" || query.Args[1] != "FUNCTION" || query.Args[2] != "PACKAGE" || query.Args[3] != 25 || query.Args[4] != 0 {
|
||||
t.Fatalf("object constraints args were not normalized: %#v", query.Args)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOracleFuzzyLikePatternEscapesSpecialCharacters(t *testing.T) {
|
||||
got := oracleFuzzyLikePattern(`a_%\b`)
|
||||
want := `%a%\_%\%%\\%b%`
|
||||
|
|
|
|||
Loading…
Reference in New Issue