fdb2 1.0.8 → 1.0.9

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.
Files changed (235) hide show
  1. package/.dockerignore +21 -21
  2. package/.editorconfig +11 -11
  3. package/.eslintrc.cjs +14 -14
  4. package/.eslintrc.json +7 -7
  5. package/.prettierrc.js +3 -3
  6. package/.tpl.env +21 -21
  7. package/.vscodeignore +45 -45
  8. package/README.md +312 -312
  9. package/bin/build.sh +28 -28
  10. package/bin/deploy.sh +8 -8
  11. package/bin/dev.sh +10 -10
  12. package/bin/docker/dev-docker-compose.yml +43 -43
  13. package/bin/docker/dev.Dockerfile +24 -24
  14. package/bin/docker/prod-docker-compose.yml +17 -17
  15. package/bin/docker/prod.Dockerfile +29 -29
  16. package/bin/fdb2.js +220 -220
  17. package/dist/package.json +29 -29
  18. package/dist/pnpm-lock.yaml +1042 -354
  19. package/dist/public/explorer.css +1464 -1437
  20. package/dist/public/explorer.js +759 -223
  21. package/dist/public/index.css +1026 -1026
  22. package/dist/public/index.js +15 -9
  23. package/dist/public/layout.css +221 -221
  24. package/dist/public/layout.js +1 -1
  25. package/dist/public/vue.js +8 -2
  26. package/dist/scripts/preinstall.js +112 -112
  27. package/dist/server/index.d.ts.map +1 -1
  28. package/dist/server/index.js +8 -0
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/index.ts +680 -671
  31. package/dist/server/model/connection.entity.ts +65 -65
  32. package/dist/server/model/database.entity.ts +245 -245
  33. package/dist/server/service/connection.service.d.ts +6 -1
  34. package/dist/server/service/connection.service.d.ts.map +1 -1
  35. package/dist/server/service/connection.service.js +15 -0
  36. package/dist/server/service/connection.service.js.map +1 -1
  37. package/dist/server/service/connection.service.ts +356 -341
  38. package/dist/server/service/database/base.service.d.ts +27 -0
  39. package/dist/server/service/database/base.service.d.ts.map +1 -1
  40. package/dist/server/service/database/base.service.js +17 -0
  41. package/dist/server/service/database/base.service.js.map +1 -1
  42. package/dist/server/service/database/base.service.ts +406 -367
  43. package/dist/server/service/database/cockroachdb.service.d.ts +16 -0
  44. package/dist/server/service/database/cockroachdb.service.d.ts.map +1 -1
  45. package/dist/server/service/database/cockroachdb.service.js +220 -154
  46. package/dist/server/service/database/cockroachdb.service.js.map +1 -1
  47. package/dist/server/service/database/cockroachdb.service.ts +871 -782
  48. package/dist/server/service/database/database.service.d.ts +4 -0
  49. package/dist/server/service/database/database.service.d.ts.map +1 -1
  50. package/dist/server/service/database/database.service.js +123 -0
  51. package/dist/server/service/database/database.service.js.map +1 -1
  52. package/dist/server/service/database/database.service.ts +775 -638
  53. package/dist/server/service/database/index.ts +6 -6
  54. package/dist/server/service/database/mongodb.service.d.ts +16 -0
  55. package/dist/server/service/database/mongodb.service.d.ts.map +1 -1
  56. package/dist/server/service/database/mongodb.service.js +35 -0
  57. package/dist/server/service/database/mongodb.service.js.map +1 -1
  58. package/dist/server/service/database/mongodb.service.ts +39 -1
  59. package/dist/server/service/database/mssql.service.d.ts +16 -0
  60. package/dist/server/service/database/mssql.service.d.ts.map +1 -1
  61. package/dist/server/service/database/mssql.service.js +168 -96
  62. package/dist/server/service/database/mssql.service.js.map +1 -1
  63. package/dist/server/service/database/mssql.service.ts +931 -840
  64. package/dist/server/service/database/mysql.service.d.ts +16 -0
  65. package/dist/server/service/database/mysql.service.d.ts.map +1 -1
  66. package/dist/server/service/database/mysql.service.js +189 -80
  67. package/dist/server/service/database/mysql.service.js.map +1 -1
  68. package/dist/server/service/database/mysql.service.ts +1025 -890
  69. package/dist/server/service/database/oracle.service.d.ts +16 -0
  70. package/dist/server/service/database/oracle.service.d.ts.map +1 -1
  71. package/dist/server/service/database/oracle.service.js +182 -120
  72. package/dist/server/service/database/oracle.service.js.map +1 -1
  73. package/dist/server/service/database/oracle.service.ts +1035 -959
  74. package/dist/server/service/database/postgres.service.d.ts +16 -0
  75. package/dist/server/service/database/postgres.service.d.ts.map +1 -1
  76. package/dist/server/service/database/postgres.service.js +154 -88
  77. package/dist/server/service/database/postgres.service.js.map +1 -1
  78. package/dist/server/service/database/postgres.service.ts +960 -871
  79. package/dist/server/service/database/sap.service.d.ts +16 -0
  80. package/dist/server/service/database/sap.service.d.ts.map +1 -1
  81. package/dist/server/service/database/sap.service.js +66 -0
  82. package/dist/server/service/database/sap.service.js.map +1 -1
  83. package/dist/server/service/database/sap.service.ts +89 -0
  84. package/dist/server/service/database/sqlite.service.d.ts +16 -0
  85. package/dist/server/service/database/sqlite.service.d.ts.map +1 -1
  86. package/dist/server/service/database/sqlite.service.js +77 -18
  87. package/dist/server/service/database/sqlite.service.js.map +1 -1
  88. package/dist/server/service/database/sqlite.service.ts +787 -708
  89. package/dist/server/service/session.service.ts +158 -158
  90. package/dist/view/index.html +38 -38
  91. package/env.d.ts +1 -1
  92. package/package.json +1 -1
  93. package/packages/vscode/.vscodeignore +44 -44
  94. package/packages/vscode/README.md +62 -62
  95. package/packages/vscode/out/database-services/cockroachdb.service.js +154 -154
  96. package/packages/vscode/out/database-services/mssql.service.js +96 -96
  97. package/packages/vscode/out/database-services/mysql.service.js +80 -80
  98. package/packages/vscode/out/database-services/oracle.service.js +120 -120
  99. package/packages/vscode/out/database-services/postgres.service.js +88 -88
  100. package/packages/vscode/out/database-services/sqlite.service.js +18 -18
  101. package/packages/vscode/out/provider/WebViewProvider.js +32 -32
  102. package/packages/vscode/package.json +142 -142
  103. package/packages/vscode/resources/icon.svg +5 -5
  104. package/packages/vscode/resources/webview/connection.css +41 -41
  105. package/packages/vscode/resources/webview/database.css +163 -163
  106. package/packages/vscode/resources/webview/index.html +9 -9
  107. package/packages/vscode/resources/webview/modules/header.tpl +13 -13
  108. package/packages/vscode/resources/webview/modules/initial_state.tpl +54 -54
  109. package/packages/vscode/resources/webview/query.css +104 -104
  110. package/packages/vscode/src/database-services/base.service.ts +362 -362
  111. package/packages/vscode/src/database-services/cockroachdb.service.ts +659 -659
  112. package/packages/vscode/src/database-services/connection.service.ts +340 -340
  113. package/packages/vscode/src/database-services/database.service.ts +629 -629
  114. package/packages/vscode/src/database-services/index.ts +6 -6
  115. package/packages/vscode/src/database-services/model/connection.entity.ts +65 -65
  116. package/packages/vscode/src/database-services/model/database.entity.ts +245 -245
  117. package/packages/vscode/src/database-services/mssql.service.ts +722 -722
  118. package/packages/vscode/src/database-services/mysql.service.ts +760 -760
  119. package/packages/vscode/src/database-services/oracle.service.ts +831 -831
  120. package/packages/vscode/src/database-services/postgres.service.ts +740 -740
  121. package/packages/vscode/src/database-services/sqlite.service.ts +558 -558
  122. package/packages/vscode/src/extension.ts +76 -76
  123. package/packages/vscode/src/provider/DatabaseTreeProvider.ts +167 -167
  124. package/packages/vscode/src/provider/WebViewProvider.ts +277 -277
  125. package/packages/vscode/src/service/DatabaseServiceBridge.ts +414 -414
  126. package/packages/vscode/src/typings/connection.ts +90 -90
  127. package/packages/vscode/tsconfig.json +21 -21
  128. package/public/index.html +9 -9
  129. package/public/modules/header.tpl +13 -13
  130. package/public/modules/initial_state.tpl +54 -54
  131. package/scripts/preinstall.js +112 -112
  132. package/server/index.ts +680 -671
  133. package/server/model/connection.entity.ts +65 -65
  134. package/server/model/database.entity.ts +245 -245
  135. package/server/service/connection.service.ts +356 -341
  136. package/server/service/database/base.service.ts +406 -367
  137. package/server/service/database/cockroachdb.service.ts +871 -782
  138. package/server/service/database/database.service.ts +775 -638
  139. package/server/service/database/index.ts +6 -6
  140. package/server/service/database/mongodb.service.ts +39 -1
  141. package/server/service/database/mssql.service.ts +931 -840
  142. package/server/service/database/mysql.service.ts +1025 -890
  143. package/server/service/database/oracle.service.ts +1035 -959
  144. package/server/service/database/postgres.service.ts +960 -871
  145. package/server/service/database/sap.service.ts +89 -0
  146. package/server/service/database/sqlite.service.ts +787 -708
  147. package/server/service/session.service.ts +158 -158
  148. package/server/tsconfig.json +20 -20
  149. package/server.js +149 -149
  150. package/server.pid +1 -0
  151. package/src/adapter/ajax.ts +135 -135
  152. package/src/assets/base.css +1 -1
  153. package/src/assets/database.css +949 -949
  154. package/src/assets/images/svg/illustrations/illustration-1.svg +1 -1
  155. package/src/assets/images/svg/illustrations/illustration-2.svg +2 -2
  156. package/src/assets/images/svg/illustrations/illustration-3.svg +50 -50
  157. package/src/assets/images/svg/illustrations/illustration-4.svg +1 -1
  158. package/src/assets/images/svg/illustrations/illustration-5.svg +73 -73
  159. package/src/assets/images/svg/illustrations/illustration-6.svg +89 -89
  160. package/src/assets/images/svg/illustrations/illustration-7.svg +39 -39
  161. package/src/assets/images/svg/separators/curve-2.svg +3 -3
  162. package/src/assets/images/svg/separators/curve.svg +3 -3
  163. package/src/assets/images/svg/separators/line.svg +3 -3
  164. package/src/assets/logo.svg +73 -73
  165. package/src/assets/main.css +1 -1
  166. package/src/base/config.ts +20 -20
  167. package/src/base/detect.ts +134 -134
  168. package/src/base/entity.ts +92 -92
  169. package/src/base/eventBus.ts +36 -36
  170. package/src/components/connection-editor/index.vue +588 -588
  171. package/src/components/dataGrid/index.vue +104 -104
  172. package/src/components/dataGrid/pagination.vue +105 -105
  173. package/src/components/loading/index.vue +42 -42
  174. package/src/components/modal/index.ts +180 -180
  175. package/src/components/modal/index.vue +560 -560
  176. package/src/components/toast/index.ts +43 -43
  177. package/src/components/toast/toast.vue +57 -57
  178. package/src/components/user/name.vue +103 -103
  179. package/src/components/user/selector.vue +416 -416
  180. package/src/domain/SysConfig.ts +74 -74
  181. package/src/platform/App.vue +7 -7
  182. package/src/platform/database/components/connection-detail.vue +1153 -1154
  183. package/src/platform/database/components/data-editor.vue +477 -477
  184. package/src/platform/database/components/database-detail.vue +1173 -1172
  185. package/src/platform/database/components/database-monitor.vue +1085 -1085
  186. package/src/platform/database/components/db-tools.vue +1264 -816
  187. package/src/platform/database/components/query-history.vue +1348 -1348
  188. package/src/platform/database/components/sql-executor.vue +737 -737
  189. package/src/platform/database/components/sql-query-editor.vue +1045 -1045
  190. package/src/platform/database/components/table-detail.vue +1375 -1376
  191. package/src/platform/database/components/table-editor.vue +916 -916
  192. package/src/platform/database/explorer.vue +1839 -1839
  193. package/src/platform/database/index.vue +1192 -1192
  194. package/src/platform/database/layout.vue +366 -366
  195. package/src/platform/database/router.ts +36 -36
  196. package/src/platform/database/styles/common.scss +601 -601
  197. package/src/platform/database/types/common.ts +444 -444
  198. package/src/platform/database/utils/export.ts +231 -231
  199. package/src/platform/database/utils/helpers.ts +436 -436
  200. package/src/platform/index.ts +32 -32
  201. package/src/platform/router.ts +40 -40
  202. package/src/platform/vscode/bridge.ts +121 -121
  203. package/src/platform/vscode/components/ConnectionPanel.vue +272 -272
  204. package/src/platform/vscode/components/DatabasePanel.vue +532 -532
  205. package/src/platform/vscode/components/QueryPanel.vue +371 -371
  206. package/src/platform/vscode/entry/connection.ts +13 -13
  207. package/src/platform/vscode/entry/database.ts +13 -13
  208. package/src/platform/vscode/entry/query.ts +13 -13
  209. package/src/platform/vscode/index.ts +5 -5
  210. package/src/service/base.ts +133 -127
  211. package/src/service/database.ts +505 -495
  212. package/src/service/login.ts +120 -120
  213. package/src/shims-vue.d.ts +6 -6
  214. package/src/stores/connection.ts +266 -266
  215. package/src/stores/session.ts +87 -87
  216. package/src/typings/database-types.ts +412 -412
  217. package/src/typings/database.ts +363 -363
  218. package/src/typings/global.d.ts +58 -58
  219. package/src/typings/pinia.d.ts +7 -7
  220. package/src/utils/clipboard.ts +29 -29
  221. package/src/utils/database-types.ts +242 -242
  222. package/src/utils/modal.ts +123 -123
  223. package/src/utils/request.ts +55 -55
  224. package/src/utils/sleep.ts +3 -3
  225. package/src/utils/toast.ts +73 -73
  226. package/src/utils/util.ts +171 -171
  227. package/src/utils/xlsx.ts +228 -228
  228. package/tsconfig.json +33 -33
  229. package/view/index.html +9 -9
  230. package/view/modules/header.tpl +13 -13
  231. package/view/modules/initial_state.tpl +19 -19
  232. package/vite.config.ts +424 -424
  233. package/vite.config.vscode.ts +47 -47
  234. package/fdb2.server.pid +0 -1
  235. package/server/backups/db_ai_breakout_2026-03-11T08-38-48-677Z.sql +0 -0
