feat(db): add SqlDialect interface and PostgreSQL type definitions

- Add 'postgresql' to DatabaseType union in database.types.ts
- Add PostgreSqlConfig interface extending DatabaseConfig
- Add postgresqlConfigSchema Zod schema with host, port, database,
  username, password, and maxPoolSize fields
- Add 'postgresql' to databaseConfigSchema and type exports
- Create SqlDialect interface with methods for quoteTableName,
  param, params, currentTimestamp, upsert, paginate, maxBatchRows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka
2026-04-05 09:19:49 +08:00
parent 6c730616b8
commit 0956bf907f
3 changed files with 110 additions and 3 deletions

View File

@@ -12,7 +12,7 @@ import { z } from 'zod'
/**
* 数据库类型枚举
*/
export const databaseTypeSchema = z.enum(['mysql', 'sqlserver'])
export const databaseTypeSchema = z.enum(['mysql', 'sqlserver', 'postgresql'])
export type DatabaseType = z.infer<typeof databaseTypeSchema>
/**
@@ -57,13 +57,27 @@ export const sqlServerConfigSchema = z.object({
trustServerCertificate: z.boolean().default(true)
})
/**
* PostgreSQL 配置 Schema
*/
export const postgresqlConfigSchema = z.object({
host: z.string().min(1, 'PostgreSQL host is required'),
port: z.number().int().min(1).max(65535).default(5432),
database: z.string().min(1, 'PostgreSQL database is required'),
username: z.string().min(1, 'PostgreSQL username is required'),
password: z.string(),
maxPoolSize: z.number().int().min(1).max(100).default(10)
})
export type PostgreSqlConfigSchema = z.infer<typeof postgresqlConfigSchema>
/**
* 数据库配置(包含两种数据库的完整配置)
*/
export const databaseConfigSchema = z.object({
activeType: databaseTypeSchema.default('mysql'),
mysql: mysqlConfigSchema,
sqlserver: sqlServerConfigSchema
sqlserver: sqlServerConfigSchema,
postgresql: postgresqlConfigSchema
})
/**
@@ -199,6 +213,7 @@ export type FullConfig = z.infer<typeof fullConfigSchema>
export type DatabaseConfig = z.infer<typeof databaseConfigSchema>
export type MySqlConfig = z.infer<typeof mysqlConfigSchema>
export type SqlServerConfig = z.infer<typeof sqlServerConfigSchema>
export type PostgreSqlConfig = z.infer<typeof postgresqlConfigSchema>
export type ErpSystemConfig = z.infer<typeof erpSystemConfigSchema>
export type LoggingConfig = z.infer<typeof loggingConfigSchema>
export type RustfsConfig = z.infer<typeof rustfsConfigSchema>

View File

@@ -8,7 +8,7 @@
/**
* Supported database types
*/
export type DatabaseType = 'mysql' | 'sqlserver'
export type DatabaseType = 'mysql' | 'sqlserver' | 'postgresql'
/**
* Standard query result interface
@@ -102,3 +102,15 @@ export interface SqlServerConfig extends DatabaseConfig {
trustServerCertificate?: boolean
}
}
/**
* PostgreSQL-specific configuration
*/
export interface PostgreSqlConfig extends DatabaseConfig {
host: string
port: number
user: string
password: string
database: string
maxPoolSize?: number
}

View File

@@ -0,0 +1,80 @@
/**
* SQL Dialect Abstraction
*
* Provides a unified interface for database-specific SQL syntax differences.
* Each database type implements this interface to encapsulate:
* - Parameter placeholder format
* - Table name quoting
* - UPSERT syntax
* - Pagination syntax
* - Current timestamp function
* - Batch size limits
*/
import type { DatabaseType } from './database.types'
export interface SqlDialect {
/** Database type identifier */
readonly dbType: DatabaseType
/**
* Quote a table name with schema prefix
* MySQL: dbo_TableName
* SQL Server: [dbo].[TableName]
* PostgreSQL: "dbo"."TableName"
*/
quoteTableName(schema: string, table: string): string
/**
* Get placeholder for parameter at given index (0-based)
* MySQL: ?
* SQL Server: @p0
* PostgreSQL: $1
*/
param(index: number): string
/**
* Get comma-separated placeholders for count parameters
*/
params(count: number): string
/**
* Get current timestamp SQL function
* MySQL: NOW()
* SQL Server: GETDATE()
* PostgreSQL: CURRENT_TIMESTAMP
*/
currentTimestamp(): string
/**
* Generate UPSERT SQL for a single row
* MySQL: INSERT ... ON DUPLICATE KEY UPDATE
* SQL Server: MERGE ... USING ...
* PostgreSQL: INSERT ... ON CONFLICT ... DO UPDATE SET
*/
upsert(params: {
table: string
keyColumns: string[]
allColumns: string[]
startParamIndex: number
}): { sql: string; nextParamIndex: number }
/**
* Append pagination clause to SQL
* MySQL/PostgreSQL: LIMIT x OFFSET y
* SQL Server: OFFSET x ROWS FETCH NEXT y ROWS ONLY
*/
paginate(params: {
sql: string
limit: number
offset?: number
paramIndex: number
}): { sql: string; nextParamIndex: number }
/**
* Maximum rows per batch given columns per row
* SQL Server: ~71 (due to 2100 param limit)
* MySQL/PostgreSQL: 1000
*/
maxBatchRows(columnsPerRow: number): number
}