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,363 +1,363 @@
1
- import { DataSource } from 'typeorm';
2
- import {
3
- DatabaseEntity,
4
- TableEntity,
5
- ColumnEntity,
6
- IndexEntity,
7
- ForeignKeyEntity
8
- } from './model/database.entity';
9
-
10
- /**
11
- * 数据库服务基础类
12
- * 提供所有数据库类型的通用操作
13
- */
14
- export abstract class BaseDatabaseService {
15
-
16
- /**
17
- * 获取数据库类型
18
- */
19
- abstract getDatabaseType(): string;
20
-
21
- /**
22
- * 获取数据库列表 - 子类实现
23
- */
24
- abstract getDatabases(dataSource: DataSource): Promise<string[]>;
25
-
26
- /**
27
- * 获取表列表 - 子类实现
28
- */
29
- abstract getTables(dataSource: DataSource, database: string): Promise<TableEntity[]>;
30
-
31
- /**
32
- * 获取列信息 - 子类实现
33
- */
34
- abstract getColumns(dataSource: DataSource, database: string, table: string): Promise<ColumnEntity[]>;
35
-
36
- /**
37
- * 获取索引信息 - 子类实现
38
- */
39
- abstract getIndexes(dataSource: DataSource, database: string, table: string): Promise<IndexEntity[]>;
40
-
41
- /**
42
- * 获取外键信息 - 子类实现
43
- */
44
- abstract getForeignKeys(dataSource: DataSource, database: string, table: string): Promise<ForeignKeyEntity[]>;
45
-
46
- /**
47
- * 获取数据库大小 - 子类实现
48
- */
49
- abstract getDatabaseSize(dataSource: DataSource, database: string): Promise<number>;
50
-
51
- /**
52
- * 通用方法:获取数据库详细信息
53
- */
54
- async getDatabaseInfo(dataSource: DataSource, databaseName: string): Promise<DatabaseEntity> {
55
- const tables = await this.getTables(dataSource, databaseName);
56
-
57
- return {
58
- name: databaseName,
59
- tableCount: tables.length,
60
- size: await this.getDatabaseSize(dataSource, databaseName),
61
- tables
62
- };
63
- }
64
-
65
- /**
66
- * 通用方法:获取表详细信息
67
- */
68
- async getTableInfo(dataSource: DataSource, databaseName: string, tableName: string): Promise<TableEntity> {
69
- const tables = await this.getTables(dataSource, databaseName);
70
- const table = tables.find(t => t.name === tableName);
71
-
72
- if (!table) {
73
- throw new Error(`表 ${tableName} 不存在`);
74
- }
75
-
76
- // 获取列信息
77
- table.columns = await this.getColumns(dataSource, databaseName, tableName);
78
-
79
- // 获取索引信息
80
- table.indexes = await this.getIndexes(dataSource, databaseName, tableName);
81
-
82
- // 获取外键信息
83
- table.foreignKeys = await this.getForeignKeys(dataSource, databaseName, tableName);
84
-
85
- return table;
86
- }
87
-
88
- /**
89
- * 通用方法:获取表数据
90
- */
91
- async getTableData(
92
- dataSource: DataSource,
93
- databaseName: string,
94
- tableName: string,
95
- page: number = 1,
96
- pageSize: number = 100,
97
- where?: string,
98
- orderBy?: string
99
- ): Promise<{ data: any[], total: number }> {
100
- // 构建查询
101
- let query = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;
102
-
103
- if (where) {
104
- query += ` WHERE ${where}`;
105
- }
106
-
107
- if (orderBy) {
108
- query += ` ORDER BY ${orderBy}`;
109
- }
110
-
111
- const offset = (page - 1) * pageSize;
112
- query += ` LIMIT ${pageSize} OFFSET ${offset}`;
113
-
114
- // 执行数据查询
115
- const data = await dataSource.query(query);
116
-
117
- // 获取总数
118
- let countQuery = `SELECT COUNT(*) as total FROM ${this.quoteIdentifier(tableName)}`;
119
- if (where) {
120
- countQuery += ` WHERE ${where}`;
121
- }
122
- const countResult = await dataSource.query(countQuery);
123
- const total = countResult[0]?.total || 0;
124
-
125
- return { data, total };
126
- }
127
-
128
- /**
129
- * 通用方法:执行SQL查询
130
- */
131
- async executeQuery(dataSource: DataSource, sql: string): Promise<any> {
132
- try {
133
- const result = await dataSource.query(sql);
134
- return result;
135
- } catch (error) {
136
- console.error('SQL执行失败:', error);
137
- throw error;
138
- }
139
- }
140
-
141
- /**
142
- * 批量执行SQL查询(支持多条语句)
143
- */
144
- async executeBatchQuery(
145
- dataSource: DataSource,
146
- sqlStatements: string[],
147
- options?: {
148
- batchSize?: number; // 每批执行的语句数量
149
- useTransaction?: boolean; // 是否使用事务
150
- continueOnError?: boolean; // 错误时是否继续执行
151
- }
152
- ): Promise<{ success: number; failed: number; errors: any[] }> {
153
- const {
154
- batchSize = 100,
155
- useTransaction = true,
156
- continueOnError = false
157
- } = options || {};
158
-
159
- let success = 0;
160
- let failed = 0;
161
- const errors: any[] = [];
162
-
163
- // 分批处理SQL语句
164
- for (let i = 0; i < sqlStatements.length; i += batchSize) {
165
- const batch = sqlStatements.slice(i, i + batchSize);
166
-
167
- try {
168
- if (useTransaction) {
169
- // 使用事务执行批次
170
- await dataSource.transaction(async (manager) => {
171
- for (const statement of batch) {
172
- try {
173
- await manager.query(statement);
174
- success++;
175
- } catch (error) {
176
- failed++;
177
- errors.push({ statement, error: error.message });
178
- if (!continueOnError) {
179
- throw error;
180
- }
181
- }
182
- }
183
- });
184
- } else {
185
- // 非事务执行批次
186
- for (const statement of batch) {
187
- try {
188
- await dataSource.query(statement);
189
- success++;
190
- } catch (error) {
191
- failed++;
192
- errors.push({ statement, error: error.message });
193
- if (!continueOnError) {
194
- throw error;
195
- }
196
- }
197
- }
198
- }
199
- } catch (batchError) {
200
- console.error(`批次执行失败 (${i}-${i + batchSize}):`, batchError);
201
- if (!continueOnError) {
202
- throw new Error(`批次执行失败: ${batchError.message}`);
203
- }
204
- }
205
- }
206
-
207
- return { success, failed, errors };
208
- }
209
-
210
- /**
211
- * 执行文件中的SQL(支持大文件)
212
- */
213
- async executeSqlFile(
214
- dataSource: DataSource,
215
- filePath: string,
216
- options?: {
217
- batchSize?: number;
218
- useTransaction?: boolean;
219
- continueOnError?: boolean;
220
- }
221
- ): Promise<{ success: number; failed: number; errors: any[] }> {
222
- const fs = require('fs');
223
- const sqlContent = fs.readFileSync(filePath, 'utf8');
224
-
225
- // 分割SQL语句
226
- const sqlStatements = sqlContent
227
- .split(';')
228
- .map(statement => statement.trim())
229
- .filter(statement => statement.length > 0);
230
-
231
- return this.executeBatchQuery(dataSource, sqlStatements, options);
232
- }
233
-
234
- /**
235
- * 通用方法:测试连接
236
- */
237
- async testConnection(dataSource: DataSource): Promise<boolean> {
238
- try {
239
- await dataSource.query('SELECT 1');
240
- return true;
241
- } catch (error) {
242
- //this.ctx.logger.error('数据库连接测试失败:', error);
243
- console.error(error);
244
- return false;
245
- }
246
- }
247
-
248
- /**
249
- * 通用方法:给标识符加引号
250
- */
251
- public quoteIdentifier(identifier: string): string {
252
- return `"${identifier}"`;
253
- }
254
-
255
- /**
256
- * 通用方法:构建分页查询
257
- */
258
- protected buildPaginationQuery(baseQuery: string, page: number, pageSize: number): string {
259
- const offset = (page - 1) * pageSize;
260
- return `${baseQuery} LIMIT ${pageSize} OFFSET ${offset}`;
261
- }
262
-
263
- /**
264
- * 通用方法:构建计数查询
265
- */
266
- protected buildCountQuery(baseQuery: string): string {
267
- return `SELECT COUNT(*) as total FROM (${baseQuery}) as count_query`;
268
- }
269
-
270
- /**
271
- * 获取视图列表 - 子类实现(如果支持)
272
- */
273
- async getViews(dataSource: DataSource, database: string): Promise<any[]> {
274
- // 默认实现,子类可以重写
275
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持视图`);
276
- }
277
-
278
- /**
279
- * 获取视图定义 - 子类实现(如果支持)
280
- */
281
- async getViewDefinition(dataSource: DataSource, database: string, viewName: string): Promise<string> {
282
- // 默认实现,子类可以重写
283
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持视图`);
284
- }
285
-
286
- /**
287
- * 获取存储过程列表 - 子类实现(如果支持)
288
- */
289
- async getProcedures(dataSource: DataSource, database: string): Promise<any[]> {
290
- // 默认实现,子类可以重写
291
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持存储过程`);
292
- }
293
-
294
- /**
295
- * 获取存储过程定义 - 子类实现(如果支持)
296
- */
297
- async getProcedureDefinition(dataSource: DataSource, database: string, procedureName: string): Promise<string> {
298
- // 默认实现,子类可以重写
299
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持存储过程`);
300
- }
301
-
302
- /**
303
- * 导出数据库架构 - 子类实现
304
- */
305
- abstract exportSchema(dataSource: DataSource, database: string): Promise<string>;
306
-
307
- /**
308
- * 查看数据库日志 - 子类实现(如果支持)
309
- */
310
- abstract viewLogs(dataSource: DataSource, database?: string, limit?: number): Promise<any[]>;
311
-
312
- /**
313
- * 创建数据库 - 子类实现(如果支持)
314
- */
315
- async createDatabase(dataSource: DataSource, databaseName: string, options?: any): Promise<void> {
316
- // 默认实现,子类可以重写
317
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持创建数据库`);
318
- }
319
-
320
- /**
321
- * 删除数据库 - 子类实现(如果支持)
322
- */
323
- async dropDatabase(dataSource: DataSource, databaseName: string): Promise<void> {
324
- // 默认实现,子类可以重写
325
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持删除数据库`);
326
- }
327
-
328
- /**
329
- * 备份数据库 - 子类实现(如果支持)
330
- */
331
- async backupDatabase(dataSource: DataSource, databaseName: string, options?: any): Promise<string> {
332
- // 默认实现,子类可以重写
333
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持备份数据库`);
334
- }
335
-
336
- /**
337
- * 恢复数据库 - 子类实现(如果支持)
338
- */
339
- async restoreDatabase(dataSource: DataSource, databaseName: string, filePath: string, options?: any): Promise<void> {
340
- // 默认实现,子类可以重写
341
- throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持恢复数据库`);
342
- }
343
-
344
- /**
345
- * 导出表数据到 SQL 文件 - 子类实现
346
- */
347
- abstract exportTableDataToSQL(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
348
-
349
- /**
350
- * 导出表数据到 CSV 文件 - 子类实现
351
- */
352
- abstract exportTableDataToCSV(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
353
-
354
- /**
355
- * 导出表数据到 JSON 文件 - 子类实现
356
- */
357
- abstract exportTableDataToJSON(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
358
-
359
- /**
360
- * 导出表数据到 Excel 文件 - 子类实现
361
- */
362
- abstract exportTableDataToExcel(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
1
+ import { DataSource } from 'typeorm';
2
+ import {
3
+ DatabaseEntity,
4
+ TableEntity,
5
+ ColumnEntity,
6
+ IndexEntity,
7
+ ForeignKeyEntity
8
+ } from './model/database.entity';
9
+
10
+ /**
11
+ * 数据库服务基础类
12
+ * 提供所有数据库类型的通用操作
13
+ */
14
+ export abstract class BaseDatabaseService {
15
+
16
+ /**
17
+ * 获取数据库类型
18
+ */
19
+ abstract getDatabaseType(): string;
20
+
21
+ /**
22
+ * 获取数据库列表 - 子类实现
23
+ */
24
+ abstract getDatabases(dataSource: DataSource): Promise<string[]>;
25
+
26
+ /**
27
+ * 获取表列表 - 子类实现
28
+ */
29
+ abstract getTables(dataSource: DataSource, database: string): Promise<TableEntity[]>;
30
+
31
+ /**
32
+ * 获取列信息 - 子类实现
33
+ */
34
+ abstract getColumns(dataSource: DataSource, database: string, table: string): Promise<ColumnEntity[]>;
35
+
36
+ /**
37
+ * 获取索引信息 - 子类实现
38
+ */
39
+ abstract getIndexes(dataSource: DataSource, database: string, table: string): Promise<IndexEntity[]>;
40
+
41
+ /**
42
+ * 获取外键信息 - 子类实现
43
+ */
44
+ abstract getForeignKeys(dataSource: DataSource, database: string, table: string): Promise<ForeignKeyEntity[]>;
45
+
46
+ /**
47
+ * 获取数据库大小 - 子类实现
48
+ */
49
+ abstract getDatabaseSize(dataSource: DataSource, database: string): Promise<number>;
50
+
51
+ /**
52
+ * 通用方法:获取数据库详细信息
53
+ */
54
+ async getDatabaseInfo(dataSource: DataSource, databaseName: string): Promise<DatabaseEntity> {
55
+ const tables = await this.getTables(dataSource, databaseName);
56
+
57
+ return {
58
+ name: databaseName,
59
+ tableCount: tables.length,
60
+ size: await this.getDatabaseSize(dataSource, databaseName),
61
+ tables
62
+ };
63
+ }
64
+
65
+ /**
66
+ * 通用方法:获取表详细信息
67
+ */
68
+ async getTableInfo(dataSource: DataSource, databaseName: string, tableName: string): Promise<TableEntity> {
69
+ const tables = await this.getTables(dataSource, databaseName);
70
+ const table = tables.find(t => t.name === tableName);
71
+
72
+ if (!table) {
73
+ throw new Error(`表 ${tableName} 不存在`);
74
+ }
75
+
76
+ // 获取列信息
77
+ table.columns = await this.getColumns(dataSource, databaseName, tableName);
78
+
79
+ // 获取索引信息
80
+ table.indexes = await this.getIndexes(dataSource, databaseName, tableName);
81
+
82
+ // 获取外键信息
83
+ table.foreignKeys = await this.getForeignKeys(dataSource, databaseName, tableName);
84
+
85
+ return table;
86
+ }
87
+
88
+ /**
89
+ * 通用方法:获取表数据
90
+ */
91
+ async getTableData(
92
+ dataSource: DataSource,
93
+ databaseName: string,
94
+ tableName: string,
95
+ page: number = 1,
96
+ pageSize: number = 100,
97
+ where?: string,
98
+ orderBy?: string
99
+ ): Promise<{ data: any[], total: number }> {
100
+ // 构建查询
101
+ let query = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;
102
+
103
+ if (where) {
104
+ query += ` WHERE ${where}`;
105
+ }
106
+
107
+ if (orderBy) {
108
+ query += ` ORDER BY ${orderBy}`;
109
+ }
110
+
111
+ const offset = (page - 1) * pageSize;
112
+ query += ` LIMIT ${pageSize} OFFSET ${offset}`;
113
+
114
+ // 执行数据查询
115
+ const data = await dataSource.query(query);
116
+
117
+ // 获取总数
118
+ let countQuery = `SELECT COUNT(*) as total FROM ${this.quoteIdentifier(tableName)}`;
119
+ if (where) {
120
+ countQuery += ` WHERE ${where}`;
121
+ }
122
+ const countResult = await dataSource.query(countQuery);
123
+ const total = countResult[0]?.total || 0;
124
+
125
+ return { data, total };
126
+ }
127
+
128
+ /**
129
+ * 通用方法:执行SQL查询
130
+ */
131
+ async executeQuery(dataSource: DataSource, sql: string): Promise<any> {
132
+ try {
133
+ const result = await dataSource.query(sql);
134
+ return result;
135
+ } catch (error) {
136
+ console.error('SQL执行失败:', error);
137
+ throw error;
138
+ }
139
+ }
140
+
141
+ /**
142
+ * 批量执行SQL查询(支持多条语句)
143
+ */
144
+ async executeBatchQuery(
145
+ dataSource: DataSource,
146
+ sqlStatements: string[],
147
+ options?: {
148
+ batchSize?: number; // 每批执行的语句数量
149
+ useTransaction?: boolean; // 是否使用事务
150
+ continueOnError?: boolean; // 错误时是否继续执行
151
+ }
152
+ ): Promise<{ success: number; failed: number; errors: any[] }> {
153
+ const {
154
+ batchSize = 100,
155
+ useTransaction = true,
156
+ continueOnError = false
157
+ } = options || {};
158
+
159
+ let success = 0;
160
+ let failed = 0;
161
+ const errors: any[] = [];
162
+
163
+ // 分批处理SQL语句
164
+ for (let i = 0; i < sqlStatements.length; i += batchSize) {
165
+ const batch = sqlStatements.slice(i, i + batchSize);
166
+
167
+ try {
168
+ if (useTransaction) {
169
+ // 使用事务执行批次
170
+ await dataSource.transaction(async (manager) => {
171
+ for (const statement of batch) {
172
+ try {
173
+ await manager.query(statement);
174
+ success++;
175
+ } catch (error) {
176
+ failed++;
177
+ errors.push({ statement, error: error.message });
178
+ if (!continueOnError) {
179
+ throw error;
180
+ }
181
+ }
182
+ }
183
+ });
184
+ } else {
185
+ // 非事务执行批次
186
+ for (const statement of batch) {
187
+ try {
188
+ await dataSource.query(statement);
189
+ success++;
190
+ } catch (error) {
191
+ failed++;
192
+ errors.push({ statement, error: error.message });
193
+ if (!continueOnError) {
194
+ throw error;
195
+ }
196
+ }
197
+ }
198
+ }
199
+ } catch (batchError) {
200
+ console.error(`批次执行失败 (${i}-${i + batchSize}):`, batchError);
201
+ if (!continueOnError) {
202
+ throw new Error(`批次执行失败: ${batchError.message}`);
203
+ }
204
+ }
205
+ }
206
+
207
+ return { success, failed, errors };
208
+ }
209
+
210
+ /**
211
+ * 执行文件中的SQL(支持大文件)
212
+ */
213
+ async executeSqlFile(
214
+ dataSource: DataSource,
215
+ filePath: string,
216
+ options?: {
217
+ batchSize?: number;
218
+ useTransaction?: boolean;
219
+ continueOnError?: boolean;
220
+ }
221
+ ): Promise<{ success: number; failed: number; errors: any[] }> {
222
+ const fs = require('fs');
223
+ const sqlContent = fs.readFileSync(filePath, 'utf8');
224
+
225
+ // 分割SQL语句
226
+ const sqlStatements = sqlContent
227
+ .split(';')
228
+ .map(statement => statement.trim())
229
+ .filter(statement => statement.length > 0);
230
+
231
+ return this.executeBatchQuery(dataSource, sqlStatements, options);
232
+ }
233
+
234
+ /**
235
+ * 通用方法:测试连接
236
+ */
237
+ async testConnection(dataSource: DataSource): Promise<boolean> {
238
+ try {
239
+ await dataSource.query('SELECT 1');
240
+ return true;
241
+ } catch (error) {
242
+ //this.ctx.logger.error('数据库连接测试失败:', error);
243
+ console.error(error);
244
+ return false;
245
+ }
246
+ }
247
+
248
+ /**
249
+ * 通用方法:给标识符加引号
250
+ */
251
+ public quoteIdentifier(identifier: string): string {
252
+ return `"${identifier}"`;
253
+ }
254
+
255
+ /**
256
+ * 通用方法:构建分页查询
257
+ */
258
+ protected buildPaginationQuery(baseQuery: string, page: number, pageSize: number): string {
259
+ const offset = (page - 1) * pageSize;
260
+ return `${baseQuery} LIMIT ${pageSize} OFFSET ${offset}`;
261
+ }
262
+
263
+ /**
264
+ * 通用方法:构建计数查询
265
+ */
266
+ protected buildCountQuery(baseQuery: string): string {
267
+ return `SELECT COUNT(*) as total FROM (${baseQuery}) as count_query`;
268
+ }
269
+
270
+ /**
271
+ * 获取视图列表 - 子类实现(如果支持)
272
+ */
273
+ async getViews(dataSource: DataSource, database: string): Promise<any[]> {
274
+ // 默认实现,子类可以重写
275
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持视图`);
276
+ }
277
+
278
+ /**
279
+ * 获取视图定义 - 子类实现(如果支持)
280
+ */
281
+ async getViewDefinition(dataSource: DataSource, database: string, viewName: string): Promise<string> {
282
+ // 默认实现,子类可以重写
283
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持视图`);
284
+ }
285
+
286
+ /**
287
+ * 获取存储过程列表 - 子类实现(如果支持)
288
+ */
289
+ async getProcedures(dataSource: DataSource, database: string): Promise<any[]> {
290
+ // 默认实现,子类可以重写
291
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持存储过程`);
292
+ }
293
+
294
+ /**
295
+ * 获取存储过程定义 - 子类实现(如果支持)
296
+ */
297
+ async getProcedureDefinition(dataSource: DataSource, database: string, procedureName: string): Promise<string> {
298
+ // 默认实现,子类可以重写
299
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持存储过程`);
300
+ }
301
+
302
+ /**
303
+ * 导出数据库架构 - 子类实现
304
+ */
305
+ abstract exportSchema(dataSource: DataSource, database: string): Promise<string>;
306
+
307
+ /**
308
+ * 查看数据库日志 - 子类实现(如果支持)
309
+ */
310
+ abstract viewLogs(dataSource: DataSource, database?: string, limit?: number): Promise<any[]>;
311
+
312
+ /**
313
+ * 创建数据库 - 子类实现(如果支持)
314
+ */
315
+ async createDatabase(dataSource: DataSource, databaseName: string, options?: any): Promise<void> {
316
+ // 默认实现,子类可以重写
317
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持创建数据库`);
318
+ }
319
+
320
+ /**
321
+ * 删除数据库 - 子类实现(如果支持)
322
+ */
323
+ async dropDatabase(dataSource: DataSource, databaseName: string): Promise<void> {
324
+ // 默认实现,子类可以重写
325
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持删除数据库`);
326
+ }
327
+
328
+ /**
329
+ * 备份数据库 - 子类实现(如果支持)
330
+ */
331
+ async backupDatabase(dataSource: DataSource, databaseName: string, options?: any): Promise<string> {
332
+ // 默认实现,子类可以重写
333
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持备份数据库`);
334
+ }
335
+
336
+ /**
337
+ * 恢复数据库 - 子类实现(如果支持)
338
+ */
339
+ async restoreDatabase(dataSource: DataSource, databaseName: string, filePath: string, options?: any): Promise<void> {
340
+ // 默认实现,子类可以重写
341
+ throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持恢复数据库`);
342
+ }
343
+
344
+ /**
345
+ * 导出表数据到 SQL 文件 - 子类实现
346
+ */
347
+ abstract exportTableDataToSQL(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
348
+
349
+ /**
350
+ * 导出表数据到 CSV 文件 - 子类实现
351
+ */
352
+ abstract exportTableDataToCSV(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
353
+
354
+ /**
355
+ * 导出表数据到 JSON 文件 - 子类实现
356
+ */
357
+ abstract exportTableDataToJSON(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
358
+
359
+ /**
360
+ * 导出表数据到 Excel 文件 - 子类实现
361
+ */
362
+ abstract exportTableDataToExcel(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
363
363
  }