fdb2 1.0.39 → 1.0.40
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 +2 -1
- package/dist/public/explorer.css +403 -380
- package/dist/public/explorer.js +1294 -737
- package/dist/public/index.js +242 -16
- package/dist/public/layout.js +1 -1
- package/dist/scripts/verify-db-support.cjs +239 -0
- package/dist/server/core/dialect.d.ts +9 -0
- package/dist/server/core/dialect.d.ts.map +1 -1
- package/dist/server/core/dialect.js +24 -9
- package/dist/server/core/dialect.js.map +1 -1
- package/dist/server/core/dialect.ts +29 -9
- package/dist/server/core/schema/__tests__/ddl-emitter.test.ts +7 -3
- package/dist/server/core/schema/ddl-emitter.d.ts.map +1 -1
- package/dist/server/core/schema/ddl-emitter.js +32 -12
- package/dist/server/core/schema/ddl-emitter.js.map +1 -1
- package/dist/server/core/schema/ddl-emitter.ts +34 -11
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +83 -6
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.ts +87 -6
- package/dist/server/model/ddl-spec.d.ts +9 -0
- package/dist/server/model/ddl-spec.d.ts.map +1 -1
- package/dist/server/model/ddl-spec.ts +9 -0
- package/dist/server/service/connection.service.d.ts +8 -0
- package/dist/server/service/connection.service.d.ts.map +1 -1
- package/dist/server/service/connection.service.js +75 -17
- package/dist/server/service/connection.service.js.map +1 -1
- package/dist/server/service/connection.service.ts +74 -17
- package/dist/server/service/database/base.service.d.ts +45 -0
- package/dist/server/service/database/base.service.d.ts.map +1 -1
- package/dist/server/service/database/base.service.js +120 -7
- package/dist/server/service/database/base.service.js.map +1 -1
- package/dist/server/service/database/base.service.ts +143 -8
- package/dist/server/service/database/cockroachdb.service.d.ts +9 -0
- package/dist/server/service/database/cockroachdb.service.d.ts.map +1 -1
- package/dist/server/service/database/cockroachdb.service.js +67 -56
- package/dist/server/service/database/cockroachdb.service.js.map +1 -1
- package/dist/server/service/database/cockroachdb.service.ts +66 -57
- package/dist/server/service/database/database.service.d.ts +3 -221
- package/dist/server/service/database/database.service.d.ts.map +1 -1
- package/dist/server/service/database/database.service.js +66 -24
- package/dist/server/service/database/database.service.js.map +1 -1
- package/dist/server/service/database/database.service.ts +69 -23
- package/dist/server/service/database/mongodb.service.d.ts +58 -3
- package/dist/server/service/database/mongodb.service.d.ts.map +1 -1
- package/dist/server/service/database/mongodb.service.js +251 -54
- package/dist/server/service/database/mongodb.service.js.map +1 -1
- package/dist/server/service/database/mongodb.service.ts +275 -60
- package/dist/server/service/database/mssql.service.d.ts +8 -0
- package/dist/server/service/database/mssql.service.d.ts.map +1 -1
- package/dist/server/service/database/mssql.service.js +41 -36
- package/dist/server/service/database/mssql.service.js.map +1 -1
- package/dist/server/service/database/mssql.service.ts +45 -40
- package/dist/server/service/database/oracle.service.d.ts +24 -0
- package/dist/server/service/database/oracle.service.d.ts.map +1 -1
- package/dist/server/service/database/oracle.service.js +146 -106
- package/dist/server/service/database/oracle.service.js.map +1 -1
- package/dist/server/service/database/oracle.service.ts +145 -105
- package/dist/server/service/database/sqlite.service.js +1 -1
- package/dist/server/service/database/sqlite.service.js.map +1 -1
- package/dist/server/service/database/sqlite.service.ts +1 -1
- package/package.json +8 -8
- package/scripts/verify-db-support.cjs +239 -0
|
@@ -24,39 +24,45 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* 获取CockroachDB数据库列表
|
|
27
|
+
* 注意:CockroachDB 兼容 PostgreSQL 协议,但没有 information_schema.databases,
|
|
28
|
+
* 数据库列表须查 pg_database。
|
|
27
29
|
*/
|
|
28
30
|
async getDatabases(dataSource: DataSource): Promise<string[]> {
|
|
29
31
|
const result = await dataSource.query(`
|
|
30
|
-
SELECT
|
|
31
|
-
|
|
32
|
-
FROM
|
|
33
|
-
|
|
34
|
-
WHERE
|
|
35
|
-
|
|
36
|
-
ORDER BY
|
|
37
|
-
|
|
32
|
+
SELECT
|
|
33
|
+
datname as name
|
|
34
|
+
FROM
|
|
35
|
+
pg_database
|
|
36
|
+
WHERE
|
|
37
|
+
datname NOT IN ('system', 'postgres')
|
|
38
|
+
ORDER BY
|
|
39
|
+
datname
|
|
38
40
|
`);
|
|
39
41
|
return result.map((row: any) => row.name);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* 获取CockroachDB表列表
|
|
46
|
+
* 注意:CockroachDB 的 information_schema.tables 没有 oid 列(与 PG 不同),
|
|
47
|
+
* 且 table_schema 是 'public' 而非数据库名。改为直接查 pg_class(relkind='r' 为普通表),
|
|
48
|
+
* 连接已定位到目标数据库,无需再按库名过滤。
|
|
44
49
|
*/
|
|
45
50
|
async getTables(dataSource: DataSource, database: string): Promise<TableEntity[]> {
|
|
46
51
|
const result = await dataSource.query(`
|
|
47
|
-
SELECT
|
|
48
|
-
|
|
52
|
+
SELECT
|
|
53
|
+
c.relname as name,
|
|
49
54
|
'table' as type,
|
|
50
|
-
obj_description(
|
|
51
|
-
FROM
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
obj_description(c.oid) as comment
|
|
56
|
+
FROM
|
|
57
|
+
pg_class c
|
|
58
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
59
|
+
WHERE
|
|
60
|
+
c.relkind = 'r'
|
|
61
|
+
AND n.nspname NOT IN ('information_schema', 'pg_catalog', 'system')
|
|
62
|
+
ORDER BY
|
|
63
|
+
c.relname
|
|
64
|
+
`);
|
|
65
|
+
|
|
60
66
|
return result.map((row: any) => ({
|
|
61
67
|
name: row.name,
|
|
62
68
|
type: row.type,
|
|
@@ -81,33 +87,31 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
81
87
|
WHEN column_name IN (
|
|
82
88
|
SELECT column_name
|
|
83
89
|
FROM information_schema.key_column_usage
|
|
84
|
-
WHERE
|
|
85
|
-
AND table_name = $2
|
|
90
|
+
WHERE table_name = $1
|
|
86
91
|
AND constraint_name LIKE '%_pkey'
|
|
87
92
|
) THEN true
|
|
88
93
|
ELSE false
|
|
89
|
-
END as isPrimary,
|
|
94
|
+
END as "isPrimary",
|
|
90
95
|
CASE
|
|
91
|
-
WHEN
|
|
96
|
+
WHEN column_default LIKE '%nextval%' OR is_identity = 'YES'
|
|
92
97
|
THEN true
|
|
93
98
|
ELSE false
|
|
94
|
-
END as isAutoIncrement
|
|
99
|
+
END as "isAutoIncrement"
|
|
95
100
|
FROM
|
|
96
101
|
information_schema.columns
|
|
97
102
|
WHERE
|
|
98
|
-
|
|
99
|
-
AND table_name = $2
|
|
103
|
+
table_name = $1
|
|
100
104
|
ORDER BY
|
|
101
105
|
ordinal_position
|
|
102
|
-
`, [
|
|
106
|
+
`, [table]);
|
|
103
107
|
|
|
104
108
|
return result.map((row: any) => ({
|
|
105
109
|
name: row.name,
|
|
106
110
|
type: row.type,
|
|
107
111
|
nullable: row.nullable === 'YES',
|
|
108
112
|
defaultValue: row.defaultValue,
|
|
109
|
-
isPrimary: row.isPrimary,
|
|
110
|
-
isAutoIncrement: row.isAutoIncrement
|
|
113
|
+
isPrimary: row.isPrimary === true,
|
|
114
|
+
isAutoIncrement: row.isAutoIncrement === true
|
|
111
115
|
}));
|
|
112
116
|
}
|
|
113
117
|
|
|
@@ -119,34 +123,43 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
119
123
|
SELECT
|
|
120
124
|
i.relname as name,
|
|
121
125
|
CASE
|
|
122
|
-
WHEN
|
|
126
|
+
WHEN ix.indisunique THEN 'UNIQUE'
|
|
123
127
|
ELSE 'INDEX'
|
|
124
128
|
END as type,
|
|
125
|
-
array_agg(a.attname ORDER BY
|
|
126
|
-
|
|
129
|
+
array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns,
|
|
130
|
+
ix.indisunique as unique
|
|
127
131
|
FROM
|
|
128
|
-
pg_index
|
|
129
|
-
JOIN pg_class t ON t.oid =
|
|
130
|
-
JOIN
|
|
131
|
-
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(
|
|
132
|
-
CROSS JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS k(n, ord) ON true
|
|
132
|
+
pg_index ix
|
|
133
|
+
JOIN pg_class t ON t.oid = ix.indrelid
|
|
134
|
+
JOIN pg_class i ON i.oid = ix.indexrelid
|
|
135
|
+
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
|
|
133
136
|
WHERE
|
|
134
|
-
|
|
135
|
-
AND t.relname = $2
|
|
137
|
+
t.relname = $1
|
|
136
138
|
GROUP BY
|
|
137
|
-
i.relname,
|
|
139
|
+
i.relname, ix.indisunique
|
|
138
140
|
ORDER BY
|
|
139
141
|
i.relname
|
|
140
|
-
`, [
|
|
142
|
+
`, [table]);
|
|
141
143
|
|
|
142
144
|
return result.map((row: any) => ({
|
|
143
145
|
name: row.name,
|
|
144
146
|
type: row.type,
|
|
145
|
-
columns: row.columns
|
|
147
|
+
columns: this.parsePgArray(row.columns),
|
|
146
148
|
unique: row.unique
|
|
147
149
|
}));
|
|
148
150
|
}
|
|
149
151
|
|
|
152
|
+
/**
|
|
153
|
+
* 解析 pg 驱动返回的数组字符串(形如 "{a,b}" 或 "{a}")为 JS 数组
|
|
154
|
+
*/
|
|
155
|
+
private parsePgArray(value: any): string[] {
|
|
156
|
+
if (Array.isArray(value)) return value;
|
|
157
|
+
if (typeof value !== 'string') return [];
|
|
158
|
+
const s = value.trim();
|
|
159
|
+
if (!s || s === '{}') return [];
|
|
160
|
+
return s.replace(/^\{|\}$/g, '').split(',').map((x) => x.trim().replace(/^"|"$/g, ''));
|
|
161
|
+
}
|
|
162
|
+
|
|
150
163
|
/**
|
|
151
164
|
* 获取CockroachDB外键信息
|
|
152
165
|
*/
|
|
@@ -171,11 +184,10 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
171
184
|
ON rc.constraint_name = tc.constraint_name
|
|
172
185
|
WHERE
|
|
173
186
|
tc.constraint_type = 'FOREIGN KEY'
|
|
174
|
-
AND tc.
|
|
175
|
-
AND tc.table_name = $2
|
|
187
|
+
AND tc.table_name = $1
|
|
176
188
|
ORDER BY
|
|
177
189
|
tc.constraint_name
|
|
178
|
-
`, [
|
|
190
|
+
`, [table]);
|
|
179
191
|
|
|
180
192
|
return result.map((row: any) => ({
|
|
181
193
|
name: row.name,
|
|
@@ -216,11 +228,9 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
216
228
|
view_definition as definition
|
|
217
229
|
FROM
|
|
218
230
|
information_schema.views
|
|
219
|
-
WHERE
|
|
220
|
-
table_schema = $1
|
|
221
231
|
ORDER BY
|
|
222
232
|
table_name
|
|
223
|
-
|
|
233
|
+
`);
|
|
224
234
|
|
|
225
235
|
return result.map((row: any) => ({
|
|
226
236
|
name: row.name,
|
|
@@ -240,9 +250,8 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
240
250
|
FROM
|
|
241
251
|
information_schema.views
|
|
242
252
|
WHERE
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
`, [database, viewName]);
|
|
253
|
+
table_name = $1
|
|
254
|
+
`, [viewName]);
|
|
246
255
|
return result[0]?.definition || '';
|
|
247
256
|
}
|
|
248
257
|
|
|
@@ -259,11 +268,11 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
259
268
|
pg_proc p
|
|
260
269
|
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
261
270
|
WHERE
|
|
262
|
-
n.nspname
|
|
271
|
+
n.nspname NOT IN ('information_schema', 'pg_catalog', 'system')
|
|
263
272
|
AND p.prokind = 'f'
|
|
264
273
|
ORDER BY
|
|
265
274
|
p.proname
|
|
266
|
-
|
|
275
|
+
`);
|
|
267
276
|
|
|
268
277
|
return result.map((row: any) => ({
|
|
269
278
|
name: row.name,
|
|
@@ -283,9 +292,9 @@ export class CockroachDBService extends BaseDatabaseService {
|
|
|
283
292
|
pg_proc p
|
|
284
293
|
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
285
294
|
WHERE
|
|
286
|
-
n.nspname
|
|
287
|
-
AND p.proname = $
|
|
288
|
-
`, [
|
|
295
|
+
n.nspname NOT IN ('information_schema', 'pg_catalog', 'system')
|
|
296
|
+
AND p.proname = $1
|
|
297
|
+
`, [procedureName]);
|
|
289
298
|
return result[0]?.definition || '';
|
|
290
299
|
}
|
|
291
300
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConnectionService } from '../connection.service';
|
|
2
2
|
import { BaseDatabaseService } from './base.service';
|
|
3
3
|
import { DatabaseEntity, TableEntity } from '../../model/database.entity';
|
|
4
|
-
import type { DdlCapability, DdlPreview, TableSpec } from '../../model/ddl-spec';
|
|
4
|
+
import type { DdlCapability, DdlExecuteResult, DdlPreview, TableSpec } from '../../model/ddl-spec';
|
|
5
5
|
/**
|
|
6
6
|
* 数据库服务管理类
|
|
7
7
|
* 负责根据数据库类型选择相应的服务实现
|
|
@@ -82,9 +82,7 @@ export declare class DatabaseService {
|
|
|
82
82
|
/**
|
|
83
83
|
* 执行建表:与预览同一出口生成语句后执行(事务包裹)。
|
|
84
84
|
*/
|
|
85
|
-
executeCreateTable(connectionId: string, databaseName: string, spec: TableSpec): Promise<
|
|
86
|
-
statements: string[];
|
|
87
|
-
}>;
|
|
85
|
+
executeCreateTable(connectionId: string, databaseName: string, spec: TableSpec): Promise<DdlExecuteResult>;
|
|
88
86
|
/**
|
|
89
87
|
* 表结构变更计划(preview/execute 的单一出口)。
|
|
90
88
|
*
|
|
@@ -132,223 +130,7 @@ export declare class DatabaseService {
|
|
|
132
130
|
/**
|
|
133
131
|
* 获取支持的数据库类型
|
|
134
132
|
*/
|
|
135
|
-
getSupportedDatabaseTypes():
|
|
136
|
-
value: string;
|
|
137
|
-
label: string;
|
|
138
|
-
icon: string;
|
|
139
|
-
defaultPort: number;
|
|
140
|
-
description: string;
|
|
141
|
-
features: {
|
|
142
|
-
supportSchemas: boolean;
|
|
143
|
-
supportProcedures: boolean;
|
|
144
|
-
supportTriggers: boolean;
|
|
145
|
-
supportViews: boolean;
|
|
146
|
-
supportFullTextSearch: boolean;
|
|
147
|
-
supportJson: boolean;
|
|
148
|
-
supportArrays?: undefined;
|
|
149
|
-
supportEnum?: undefined;
|
|
150
|
-
supportSequences?: undefined;
|
|
151
|
-
supportSynonyms?: undefined;
|
|
152
|
-
supportStoredProcedures?: undefined;
|
|
153
|
-
supportDistributed?: undefined;
|
|
154
|
-
supportDocuments?: undefined;
|
|
155
|
-
supportNoSQL?: undefined;
|
|
156
|
-
supportInMemory?: undefined;
|
|
157
|
-
supportHighPerformance?: undefined;
|
|
158
|
-
};
|
|
159
|
-
} | {
|
|
160
|
-
value: string;
|
|
161
|
-
label: string;
|
|
162
|
-
icon: string;
|
|
163
|
-
defaultPort: number;
|
|
164
|
-
description: string;
|
|
165
|
-
features: {
|
|
166
|
-
supportSchemas: boolean;
|
|
167
|
-
supportProcedures: boolean;
|
|
168
|
-
supportTriggers: boolean;
|
|
169
|
-
supportViews: boolean;
|
|
170
|
-
supportFullTextSearch: boolean;
|
|
171
|
-
supportJson: boolean;
|
|
172
|
-
supportArrays: boolean;
|
|
173
|
-
supportEnum: boolean;
|
|
174
|
-
supportSequences?: undefined;
|
|
175
|
-
supportSynonyms?: undefined;
|
|
176
|
-
supportStoredProcedures?: undefined;
|
|
177
|
-
supportDistributed?: undefined;
|
|
178
|
-
supportDocuments?: undefined;
|
|
179
|
-
supportNoSQL?: undefined;
|
|
180
|
-
supportInMemory?: undefined;
|
|
181
|
-
supportHighPerformance?: undefined;
|
|
182
|
-
};
|
|
183
|
-
} | {
|
|
184
|
-
value: string;
|
|
185
|
-
label: string;
|
|
186
|
-
icon: string;
|
|
187
|
-
defaultPort: any;
|
|
188
|
-
description: string;
|
|
189
|
-
features: {
|
|
190
|
-
supportSchemas: boolean;
|
|
191
|
-
supportProcedures: boolean;
|
|
192
|
-
supportTriggers: boolean;
|
|
193
|
-
supportViews: boolean;
|
|
194
|
-
supportFullTextSearch: boolean;
|
|
195
|
-
supportJson: boolean;
|
|
196
|
-
supportArrays: boolean;
|
|
197
|
-
supportEnum?: undefined;
|
|
198
|
-
supportSequences?: undefined;
|
|
199
|
-
supportSynonyms?: undefined;
|
|
200
|
-
supportStoredProcedures?: undefined;
|
|
201
|
-
supportDistributed?: undefined;
|
|
202
|
-
supportDocuments?: undefined;
|
|
203
|
-
supportNoSQL?: undefined;
|
|
204
|
-
supportInMemory?: undefined;
|
|
205
|
-
supportHighPerformance?: undefined;
|
|
206
|
-
};
|
|
207
|
-
} | {
|
|
208
|
-
value: string;
|
|
209
|
-
label: string;
|
|
210
|
-
icon: string;
|
|
211
|
-
defaultPort: number;
|
|
212
|
-
description: string;
|
|
213
|
-
features: {
|
|
214
|
-
supportSchemas: boolean;
|
|
215
|
-
supportProcedures: boolean;
|
|
216
|
-
supportTriggers: boolean;
|
|
217
|
-
supportViews: boolean;
|
|
218
|
-
supportFullTextSearch: boolean;
|
|
219
|
-
supportJson: boolean;
|
|
220
|
-
supportArrays: boolean;
|
|
221
|
-
supportSequences: boolean;
|
|
222
|
-
supportSynonyms: boolean;
|
|
223
|
-
supportEnum?: undefined;
|
|
224
|
-
supportStoredProcedures?: undefined;
|
|
225
|
-
supportDistributed?: undefined;
|
|
226
|
-
supportDocuments?: undefined;
|
|
227
|
-
supportNoSQL?: undefined;
|
|
228
|
-
supportInMemory?: undefined;
|
|
229
|
-
supportHighPerformance?: undefined;
|
|
230
|
-
};
|
|
231
|
-
} | {
|
|
232
|
-
value: string;
|
|
233
|
-
label: string;
|
|
234
|
-
icon: string;
|
|
235
|
-
defaultPort: number;
|
|
236
|
-
description: string;
|
|
237
|
-
features: {
|
|
238
|
-
supportSchemas: boolean;
|
|
239
|
-
supportProcedures: boolean;
|
|
240
|
-
supportTriggers: boolean;
|
|
241
|
-
supportViews: boolean;
|
|
242
|
-
supportFullTextSearch: boolean;
|
|
243
|
-
supportJson: boolean;
|
|
244
|
-
supportArrays: boolean;
|
|
245
|
-
supportStoredProcedures: boolean;
|
|
246
|
-
supportEnum?: undefined;
|
|
247
|
-
supportSequences?: undefined;
|
|
248
|
-
supportSynonyms?: undefined;
|
|
249
|
-
supportDistributed?: undefined;
|
|
250
|
-
supportDocuments?: undefined;
|
|
251
|
-
supportNoSQL?: undefined;
|
|
252
|
-
supportInMemory?: undefined;
|
|
253
|
-
supportHighPerformance?: undefined;
|
|
254
|
-
};
|
|
255
|
-
} | {
|
|
256
|
-
value: string;
|
|
257
|
-
label: string;
|
|
258
|
-
icon: string;
|
|
259
|
-
defaultPort: number;
|
|
260
|
-
description: string;
|
|
261
|
-
features: {
|
|
262
|
-
supportSchemas: boolean;
|
|
263
|
-
supportProcedures: boolean;
|
|
264
|
-
supportTriggers: boolean;
|
|
265
|
-
supportViews: boolean;
|
|
266
|
-
supportFullTextSearch: boolean;
|
|
267
|
-
supportJson: boolean;
|
|
268
|
-
supportArrays: boolean;
|
|
269
|
-
supportEnum: boolean;
|
|
270
|
-
supportDistributed: boolean;
|
|
271
|
-
supportSequences?: undefined;
|
|
272
|
-
supportSynonyms?: undefined;
|
|
273
|
-
supportStoredProcedures?: undefined;
|
|
274
|
-
supportDocuments?: undefined;
|
|
275
|
-
supportNoSQL?: undefined;
|
|
276
|
-
supportInMemory?: undefined;
|
|
277
|
-
supportHighPerformance?: undefined;
|
|
278
|
-
};
|
|
279
|
-
} | {
|
|
280
|
-
value: string;
|
|
281
|
-
label: string;
|
|
282
|
-
icon: string;
|
|
283
|
-
defaultPort: number;
|
|
284
|
-
description: string;
|
|
285
|
-
features: {
|
|
286
|
-
supportSchemas: boolean;
|
|
287
|
-
supportProcedures: boolean;
|
|
288
|
-
supportTriggers: boolean;
|
|
289
|
-
supportViews: boolean;
|
|
290
|
-
supportFullTextSearch: boolean;
|
|
291
|
-
supportJson: boolean;
|
|
292
|
-
supportArrays: boolean;
|
|
293
|
-
supportDocuments: boolean;
|
|
294
|
-
supportNoSQL: boolean;
|
|
295
|
-
supportEnum?: undefined;
|
|
296
|
-
supportSequences?: undefined;
|
|
297
|
-
supportSynonyms?: undefined;
|
|
298
|
-
supportStoredProcedures?: undefined;
|
|
299
|
-
supportDistributed?: undefined;
|
|
300
|
-
supportInMemory?: undefined;
|
|
301
|
-
supportHighPerformance?: undefined;
|
|
302
|
-
};
|
|
303
|
-
} | {
|
|
304
|
-
value: string;
|
|
305
|
-
label: string;
|
|
306
|
-
icon: string;
|
|
307
|
-
defaultPort: number;
|
|
308
|
-
description: string;
|
|
309
|
-
features: {
|
|
310
|
-
supportSchemas: boolean;
|
|
311
|
-
supportProcedures: boolean;
|
|
312
|
-
supportTriggers: boolean;
|
|
313
|
-
supportViews: boolean;
|
|
314
|
-
supportFullTextSearch: boolean;
|
|
315
|
-
supportJson: boolean;
|
|
316
|
-
supportArrays: boolean;
|
|
317
|
-
supportInMemory: boolean;
|
|
318
|
-
supportHighPerformance: boolean;
|
|
319
|
-
supportEnum?: undefined;
|
|
320
|
-
supportSequences?: undefined;
|
|
321
|
-
supportSynonyms?: undefined;
|
|
322
|
-
supportStoredProcedures?: undefined;
|
|
323
|
-
supportDistributed?: undefined;
|
|
324
|
-
supportDocuments?: undefined;
|
|
325
|
-
supportNoSQL?: undefined;
|
|
326
|
-
};
|
|
327
|
-
} | {
|
|
328
|
-
value: string;
|
|
329
|
-
label: string;
|
|
330
|
-
icon: string;
|
|
331
|
-
defaultPort: number;
|
|
332
|
-
description: string;
|
|
333
|
-
features: {
|
|
334
|
-
supportSchemas: boolean;
|
|
335
|
-
supportProcedures: boolean;
|
|
336
|
-
supportTriggers: boolean;
|
|
337
|
-
supportViews: boolean;
|
|
338
|
-
supportFullTextSearch: boolean;
|
|
339
|
-
supportJson: boolean;
|
|
340
|
-
supportArrays: boolean;
|
|
341
|
-
supportDistributed: boolean;
|
|
342
|
-
supportHighPerformance: boolean;
|
|
343
|
-
supportEnum?: undefined;
|
|
344
|
-
supportSequences?: undefined;
|
|
345
|
-
supportSynonyms?: undefined;
|
|
346
|
-
supportStoredProcedures?: undefined;
|
|
347
|
-
supportDocuments?: undefined;
|
|
348
|
-
supportNoSQL?: undefined;
|
|
349
|
-
supportInMemory?: undefined;
|
|
350
|
-
};
|
|
351
|
-
})[];
|
|
133
|
+
getSupportedDatabaseTypes(): any[];
|
|
352
134
|
/**
|
|
353
135
|
* 创建数据库
|
|
354
136
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.service.d.ts","sourceRoot":"","sources":["../../../../server/service/database/database.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EACL,cAAc,EACd,WAAW,EACZ,MAAM,6BAA6B,CAAC;AAKrC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"database.service.d.ts","sourceRoot":"","sources":["../../../../server/service/database/database.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -165,20 +165,23 @@ class DatabaseService {
|
|
|
165
165
|
/**
|
|
166
166
|
* 目标态 TableSpec 的静态校验(建表/改表共用)
|
|
167
167
|
*/
|
|
168
|
-
validateTableSpec(spec) {
|
|
168
|
+
validateTableSpec(spec, requireColumns = true) {
|
|
169
169
|
if (!spec || typeof spec.name !== 'string' || !spec.name.trim()) {
|
|
170
170
|
throw new Error('目标表名不能为空');
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
// 无模式方言(MongoDB 建集合)没有列定义,不强制要求至少一列
|
|
173
|
+
if (requireColumns && (!Array.isArray(spec.columns) || spec.columns.length === 0)) {
|
|
173
174
|
throw new Error('目标结构至少需要一列');
|
|
174
175
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
if (Array.isArray(spec.columns) && spec.columns.length > 0) {
|
|
177
|
+
const names = new Set(spec.columns.map((c) => c.name));
|
|
178
|
+
if (names.size !== spec.columns.length) {
|
|
179
|
+
throw new Error('目标结构存在重名列');
|
|
180
|
+
}
|
|
181
|
+
for (const pk of spec.primaryKey || []) {
|
|
182
|
+
if (!names.has(pk))
|
|
183
|
+
throw new Error(`主键列 "${pk}" 不在目标结构中`);
|
|
184
|
+
}
|
|
182
185
|
}
|
|
183
186
|
return spec.name.trim();
|
|
184
187
|
}
|
|
@@ -188,25 +191,31 @@ class DatabaseService {
|
|
|
188
191
|
* 前端建表全部走同一渲染出口,CREATE TABLE 不再有第二份方言实现。
|
|
189
192
|
*/
|
|
190
193
|
async buildCreatePlan(connectionId, databaseName, spec, forceRefresh = false) {
|
|
191
|
-
const tableName = this.validateTableSpec(spec);
|
|
192
194
|
const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
|
|
193
195
|
const type = dataSource.options.type;
|
|
194
196
|
const kind = (0, dialect_1.getDialectInfo)(type).kind;
|
|
195
197
|
const dbService = this.getDatabaseService(type);
|
|
196
198
|
const caps = (0, ddl_emitter_1.ddlCapabilities)(kind);
|
|
199
|
+
// 无模式方言(MongoDB):走驱动原生建集合——不生成 CREATE TABLE SQL,也不需要列定义
|
|
200
|
+
const driverCreate = caps.createStrategy === 'driver';
|
|
201
|
+
const tableName = this.validateTableSpec(spec, !driverCreate);
|
|
197
202
|
// 方言不支持建表:作为计划内错误返回(而非抛出)——capabilities 仍要带回前端用于禁用 UI
|
|
198
203
|
if (!caps.createTable) {
|
|
199
|
-
return { dataSource, kind, caps, dbService, statements: [], error: `该数据库类型(${kind})不支持通过 SQL 建表` };
|
|
204
|
+
return { dataSource, kind, caps, dbService, tableName, statements: [], error: `该数据库类型(${kind})不支持通过 SQL 建表` };
|
|
200
205
|
}
|
|
201
206
|
// 重名检测:目标态与实时结构冲突(等价 409 语义)。
|
|
202
207
|
// 预览走缓存避免每次输入都全量拉表;执行前必须 force 刷新,否则缓存会让重名检测失效。
|
|
203
208
|
const tables = await this.getTableList(connectionId, databaseName, forceRefresh);
|
|
204
209
|
if (tables.some((t) => (0, ddl_emitter_1.tableNameEquals)(kind, String(t?.name ?? ''), tableName))) {
|
|
205
|
-
return { dataSource, kind, caps, dbService, statements: [], error: `表 "${tableName}" 已存在` };
|
|
210
|
+
return { dataSource, kind, caps, dbService, tableName, statements: [], error: `表 "${tableName}" 已存在` };
|
|
211
|
+
}
|
|
212
|
+
// 驱动路径:无列定义、无 SQL 语句,执行阶段直接调 dbService.createTable
|
|
213
|
+
if (driverCreate) {
|
|
214
|
+
return { dataSource, kind, caps, dbService, tableName, statements: [], error: '' };
|
|
206
215
|
}
|
|
207
216
|
const desired = (0, canonical_1.canonicalizeTableSpec)(spec);
|
|
208
217
|
const statements = (0, ddl_emitter_1.emitCreateDdl)(kind, desired, { mssqlDatabase: databaseName });
|
|
209
|
-
return { dataSource, kind, caps, dbService, statements, error: '' };
|
|
218
|
+
return { dataSource, kind, caps, dbService, tableName, statements, error: '' };
|
|
210
219
|
}
|
|
211
220
|
/**
|
|
212
221
|
* 预览建表:纯计算不执行。与执行同一出口生成语句,所见即所得。
|
|
@@ -216,14 +225,21 @@ class DatabaseService {
|
|
|
216
225
|
*/
|
|
217
226
|
async previewCreateTable(connectionId, databaseName, spec) {
|
|
218
227
|
const plan = await this.buildCreatePlan(connectionId, databaseName, spec);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const previewText = plan.statements.length > 0
|
|
228
|
+
// 注意:计划级非致命错误(方言不支持建表、表已存在)不能抛——否则 capabilities 不会返回,
|
|
229
|
+
// 前端无法据此禁用提交按钮。错误以注释形式写入预览,并由前端 submitDisabledHint 展示。
|
|
230
|
+
const previewText = plan.statements.length > 0
|
|
231
|
+
? plan.statements.join(';\n') + ';'
|
|
232
|
+
: plan.error
|
|
233
|
+
? `-- ${plan.error}`
|
|
234
|
+
: (plan.caps.createStrategy === 'driver'
|
|
235
|
+
? `-- 创建集合 "${plan.tableName}"(无模式集合,不生成建表 SQL)`
|
|
236
|
+
: '');
|
|
222
237
|
return {
|
|
223
238
|
statements: plan.statements,
|
|
224
239
|
preview: previewText,
|
|
225
240
|
changeSet: null,
|
|
226
|
-
capabilities: plan.caps
|
|
241
|
+
capabilities: plan.caps,
|
|
242
|
+
error: plan.error || null
|
|
227
243
|
};
|
|
228
244
|
}
|
|
229
245
|
/**
|
|
@@ -234,6 +250,19 @@ class DatabaseService {
|
|
|
234
250
|
const plan = await this.buildCreatePlan(connectionId, databaseName, spec, true);
|
|
235
251
|
if (plan.error)
|
|
236
252
|
throw new Error(plan.error);
|
|
253
|
+
// 无模式方言(MongoDB):没有建表 SQL,直接走驱动原生建集合
|
|
254
|
+
if (plan.caps.createStrategy === 'driver') {
|
|
255
|
+
try {
|
|
256
|
+
await plan.dbService.createTable(plan.dataSource, databaseName, { name: plan.tableName });
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.error('执行创建集合失败:', error);
|
|
260
|
+
throw new Error(`创建集合失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
261
|
+
}
|
|
262
|
+
this.invalidateTableList(connectionId, databaseName); // 集合列表已变化
|
|
263
|
+
// native: 无 SQL 语句但集合已实际创建——前端据此与"无修改"区分
|
|
264
|
+
return { statements: plan.statements, native: true };
|
|
265
|
+
}
|
|
237
266
|
if (plan.statements.length === 0)
|
|
238
267
|
throw new Error('未能生成建表语句');
|
|
239
268
|
try {
|
|
@@ -315,14 +344,16 @@ class DatabaseService {
|
|
|
315
344
|
*/
|
|
316
345
|
async previewAlterTable(connectionId, databaseName, tableName, spec) {
|
|
317
346
|
const plan = await this.buildAlterPlan(connectionId, databaseName, tableName, spec);
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
347
|
+
// 与 previewCreateTable 同理:计划级非致命错误不抛,确保 capabilities 返回以驱动 UI 禁用。
|
|
348
|
+
const previewText = plan.statements.length > 0
|
|
349
|
+
? plan.statements.join(';\n') + ';'
|
|
350
|
+
: (plan.error ? `-- ${plan.error}` : '');
|
|
321
351
|
return {
|
|
322
352
|
statements: plan.statements,
|
|
323
353
|
preview: previewText,
|
|
324
354
|
changeSet: plan.changeSet,
|
|
325
|
-
capabilities: plan.caps
|
|
355
|
+
capabilities: plan.caps,
|
|
356
|
+
error: plan.error || null
|
|
326
357
|
};
|
|
327
358
|
}
|
|
328
359
|
/**
|
|
@@ -646,7 +677,10 @@ class DatabaseService {
|
|
|
646
677
|
supportJson: true,
|
|
647
678
|
supportArrays: true,
|
|
648
679
|
supportDocuments: true,
|
|
649
|
-
supportNoSQL: true
|
|
680
|
+
supportNoSQL: true,
|
|
681
|
+
// 数据层能力:文档型、无 SQL 编辑器(前端据此切文档模式 UI)
|
|
682
|
+
dataModel: 'document',
|
|
683
|
+
supportSqlEditor: false
|
|
650
684
|
}
|
|
651
685
|
},
|
|
652
686
|
{
|
|
@@ -654,7 +688,11 @@ class DatabaseService {
|
|
|
654
688
|
label: 'SAP HANA',
|
|
655
689
|
icon: 'bi-database',
|
|
656
690
|
defaultPort: 39013,
|
|
657
|
-
description: 'SAP HANA
|
|
691
|
+
description: 'SAP HANA内存数据库(实验性)',
|
|
692
|
+
// 实验性:依赖未随默认依赖安装的 @sap/hana-client 驱动,且官方无免费 Docker 镜像,
|
|
693
|
+
// 本仓库尚未做端到端运行验证。驱动缺失时会给出明确的安装提示。
|
|
694
|
+
experimental: true,
|
|
695
|
+
driverPackage: '@sap/hana-client',
|
|
658
696
|
features: {
|
|
659
697
|
supportSchemas: true,
|
|
660
698
|
supportProcedures: true,
|
|
@@ -700,7 +738,11 @@ class DatabaseService {
|
|
|
700
738
|
supportJson: false
|
|
701
739
|
}
|
|
702
740
|
}
|
|
703
|
-
]
|
|
741
|
+
].map((t) => ({
|
|
742
|
+
...t,
|
|
743
|
+
// 数据层能力默认值:关系型 + 支持 SQL;文档型(MongoDB)在自身 features 中覆盖
|
|
744
|
+
features: { dataModel: 'relational', supportSqlEditor: true, ...(t.features || {}) }
|
|
745
|
+
}));
|
|
704
746
|
}
|
|
705
747
|
/**
|
|
706
748
|
* 创建数据库
|