feat: orm-cj 仓颉版 EF Core 风格 ORM 初始版本
- 基于数据模型(POCO + 注解)的映射与增删改查:DbContext/DbSet/ChangeTracker/QueryBuilder - ISqlDialect 方言接口 + PostgreSQL/openGauss 实现,零外部依赖 - @DbContext 宏:纯声明 DbSet 类自动展开为完整 DbContext 子类 - 迁移:Migration/Migrator/ModelSnapshot(快照 JSON)/MiniJson,从模型生成迁移 - 迁移 CLI:add/rm/update/downgrade/list/help,应用内嵌一行 db.cli(args) 接入 - DbContext 便捷方法:databaseExists/hasPendingMigrations/migrate - 57 个单元测试全部通过
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user