Skip to content

Commit 715c8cd

Browse files
akoclaude
andcommitted
feat: SQL CONNECT from connections.yaml and auto-connect on first use
Three improvements to external SQL connectivity: 1. SQL CONNECT <alias> — short form that resolves driver and DSN from env vars or .mxcli/connections.yaml, avoiding credential exposure in command history. 2. Auto-connect on first use — SQL ora SHOW TABLES auto-connects using the config if no active connection exists for that alias. 3. Oracle DESCRIBE with schema support — SQL ora DESCRIBE SCHEMA.TABLE now splits into owner + table_name filters. Also replaced data_default (LONG type) with data_length in the Oracle query. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8fedb49 commit 715c8cd

File tree

9 files changed

+1135
-993
lines changed

9 files changed

+1135
-993
lines changed

mdl/executor/cmd_import.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ func (e *Executor) execImport(s *ast.ImportStmt) error {
2525
return err
2626
}
2727

28-
// Get source connection
29-
mgr := e.ensureSQLManager()
30-
sourceConn, err := mgr.Get(s.SourceAlias)
28+
// Get source connection (auto-connects from config if needed)
29+
sourceConn, err := e.getOrAutoConnect(s.SourceAlias)
3130
if err != nil {
3231
return fmt.Errorf("source connection: %w", err)
3332
}

mdl/executor/cmd_sql.go

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,29 @@ func (e *Executor) ensureSQLManager() *sqllib.Manager {
2121
return e.sqlMgr
2222
}
2323

