mcp-database-inspector 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +197 -0
- package/dist/database/connection.d.ts +13 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +155 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/manager.d.ts +28 -0
- package/dist/database/manager.d.ts.map +1 -0
- package/dist/database/manager.js +621 -0
- package/dist/database/manager.js.map +1 -0
- package/dist/database/postgres-connection.d.ts +10 -0
- package/dist/database/postgres-connection.d.ts.map +1 -0
- package/dist/database/postgres-connection.js +113 -0
- package/dist/database/postgres-connection.js.map +1 -0
- package/dist/database/types.d.ts +84 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +6 -0
- package/dist/database/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +186 -0
- package/dist/server.js.map +1 -0
- package/dist/test-defaults.d.ts +2 -0
- package/dist/test-defaults.d.ts.map +1 -0
- package/dist/test-defaults.js +57 -0
- package/dist/test-defaults.js.map +1 -0
- package/dist/tools/analyze-query.d.ts +27 -0
- package/dist/tools/analyze-query.d.ts.map +1 -0
- package/dist/tools/analyze-query.js +71 -0
- package/dist/tools/analyze-query.js.map +1 -0
- package/dist/tools/execute-query.d.ts +33 -0
- package/dist/tools/execute-query.d.ts.map +1 -0
- package/dist/tools/execute-query.js +57 -0
- package/dist/tools/execute-query.js.map +1 -0
- package/dist/tools/get-foreign-keys.d.ts +38 -0
- package/dist/tools/get-foreign-keys.d.ts.map +1 -0
- package/dist/tools/get-foreign-keys.js +391 -0
- package/dist/tools/get-foreign-keys.js.map +1 -0
- package/dist/tools/get-indexes.d.ts +38 -0
- package/dist/tools/get-indexes.d.ts.map +1 -0
- package/dist/tools/get-indexes.js +472 -0
- package/dist/tools/get-indexes.js.map +1 -0
- package/dist/tools/information-schema-query.d.ts +33 -0
- package/dist/tools/information-schema-query.d.ts.map +1 -0
- package/dist/tools/information-schema-query.js +76 -0
- package/dist/tools/information-schema-query.js.map +1 -0
- package/dist/tools/inspect-table.d.ts +38 -0
- package/dist/tools/inspect-table.d.ts.map +1 -0
- package/dist/tools/inspect-table.js +351 -0
- package/dist/tools/inspect-table.js.map +1 -0
- package/dist/tools/list-databases.d.ts +14 -0
- package/dist/tools/list-databases.d.ts.map +1 -0
- package/dist/tools/list-databases.js +83 -0
- package/dist/tools/list-databases.js.map +1 -0
- package/dist/tools/list-tables.d.ts +19 -0
- package/dist/tools/list-tables.d.ts.map +1 -0
- package/dist/tools/list-tables.js +130 -0
- package/dist/tools/list-tables.js.map +1 -0
- package/dist/utils/errors.d.ts +32 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +98 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +132 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/validators/input-validator.d.ts +76 -0
- package/dist/validators/input-validator.d.ts.map +1 -0
- package/dist/validators/input-validator.js +295 -0
- package/dist/validators/input-validator.js.map +1 -0
- package/dist/validators/query-validator.d.ts +19 -0
- package/dist/validators/query-validator.d.ts.map +1 -0
- package/dist/validators/query-validator.js +229 -0
- package/dist/validators/query-validator.js.map +1 -0
- package/enhanced_sql_prompt.md +324 -0
- package/examples/claude-config.json +23 -0
- package/examples/roo-config.json +16 -0
- package/package.json +42 -0
- package/src/database/connection.ts +165 -0
- package/src/database/manager.ts +682 -0
- package/src/database/postgres-connection.ts +123 -0
- package/src/database/types.ts +93 -0
- package/src/index.ts +136 -0
- package/src/server.ts +254 -0
- package/src/test-defaults.ts +63 -0
- package/src/tools/analyze-query.test.ts +100 -0
- package/src/tools/analyze-query.ts +112 -0
- package/src/tools/execute-query.ts +91 -0
- package/src/tools/get-foreign-keys.test.ts +51 -0
- package/src/tools/get-foreign-keys.ts +488 -0
- package/src/tools/get-indexes.test.ts +51 -0
- package/src/tools/get-indexes.ts +570 -0
- package/src/tools/information-schema-query.ts +125 -0
- package/src/tools/inspect-table.test.ts +59 -0
- package/src/tools/inspect-table.ts +440 -0
- package/src/tools/list-databases.ts +119 -0
- package/src/tools/list-tables.ts +181 -0
- package/src/utils/errors.ts +103 -0
- package/src/utils/logger.ts +158 -0
- package/src/validators/input-validator.ts +318 -0
- package/src/validators/query-validator.ts +267 -0
- package/tsconfig.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# MCP MySQL Inspector
|
|
2
|
+
|
|
3
|
+
A powerful Model Context Protocol (MCP) server for inspecting MySQL database schemas, relationships, and structure. This tool provides AI assistants with comprehensive database introspection capabilities while maintaining strict read-only access for security.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- **Read-Only Database Inspection**: Secure schema exploration without modification risks
|
|
8
|
+
- **Multi-Database Support**: Connect to multiple MySQL databases simultaneously
|
|
9
|
+
- **Comprehensive Schema Analysis**: Detailed table, column, index, and relationship information
|
|
10
|
+
- **Foreign Key Relationship Mapping**: Understand data relationships across tables
|
|
11
|
+
- **Index Performance Analysis**: Identify optimization opportunities
|
|
12
|
+
- **Security-First Design**: Query validation, input sanitization, and audit logging
|
|
13
|
+
- **Cross-Database Awareness**: Analyze relationships across multiple database instances
|
|
14
|
+
|
|
15
|
+
## 📋 Requirements
|
|
16
|
+
|
|
17
|
+
- Node.js 18 or higher
|
|
18
|
+
- MySQL 5.7+ or compatible database (MariaDB, Aurora, etc.)
|
|
19
|
+
- Network access to target database(s)
|
|
20
|
+
- Valid database credentials with SELECT permissions
|
|
21
|
+
|
|
22
|
+
## 📦 Installation
|
|
23
|
+
|
|
24
|
+
### Global Installation
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g mcp-mysql-inspector
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Local Development
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/kokorolx/mcp-mysql-inspector.git
|
|
32
|
+
cd mcp-mysql-inspector
|
|
33
|
+
npm install
|
|
34
|
+
npm run build
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### MCP Client Integration
|
|
38
|
+
|
|
39
|
+
#### Roo Configuration
|
|
40
|
+
Create `roo-config.json`:
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"servers": {
|
|
44
|
+
"mysql-inspector": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": [
|
|
47
|
+
"mcp-mysql-inspector",
|
|
48
|
+
"mysql://dev:password@localhost:3306/ecommerce",
|
|
49
|
+
"mysql://dev:password@localhost:3306/analytics"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Claude Desktop Configuration
|
|
57
|
+
Add to `claude_desktop_config.json`:
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"mysql-inspector": {
|
|
62
|
+
"command": "node",
|
|
63
|
+
"args": [
|
|
64
|
+
"/path/to/mcp-mysql-inspector/dist/index.js",
|
|
65
|
+
"mysql://username:password@localhost:3306/database1",
|
|
66
|
+
"mysql://username:password@localhost:3306/database2"
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 🛠 Available Tools
|
|
74
|
+
|
|
75
|
+
### 1. `list_databases`
|
|
76
|
+
Lists all connected databases with connection status.
|
|
77
|
+
|
|
78
|
+
### 2. `list_tables`
|
|
79
|
+
Lists all tables in a specified database with metadata.
|
|
80
|
+
|
|
81
|
+
### 3. `inspect_table`
|
|
82
|
+
Get complete table schema including columns, types, constraints, and metadata.
|
|
83
|
+
Supports both single-table and multi-table inspection via the `table` (string) or `tables` (string[]) parameter.
|
|
84
|
+
|
|
85
|
+
**Parameters:**
|
|
86
|
+
- `database` (string, required): Name of the database.
|
|
87
|
+
- `table` (string, optional): Name of a single table to inspect.
|
|
88
|
+
- `tables` (string[], optional): Array of table names to inspect (multi-table mode).
|
|
89
|
+
Provide either `table` or `tables`, not both.
|
|
90
|
+
|
|
91
|
+
**Examples:**
|
|
92
|
+
```json
|
|
93
|
+
{ "database": "mydb", "table": "users" }
|
|
94
|
+
{ "database": "mydb", "tables": ["users", "orders", "products"] }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 4. `get_foreign_keys`
|
|
98
|
+
Get foreign key relationships for one or more tables, or the entire database.
|
|
99
|
+
Supports both single-table and multi-table inspection via the `table` (string) or `tables` (string[]) parameter.
|
|
100
|
+
|
|
101
|
+
**Parameters:**
|
|
102
|
+
- `database` (string, required): Name of the database.
|
|
103
|
+
- `table` (string, optional): Name of a single table to analyze.
|
|
104
|
+
- `tables` (string[], optional): Array of table names to analyze (multi-table mode).
|
|
105
|
+
Provide either `table` or `tables`, not both.
|
|
106
|
+
|
|
107
|
+
**Examples:**
|
|
108
|
+
```json
|
|
109
|
+
{ "database": "mydb", "table": "orders" }
|
|
110
|
+
{ "database": "mydb", "tables": ["orders", "order_items"] }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 5. `get_indexes`
|
|
114
|
+
Get detailed index information for one or more tables.
|
|
115
|
+
Supports both single-table and multi-table inspection via the `table` (string) or `tables` (string[]) parameter.
|
|
116
|
+
|
|
117
|
+
**Parameters:**
|
|
118
|
+
- `database` (string, required): Name of the database.
|
|
119
|
+
- `table` (string, optional): Name of a single table to analyze.
|
|
120
|
+
- `tables` (string[], optional): Array of table names to analyze (multi-table mode).
|
|
121
|
+
Provide either `table` or `tables`, not both.
|
|
122
|
+
|
|
123
|
+
**Examples:**
|
|
124
|
+
```json
|
|
125
|
+
{ "database": "mydb", "table": "products" }
|
|
126
|
+
{ "database": "mydb", "tables": ["products", "categories"] }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 🔒 Security Features
|
|
130
|
+
|
|
131
|
+
### Query Safety
|
|
132
|
+
- **Whitelist-Only Approach**: Only SELECT, SHOW, DESCRIBE, EXPLAIN queries allowed
|
|
133
|
+
- **SQL Injection Prevention**: Multi-layer validation and parameter binding
|
|
134
|
+
- **Row Limits**: Automatic limits to prevent resource exhaustion
|
|
135
|
+
- **Timeout Protection**: Internal query timeouts are enforced, but `timeout` is not a valid connection option.
|
|
136
|
+
|
|
137
|
+
### Input Validation
|
|
138
|
+
- **URL Validation**: Comprehensive connection string validation
|
|
139
|
+
- **Identifier Sanitization**: MySQL identifier format validation
|
|
140
|
+
- **Parameter Sanitization**: Input cleaning and null-byte removal
|
|
141
|
+
|
|
142
|
+
### Audit & Logging
|
|
143
|
+
- **Comprehensive Logging**: All operations logged with configurable levels
|
|
144
|
+
- **Sensitive Data Masking**: Credentials automatically redacted from logs
|
|
145
|
+
- **Performance Monitoring**: Query timing and resource usage tracking
|
|
146
|
+
|
|
147
|
+
## ⚙️ Configuration
|
|
148
|
+
|
|
149
|
+
### Environment Variables
|
|
150
|
+
|
|
151
|
+
| Variable | Description | Default | Example |
|
|
152
|
+
|----------|-------------|---------|----------|
|
|
153
|
+
| `LOG_LEVEL` | Logging level (error, warn, info, debug, trace) | `info` | `LOG_LEVEL=debug` |
|
|
154
|
+
|
|
155
|
+
### Database URL Format
|
|
156
|
+
```
|
|
157
|
+
mysql://username:password@hostname:port/database?options
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Supported Options:**
|
|
161
|
+
- `ssl=true/false` - Enable/disable SSL connections
|
|
162
|
+
<!--
|
|
163
|
+
- `timeout=seconds` - (Not supported) The `timeout` option is not valid for MySQL2 Connection and will be ignored.
|
|
164
|
+
-->
|
|
165
|
+
|
|
166
|
+
## 🚨 Troubleshooting
|
|
167
|
+
|
|
168
|
+
### Common Issues
|
|
169
|
+
|
|
170
|
+
#### Connection Failures
|
|
171
|
+
```bash
|
|
172
|
+
# Test connection manually
|
|
173
|
+
mysql -h hostname -u username -p database_name
|
|
174
|
+
|
|
175
|
+
# Check network connectivity
|
|
176
|
+
telnet hostname 3306
|
|
177
|
+
|
|
178
|
+
# Verify credentials and permissions
|
|
179
|
+
SHOW GRANTS FOR 'username'@'hostname';
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Permission Errors
|
|
183
|
+
Ensure the database user has at least:
|
|
184
|
+
```sql
|
|
185
|
+
GRANT SELECT ON database_name.* TO 'username'@'%';
|
|
186
|
+
GRANT SELECT ON INFORMATION_SCHEMA.* TO 'username'@'%';
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Debug Mode
|
|
190
|
+
Enable detailed logging:
|
|
191
|
+
```bash
|
|
192
|
+
LOG_LEVEL=debug mcp-mysql-inspector "mysql://..."
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## 📄 License
|
|
196
|
+
|
|
197
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DatabaseType, DatabaseConnectionOptions, QueryResult } from './types.js';
|
|
2
|
+
export declare class DatabaseConnection {
|
|
3
|
+
private static readonly DEFAULT_TIMEOUT;
|
|
4
|
+
private static readonly DEFAULT_ACQUIRE_TIMEOUT;
|
|
5
|
+
static detectDatabaseType(url: string): DatabaseType;
|
|
6
|
+
static parseConnectionUrl(url: string): DatabaseConnectionOptions;
|
|
7
|
+
static createConnection(options: DatabaseConnectionOptions): Promise<any>;
|
|
8
|
+
static executeQuery(connection: any, query: string, params?: any[], type?: DatabaseType): Promise<QueryResult>;
|
|
9
|
+
static closeConnection(connection: any, type?: DatabaseType): Promise<void>;
|
|
10
|
+
static testConnection(options: DatabaseConnectionOptions): Promise<boolean>;
|
|
11
|
+
static extractDatabaseName(url: string): string;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/database/connection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAKlF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAS;IAChD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAS;IAExD,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY;IAYpD,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,yBAAyB;WAqCpD,gBAAgB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,GAAG,CAAC;WAqClE,YAAY,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,GAAE,YAAiC,GAAG,OAAO,CAAC,WAAW,CAAC;WA2B3H,eAAe,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,GAAE,YAAiC,GAAG,OAAO,CAAC,IAAI,CAAC;WAaxF,cAAc,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBjF,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;CAQhD"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import mysql from 'mysql2/promise';
|
|
2
|
+
import { URL } from 'url';
|
|
3
|
+
import { DatabaseType } from './types.js';
|
|
4
|
+
import { Logger } from '../utils/logger.js';
|
|
5
|
+
import { DatabaseError } from '../utils/errors.js';
|
|
6
|
+
import { PostgresConnection } from './postgres-connection.js';
|
|
7
|
+
export class DatabaseConnection {
|
|
8
|
+
static DEFAULT_TIMEOUT = 30000;
|
|
9
|
+
static DEFAULT_ACQUIRE_TIMEOUT = 60000;
|
|
10
|
+
static detectDatabaseType(url) {
|
|
11
|
+
try {
|
|
12
|
+
const protocol = new URL(url).protocol.replace(':', '');
|
|
13
|
+
if (protocol === 'mysql')
|
|
14
|
+
return DatabaseType.MySQL;
|
|
15
|
+
if (protocol === 'postgresql' || protocol === 'postgres')
|
|
16
|
+
return DatabaseType.PostgreSQL;
|
|
17
|
+
throw new DatabaseError(`Unsupported database protocol: ${protocol}. Supported protocols: mysql, postgresql, postgres.`);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error instanceof DatabaseError)
|
|
21
|
+
throw error;
|
|
22
|
+
throw new DatabaseError(`Invalid connection URL: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
static parseConnectionUrl(url) {
|
|
26
|
+
const type = this.detectDatabaseType(url);
|
|
27
|
+
if (type === DatabaseType.PostgreSQL) {
|
|
28
|
+
return PostgresConnection.parseConnectionUrl(url);
|
|
29
|
+
}
|
|
30
|
+
// MySQL parsing logic (orig)
|
|
31
|
+
try {
|
|
32
|
+
const parsedUrl = new URL(url);
|
|
33
|
+
const options = {
|
|
34
|
+
type: DatabaseType.MySQL,
|
|
35
|
+
host: parsedUrl.hostname,
|
|
36
|
+
port: parsedUrl.port ? parseInt(parsedUrl.port) : 3306,
|
|
37
|
+
user: parsedUrl.username,
|
|
38
|
+
password: parsedUrl.password,
|
|
39
|
+
database: parsedUrl.pathname.slice(1), // Remove leading slash
|
|
40
|
+
reconnect: true
|
|
41
|
+
};
|
|
42
|
+
// Parse SSL settings from query parameters
|
|
43
|
+
const searchParams = parsedUrl.searchParams;
|
|
44
|
+
if (searchParams.has('ssl')) {
|
|
45
|
+
const sslValue = searchParams.get('ssl');
|
|
46
|
+
if (sslValue === 'true' || sslValue === '1') {
|
|
47
|
+
options.ssl = true;
|
|
48
|
+
}
|
|
49
|
+
else if (sslValue === 'false' || sslValue === '0') {
|
|
50
|
+
options.ssl = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return options;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw new DatabaseError(`Invalid connection URL: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
static async createConnection(options) {
|
|
60
|
+
if (options.type === DatabaseType.PostgreSQL) {
|
|
61
|
+
return PostgresConnection.createClient(options);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
Logger.info(`Connecting to MySQL database at ${options.host}:${options.port}/${options.database}`);
|
|
65
|
+
const connectionConfig = {
|
|
66
|
+
host: options.host,
|
|
67
|
+
port: options.port,
|
|
68
|
+
user: options.user,
|
|
69
|
+
password: options.password,
|
|
70
|
+
database: options.database,
|
|
71
|
+
multipleStatements: false,
|
|
72
|
+
dateStrings: true,
|
|
73
|
+
};
|
|
74
|
+
if (options.ssl === false) {
|
|
75
|
+
connectionConfig.ssl = false;
|
|
76
|
+
}
|
|
77
|
+
else if (options.ssl === true) {
|
|
78
|
+
connectionConfig.ssl = {};
|
|
79
|
+
}
|
|
80
|
+
else if (options.ssl && typeof options.ssl === 'object') {
|
|
81
|
+
connectionConfig.ssl = options.ssl;
|
|
82
|
+
}
|
|
83
|
+
const connection = await mysql.createConnection(connectionConfig);
|
|
84
|
+
await connection.ping();
|
|
85
|
+
Logger.info(`Successfully connected to MySQL database: ${options.database}`);
|
|
86
|
+
return connection;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
Logger.error(`Failed to connect to MySQL database: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
90
|
+
throw new DatabaseError(`Connection failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
static async executeQuery(connection, query, params, type = DatabaseType.MySQL) {
|
|
94
|
+
if (type === DatabaseType.PostgreSQL) {
|
|
95
|
+
return PostgresConnection.executeQuery(connection, query, params);
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
Logger.debug(`Executing MySQL query: ${query.substring(0, 100)}${query.length > 100 ? '...' : ''}`);
|
|
99
|
+
const [rows, fields] = await connection.execute(query, params);
|
|
100
|
+
const result = {
|
|
101
|
+
rows: Array.isArray(rows) ? rows : [],
|
|
102
|
+
fields: Array.isArray(fields) ? fields : [],
|
|
103
|
+
};
|
|
104
|
+
Logger.debug(`Query executed successfully, returned ${result.rows.length} rows`);
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
Logger.error(`MySQL query execution failed: ${error instanceof Error ? error.message : 'Unknown error'}\n` +
|
|
109
|
+
`Full SQL: ${query}\n` +
|
|
110
|
+
`Params: ${JSON.stringify(params)}`);
|
|
111
|
+
throw new DatabaseError(`Query execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
static async closeConnection(connection, type = DatabaseType.MySQL) {
|
|
115
|
+
if (type === DatabaseType.PostgreSQL) {
|
|
116
|
+
return PostgresConnection.closeConnection(connection);
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await connection.end();
|
|
120
|
+
Logger.info('MySQL connection closed successfully');
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
Logger.warn(`Error closing MySQL connection: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
static async testConnection(options) {
|
|
127
|
+
if (options.type === DatabaseType.PostgreSQL) {
|
|
128
|
+
return PostgresConnection.testConnection(options);
|
|
129
|
+
}
|
|
130
|
+
let connection = null;
|
|
131
|
+
try {
|
|
132
|
+
connection = await this.createConnection(options);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
Logger.warn(`MySQL connection test failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
if (connection) {
|
|
141
|
+
await this.closeConnection(connection);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
static extractDatabaseName(url) {
|
|
146
|
+
try {
|
|
147
|
+
const parsedUrl = new URL(url);
|
|
148
|
+
return parsedUrl.pathname.slice(1) || 'default';
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return 'default';
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/database/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DatabaseInfo, QueryResult, TableInfo, ColumnInfo, ForeignKeyInfo, IndexInfo, DatabaseType } from './types.js';
|
|
2
|
+
export declare class DatabaseManager {
|
|
3
|
+
private databases;
|
|
4
|
+
private readonly connectionTimeout;
|
|
5
|
+
private readonly maxRowLimit;
|
|
6
|
+
addDatabase(url: string, name?: string): Promise<string>;
|
|
7
|
+
removeDatabase(name: string): Promise<void>;
|
|
8
|
+
listDatabases(): DatabaseInfo[];
|
|
9
|
+
getDatabaseType(dbName: string): DatabaseType;
|
|
10
|
+
private getConnection;
|
|
11
|
+
executeQuery(dbName: string, query: string, params?: any[]): Promise<QueryResult>;
|
|
12
|
+
private addRowLimitToQuery;
|
|
13
|
+
getTables(dbName: string): Promise<TableInfo[]>;
|
|
14
|
+
private getTablesPostgres;
|
|
15
|
+
getTableSchema(dbName: string, tableName: string): Promise<ColumnInfo[]>;
|
|
16
|
+
private getTableSchemaPostgres;
|
|
17
|
+
getForeignKeys(dbName: string, tableName?: string): Promise<ForeignKeyInfo[]>;
|
|
18
|
+
private getForeignKeysPostgres;
|
|
19
|
+
getIndexes(dbName: string, tableName: string): Promise<IndexInfo[]>;
|
|
20
|
+
private getIndexesPostgres;
|
|
21
|
+
cleanup(): Promise<void>;
|
|
22
|
+
queryInformationSchema(dbName: string, table: 'COLUMNS' | 'TABLES' | 'ROUTINES', filters?: Record<string, string>, limit?: number): Promise<QueryResult>;
|
|
23
|
+
analyzeQuery(dbName: string, query: string): Promise<any>;
|
|
24
|
+
private summarizePlan;
|
|
25
|
+
private traversePostgresPlan;
|
|
26
|
+
private traverseMySQLPlan;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/database/manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAMvI,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IACnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAEtC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmCxD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcjD,aAAa,IAAI,YAAY,EAAE;IAW/B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY;YAQ/B,aAAa;IAarB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BvF,OAAO,CAAC,kBAAkB;IAapB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YAuCvC,iBAAiB;IAkCzB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;YAsDhE,sBAAsB;IAiD9B,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;YAuDrE,sBAAsB;IA+C9B,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YA8C3D,kBAAkB;IA0C1B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,sBAAsB,CAC1B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,EACxC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,KAAK,GAAE,MAAY,GAClB,OAAO,CAAC,WAAW,CAAC;IAoDjB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAsD/D,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,iBAAiB;CAc1B"}
|