refactor: use dot notation for table name config (schema.table instead of schema_table)

Replace underscore-based table name splitting with dot-based splitting
to match the standard schema.tablename format, removing MySQL compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-04-28 11:10:03 +08:00
parent 664f26d63f
commit 5ff99cdd0f
8 changed files with 57 additions and 68 deletions

View File

@@ -188,21 +188,26 @@ flowchart LR
**表名转换逻辑**:
```typescript
// MySQL: dbo_MaterialsToBeDeleted
// 输入格式: dbo.MaterialsToBeDeleted
// SQL Server: [dbo].[MaterialsToBeDeleted]
function getTableName(mysqlTableName: string): string {
const dbType = process.env.DB_TYPE?.toLowerCase()
if (dbType === 'sqlserver' || dbType === 'mssql') {
// 找到第一个下划线分割schema和表名
const firstUnderscoreIndex = mysqlTableName.indexOf('_')
if (firstUnderscoreIndex > 0) {
const schema = mysqlTableName.substring(0, firstUnderscoreIndex)
const tableName = mysqlTableName.substring(firstUnderscoreIndex + 1)
// PostgreSQL: "dbo"."MaterialsToBeDeleted"
function getValidationTableName(dottedTableName: string): string {
const configManager = ConfigManager.getInstance()
const dbType = configManager.getDatabaseType()
const dotIndex = dottedTableName.indexOf('.')
if (dotIndex > 0) {
const schema = dottedTableName.substring(0, dotIndex)
const tableName = dottedTableName.substring(dotIndex + 1)
if (dbType === 'sqlserver') {
return `[${schema}].[${tableName}]`
}
return `[dbo].[${mysqlTableName}]`
return `"${schema}"."${tableName}"`
}
return mysqlTableName
if (dbType === 'sqlserver') {
return `[dbo].[${dottedTableName}]`
}
return `"public"."${dottedTableName}"`
}
```

View File

@@ -541,7 +541,7 @@ graph LR
### 10.2 默认配置示例
```env
DB_TABLE_NAME=productionContractData_26 年压力表合同数据
DB_TABLE_NAME=ERPAuto.vw_productionContractData
DB_FIELD_PRODUCTION_ID=总排号
DB_FIELD_ORDER_NUMBER=生产订单号
```

View File