24+
// getOrAutoConnect returns an existing connection or auto-connects using connections.yaml.
25+
func (e *Executor) getOrAutoConnect(alias string) (*sqllib.Connection, error) {
26+
mgr := e.ensureSQLManager()
27+
conn, err := mgr.Get(alias)
28+
if err == nil {
29+
return conn, nil
30+
}
31+
32+
// Not connected yet — try auto-connect from config
33+
if acErr := e.autoConnect(alias); acErr != nil {
34+
return nil, fmt.Errorf("no connection '%s' (and auto-connect failed: %v)", alias, acErr)
35+
}
36+
return mgr.Get(alias)
37+
}
38+
2439
// execSQLConnect handles SQL CONNECT <driver> '<dsn>' AS <alias>
40+
// and SQL CONNECT <alias> (resolve from connections.yaml).
2541
func (e *Executor) execSQLConnect(s *ast.SQLConnectStmt) error {
42+
if s.DSN == "" && s.Driver == "" {
43+
// Short form: SQL CONNECT <alias> — resolve from config
44+
return e.autoConnect(s.Alias)
45+
}
46+
2647
driver, err := sqllib.ParseDriver(s.Driver)
2748
if err != nil {
2849
return err
@@ -37,6 +58,23 @@ func (e *Executor) execSQLConnect(s *ast.SQLConnectStmt) error {
3758
return nil
3859
}
3960

61+
// autoConnect resolves a connection alias from env vars or .mxcli/connections.yaml
62+
// and connects automatically.
63+
func (e *Executor) autoConnect(alias string) error {
64+
rc, err := sqllib.ResolveConnection(sqllib.ResolveOptions{Alias: alias})
65+
if err != nil {
66+
return fmt.Errorf("cannot resolve connection '%s': %w\nAdd it to .mxcli/connections.yaml or use: SQL CONNECT <driver> '<dsn>' AS %s", alias, err, alias)
67+
}
68+
69+
mgr := e.ensureSQLManager()
70+
if err := mgr.Connect(rc.Driver, rc.DSN, alias); err != nil {
71+
return err
72+
}
73+
74+
fmt.Fprintf(e.output, "Connected to %s database as '%s' (from config)\n", rc.Driver, alias)
75+
return nil
76+
}
77+
4078
// execSQLDisconnect handles SQL DISCONNECT <alias>
4179
func (e *Executor) execSQLDisconnect(s *ast.SQLDisconnectStmt) error {
4280
mgr := e.ensureSQLManager()
@@ -75,8 +113,7 @@ func (e *Executor) execSQLConnections() error {
75113

76114
// execSQLQuery handles SQL <alias> <raw-sql>
77115
func (e *Executor) execSQLQuery(s *ast.SQLQueryStmt) error {
78-
mgr := e.ensureSQLManager()
79-
conn, err := mgr.Get(s.Alias)
116+
conn, err := e.getOrAutoConnect(s.Alias)
80117
if err != nil {
81118
return err
82119
}
@@ -96,8 +133,7 @@ func (e *Executor) execSQLQuery(s *ast.SQLQueryStmt) error {
96133

97134
// execSQLShowTables handles SQL <alias> SHOW TABLES
98135
func (e *Executor) execSQLShowTables(s *ast.SQLShowTablesStmt) error {
99-
mgr := e.ensureSQLManager()
100-
conn, err := mgr.Get(s.Alias)
136+
conn, err := e.getOrAutoConnect(s.Alias)
101137
if err != nil {
102138
return err
103139
}
@@ -117,8 +153,7 @@ func (e *Executor) execSQLShowTables(s *ast.SQLShowTablesStmt) error {
117153

118154
// execSQLShowViews handles SQL <alias> SHOW VIEWS
119155
func (e *Executor) execSQLShowViews(s *ast.SQLShowViewsStmt) error {
120-
mgr := e.ensureSQLManager()
121-
conn, err := mgr.Get(s.Alias)
156+
conn, err := e.getOrAutoConnect(s.Alias)
122157
if err != nil {
123158
return err
124159
}
@@ -138,8 +173,7 @@ func (e *Executor) execSQLShowViews(s *ast.SQLShowViewsStmt) error {
138173

139174
// execSQLShowFunctions handles SQL <alias> SHOW FUNCTIONS
140175
func (e *Executor) execSQLShowFunctions(s *ast.SQLShowFunctionsStmt) error {
141-
mgr := e.ensureSQLManager()
142-
conn, err := mgr.Get(s.Alias)
176+
conn, err := e.getOrAutoConnect(s.Alias)
143177
if err != nil {
144178
return err
145179
}
@@ -159,8 +193,7 @@ func (e *Executor) execSQLShowFunctions(s *ast.SQLShowFunctionsStmt) error {
159193

160194
// execSQLGenerateConnector handles SQL <alias> GENERATE CONNECTOR INTO <module> [TABLES (...)] [VIEWS (...)] [EXEC]
161195
func (e *Executor) execSQLGenerateConnector(s *ast.SQLGenerateConnectorStmt) error {
162-
mgr := e.ensureSQLManager()
163-
conn, err := mgr.Get(s.Alias)
196+
conn, err := e.getOrAutoConnect(s.Alias)
164197
if err != nil {
165198
return err
166199
}
@@ -216,8 +249,7 @@ func (e *Executor) executeGeneratedMDL(mdl string) error {
216249

217250
// execSQLDescribeTable handles SQL <alias> DESCRIBE <table>
218251
func (e *Executor) execSQLDescribeTable(s *ast.SQLDescribeTableStmt) error {
219-
mgr := e.ensureSQLManager()
220-
conn, err := mgr.Get(s.Alias)
252+
conn, err := e.getOrAutoConnect(s.Alias)
221253
if err != nil {
222254
return err
223255
}

mdl/grammar/MDLParser.g4

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2916,10 +2916,11 @@ debugStatement
29162916
*/
29172917
sqlStatement
29182918
: SQL CONNECT IDENTIFIER STRING_LITERAL AS IDENTIFIER # sqlConnect
2919+
| SQL CONNECT IDENTIFIER # sqlConnectAlias
29192920
| SQL DISCONNECT IDENTIFIER # sqlDisconnect
29202921
| SQL CONNECTIONS # sqlConnections
29212922
| SQL IDENTIFIER SHOW identifierOrKeyword # sqlShowTables
2922-
| SQL IDENTIFIER DESCRIBE identifierOrKeyword # sqlDescribeTable
2923+
| SQL IDENTIFIER DESCRIBE qualifiedName # sqlDescribeTable
29232924
| SQL IDENTIFIER GENERATE CONNECTOR INTO identifierOrKeyword
29242925
(TABLES LPAREN identifierOrKeyword (COMMA identifierOrKeyword)* RPAREN)?
29252926
(VIEWS LPAREN identifierOrKeyword (COMMA identifierOrKeyword)* RPAREN)?

mdl/grammar/parser/MDLParser.interp

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)