|
6 | 6 | * LICENSE file in the root directory of this source tree. |
7 | 7 | */ |
8 | 8 |
|
9 | | -import { Driver, IntrospectedSchema, IntrospectedTable, IntrospectedColumn, IntrospectedForeignKey } from '@objectql/types'; |
| 9 | +import { IntrospectedSchema, IntrospectedTable, IntrospectedColumn, IntrospectedForeignKey } from '@objectql/types'; |
| 10 | +import type { DriverInterface } from '@objectstack/spec'; |
10 | 11 | import knex, { Knex } from 'knex'; |
11 | 12 |
|
12 | | -export class SqlDriver implements Driver { |
| 13 | +export class SqlDriver implements DriverInterface { |
| 14 | + readonly name = 'sql'; |
| 15 | + readonly version = '3.0.1'; |
| 16 | + readonly supports = { |
| 17 | + transactions: true, |
| 18 | + joins: true, |
| 19 | + fullTextSearch: false, |
| 20 | + jsonFields: true, |
| 21 | + arrayFields: false |
| 22 | + }; |
| 23 | + |
13 | 24 | private knex: Knex; |
14 | 25 | private config: any; |
15 | 26 | private jsonFields: Record<string, string[]> = {}; |
@@ -219,16 +230,41 @@ export class SqlDriver implements Driver { |
219 | 230 | return 0; |
220 | 231 | } |
221 | 232 |
|
| 233 | + // Connection Management |
| 234 | + async connect(): Promise<void> { |
| 235 | + // Knex initializes connection pool automatically |
| 236 | + // We can test the connection here |
| 237 | + await this.knex.raw('SELECT 1'); |
| 238 | + } |
| 239 | + |
| 240 | + async checkHealth(): Promise<boolean> { |
| 241 | + try { |
| 242 | + await this.knex.raw('SELECT 1'); |
| 243 | + return true; |
| 244 | + } catch { |
| 245 | + return false; |
| 246 | + } |
| 247 | + } |
| 248 | + |
| 249 | + async execute(command: any, parameters?: any[], options?: any): Promise<any> { |
| 250 | + // For SQL driver, execute raw SQL |
| 251 | + if (typeof command === 'string') { |
| 252 | + return await this.knex.raw(command, parameters); |
| 253 | + } |
| 254 | + // For object commands, could be knex query builder |
| 255 | + throw new Error('Execute with non-string commands not supported in SQL driver'); |
| 256 | + } |
| 257 | + |
222 | 258 | // Transaction Support |
223 | 259 | async beginTransaction(): Promise<any> { |
224 | 260 | return await this.knex.transaction(); |
225 | 261 | } |
226 | 262 |
|
227 | | - async commitTransaction(trx: Knex.Transaction): Promise<void> { |
| 263 | + async commit(trx: Knex.Transaction): Promise<void> { |
228 | 264 | await trx.commit(); |
229 | 265 | } |
230 | 266 |
|
231 | | - async rollbackTransaction(trx: Knex.Transaction): Promise<void> { |
| 267 | + async rollback(trx: Knex.Transaction): Promise<void> { |
232 | 268 | await trx.rollback(); |
233 | 269 | } |
234 | 270 |
|
@@ -277,23 +313,45 @@ export class SqlDriver implements Driver { |
277 | 313 | } |
278 | 314 | } |
279 | 315 |
|
280 | | - // Bulk |
281 | | - async createMany(objectName: string, data: any[], options?: any): Promise<any> { |
| 316 | + // Bulk Operations |
| 317 | + async bulkCreate(objectName: string, data: any[], options?: any): Promise<any> { |
282 | 318 | const builder = this.getBuilder(objectName, options); |
283 | 319 | return await builder.insert(data).returning('*'); |
284 | 320 | } |
285 | 321 |
|
286 | | - async updateMany(objectName: string, filters: any, data: any, options?: any): Promise<any> { |
| 322 | + async bulkUpdate(objectName: string, filters: any, data: any, options?: any): Promise<any> { |
287 | 323 | const builder = this.getBuilder(objectName, options); |
288 | 324 | if(filters) this.applyFilters(builder, filters); |
289 | 325 | return await builder.update(data); |
290 | 326 | } |
291 | 327 |
|
292 | | - async deleteMany(objectName: string, filters: any, options?: any): Promise<any> { |
| 328 | + async bulkDelete(objectName: string, filters: any, options?: any): Promise<any> { |
293 | 329 | const builder = this.getBuilder(objectName, options); |
294 | 330 | if(filters) this.applyFilters(builder, filters); |
295 | 331 | return await builder.delete(); |
296 | 332 | } |
| 333 | + |
| 334 | + // Aliases for backward compatibility |
| 335 | + async createMany(objectName: string, data: any[], options?: any): Promise<any> { |
| 336 | + return this.bulkCreate(objectName, data, options); |
| 337 | + } |
| 338 | + |
| 339 | + async updateMany(objectName: string, filters: any, data: any, options?: any): Promise<any> { |
| 340 | + return this.bulkUpdate(objectName, filters, data, options); |
| 341 | + } |
| 342 | + |
| 343 | + async deleteMany(objectName: string, filters: any, options?: any): Promise<any> { |
| 344 | + return this.bulkDelete(objectName, filters, options); |
| 345 | + } |
| 346 | + |
| 347 | + // Transaction aliases for backward compatibility |
| 348 | + async commitTransaction(trx: Knex.Transaction): Promise<void> { |
| 349 | + return this.commit(trx); |
| 350 | + } |
| 351 | + |
| 352 | + async rollbackTransaction(trx: Knex.Transaction): Promise<void> { |
| 353 | + return this.rollback(trx); |
| 354 | + } |
297 | 355 |
|
298 | 356 | async init(objects: any[]): Promise<void> { |
299 | 357 | await this.ensureDatabaseExists(); |
@@ -506,6 +564,23 @@ export class SqlDriver implements Driver { |
506 | 564 | return data; |
507 | 565 | } |
508 | 566 |
|
| 567 | + /** |
| 568 | + * Synchronize schema - alias for init for DriverInterface compatibility |
| 569 | + */ |
| 570 | + async syncSchema(objects: any[]): Promise<void> { |
| 571 | + return this.init(objects); |
| 572 | + } |
| 573 | + |
| 574 | + /** |
| 575 | + * Drop a table from the database |
| 576 | + */ |
| 577 | + async dropTable(tableName: string): Promise<void> { |
| 578 | + const exists = await this.knex.schema.hasTable(tableName); |
| 579 | + if (exists) { |
| 580 | + await this.knex.schema.dropTable(tableName); |
| 581 | + } |
| 582 | + } |
| 583 | + |
509 | 584 | /** |
510 | 585 | * Introspect the database schema to discover existing tables, columns, and relationships. |
511 | 586 | */ |
|
0 commit comments