@@ -180,7 +180,7 @@ validation:
# 订单号解析配置
orderResolution:
tableName: 'productionContractData_26 年压力表合同数据'
tableName: 'ERPAuto.vw_productionContractData'
productionIdField: '总排号'
orderNumberField: '生产订单号'
```

View File

@@ -40,7 +40,7 @@ export function getDbConfig() {
const configManager = ConfigManager.getInstance()
const config = configManager.getConfig()
return {
TABLE_NAME: config.orderResolution.tableName || 'productionContractData_26 年压力表合同数据',
TABLE_NAME: config.orderResolution.tableName || 'ERPAuto.vw_productionContractData',
FIELD_PRODUCTION_ID: config.orderResolution.productionIdField || '总排号',
FIELD_ORDER_NUMBER: config.orderResolution.orderNumberField || '生产订单号'
}
@@ -58,35 +58,28 @@ export class OrderNumberResolver {
/**
* Get table name based on database type
* Converts schema_tablename format to database-specific quoting:
* Converts schema.tablename format to database-specific quoting:
* - SQL Server: [schema].[tablename]
* - PostgreSQL: "schema"."tablename"
* - MySQL: schema_tablename (as-is)
* e.g., productionContractData_26年压力表合同数据 ->
* SQL Server: [productionContractData].[26年压力表合同数据]
* PostgreSQL: "productionContractData"."26年压力表合同数据"
* MySQL: productionContractData_26年压力表合同数据
* e.g., ERPAuto.vw_productionContractData ->
* SQL Server: [ERPAuto].[vw_productionContractData]
* PostgreSQL: "ERPAuto"."vw_productionContractData"
*/
private getTableName(tableName: string): string {
if (this.dbService.type === 'sqlserver' || this.dbService.type === 'postgresql') {
// Find the FIRST underscore to split schema and table name
// This handles patterns like: schema_tablename
const firstUnderscoreIndex = tableName.indexOf('_')
if (firstUnderscoreIndex > 0) {
const schema = tableName.substring(0, firstUnderscoreIndex)
const actualTableName = tableName.substring(firstUnderscoreIndex + 1)
if (this.dbService.type === 'sqlserver') {
return `[${schema}].[${actualTableName}]`
}
return `"${schema}"."${actualTableName}"`
}
// If no underscore found, default schema
const dotIndex = tableName.indexOf('.')
if (dotIndex > 0) {
const schema = tableName.substring(0, dotIndex)
const actualTableName = tableName.substring(dotIndex + 1)
if (this.dbService.type === 'sqlserver') {
return `[dbo].[${tableName}]`
return `[${schema}].[${actualTableName}]`
}
return `"public"."${tableName}"`
return `"${schema}"."${actualTableName}"`
}
return tableName
// No dot found — use default schema
if (this.dbService.type === 'sqlserver') {
return `[dbo].[${tableName}]`
}
return `"public"."${tableName}"`
}
/**

View File

@@ -41,7 +41,7 @@ export async function getSourceNumbersFromInputs(
}
if (productionIds.length > 0) {
const contractTableName = getValidationTableName('productionContractData_26年压力表合同数据')
const contractTableName = getValidationTableName('ERPAuto.vw_productionContractData')
const batchSize = 2000
if (dbType === 'sqlserver') {

View File

@@ -325,7 +325,7 @@ export class ValidationApplicationService {
}
private async loadTypeKeywords(dbService: ValidationDatabaseService): Promise<TypeKeyword[]> {
const typeKeywordTableName = getValidationTableName('dbo_MaterialsTypeToBeDeleted')
const typeKeywordTableName = getValidationTableName('dbo.MaterialsTypeToBeDeleted')
const sql = `
SELECT MaterialName, ManagerName
FROM ${typeKeywordTableName}
@@ -341,7 +341,7 @@ export class ValidationApplicationService {
private async loadMarkedCodes(
dbService: ValidationDatabaseService
): Promise<Map<string, string>> {
const markedTableName = getValidationTableName('dbo_MaterialsToBeDeleted')
const markedTableName = getValidationTableName('dbo.MaterialsToBeDeleted')
const sql = `
SELECT MaterialCode, ManagerName
FROM ${markedTableName}
@@ -416,7 +416,7 @@ export class ValidationApplicationService {
try {
dbService = await createValidationDatabaseService()
const detailTableName = getValidationTableName('dbo_DiscreteMaterialPlanData')
const detailTableName = getValidationTableName('dbo.DiscreteMaterialPlanData')
const enrichedMaterials: MaterialRecordSummary[] = []
log.info(`Enriching ${materials.length} materials with details`)
@@ -501,7 +501,7 @@ export class ValidationApplicationService {
selectedManagers: string[],
orderNumbers: string[]
): Promise<string[]> {
const markedTableName = getValidationTableName('dbo_MaterialsToBeDeleted')
const markedTableName = getValidationTableName('dbo.MaterialsToBeDeleted')
// Admin with selected managers: filter MaterialsToBeDeleted by ManagerName IN (selectedManagers)
if (isAdmin && selectedManagers && selectedManagers.length > 0) {

View File

@@ -52,25 +52,22 @@ export async function createValidationDatabaseService(): Promise<ValidationDatab
return mysqlService
}
export function getValidationTableName(mysqlTableName: string): string {
export function getValidationTableName(dottedTableName: string): string {
const configManager = ConfigManager.getInstance()
const dbType = configManager.getDatabaseType()
if (dbType === 'sqlserver' || dbType === 'postgresql') {
const firstUnderscoreIndex = mysqlTableName.indexOf('_')
if (firstUnderscoreIndex > 0) {
const schema = mysqlTableName.substring(0, firstUnderscoreIndex)
const tableName = mysqlTableName.substring(firstUnderscoreIndex + 1)
if (dbType === 'sqlserver') {
return `[${schema}].[${tableName}]`
}
return `"${schema}"."${tableName}"`
}
const dotIndex = dottedTableName.indexOf('.')
if (dotIndex > 0) {
const schema = dottedTableName.substring(0, dotIndex)
const tableName = dottedTableName.substring(dotIndex + 1)
if (dbType === 'sqlserver') {
return `[dbo].[${mysqlTableName}]`
return `[${schema}].[${tableName}]`
}
return `"public"."${mysqlTableName}"`
return `"${schema}"."${tableName}"`
}
return mysqlTableName
// No dot found — use default schema
if (dbType === 'sqlserver') {
return `[dbo].[${dottedTableName}]`
}
return `"public"."${dottedTableName}"`
}

View File

@@ -125,31 +125,25 @@ describe('ValidationDatabaseService', () => {
})
describe('getValidationTableName', () => {
it('returns table name unchanged for mysql', async () => {
currentDbType = 'mysql'
const mod = await import('../../../../src/main/services/validation/validation-database')
expect(mod.getValidationTableName('MaterialsToBeDeleted')).toBe('MaterialsToBeDeleted')
})
it('converts schema_table to [schema].[table] for sqlserver', async () => {
it('converts schema.table to [schema].[table] for sqlserver', async () => {
currentDbType = 'sqlserver'
const mod = await import('../../../../src/main/services/validation/validation-database')
expect(mod.getValidationTableName('dbo_Materials')).toBe('[dbo].[Materials]')
expect(mod.getValidationTableName('dbo.Materials')).toBe('[dbo].[Materials]')
})
it('wraps nameless table in [dbo].[name] for sqlserver', async () => {
it('wraps dotless table in [dbo].[name] for sqlserver', async () => {
currentDbType = 'sqlserver'
const mod = await import('../../../../src/main/services/validation/validation-database')
expect(mod.getValidationTableName('Materials')).toBe('[dbo].[Materials]')
})
it('converts schema_table to "schema"."table" for postgresql', async () => {
it('converts schema.table to "schema"."table" for postgresql', async () => {
currentDbType = 'postgresql'
const mod = await import('../../../../src/main/services/validation/validation-database')
expect(mod.getValidationTableName('public_Materials')).toBe('"public"."Materials"')
expect(mod.getValidationTableName('public.Materials')).toBe('"public"."Materials"')
})
it('wraps nameless table in "public"."name" for postgresql', async () => {
it('wraps dotless table in "public"."name" for postgresql', async () => {
currentDbType = 'postgresql'
const mod = await import('../../../../src/main/services/validation/validation-database')
expect(mod.getValidationTableName('Materials')).toBe('"public"."Materials"')