diff --git a/agents/drivers/oracle-go/main.go b/agents/drivers/oracle-go/main.go index a0d5be457..3668aa931 100644 --- a/agents/drivers/oracle-go/main.go +++ b/agents/drivers/oracle-go/main.go @@ -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() diff --git a/agents/drivers/oracle-go/main_test.go b/agents/drivers/oracle-go/main_test.go index fe6e26aad..b749ac402 100644 --- a/agents/drivers/oracle-go/main_test.go +++ b/agents/drivers/oracle-go/main_test.go @@ -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"`