fix(oracle): avoid SYSDBA service as explain schema

This commit is contained in:
t8y2 2026-07-27 13:39:40 +08:00
parent 39d0f5b30f
commit a0b9e0b37b
No known key found for this signature in database
2 changed files with 36 additions and 8 deletions

View File

@ -952,10 +952,7 @@ func buildDSN(params connectParams) string {
return buildGoOraURL(host, port, jdbc.Database, username, params.Password, options)
}
service := strings.TrimSpace(params.Database)
if strings.HasPrefix(strings.ToUpper(service), "SYSDBA:") {
service = strings.TrimSpace(service[len("SYSDBA:"):])
}
service := oracleConnectionDatabaseName(params.Database)
port := params.Port
if port == 0 {
port = 1521
@ -963,6 +960,14 @@ func buildDSN(params connectParams) string {
return buildGoOraURL(params.Host, port, service, username, params.Password, options)
}
func oracleConnectionDatabaseName(database string) string {
database = strings.TrimSpace(database)
if strings.HasPrefix(strings.ToUpper(database), "SYSDBA:") {
return strings.TrimSpace(database[len("SYSDBA:"):])
}
return database
}
func buildGoOraJDBC(user, password, connStr string, options map[string]string) string {
if options == nil {
options = make(map[string]string)
@ -2337,10 +2342,7 @@ func (s *server) getExplainInfo(sqlText, database, schema string, timeoutSecs in
}
defer conn.Close()
targetSchema := strings.TrimSpace(schema)
if targetSchema == "" && !strings.EqualFold(strings.TrimSpace(database), strings.TrimSpace(s.params.Database)) {
targetSchema = strings.TrimSpace(database)
}
targetSchema := oracleExplainTargetSchema(database, schema, s.params.Database)
if targetSchema != "" {
var originalSchema string
if err := conn.QueryRowContext(ctx, "SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') FROM DUAL").Scan(&originalSchema); err != nil {
@ -2382,6 +2384,17 @@ func (s *server) getExplainInfo(sqlText, database, schema string, timeoutSecs in
return strings.TrimSpace(builder.String()), planRows.Err()
}
func oracleExplainTargetSchema(database, schema, configuredDatabase string) string {
if schema = strings.TrimSpace(schema); schema != "" {
return schema
}
database = oracleConnectionDatabaseName(database)
if database == "" || strings.EqualFold(database, oracleConnectionDatabaseName(configuredDatabase)) {
return ""
}
return database
}
func cleanupOracleExplainPlan(conn *sql.Conn, statementID string) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

View File

@ -425,6 +425,21 @@ func TestOracleExplainPlanBindArgsUsesNamedArguments(t *testing.T) {
}
}
func TestOracleExplainTargetSchemaIgnoresSysDBAServicePrefix(t *testing.T) {
if got := oracleExplainTargetSchema("ORCLPDB1", "", "SYSDBA:ORCLPDB1"); got != "" {
t.Fatalf("oracleExplainTargetSchema() = %q, want no schema switch", got)
}
}
func TestOracleExplainTargetSchemaKeepsSelectedSchema(t *testing.T) {
if got := oracleExplainTargetSchema("APP", "", "SYSDBA:ORCLPDB1"); got != "APP" {
t.Fatalf("oracleExplainTargetSchema() = %q, want APP", got)
}
if got := oracleExplainTargetSchema("ORCLPDB1", "REPORTING", "SYSDBA:ORCLPDB1"); got != "REPORTING" {
t.Fatalf("oracleExplainTargetSchema() = %q, want REPORTING", got)
}
}
func protocolContract(t *testing.T) struct {
ProtocolVersion int `json:"protocolVersion"`
AllCapabilities []string `json:"allCapabilities"`