115 lines
4.3 KiB
Plaintext
115 lines
4.3 KiB
Plaintext
/*
|
||||
|
|
* Copyright (c) 2025 SimcuTeam. All rights reserved.
|
|||
|
|
* 连接串 → Datasource 工厂:把"驱动与配置构建"收敛到 orm-cj,应用侧只需传连接字符串。
|
|||
|
|
*
|
|||
|
|
* 支持两种连接串格式:
|
|||
|
|
* 1. URL 格式(推荐):postgres://user:pass@host:port/db?sslmode=disable(opengauss:// 亦可)
|
|||
|
|
* 2. ADO.NET 风格:Host=..;Port=..;Database=..;Username=..;Password=..(自动转 URL)
|
|||
|
|
*
|
|||
|
|
* 驱动通过 std.database.sql.DriverManager 查找:应用只需引入并链接驱动包
|
|||
|
|
* (如 opengauss-driver,其模块加载时自动注册 "postgres"/"opengauss"),
|
|||
|
|
* orm-cj 本身不依赖任何具体驱动实现。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
package simcu::orm.db
|
|||
|
|
|
|||
|
|
import std.database.sql.*
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 连接串 → Datasource 工厂(对齐 .NET NpgsqlDataSource.Create / EF Core UseNpgsql(connStr))。
|
|||
|
|
*/
|
|||
|
|
public class DatasourceFactory {
|
|||
|
|
/// 默认驱动名(ADO 风格连接串无 scheme 时使用)
|
|||
|
|
public static let DEFAULT_DRIVER = "postgres"
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 由连接字符串创建 Datasource。驱动名自动推断:
|
|||
|
|
* URL 格式按 scheme(postgres/postgresql/pgsql/pg → postgres,opengauss → opengauss);
|
|||
|
|
* ADO 风格默认 postgres。
|
|||
|
|
*/
|
|||
|
|
public static func create(connStr: String): Datasource {
|
|||
|
|
build(detectDriver(connStr, DEFAULT_DRIVER), toUrl(connStr))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 由连接字符串创建 Datasource,可显式指定驱动名(如 "pgsql"/"postgres"/"opengauss")。
|
|||
|
|
* 显式驱动名优先于连接串内 scheme。
|
|||
|
|
*/
|
|||
|
|
public static func create(connStr: String, driverName: String): Datasource {
|
|||
|
|
build(normalizeDriverName(driverName), toUrl(connStr))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static func build(name: String, url: String): Datasource {
|
|||
|
|
let driver = DriverManager.getDriver(name) ??
|
|||
|
|
throw Exception(
|
|||
|
|
"simorm: 未注册数据库驱动 '${name}'。请确认应用已引入并链接对应驱动包" +
|
|||
|
|
"(如 opengauss-driver,其加载时自动注册 postgres/opengauss)")
|
|||
|
|
driver.open(url)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 从连接串推断驱动注册名。
|
|||
|
|
*/
|
|||
|
|
public static func detectDriver(connStr: String, defaultDriver: String): String {
|
|||
|
|
if (connStr.contains("://")) {
|
|||
|
|
let i = connStr.indexOf("://").getOrThrow()
|
|||
|
|
let scheme = connStr[0..i].toAsciiLower()
|
|||
|
|
match (scheme) {
|
|||
|
|
case "postgresql" | "pgsql" | "pg" => "postgres"
|
|||
|
|
case _ => scheme
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
normalizeDriverName(defaultDriver)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 驱动名别名归一化到 DriverManager 注册名。
|
|||
|
|
*/
|
|||
|
|
public static func normalizeDriverName(name: String): String {
|
|||
|
|
match (name.trimAscii().toAsciiLower()) {
|
|||
|
|
case "pgsql" | "pg" | "postgresql" => "postgres"
|
|||
|
|
case _ => name.trimAscii()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 统一为驱动可解析的 URL 格式。
|
|||
|
|
* ADO.NET 风格(.NET Npgsql 连接串)示例:
|
|||
|
|
* Host=192.168.0.2;Port=5432;Database=lemon-lurmix;Username=postgres;Password=Love@1314
|
|||
|
|
* → postgres://postgres:Love@1314@192.168.0.2:5432/lemon-lurmix?sslmode=disable
|
|||
|
|
* 已是 URL(含 "://")则原样返回。
|
|||
|
|
*/
|
|||
|
|
public static func toUrl(connStr: String): String {
|
|||
|
|
if (connStr.contains("://")) {
|
|||
|
|
return connStr
|
|||
|
|
}
|
|||
|
|
var host = ""
|
|||
|
|
var port = "5432"
|
|||
|
|
var database = ""
|
|||
|
|
var username = ""
|
|||
|
|
var password = ""
|
|||
|
|
for (part in connStr.split(";")) {
|
|||
|
|
let seg = part.trimAscii()
|
|||
|
|
if (seg.isEmpty()) {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
match (seg.indexOf("=")) {
|
|||
|
|
case Some(i) =>
|
|||
|
|
let key = seg[0..i].trimAscii().toAsciiLower()
|
|||
|
|
let value = seg[i + 1..].trimAscii()
|
|||
|
|
match (key) {
|
|||
|
|
case "host" => host = value
|
|||
|
|
case "port" => port = value
|
|||
|
|
case "database" => database = value
|
|||
|
|
case "username" | "user id" | "uid" => username = value
|
|||
|
|
case "password" | "pwd" => password = value
|
|||
|
|
case _ => ()
|
|||
|
|
}
|
|||
|
|
case None => ()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return "${DEFAULT_DRIVER}://${username}:${password}@${host}:${port}/${database}?sslmode=disable"
|
|||
|
|
}
|
|||
|
|
}
|