refactor(db): use SqlDialect in MaterialsToBeDeletedDAO

Replace all isSqlServer/if-else branches with SqlDialect calls:
- Table name via dialect.quoteTableName()
- Placeholders via dialect.param() and dialect.params()
- UPSERT via dialect.upsert() in upsertMaterial(), upsertBatch(), updateManager()
- Remove buildPlaceholders(), TABLE_NAME_SQLSERVER, TABLE_NAME_MYSQL
- Re-export SqlDialect type from dialects barrel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka
2026-04-05 10:17:21 +08:00
parent 9300f3455f
commit fa57f9e564
2 changed files with 59 additions and 103 deletions

View File

@@ -14,6 +14,7 @@ import { SqlServerDialect } from './sqlserver-dialect'
export { MySqlDialect } from './mysql-dialect' export { MySqlDialect } from './mysql-dialect'
export { PostgreSqlDialect } from './postgresql-dialect' export { PostgreSqlDialect } from './postgresql-dialect'
export { SqlServerDialect } from './sqlserver-dialect' export { SqlServerDialect } from './sqlserver-dialect'
export type { SqlDialect } from '@types/sql-dialect.types'
export function createDialect(type: DatabaseType): SqlDialect { export function createDialect(type: DatabaseType): SqlDialect {
switch (type) { switch (type) {

View File

@@ -9,6 +9,7 @@
*/ */
import { create, type IDatabaseService } from './index' import { create, type IDatabaseService } from './index'
import { createDialect, type SqlDialect } from './dialects'
import { createLogger, run, getRequestId, trackDuration } from '../logger' import { createLogger, run, getRequestId, trackDuration } from '../logger'
const log = createLogger('MaterialsToBeDeletedDAO') const log = createLogger('MaterialsToBeDeletedDAO')
@@ -44,8 +45,6 @@ export interface MaterialStats {
* Configuration for MaterialsToBeDeleted table * Configuration for MaterialsToBeDeleted table
*/ */
export const MATERIALS_TO_BE_DELETED_CONFIG = { export const MATERIALS_TO_BE_DELETED_CONFIG = {
TABLE_NAME_SQLSERVER: '[dbo].[MaterialsToBeDeleted]',
TABLE_NAME_MYSQL: 'dbo_MaterialsToBeDeleted',
COLUMNS: { COLUMNS: {
ID: 'ID', ID: 'ID',
MATERIAL_CODE: 'MaterialCode', MATERIAL_CODE: 'MaterialCode',
@@ -58,15 +57,20 @@ export const MATERIALS_TO_BE_DELETED_CONFIG = {
*/ */
export class MaterialsToBeDeletedDAO { export class MaterialsToBeDeletedDAO {
private dbService: IDatabaseService | null = null private dbService: IDatabaseService | null = null
private dialect: SqlDialect | null = null
private getDialect(): SqlDialect {
if (!this.dialect) {
this.dialect = createDialect(this.dbService!.type)
}
return this.dialect
}
/** /**
* Get the appropriate table name based on database type * Get the appropriate table name based on database type
*/ */
private getTableName(): string { private getTableName(): string {
const isSqlServer = this.dbService?.type === 'sqlserver' return this.getDialect().quoteTableName('dbo', 'MaterialsToBeDeleted')
return isSqlServer
? MATERIALS_TO_BE_DELETED_CONFIG.TABLE_NAME_SQLSERVER
: MATERIALS_TO_BE_DELETED_CONFIG.TABLE_NAME_MYSQL
} }
/** /**
@@ -81,15 +85,6 @@ export class MaterialsToBeDeletedDAO {
return this.dbService return this.dbService
} }
/**
* Build placeholders for IN clause based on database type
*/
private buildPlaceholders(count: number, isSqlServer: boolean): string {
return isSqlServer
? Array.from({ length: count }, (_, idx) => `@p${idx}`).join(',')
: Array.from({ length: count }, () => '?').join(',')
}
// ==================== UPSERT (MERGE) ==================== // ==================== UPSERT (MERGE) ====================
/** /**
@@ -113,33 +108,19 @@ export class MaterialsToBeDeletedDAO {
const tableName = this.getTableName() const tableName = this.getTableName()
const code = materialCode.trim() const code = materialCode.trim()
const manager = managerName?.trim() || null const manager = managerName?.trim() || null
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
if (isSqlServer) { const { sql: sqlString } = dialect.upsert({
const sqlString = ` table: tableName,
MERGE ${tableName} AS target keyColumns: ['MaterialCode'],
USING (VALUES (@p0, @p1)) AS source (MaterialCode, ManagerName) allColumns: ['MaterialCode', 'ManagerName'],
ON target.MaterialCode = source.MaterialCode startParamIndex: 0
WHEN MATCHED THEN UPDATE SET ManagerName = source.ManagerName })
WHEN NOT MATCHED THEN INSERT (MaterialCode, ManagerName) VALUES (source.MaterialCode, source.ManagerName);
`
await trackDuration(async () => await dbService.query(sqlString, [code, manager]), { await trackDuration(async () => await dbService.query(sqlString, [code, manager]), {
operationName: 'MaterialsToBeDeletedDAO.upsertMaterial', operationName: 'MaterialsToBeDeletedDAO.upsertMaterial',
context: { tableName, operationType: 'MERGE' } context: { tableName, operationType: 'UPSERT' }
}) })
} else {
const sqlString = `
INSERT INTO ${tableName} (MaterialCode, ManagerName)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE ManagerName = VALUES(ManagerName)
`
await trackDuration(async () => await dbService.query(sqlString, [code, manager]), {
operationName: 'MaterialsToBeDeletedDAO.upsertMaterial',
context: { tableName, operationType: 'INSERT' }
})
}
return true return true
} catch (error) { } catch (error) {
@@ -176,7 +157,7 @@ export class MaterialsToBeDeletedDAO {
try { try {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
log.info('Batch upsert started', { log.info('Batch upsert started', {
tableName, tableName,
@@ -196,37 +177,20 @@ export class MaterialsToBeDeletedDAO {
} }
try { try {
if (isSqlServer) { const { sql: sqlString } = dialect.upsert({
const sqlString = ` table: tableName,
MERGE ${tableName} AS target keyColumns: ['MaterialCode'],
USING (VALUES (@p0, @p1)) AS source (MaterialCode, ManagerName) allColumns: ['MaterialCode', 'ManagerName'],
ON target.MaterialCode = source.MaterialCode startParamIndex: 0
WHEN MATCHED THEN UPDATE SET ManagerName = source.ManagerName })
WHEN NOT MATCHED THEN INSERT (MaterialCode, ManagerName) VALUES (source.MaterialCode, source.ManagerName);
`
await trackDuration( await trackDuration(
async () => await dbService.query(sqlString, [materialCode, managerName || null]), async () => await dbService.query(sqlString, [materialCode, managerName || null]),
{ {
operationName: 'MaterialsToBeDeletedDAO.upsertBatch', operationName: 'MaterialsToBeDeletedDAO.upsertBatch',
context: { tableName, operationType: 'MERGE', batchId } context: { tableName, operationType: 'UPSERT', batchId }
} }
) )
} else {
const sqlString = `
INSERT INTO ${tableName} (MaterialCode, ManagerName)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE ManagerName = VALUES(ManagerName)
`
await trackDuration(
async () => await dbService.query(sqlString, [materialCode, managerName || null]),
{
operationName: 'MaterialsToBeDeletedDAO.upsertBatch',
context: { tableName, operationType: 'INSERT', batchId }
}
)
}
stats.success++ stats.success++
} catch (error) { } catch (error) {
@@ -276,25 +240,15 @@ export class MaterialsToBeDeletedDAO {
try { try {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
if (isSqlServer) { const { sql: sqlString } = dialect.upsert({
const sqlString = ` table: tableName,
MERGE ${tableName} AS target keyColumns: ['MaterialCode'],
USING (VALUES (@p0, @p1)) AS source (MaterialCode, ManagerName) allColumns: ['MaterialCode', 'ManagerName'],
ON target.MaterialCode = source.MaterialCode startParamIndex: 0
WHEN MATCHED THEN UPDATE SET ManagerName = source.ManagerName })
WHEN NOT MATCHED THEN INSERT (MaterialCode, ManagerName) VALUES (source.MaterialCode, source.ManagerName); await dbService.query(sqlString, [materialCode, managerName || null])
`
await dbService.query(sqlString, [materialCode, managerName || null])
} else {
const sqlString = `
INSERT INTO ${tableName} (MaterialCode, ManagerName)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE ManagerName = VALUES(ManagerName)
`
await dbService.query(sqlString, [materialCode, managerName || null])
}
return { success: true } return { success: true }
} catch (error) { } catch (error) {
@@ -387,9 +341,9 @@ export class MaterialsToBeDeletedDAO {
try { try {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const placeholder = isSqlServer ? '@p0' : '?' const placeholder = dialect.param(0)
const sqlString = ` const sqlString = `
SELECT ID, MaterialCode, ManagerName SELECT ID, MaterialCode, ManagerName
FROM ${tableName} FROM ${tableName}
@@ -462,9 +416,9 @@ export class MaterialsToBeDeletedDAO {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const code = materialCode.trim() const code = materialCode.trim()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const placeholder = isSqlServer ? '@p0' : '?' const placeholder = dialect.param(0)
const sqlString = ` const sqlString = `
SELECT ID, MaterialCode, ManagerName SELECT ID, MaterialCode, ManagerName
FROM ${tableName} FROM ${tableName}
@@ -509,9 +463,9 @@ export class MaterialsToBeDeletedDAO {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const code = materialCode.trim() const code = materialCode.trim()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const placeholder = isSqlServer ? '@p0' : '?' const placeholder = dialect.param(0)
const sqlString = ` const sqlString = `
DELETE FROM ${tableName} DELETE FROM ${tableName}
WHERE MaterialCode = ${placeholder} WHERE MaterialCode = ${placeholder}
@@ -542,9 +496,9 @@ export class MaterialsToBeDeletedDAO {
try { try {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const placeholder = isSqlServer ? '@p0' : '?' const placeholder = dialect.param(0)
const sqlString = ` const sqlString = `
DELETE FROM ${tableName} DELETE FROM ${tableName}
WHERE ManagerName = ${placeholder} WHERE ManagerName = ${placeholder}
@@ -612,7 +566,7 @@ export class MaterialsToBeDeletedDAO {
try { try {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const totalBatches = Math.ceil(materialCodes.length / batchSize) const totalBatches = Math.ceil(materialCodes.length / batchSize)
log.info('Batch delete started', { log.info('Batch delete started', {
@@ -627,7 +581,7 @@ export class MaterialsToBeDeletedDAO {
for (let i = 0; i < materialCodes.length; i += batchSize) { for (let i = 0; i < materialCodes.length; i += batchSize) {
const batch = materialCodes.slice(i, i + batchSize) const batch = materialCodes.slice(i, i + batchSize)
const batchNumber = Math.floor(i / batchSize) + 1 const batchNumber = Math.floor(i / batchSize) + 1
const placeholders = this.buildPlaceholders(batch.length, isSqlServer) const placeholders = dialect.params(batch.length)
const sqlString = ` const sqlString = `
DELETE FROM ${tableName} DELETE FROM ${tableName}
@@ -688,9 +642,9 @@ export class MaterialsToBeDeletedDAO {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const code = materialCode.trim() const code = materialCode.trim()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const placeholder = isSqlServer ? '@p0' : '?' const placeholder = dialect.param(0)
const sqlString = ` const sqlString = `
SELECT COUNT(*) as count SELECT COUNT(*) as count
FROM ${tableName} FROM ${tableName}
@@ -749,9 +703,9 @@ export class MaterialsToBeDeletedDAO {
try { try {
const dbService = await this.getDatabaseService() const dbService = await this.getDatabaseService()
const tableName = this.getTableName() const tableName = this.getTableName()
const isSqlServer = dbService.type === 'sqlserver' const dialect = this.getDialect()
const placeholder = isSqlServer ? '@p0' : '?' const placeholder = dialect.param(0)
const sqlString = ` const sqlString = `
SELECT COUNT(*) as count SELECT COUNT(*) as count
FROM ${tableName} FROM ${tableName}
@@ -845,6 +799,7 @@ export class MaterialsToBeDeletedDAO {
if (this.dbService) { if (this.dbService) {
await this.dbService.disconnect() await this.dbService.disconnect()
this.dbService = null this.dbService = null
this.dialect = null
} }
} }
} }