@@ -1,639 +1,776 @@
1
- import { ConnectionService } from '../connection.service';
2
- import { BaseDatabaseService } from './base.service';
3
- import {
4
- DatabaseEntity,
5
- TableEntity
6
- } from '../../model/database.entity';
7
- import { MySQLService } from './mysql.service';
8
- import { PostgreSQLService } from './postgres.service';
9
- import { SQLiteService } from './sqlite.service';
10
- import { OracleService } from './oracle.service';
11
- import { SQLServerService } from './mssql.service';
12
- import { CockroachDBService } from './cockroachdb.service';
13
- import { MongoDBService } from './mongodb.service';
14
- import { SAPHANADatabaseService } from './sap.service';
15
-
16
- /**
17
- * 数据库服务管理类
18
- * 负责根据数据库类型选择相应的服务实现
19
- */
20
- export class DatabaseService {
21
-
22
- public connectionService: ConnectionService;
23
- private mysqlService: MySQLService;
24
- private postgreSQLService: PostgreSQLService;
25
- private sqliteService: SQLiteService;
26
- private oracleService: OracleService;
27
- private sqlServerService: SQLServerService;
28
- private cockroachDBService: CockroachDBService;
29
- private mongoDBService: MongoDBService;
30
- private sapHANADatabaseService: SAPHANADatabaseService;
31
-
32
- constructor() {
33
- this.connectionService = new ConnectionService();
34
-
35
- this.mysqlService = new MySQLService();
36
- this.postgreSQLService = new PostgreSQLService();
37
- this.sqliteService = new SQLiteService();
38
- this.oracleService = new OracleService();
39
- this.sqlServerService = new SQLServerService();
40
- this.cockroachDBService = new CockroachDBService();
41
- this.mongoDBService = new MongoDBService();
42
- this.sapHANADatabaseService = new SAPHANADatabaseService();
43
- }
44
-
45
- /**
46
- * 获取数据库服务实例
47
- */
48
- public getDatabaseService(type: string): BaseDatabaseService {
49
-
50
- switch (type.toLowerCase()) {
51
- case 'mysql':
52
- case 'aurora-mysql':
53
- case 'auroramysql':
54
- return this.mysqlService;
55
- case 'postgres':
56
- case 'postgresql':
57
- case 'aurora-postgres':
58
- case 'aurorapostgres':
59
- case 'aurora-postgresql':
60
- return this.postgreSQLService;
61
- case 'sqlite':
62
- case 'better-sqlite3':
63
- case 'bettersqlite3':
64
- return this.sqliteService;
65
- case 'oracle':
66
- return this.oracleService;
67
- case 'mssql':
68
- case 'sqlserver':
69
- return this.sqlServerService;
70
- case 'cockroachdb':
71
- case 'cockroach':
72
- return this.cockroachDBService;
73
- case 'mongodb':
74
- case 'mongo':
75
- return this.mongoDBService;
76
- case 'sap':
77
- case 'sap-hana':
78
- case 'saphana':
79
- return this.sapHANADatabaseService;
80
- default:
81
- throw new Error(`不支持的数据库类型: ${type}`);
82
- }
83
- }
84
-
85
- /**
86
- * 获取数据库列表
87
- */
88
- async getDatabases(connectionId: string): Promise<string[]> {
89
- const dataSource = await this.connectionService.getActiveConnection(connectionId);
90
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
91
- return databaseService.getDatabases(dataSource);
92
- }
93
-
94
- /**
95
- * 获取数据库详细信息
96
- */
97
- async getDatabaseInfo(connectionId: string, databaseName: string): Promise<DatabaseEntity> {
98
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
99
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
100
- return databaseService.getDatabaseInfo(dataSource, databaseName);
101
- }
102
-
103
- /**
104
- * 获取数据库表列表
105
- */
106
- async getTables(connectionId: string, databaseName: string): Promise<TableEntity[]> {
107
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
108
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
109
- return databaseService.getTables(dataSource, databaseName);
110
- }
111
-
112
- /**
113
- * 获取表详细信息
114
- */
115
- async getTableInfo(connectionId: string, databaseName: string, tableName: string): Promise<TableEntity> {
116
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
117
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
118
- return databaseService.getTableInfo(dataSource, databaseName, tableName);
119
- }
120
-
121
- /**
122
- * 获取表数据
123
- */
124
- async getTableData(
125
- connectionId: string,
126
- databaseName: string,
127
- tableName: string,
128
- page: number = 1,
129
- pageSize: number = 100,
130
- where?: string,
131
- orderBy?: string
132
- ): Promise<{ data: any[], total: number }> {
133
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
134
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
135
- return databaseService.getTableData(dataSource, databaseName, tableName, page, pageSize, where, orderBy);
136
- }
137
-
138
- /**
139
- * 执行SQL查询
140
- */
141
- async executeQuery(connectionId: string, sql: string, databaseName?: string): Promise<any> {
142
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
143
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
144
- return databaseService.executeQuery(dataSource, sql);
145
- }
146
-
147
- /**
148
- * 修改表结构
149
- */
150
- async alterTable(connectionId: string, databaseName: string, tableDiff: any): Promise<any> {
151
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
152
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
153
- return databaseService.alterTable(dataSource, databaseName, tableDiff);
154
- }
155
-
156
- /**
157
- * 获取视图列表
158
- */
159
- async getViews(connectionId: string, databaseName: string): Promise<any[]> {
160
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
161
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
162
- return databaseService.getViews(dataSource, databaseName);
163
- }
164
-
165
- /**
166
- * 获取视图定义
167
- */
168
- async getViewDefinition(connectionId: string, databaseName: string, viewName: string): Promise<string> {
169
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
170
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
171
- return databaseService.getViewDefinition(dataSource, databaseName, viewName);
172
- }
173
-
174
- /**
175
- * 获取存储过程列表
176
- */
177
- async getProcedures(connectionId: string, databaseName: string): Promise<any[]> {
178
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
179
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
180
- return databaseService.getProcedures(dataSource, databaseName);
181
- }
182
-
183
- /**
184
- * 获取存储过程定义
185
- */
186
- async getProcedureDefinition(connectionId: string, databaseName: string, procedureName: string): Promise<string> {
187
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
188
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
189
- return databaseService.getProcedureDefinition(dataSource, databaseName, procedureName);
190
- }
191
-
192
- /**
193
- * 测试数据库连接
194
- */
195
- async testConnection(connectionId: string): Promise<boolean> {
196
- const dataSource = await this.connectionService.getActiveConnection(connectionId);
197
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
198
- return databaseService.testConnection(dataSource);
199
- }
200
-
201
- /**
202
- * 获取支持的数据库类型
203
- */
204
- getSupportedDatabaseTypes() {
205
- return [
206
- {
207
- value: 'mysql',
208
- label: 'MySQL',
209
- icon: 'bi-database',
210
- defaultPort: 3306,
211
- description: 'MySQL数据库',
212
- features: {
213
- supportSchemas: false,
214
- supportProcedures: true,
215
- supportTriggers: true,
216
- supportViews: true,
217
- supportFullTextSearch: true,
218
- supportJson: true
219
- }
220
- },
221
- {
222
- value: 'postgres',
223
- label: 'PostgreSQL',
224
- icon: 'bi-database',
225
- defaultPort: 5432,
226
- description: 'PostgreSQL数据库',
227
- features: {
228
- supportSchemas: true,
229
- supportProcedures: true,
230
- supportTriggers: true,
231
- supportViews: true,
232
- supportFullTextSearch: true,
233
- supportJson: true,
234
- supportArrays: true,
235
- supportEnum: true
236
- }
237
- },
238
- {
239
- value: 'sqlite',
240
- label: 'SQLite',
241
- icon: 'bi-database',
242
- defaultPort: null,
243
- description: 'SQLite数据库文件',
244
- features: {
245
- supportSchemas: false,
246
- supportProcedures: false,
247
- supportTriggers: true,
248
- supportViews: true,
249
- supportFullTextSearch: true,
250
- supportJson: false,
251
- supportArrays: false
252
- }
253
- },
254
- {
255
- value: 'oracle',
256
- label: 'Oracle',
257
- icon: 'bi-database',
258
- defaultPort: 1521,
259
- description: 'Oracle数据库',
260
- features: {
261
- supportSchemas: true,
262
- supportProcedures: true,
263
- supportTriggers: true,
264
- supportViews: true,
265
- supportFullTextSearch: true,
266
- supportJson: false,
267
- supportArrays: false,
268
- supportSequences: true,
269
- supportSynonyms: true
270
- }
271
- },
272
- {
273
- value: 'mssql',
274
- label: 'SQL Server',
275
- icon: 'bi-database',
276
- defaultPort: 1433,
277
- description: 'Microsoft SQL Server',
278
- features: {
279
- supportSchemas: false,
280
- supportProcedures: true,
281
- supportTriggers: true,
282
- supportViews: true,
283
- supportFullTextSearch: true,
284
- supportJson: true,
285
- supportArrays: false,
286
- supportStoredProcedures: true
287
- }
288
- },
289
- {
290
- value: 'cockroachdb',
291
- label: 'CockroachDB',
292
- icon: 'bi-database',
293
- defaultPort: 26257,
294
- description: 'CockroachDB分布式SQL数据库',
295
- features: {
296
- supportSchemas: true,
297
- supportProcedures: true,
298
- supportTriggers: true,
299
- supportViews: true,
300
- supportFullTextSearch: true,
301
- supportJson: true,
302
- supportArrays: true,
303
- supportEnum: true,
304
- supportDistributed: true
305
- }
306
- },
307
- {
308
- value: 'mongodb',
309
- label: 'MongoDB',
310
- icon: 'bi-database',
311
- defaultPort: 27017,
312
- description: 'MongoDB文档数据库',
313
- features: {
314
- supportSchemas: false,
315
- supportProcedures: false,
316
- supportTriggers: false,
317
- supportViews: false,
318
- supportFullTextSearch: true,
319
- supportJson: true,
320
- supportArrays: true,
321
- supportDocuments: true,
322
- supportNoSQL: true
323
- }
324
- },
325
- {
326
- value: 'sap',
327
- label: 'SAP HANA',
328
- icon: 'bi-database',
329
- defaultPort: 39013,
330
- description: 'SAP HANA内存数据库',
331
- features: {
332
- supportSchemas: true,
333
- supportProcedures: true,
334
- supportTriggers: true,
335
- supportViews: true,
336
- supportFullTextSearch: true,
337
- supportJson: true,
338
- supportArrays: false,
339
- supportInMemory: true,
340
- supportHighPerformance: true
341
- }
342
- }
343
- ];
344
- }
345
-
346
- /**
347
- * 创建数据库
348
- */
349
- async createDatabase(connectionId: string, databaseName: string, options?: any): Promise<void> {
350
- const dataSource = await this.connectionService.getActiveConnection(connectionId);
351
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
352
- return databaseService.createDatabase(dataSource, databaseName, options);
353
- }
354
-
355
- /**
356
- * 删除数据库
357
- */
358
- async dropDatabase(connectionId: string, databaseName: string): Promise<void> {
359
- const dataSource = await this.connectionService.getActiveConnection(connectionId);
360
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
361
- return databaseService.dropDatabase(dataSource, databaseName);
362
- }
363
-
364
- /**
365
- * 导出数据库架构
366
- */
367
- async exportSchema(connectionId: string, databaseName: string): Promise<string> {
368
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
369
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
370
- return databaseService.exportSchema(dataSource, databaseName);
371
- }
372
-
373
- /**
374
- * 查看数据库日志
375
- */
376
- async viewLogs(connectionId: string, databaseName?: string, limit: number = 100): Promise<any[]> {
377
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
378
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
379
- return databaseService.viewLogs(dataSource, databaseName, limit);
380
- }
381
-
382
- /**
383
- * 备份数据库
384
- */
385
- async backupDatabase(connectionId: string, databaseName: string, options?: any): Promise<string> {
386
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
387
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
388
- return databaseService.backupDatabase(dataSource, databaseName, options);
389
- }
390
-
391
- /**
392
- * 恢复数据库
393
- */
394
- async restoreDatabase(connectionId: string, databaseName: string, filePath: string, options?: any): Promise<void> {
395
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
396
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
397
- return databaseService.restoreDatabase(dataSource, databaseName, filePath, options);
398
- }
399
-
400
- /**
401
- * 获取数据库统计信息
402
- */
403
- async getDatabaseStats(connectionId: string, databaseName: string): Promise<any> {
404
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
405
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
406
-
407
- const tables = await databaseService.getTables(dataSource, databaseName);
408
- const tableCount = tables.length;
409
- const size = await databaseService.getDatabaseSize(dataSource, databaseName);
410
-
411
- return {
412
- tableCount,
413
- size,
414
- tables: tables.map(table => ({
415
- name: table.name,
416
- rowCount: table.rowCount || 0,
417
- size: table.dataSize || 0
418
- }))
419
- };
420
- }
421
-
422
- /**
423
- * 优化数据库
424
- */
425
- async optimizeDatabase(connectionId: string, databaseName: string): Promise<any> {
426
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
427
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
428
-
429
- const tables = await databaseService.getTables(dataSource, databaseName);
430
- const results = [];
431
-
432
- for (const table of tables) {
433
- try {
434
- const result = await dataSource.query(`OPTIMIZE TABLE \`${table.name}\``);
435
- results.push({ table: table.name, success: true, result });
436
- } catch (error) {
437
- results.push({ table: table.name, success: false, error: error.message });
438
- }
439
- }
440
-
441
- return { results };
442
- }
443
-
444
- /**
445
- * 分析表
446
- */
447
- async analyzeTables(connectionId: string, databaseName: string): Promise<any> {
448
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
449
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
450
-
451
- const tables = await databaseService.getTables(dataSource, databaseName);
452
- const results = [];
453
-
454
- for (const table of tables) {
455
- try {
456
- const result = await dataSource.query(`ANALYZE TABLE \`${table.name}\``);
457
- results.push({ table: table.name, success: true, result });
458
- } catch (error) {
459
- results.push({ table: table.name, success: false, error: error.message });
460
- }
461
- }
462
-
463
- return { results };
464
- }
465
-
466
- /**
467
- * 修复表
468
- */
469
- async repairTables(connectionId: string, databaseName: string): Promise<any> {
470
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
471
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
472
-
473
- const tables = await databaseService.getTables(dataSource, databaseName);
474
- const results = [];
475
-
476
- for (const table of tables) {
477
- try {
478
- const result = await dataSource.query(`REPAIR TABLE \`${table.name}\``);
479
- results.push({ table: table.name, success: true, result });
480
- } catch (error) {
481
- results.push({ table: table.name, success: false, error: error.message });
482
- }
483
- }
484
-
485
- return { results };
486
- }
487
-
488
- /**
489
- * 导出表数据到 SQL 文件
490
- */
491
- async exportTableDataToSQL(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
492
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
493
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
494
- return databaseService.exportTableDataToSQL(dataSource, databaseName, tableName, options);
495
- }
496
-
497
- /**
498
- * 导出表数据到 CSV 文件
499
- */
500
- async exportTableDataToCSV(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
501
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
502
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
503
- return databaseService.exportTableDataToCSV(dataSource, databaseName, tableName, options);
504
- }
505
-
506
- /**
507
- * 导出表数据到 JSON 文件
508
- */
509
- async exportTableDataToJSON(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
510
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
511
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
512
- return databaseService.exportTableDataToJSON(dataSource, databaseName, tableName, options);
513
- }
514
-
515
- /**
516
- * 导出表数据到 Excel 文件
517
- */
518
- async exportTableDataToExcel(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
519
- const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
520
- const databaseService = this.getDatabaseService(dataSource.options.type as string);
521
- return databaseService.exportTableDataToExcel(dataSource, databaseName, tableName, options);
522
- }
523
-
524
- /**
525
- * 获取数据库类型特定的配置
526
- */
527
- getDatabaseTypeSpecificConfig(type: string) {
528
- const service = this.getDatabaseService(type);
529
- return {
530
- type: service.getDatabaseType(),
531
- features: this.getDatabaseFeatures(type)
532
- };
533
- }
534
-
535
- /**
536
- * 获取数据库特性
537
- */
538
- private getDatabaseFeatures(type: string) {
539
- switch (type.toLowerCase()) {
540
- case 'mysql':
541
- return {
542
- supportSchemas: false,
543
- supportProcedures: true,
544
- supportTriggers: true,
545
- supportViews: true,
546
- supportFullTextSearch: true,
547
- supportJson: true
548
- };
549
- case 'postgres':
550
- case 'postgresql':
551
- return {
552
- supportSchemas: true,
553
- supportProcedures: true,
554
- supportTriggers: true,
555
- supportViews: true,
556
- supportFullTextSearch: true,
557
- supportJson: true,
558
- supportArrays: true,
559
- supportEnum: true
560
- };
561
- case 'sqlite':
562
- return {
563
- supportSchemas: false,
564
- supportProcedures: false,
565
- supportTriggers: true,
566
- supportViews: true,
567
- supportFullTextSearch: true,
568
- supportJson: false,
569
- supportArrays: false
570
- };
571
- case 'oracle':
572
- return {
573
- supportSchemas: true,
574
- supportProcedures: true,
575
- supportTriggers: true,
576
- supportViews: true,
577
- supportFullTextSearch: true,
578
- supportJson: false,
579
- supportArrays: false,
580
- supportSequences: true,
581
- supportSynonyms: true
582
- };
583
- case 'mssql':
584
- case 'sqlserver':
585
- return {
586
- supportSchemas: false,
587
- supportProcedures: true,
588
- supportTriggers: true,
589
- supportViews: true,
590
- supportFullTextSearch: true,
591
- supportJson: true,
592
- supportArrays: false,
593
- supportStoredProcedures: true
594
- };
595
- case 'cockroachdb':
596
- case 'cockroach':
597
- return {
598
- supportSchemas: true,
599
- supportProcedures: true,
600
- supportTriggers: true,
601
- supportViews: true,
602
- supportFullTextSearch: true,
603
- supportJson: true,
604
- supportArrays: true,
605
- supportEnum: true,
606
- supportDistributed: true
607
- };
608
- case 'mongodb':
609
- case 'mongo':
610
- return {
611
- supportSchemas: false,
612
- supportProcedures: false,
613
- supportTriggers: false,
614
- supportViews: false,
615
- supportFullTextSearch: true,
616
- supportJson: true,
617
- supportArrays: true,
618
- supportDocuments: true,
619
- supportNoSQL: true
620
- };
621
- case 'sap':
622
- case 'sap-hana':
623
- case 'saphana':
624
- return {
625
- supportSchemas: true,
626
- supportProcedures: true,
627
- supportTriggers: true,
628
- supportViews: true,
629
- supportFullTextSearch: true,
630
- supportJson: true,
631
- supportArrays: false,
632
- supportInMemory: true,
633
- supportHighPerformance: true
634
- };
635
- default:
636
- return {};
637
- }
638
- }
1
+ import { ConnectionService } from '../connection.service';
2
+ import { BaseDatabaseService } from './base.service';
3
+ import {
4
+ DatabaseEntity,
5
+ TableEntity
6
+ } from '../../model/database.entity';
7
+ import { MySQLService } from './mysql.service';
8
+ import { PostgreSQLService } from './postgres.service';
9
+ import { SQLiteService } from './sqlite.service';
10
+ import { OracleService } from './oracle.service';
11
+ import { SQLServerService } from './mssql.service';
12
+ import { CockroachDBService } from './cockroachdb.service';
13
+ import { MongoDBService } from './mongodb.service';
14
+ import { SAPHANADatabaseService } from './sap.service';
15
+
16
+ /**
17
+ * 数据库服务管理类
18
+ * 负责根据数据库类型选择相应的服务实现
19
+ */
20
+ export class DatabaseService {
21
+
22
+ public connectionService: ConnectionService;
23
+ private mysqlService: MySQLService;
24
+ private postgreSQLService: PostgreSQLService;
25
+ private sqliteService: SQLiteService;
26
+ private oracleService: OracleService;
27
+ private sqlServerService: SQLServerService;
28
+ private cockroachDBService: CockroachDBService;
29
+ private mongoDBService: MongoDBService;
30
+ private sapHANADatabaseService: SAPHANADatabaseService;
31
+
32
+ constructor() {
33
+ this.connectionService = new ConnectionService();
34
+
35
+ this.mysqlService = new MySQLService();
36
+ this.postgreSQLService = new PostgreSQLService();
37
+ this.sqliteService = new SQLiteService();
38
+ this.oracleService = new OracleService();
39
+ this.sqlServerService = new SQLServerService();
40
+ this.cockroachDBService = new CockroachDBService();
41
+ this.mongoDBService = new MongoDBService();
42
+ this.sapHANADatabaseService = new SAPHANADatabaseService();
43
+ }
44
+
45
+ /**
46
+ * 获取数据库服务实例
47
+ */
48
+ public getDatabaseService(type: string): BaseDatabaseService {
49
+
50
+ switch (type.toLowerCase()) {
51
+ case 'mysql':
52
+ case 'aurora-mysql':
53
+ case 'auroramysql':
54
+ return this.mysqlService;
55
+ case 'postgres':
56
+ case 'postgresql':
57
+ case 'aurora-postgres':
58
+ case 'aurorapostgres':
59
+ case 'aurora-postgresql':
60
+ return this.postgreSQLService;
61
+ case 'sqlite':
62
+ case 'better-sqlite3':
63
+ case 'bettersqlite3':
64
+ return this.sqliteService;
65
+ case 'oracle':
66
+ return this.oracleService;
67
+ case 'mssql':
68
+ case 'sqlserver':
69
+ return this.sqlServerService;
70
+ case 'cockroachdb':
71
+ case 'cockroach':
72
+ return this.cockroachDBService;
73
+ case 'mongodb':
74
+ case 'mongo':
75
+ return this.mongoDBService;
76
+ case 'sap':
77
+ case 'sap-hana':
78
+ case 'saphana':
79
+ return this.sapHANADatabaseService;
80
+ default:
81
+ throw new Error(`不支持的数据库类型: ${type}`);
82
+ }
83
+ }
84
+
85
+ /**
86
+ * 获取数据库列表
87
+ */
88
+ async getDatabases(connectionId: string): Promise<string[]> {
89
+ const dataSource = await this.connectionService.getActiveConnection(connectionId);
90
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
91
+ return databaseService.getDatabases(dataSource);
92
+ }
93
+
94
+ /**
95
+ * 获取数据库详细信息
96
+ */
97
+ async getDatabaseInfo(connectionId: string, databaseName: string): Promise<DatabaseEntity> {
98
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
99
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
100
+ return databaseService.getDatabaseInfo(dataSource, databaseName);
101
+ }
102
+
103
+ /**
104
+ * 获取数据库表列表
105
+ */
106
+ async getTables(connectionId: string, databaseName: string): Promise<TableEntity[]> {
107
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
108
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
109
+ return databaseService.getTables(dataSource, databaseName);
110
+ }
111
+
112
+ /**
113
+ * 获取表详细信息
114
+ */
115
+ async getTableInfo(connectionId: string, databaseName: string, tableName: string): Promise<TableEntity> {
116
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
117
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
118
+ return databaseService.getTableInfo(dataSource, databaseName, tableName);
119
+ }
120
+
121
+ /**
122
+ * 获取表数据
123
+ */
124
+ async getTableData(
125
+ connectionId: string,
126
+ databaseName: string,
127
+ tableName: string,
128
+ page: number = 1,
129
+ pageSize: number = 100,
130
+ where?: string,
131
+ orderBy?: string
132
+ ): Promise<{ data: any[], total: number }> {
133
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
134
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
135
+ return databaseService.getTableData(dataSource, databaseName, tableName, page, pageSize, where, orderBy);
136
+ }
137
+
138
+ /**
139
+ * 执行SQL查询
140
+ */
141
+ async executeQuery(connectionId: string, sql: string, databaseName?: string): Promise<any> {
142
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
143
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
144
+ return databaseService.executeQuery(dataSource, sql);
145
+ }
146
+
147
+ /**
148
+ * 修改表结构
149
+ */
150
+ async alterTable(connectionId: string, databaseName: string, tableDiff: any): Promise<any> {
151
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
152
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
153
+ return databaseService.alterTable(dataSource, databaseName, tableDiff);
154
+ }
155
+
156
+ /**
157
+ * 同步表结构和数据到其他数据库
158
+ */
159
+ async syncTable(connectionId: string, syncConfig: any): Promise<any> {
160
+ try {
161
+ const { source, target, options } = syncConfig;
162
+
163
+ // 获取源数据库连接
164
+ const sourceDataSource = await this.connectionService.getActiveConnection(connectionId, source.database);
165
+ const sourceService = this.getDatabaseService(sourceDataSource.options.type as string);
166
+
167
+ // 创建目标数据库连接
168
+ let targetDataSource;
169
+ let targetService;
170
+ let targetDatabaseName;
171
+
172
+ if (target.connectionId) {
173
+ // 使用已配置的连接
174
+ const dbName = target.database || source.database;
175
+ targetDataSource = await this.connectionService.getActiveConnection(target.connectionId, dbName);
176
+ targetService = this.getDatabaseService(targetDataSource.options.type as string);
177
+ targetDatabaseName = dbName;
178
+ } else {
179
+ // 使用手动配置的连接
180
+ targetDataSource = await this.connectionService.createTemporaryConnection({
181
+ type: target.dbType,
182
+ host: target.host,
183
+ port: target.port,
184
+ username: target.username,
185
+ password: target.password,
186
+ database: target.database
187
+ });
188
+ targetService = this.getDatabaseService(target.dbType);
189
+ targetDatabaseName = target.database;
190
+ }
191
+
192
+ const syncResults = [];
193
+
194
+ // 处理单个表
195
+ const sourceTableName = source.tableName;
196
+ const tableSyncResult = {
197
+ tableName: sourceTableName,
198
+ structureSynced: false,
199
+ dataSynced: false,
200
+ rowsSynced: 0,
201
+ messages: []
202
+ };
203
+
204
+ try {
205
+ // 获取源表结构
206
+ const tableStructure = await sourceService.getTableStructure(sourceDataSource, source.database, sourceTableName);
207
+ const columns = tableStructure.columns;
208
+
209
+ // 同步表结构
210
+ if (options.syncStructure) {
211
+ console.log(`开始同步表结构: ${sourceTableName} -> ${target.tableName}`);
212
+ tableSyncResult.messages.push(`开始同步表结构: ${sourceTableName} -> ${target.tableName}`);
213
+
214
+ // 检查目标表是否存在
215
+ const targetTables = await targetService.getTables(targetDataSource, targetDatabaseName);
216
+ const tableExists = targetTables.some(t => t.name === target.tableName);
217
+
218
+ if (tableExists) {
219
+ if (options.dropIfExists) {
220
+ tableSyncResult.messages.push(`目标表已存在,删除表: ${target.tableName}`);
221
+ await targetService.dropTable(targetDataSource, targetDatabaseName, target.tableName);
222
+ } else {
223
+ tableSyncResult.messages.push(`目标表已存在,跳过表结构同步`);
224
+ }
225
+ }
226
+
227
+ if (!tableExists || options.dropIfExists) {
228
+ tableSyncResult.messages.push(`创建目标表: ${target.tableName}`);
229
+ await targetService.createTable(targetDataSource, targetDatabaseName, {
230
+ name: target.tableName,
231
+ columns: columns,
232
+ comment: tableStructure.comment
233
+ });
234
+ tableSyncResult.structureSynced = true;
235
+ }
236
+ }
237
+
238
+ // 同步表数据
239
+ if (options.syncData) {
240
+ tableSyncResult.messages.push(`开始同步表数据: ${sourceTableName} -> ${target.tableName}`);
241
+
242
+ // 获取源表数据(分批获取,避免内存问题)
243
+ const batchSize = 1000;
244
+ let offset = 0;
245
+ let totalRows = 0;
246
+
247
+ while (true) {
248
+ const sourceData = await sourceService.query(sourceDataSource, {
249
+ sql: `SELECT * FROM ${sourceService.quoteIdentifier(sourceTableName)} LIMIT ? OFFSET ?`,
250
+ params: [batchSize, offset]
251
+ });
252
+
253
+ if (sourceData.length === 0) {
254
+ break;
255
+ }
256
+
257
+ // 插入数据到目标表
258
+ if (options.bulkInsert) {
259
+ await targetService.bulkInsert(targetDataSource, targetDatabaseName, target.tableName, sourceData, options.overrideExisting);
260
+ } else {
261
+ for (const row of sourceData) {
262
+ await targetService.insertData(targetDataSource, targetDatabaseName, target.tableName, row, options.overrideExisting);
263
+ }
264
+ }
265
+
266
+ totalRows += sourceData.length;
267
+ tableSyncResult.messages.push(`已同步 ${totalRows} 行数据`);
268
+ offset += batchSize;
269
+ }
270
+
271
+ tableSyncResult.dataSynced = true;
272
+ tableSyncResult.rowsSynced = totalRows;
273
+ tableSyncResult.messages.push(`数据同步完成,共同步 ${totalRows} 行`);
274
+ }
275
+
276
+ syncResults.push(tableSyncResult);
277
+ } catch (error: any) {
278
+ console.error(`同步表 ${sourceTableName} 失败:`, error);
279
+ tableSyncResult.messages.push(`同步失败: ${error instanceof Error ? error.message : String(error)}`);
280
+ syncResults.push(tableSyncResult);
281
+ throw error;
282
+ }
283
+ finally {
284
+ console.log(tableSyncResult.messages);
285
+ }
286
+ return { tables: syncResults };
287
+ } catch (error: any) {
288
+ console.error('同步表失败:', error);
289
+ throw error;
290
+ }
291
+ }
292
+
293
+ /**
294
+ * 获取视图列表
295
+ */
296
+ async getViews(connectionId: string, databaseName: string): Promise<any[]> {
297
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
298
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
299
+ return databaseService.getViews(dataSource, databaseName);
300
+ }
301
+
302
+ /**
303
+ * 获取视图定义
304
+ */
305
+ async getViewDefinition(connectionId: string, databaseName: string, viewName: string): Promise<string> {
306
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
307
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
308
+ return databaseService.getViewDefinition(dataSource, databaseName, viewName);
309
+ }
310
+
311
+ /**
312
+ * 获取存储过程列表
313
+ */
314
+ async getProcedures(connectionId: string, databaseName: string): Promise<any[]> {
315
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
316
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
317
+ return databaseService.getProcedures(dataSource, databaseName);
318
+ }
319
+
320
+ /**
321
+ * 获取存储过程定义
322
+ */
323
+ async getProcedureDefinition(connectionId: string, databaseName: string, procedureName: string): Promise<string> {
324
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
325
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
326
+ return databaseService.getProcedureDefinition(dataSource, databaseName, procedureName);
327
+ }
328
+
329
+ /**
330
+ * 测试数据库连接
331
+ */
332
+ async testConnection(connectionId: string): Promise<boolean> {
333
+ const dataSource = await this.connectionService.getActiveConnection(connectionId);
334
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
335
+ return databaseService.testConnection(dataSource);
336
+ }
337
+
338
+ /**
339
+ * 获取支持的数据库类型
340
+ */
341
+ getSupportedDatabaseTypes() {
342
+ return [
343
+ {
344
+ value: 'mysql',
345
+ label: 'MySQL',
346
+ icon: 'bi-database',
347
+ defaultPort: 3306,
348
+ description: 'MySQL数据库',
349
+ features: {
350
+ supportSchemas: false,
351
+ supportProcedures: true,
352
+ supportTriggers: true,
353
+ supportViews: true,
354
+ supportFullTextSearch: true,
355
+ supportJson: true
356
+ }
357
+ },
358
+ {
359
+ value: 'postgres',
360
+ label: 'PostgreSQL',
361
+ icon: 'bi-database',
362
+ defaultPort: 5432,
363
+ description: 'PostgreSQL数据库',
364
+ features: {
365
+ supportSchemas: true,
366
+ supportProcedures: true,
367
+ supportTriggers: true,
368
+ supportViews: true,
369
+ supportFullTextSearch: true,
370
+ supportJson: true,
371
+ supportArrays: true,
372
+ supportEnum: true
373
+ }
374
+ },
375
+ {
376
+ value: 'sqlite',
377
+ label: 'SQLite',
378
+ icon: 'bi-database',
379
+ defaultPort: null,
380
+ description: 'SQLite数据库文件',
381
+ features: {
382
+ supportSchemas: false,
383
+ supportProcedures: false,
384
+ supportTriggers: true,
385
+ supportViews: true,
386
+ supportFullTextSearch: true,
387
+ supportJson: false,
388
+ supportArrays: false
389
+ }
390
+ },
391
+ {
392
+ value: 'oracle',
393
+ label: 'Oracle',
394
+ icon: 'bi-database',
395
+ defaultPort: 1521,
396
+ description: 'Oracle数据库',
397
+ features: {
398
+ supportSchemas: true,
399
+ supportProcedures: true,
400
+ supportTriggers: true,
401
+ supportViews: true,
402
+ supportFullTextSearch: true,
403
+ supportJson: false,
404
+ supportArrays: false,
405
+ supportSequences: true,
406
+ supportSynonyms: true
407
+ }
408
+ },
409
+ {
410
+ value: 'mssql',
411
+ label: 'SQL Server',
412
+ icon: 'bi-database',
413
+ defaultPort: 1433,
414
+ description: 'Microsoft SQL Server',
415
+ features: {
416
+ supportSchemas: false,
417
+ supportProcedures: true,
418
+ supportTriggers: true,
419
+ supportViews: true,
420
+ supportFullTextSearch: true,
421
+ supportJson: true,
422
+ supportArrays: false,
423
+ supportStoredProcedures: true
424
+ }
425
+ },
426
+ {
427
+ value: 'cockroachdb',
428
+ label: 'CockroachDB',
429
+ icon: 'bi-database',
430
+ defaultPort: 26257,
431
+ description: 'CockroachDB分布式SQL数据库',
432
+ features: {
433
+ supportSchemas: true,
434
+ supportProcedures: true,
435
+ supportTriggers: true,
436
+ supportViews: true,
437
+ supportFullTextSearch: true,
438
+ supportJson: true,
439
+ supportArrays: true,
440
+ supportEnum: true,
441
+ supportDistributed: true
442
+ }
443
+ },
444
+ {
445
+ value: 'mongodb',
446
+ label: 'MongoDB',
447
+ icon: 'bi-database',
448
+ defaultPort: 27017,
449
+ description: 'MongoDB文档数据库',
450
+ features: {
451
+ supportSchemas: false,
452
+ supportProcedures: false,
453
+ supportTriggers: false,
454
+ supportViews: false,
455
+ supportFullTextSearch: true,
456
+ supportJson: true,
457
+ supportArrays: true,
458
+ supportDocuments: true,
459
+ supportNoSQL: true
460
+ }
461
+ },
462
+ {
463
+ value: 'sap',
464
+ label: 'SAP HANA',
465
+ icon: 'bi-database',
466
+ defaultPort: 39013,
467
+ description: 'SAP HANA内存数据库',
468
+ features: {
469
+ supportSchemas: true,
470
+ supportProcedures: true,
471
+ supportTriggers: true,
472
+ supportViews: true,
473
+ supportFullTextSearch: true,
474
+ supportJson: true,
475
+ supportArrays: false,
476
+ supportInMemory: true,
477
+ supportHighPerformance: true
478
+ }
479
+ }
480
+ ];
481
+ }
482
+
483
+ /**
484
+ * 创建数据库
485
+ */
486
+ async createDatabase(connectionId: string, databaseName: string, options?: any): Promise<void> {
487
+ const dataSource = await this.connectionService.getActiveConnection(connectionId);
488
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
489
+ return databaseService.createDatabase(dataSource, databaseName, options);
490
+ }
491
+
492
+ /**
493
+ * 删除数据库
494
+ */
495
+ async dropDatabase(connectionId: string, databaseName: string): Promise<void> {
496
+ const dataSource = await this.connectionService.getActiveConnection(connectionId);
497
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
498
+ return databaseService.dropDatabase(dataSource, databaseName);
499
+ }
500
+
501
+ /**
502
+ * 导出数据库架构
503
+ */
504
+ async exportSchema(connectionId: string, databaseName: string): Promise<string> {
505
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
506
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
507
+ return databaseService.exportSchema(dataSource, databaseName);
508
+ }
509
+
510
+ /**
511
+ * 查看数据库日志
512
+ */
513
+ async viewLogs(connectionId: string, databaseName?: string, limit: number = 100): Promise<any[]> {
514
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
515
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
516
+ return databaseService.viewLogs(dataSource, databaseName, limit);
517
+ }
518
+
519
+ /**
520
+ * 备份数据库
521
+ */
522
+ async backupDatabase(connectionId: string, databaseName: string, options?: any): Promise<string> {
523
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
524
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
525
+ return databaseService.backupDatabase(dataSource, databaseName, options);
526
+ }
527
+
528
+ /**
529
+ * 恢复数据库
530
+ */
531
+ async restoreDatabase(connectionId: string, databaseName: string, filePath: string, options?: any): Promise<void> {
532
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
533
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
534
+ return databaseService.restoreDatabase(dataSource, databaseName, filePath, options);
535
+ }
536
+
537
+ /**
538
+ * 获取数据库统计信息
539
+ */
540
+ async getDatabaseStats(connectionId: string, databaseName: string): Promise<any> {
541
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
542
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
543
+
544
+ const tables = await databaseService.getTables(dataSource, databaseName);
545
+ const tableCount = tables.length;
546
+ const size = await databaseService.getDatabaseSize(dataSource, databaseName);
547
+
548
+ return {
549
+ tableCount,
550
+ size,
551
+ tables: tables.map(table => ({
552
+ name: table.name,
553
+ rowCount: table.rowCount || 0,
554
+ size: table.dataSize || 0
555
+ }))
556
+ };
557
+ }
558
+
559
+ /**
560
+ * 优化数据库
561
+ */
562
+ async optimizeDatabase(connectionId: string, databaseName: string): Promise<any> {
563
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
564
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
565
+
566
+ const tables = await databaseService.getTables(dataSource, databaseName);
567
+ const results = [];
568
+
569
+ for (const table of tables) {
570
+ try {
571
+ const result = await dataSource.query(`OPTIMIZE TABLE \`${table.name}\``);
572
+ results.push({ table: table.name, success: true, result });
573
+ } catch (error) {
574
+ results.push({ table: table.name, success: false, error: error.message });
575
+ }
576
+ }
577
+
578
+ return { results };
579
+ }
580
+
581
+ /**
582
+ * 分析表
583
+ */
584
+ async analyzeTables(connectionId: string, databaseName: string): Promise<any> {
585
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
586
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
587
+
588
+ const tables = await databaseService.getTables(dataSource, databaseName);
589
+ const results = [];
590
+
591
+ for (const table of tables) {
592
+ try {
593
+ const result = await dataSource.query(`ANALYZE TABLE \`${table.name}\``);
594
+ results.push({ table: table.name, success: true, result });
595
+ } catch (error) {
596
+ results.push({ table: table.name, success: false, error: error.message });
597
+ }
598
+ }
599
+
600
+ return { results };
601
+ }
602
+
603
+ /**
604
+ * 修复表
605
+ */
606
+ async repairTables(connectionId: string, databaseName: string): Promise<any> {
607
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
608
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
609
+
610
+ const tables = await databaseService.getTables(dataSource, databaseName);
611
+ const results = [];
612
+
613
+ for (const table of tables) {
614
+ try {
615
+ const result = await dataSource.query(`REPAIR TABLE \`${table.name}\``);
616
+ results.push({ table: table.name, success: true, result });
617
+ } catch (error) {
618
+ results.push({ table: table.name, success: false, error: error.message });
619
+ }
620
+ }
621
+
622
+ return { results };
623
+ }
624
+
625
+ /**
626
+ * 导出表数据到 SQL 文件
627
+ */
628
+ async exportTableDataToSQL(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
629
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
630
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
631
+ return databaseService.exportTableDataToSQL(dataSource, databaseName, tableName, options);
632
+ }
633
+
634
+ /**
635
+ * 导出表数据到 CSV 文件
636
+ */
637
+ async exportTableDataToCSV(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
638
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
639
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
640
+ return databaseService.exportTableDataToCSV(dataSource, databaseName, tableName, options);
641
+ }
642
+
643
+ /**
644
+ * 导出表数据到 JSON 文件
645
+ */
646
+ async exportTableDataToJSON(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
647
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
648
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
649
+ return databaseService.exportTableDataToJSON(dataSource, databaseName, tableName, options);
650
+ }
651
+
652
+ /**
653
+ * 导出表数据到 Excel 文件
654
+ */
655
+ async exportTableDataToExcel(connectionId: string, databaseName: string, tableName: string, options?: any): Promise<string> {
656
+ const dataSource = await this.connectionService.getActiveConnection(connectionId, databaseName);
657
+ const databaseService = this.getDatabaseService(dataSource.options.type as string);
658
+ return databaseService.exportTableDataToExcel(dataSource, databaseName, tableName, options);
659
+ }
660
+
661
+ /**
662
+ * 获取数据库类型特定的配置
663
+ */
664
+ getDatabaseTypeSpecificConfig(type: string) {
665
+ const service = this.getDatabaseService(type);
666
+ return {
667
+ type: service.getDatabaseType(),
668
+ features: this.getDatabaseFeatures(type)
669
+ };
670
+ }
671
+
672
+ /**
673
+ * 获取数据库特性
674
+ */
675
+ private getDatabaseFeatures(type: string) {
676
+ switch (type.toLowerCase()) {
677
+ case 'mysql':
678
+ return {
679
+ supportSchemas: false,
680
+ supportProcedures: true,
681
+ supportTriggers: true,
682
+ supportViews: true,
683
+ supportFullTextSearch: true,
684
+ supportJson: true
685
+ };
686
+ case 'postgres':
687
+ case 'postgresql':
688
+ return {
689
+ supportSchemas: true,
690
+ supportProcedures: true,
691
+ supportTriggers: true,
692
+ supportViews: true,
693
+ supportFullTextSearch: true,
694
+ supportJson: true,
695
+ supportArrays: true,
696
+ supportEnum: true
697
+ };
698
+ case 'sqlite':
699
+ return {
700
+ supportSchemas: false,
701
+ supportProcedures: false,
702
+ supportTriggers: true,
703
+ supportViews: true,
704
+ supportFullTextSearch: true,
705
+ supportJson: false,
706
+ supportArrays: false
707
+ };
708
+ case 'oracle':
709
+ return {
710
+ supportSchemas: true,
711
+ supportProcedures: true,
712
+ supportTriggers: true,
713
+ supportViews: true,
714
+ supportFullTextSearch: true,
715
+ supportJson: false,
716
+ supportArrays: false,
717
+ supportSequences: true,
718
+ supportSynonyms: true
719
+ };
720
+ case 'mssql':
721
+ case 'sqlserver':
722
+ return {
723
+ supportSchemas: false,
724
+ supportProcedures: true,
725
+ supportTriggers: true,
726
+ supportViews: true,
727
+ supportFullTextSearch: true,
728
+ supportJson: true,
729
+ supportArrays: false,
730
+ supportStoredProcedures: true
731
+ };
732
+ case 'cockroachdb':
733
+ case 'cockroach':
734
+ return {
735
+ supportSchemas: true,
736
+ supportProcedures: true,
737
+ supportTriggers: true,
738
+ supportViews: true,
739
+ supportFullTextSearch: true,
740
+ supportJson: true,
741
+ supportArrays: true,
742
+ supportEnum: true,
743
+ supportDistributed: true
744
+ };
745
+ case 'mongodb':
746
+ case 'mongo':
747
+ return {
748
+ supportSchemas: false,
749
+ supportProcedures: false,
750
+ supportTriggers: false,
751
+ supportViews: false,
752
+ supportFullTextSearch: true,
753
+ supportJson: true,
754
+ supportArrays: true,
755
+ supportDocuments: true,
756
+ supportNoSQL: true
757
+ };
758
+ case 'sap':
759
+ case 'sap-hana':
760
+ case 'saphana':
761
+ return {
762
+ supportSchemas: true,
763
+ supportProcedures: true,
764
+ supportTriggers: true,
765
+ supportViews: true,
766
+ supportFullTextSearch: true,
767
+ supportJson: true,
768
+ supportArrays: false,
769
+ supportInMemory: true,
770
+ supportHighPerformance: true
771
+ };
772
+ default:
773
+ return {};
774
+ }
775
+ }
639
776
  }