Files
orm-cj/src/db/datasource_factory.cj
T

115 lines
4.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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: String = "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(
"simcu::orm: 未注册数据库驱动 '${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 pwd = ""
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" => pwd = value
case _ => ()
}
case None => ()
}
}
return "${DEFAULT_DRIVER}://${username}:${pwd}@${host}:${port}/${database}?sslmode=disable"
}
}