Sign in

    morm

    Download zip
    Author
    Version
    0.2.7
    License
    Apache-2.0
    Last updated
    7 months ago
    Downloads
    660

    #oboard/morm

    MoonBit 生态下的轻量级 ORM。目标很直接:

    • 用尽量少的属性和 API 覆盖大部分常见场景
    • 保持实现透明,允许随时绕过 ORM 手写 SQL
    • 不使用运行时反射,不隐式修改用户语义

    #Quick Start

    1. 在你的应用 moon.mod.json 中添加依赖:

    "bin-deps": { "oboard/morm": "latest" },

    1. 在你的 moon.pkg 添加

    options(
    "pre-build": [
    {
    "command": "$mod_dir/.mooncakes/oboard/morm/morm-gen $input -o $output && moonfmt -w $output",
    "input": "entities.mbt",
    "output": "entities.g.mbt",
    },
    {
    "command": "$mod_dir/.mooncakes/oboard/morm/morm-gen $input -o $output && moonfmt -w $output",
    "input": "mapper.mbt",
    "output": "mapper.g.mbt",
    },
    ],
    )

    1. 在你的 entities.mbt 中定义实体:

    通过在 struct 上加少量 #morm.* 属性,可以自动生成:

    • impl @morm.Entity 与 table() 元数据
    • 各数据库方言下的建表 / 迁移 SQL
    • 基于 #morm.query 的类型安全 Mapper 方法(含 save / delete)
    • 统一返回 (String, FixedArray[@engine.Param]) 的参数化 SQL 构造器

    核心设计取舍:

    • 类型驱动:字段的可空性由 T / T? 决定,而不是依赖大量注解
    • 方言内建:支持 MySQL / PostgreSQL / Sqlite / SQLServer / Oracle 的建表和占位符差异
    • SQL 优先:Query/Insert/Update/Delete/Upsert 只负责构造参数化 SQL,不绑定执行层
    • 生成代码:所有内容都生成成普通 MoonBit 代码(见 example/*.g.mbt),可以直接查看和修改

    该库主要解决三个问题:

    • 统一建表与迁移 SQL 的生成
    • 统一各数据库方言的语法差异
    • 统一 SQL 参数绑定方式

    业务层的查询依然以显式 SQL 为主,由用户自己控制每一条语句。

    你还需要自己实现一个满足 @oboard/morm/engine.Engine 的驱动,用来真正连到 MySQL / PostgreSQL / Sqlite 等数据库。example/generator_test.mbt 里有一个简化版的 MySQLEngine 示例。

    #实体建模与可空性

    一个典型实体定义如下(摘自 example/entities.mbt):

    ///|
    #morm.entity(name="teacher")
    pub(all) struct Teacher {
    #morm.primary_key
    #morm.auto_increment
    #morm.bigint
    id : Int
    #morm.varchar(length="255")
    name : String
    #morm.varchar(length="255")
    major : String
    age : Int
    #morm.datetime
    birth_date : String?
    } derive(ToJson, FromJson)

    当前版本关于可空性的规则非常简单:

    • 字段类型为 T(非 Option)时:列默认 NOT NULL
    • 字段类型为 T?(Option[T])时:列默认 NULLABLE
    • 主键永远视为非空,即便你写成 id : Int?,也会被当成 NOT NULL 主键

    属性 #morm.not_null 目前不再参与可空性判断,仅作为保留标签;真实行为完全由类型决定。

    #Attributes 使用指南

    下表列出当前支持的 #morm 属性、用法示例与效果说明。

    属性示例说明
    #morm.entity置于 struct 顶部声明该结构体为 ORM 实体,生成 impl @morm.Entity
    #morm.primary_key放在某字段上一行将该列标记为主键;主键总是非空
    #morm.auto_increment放在主键字段上一行将该列设置为自增,同时 primary_key=true、nullable=false
    #morm.not_null放在字段上一行当前版本仅作标记,实际可空性仍由类型 T / T? 决定
    #morm.varchar#morm.varchar(length="255")将该列类型设为 VarChar(255);若未提供参数,默认 255
    #morm.char#morm.char(length="1")将该列类型设为 Char(1);若未提供参数,默认 1
    #morm.text纯标签将该列类型设为 Text
    #morm.mediumtext纯标签将该列类型设为 MediumText
    #morm.longtext纯标签将该列类型设为 LongText
    #morm.binary#morm.binary(length="1")将该列类型设为 Binary(1);若未提供参数,默认 1
    #morm.varbinary#morm.varbinary(length="255")将该列类型设为 VarBinary(255);若未提供参数,默认 255
    #morm.blob纯标签将该列类型设为 Blob
    #morm.tinyint纯标签将该列类型设为 TinyInt
    #morm.smallint纯标签将该列类型设为 SmallInt
    #morm.int纯标签将该列类型设为 Int
    #morm.bigint纯标签将该列类型设为 BigInt
    #morm.float纯标签将该列类型设为 Float
    #morm.double纯标签将该列类型设为 Double
    #morm.decimal#morm.decimal(precision="10", scale="2")将该列类型设为 Decimal(10,2);若未提供参数,默认 10,2
    #morm.boolean纯标签将该列类型设为 Boolean
    #morm.json纯标签将该列类型设为 Json
    #morm.jsonb纯标签将该列类型设为 JsonB
    #morm.uuid纯标签将该列类型设为 VarChar(36)
    #morm.datetime纯标签将该列类型设为 DateTime
    #morm.date纯标签将该列类型设为 Date
    #morm.time纯标签将该列类型设为 Time
    #morm.timestamp纯标签将该列类型设为 Timestamp
    #morm.foreign_key放在外键字段上一行将该字段解析为外键,约束名:fk_<表名>_<列名>,引用列默认 id;引用表按列名约定或类型名推断
    #morm.on_delete_cascade与 #morm.foreign_key 同用外键 on_delete 设为 CASCADE
    #morm.on_update_cascade与 #morm.foreign_key 同用外键 on_update 设为 CASCADE

    说明:目前生成器尚未读取编译器暴露的参数字典,长度/精度等参数采用保守默认与示例形式;未来会增强为真正读取参数值并完全可配置。

    #代码生成:mormgen CLI

    仓库包含一个生成器二进制 mormgen(见 main/main.mbt),负责把带 #morm.* 的源码翻译成实体和 mapper 实现。用法:

    mormgen -i <input_file> -o <output_file>

    典型流程(对应 example/):

    # 生成实体的 table() 实现 mormgen example/entities.mbt -o example/entities.g.mbt # 生成 mapper 实现 mormgen example/mapper.mbt -o example/mapper.g.mbt

    entities.g.mbt 会包含每个实体的 impl @morm.Entity 和 table(),mapper.g.mbt 会包含 mapper struct、Struct::new 工厂函数以及基于 #morm.query 的方法实现。

    #Mapper 与查询

    在实体定义之外,你可以用 #morm.mapper 声明一个 mapper 接口(见 example/mapper.mbt):

    #morm.mapper(entity="Student")
    pub trait StudentMapper {
    #morm.query("SELECT * FROM students WHERE id = ?")
    pub fn find_student_by_id(Self, id : Int) -> Student?

    #morm.query("SELECT count(*) FROM students WHERE age = ?")
    pub fn count_students_by_age(Self, age : Int) -> Int?
    }

    生成器会为你生成:

    • pub struct StudentMapperImpl { engine : &@engine.Engine }
    • pub fn StudentMapperImpl::new(engine : &@engine.Engine) -> StudentMapperImpl
    • 对应的 impl StudentMapper for StudentMapperImpl,内部用参数化 SQL 调用 engine.exec / engine.query
    • 额外的通用方法:save 和 delete,直接基于实体的主键和唯一索引做 UPSERT / DELETE

    使用方式示例(简化):

    ///|
    let engine = MySQLEngine::open("mysql://...")

    ///|
    let mapper = StudentMapperImpl::new(engine)

    ///|
    let stu = mapper.find_student_by_id(1)

    ///|
    let n = mapper.count_students_by_age(18)

    ///|
    let saved = mapper.save(stu)

    ///|
    let deleted = mapper.delete(stu)

    #SQL 构造器与渲染

    morm.mbt 提供一组查询构造器:

    • select_from(table)
    • insert_into(table)
    • update(table)
    • delete_from(table)
    • upsert_into(table)

    通过 to_statement() + @engine.render_default_sql(...) 得到 SQL 和参数:

    let q = @morm.select_from("students")
    .where_eq("id", 1)
    .where_eq("name", "Alice")
    .order_by(Desc("id"))
    .offset(5)
    .limit(5)
    let (sql, params) = @engine.render_default_sql(q.to_statement())

    sql 会是:

    SELECT * FROM students WHERE id = ? AND name = ? ORDER BY id DESC LIMIT 5 OFFSET 5

    params 则是对应顺序的 JSON 数组。

    UPSERT 使用 upsert_into(table),并且:

    • 在 PostgreSQL / Sqlite 下附带 RETURNING *,直接返回插入/更新后的行
    • 在不支持 RETURNING 的方言(如 MySQL)下,save 会用主键或唯一索引回读一行,保证你最终拿到一条完整记录

    #自动迁移(Auto-migrate)

    auto_migrate 可以根据实体的 table() 定义生成并执行建表 / 修改表 SQL。示例见 example/generator_test.mbt:

    let engine = MySQLEngine::open("mysql://root:123456@localhost:3306/test")
    @morm.auto_migrate(engine, [Student::table()])
    engine.close()

    当前版本偏保守,只覆盖基础场景;复杂 schema 变更建议显式写迁移。

    #运行测试与示例

    仓库内置了一些针对 SQL 生成和生成器的测试与示例:

    # 运行全部测试 moon test

    DbResult

    type DbResult[T] = Result[T, DbError]

    Driver

    pub(open) trait Driver {
    open(Self, dsn : String) -> Result[Self, DbError]
    close(Self) -> Result[Self, DbError]
    ping(Self) -> Result[Unit, DbError]
    exec(Self, sql : String, args : FixedArray[
    Param
    ]) -> Result[Unit, DbError]
    query(Self, sql : String, args : FixedArray[
    Param
    ]) -> Result[FixedArray[Json], DbError]
    }

    Entity

    pub(open) trait Entity : ToJson +
    FromJson
    {
    table(Self) -> Table
    }

    Association

    pub(all) struct Association {
    name : String
    kind : AssociationKind
    owner_key : String
    target_table : String
    target_key : String
    join_table : String?
    join_owner_key : String?
    join_target_key : String?
    }

    impl Eq for Association
    impl Show for Association

    AssociationKind

    pub(all) enum AssociationKind {
    BelongsTo
    HasOne
    HasMany
    ManyToMany
    }

    Column

    pub(all) struct Column {
    name : String
    column_type : ColumnType
    size : Int
    nullable : Bool
    default_value : String?
    auto_increment : Bool
    primary_key : Bool
    unique : Bool
    comment : String
    charset : String?
    collation : String?
    }

    impl Compare for Column
    impl Eq for Column
    impl Hash for Column
    impl Show for Column
    impl ToJson for Column

    Column::new

    fn Column::new(name : String, column_type : ColumnType) -> Column

    ColumnDiff

    pub(all) struct ColumnDiff {
    added : FixedArray[Column]
    removed : FixedArray[Column]
    changed : FixedArray[(String, Column, Column)]
    }

    impl Eq for ColumnDiff
    impl Show for ColumnDiff

    ColumnType

    pub(all) enum ColumnType {
    TinyInt
    SmallInt
    MediumInt
    Int
    BigInt
    Float
    Double
    Decimal(Int, Int)
    Char(Int)
    VarChar(Int)
    Text
    MediumText
    LongText
    Binary(Int)
    VarBinary(Int)
    Blob
    MediumBlob
    LongBlob
    Date
    Time
    DateTime
    Timestamp
    Year
    Json
    JsonB
    Boolean
    }

    impl Eq for ColumnType
    impl Hash for ColumnType
    impl Show for ColumnType

    DbError

    pub(all) struct DbError {
    message : String
    }

    impl Show for DbError
    impl ToJson for DbError

    DeleteQuery

    pub struct DeleteQuery {
    from : String
    where_ : FixedArray[Where]
    }

    impl Eq for DeleteQuery
    impl Show for DeleteQuery

    DeleteQuery::from

    DeleteQuery::where_eq

    fn[V :
    ToParam
    ] DeleteQuery::where_eq(self : DeleteQuery, col : String, value : V) -> DeleteQuery

    DeleteQuery::where_gt

    fn[V :
    ToParam
    ] DeleteQuery::where_gt(self : DeleteQuery, col : String, value : V) -> DeleteQuery

    DeleteQuery::where_gte

    fn[V :
    ToParam
    ] DeleteQuery::where_gte(self : DeleteQuery, col : String, value : V) -> DeleteQuery

    DeleteQuery::where_like

    fn[V :
    ToParam
    ] DeleteQuery::where_like(self : DeleteQuery, col : String, pattern : V) -> DeleteQuery

    DeleteQuery::where_lt

    fn[V :
    ToParam
    ] DeleteQuery::where_lt(self : DeleteQuery, col : String, value : V) -> DeleteQuery

    DeleteQuery::where_lte

    fn[V :
    ToParam
    ] DeleteQuery::where_lte(self : DeleteQuery, col : String, value : V) -> DeleteQuery

    DeleteQuery::where_ne

    fn[V :
    ToParam
    ] DeleteQuery::where_ne(self : DeleteQuery, col : String, value : V) -> DeleteQuery

    ForeignKey

    pub(all) struct ForeignKey {
    name : String
    column : String
    referenced_table : String
    referenced_column : String
    on_delete : String
    on_update : String
    }

    impl Eq for ForeignKey
    impl Hash for ForeignKey
    impl Show for ForeignKey

    ForeignKey::new

    fn ForeignKey::new(name : String, column : String, referenced_table : String, referenced_column : String) -> ForeignKey

    ForeignKeyDiff

    pub(all) struct ForeignKeyDiff {
    added : FixedArray[ForeignKey]
    removed : FixedArray[ForeignKey]
    changed : FixedArray[(String, ForeignKey, ForeignKey)]
    }

    Index

    pub(all) struct Index {
    name : String
    index_type : IndexType
    columns : FixedArray[String]
    comment : String
    }

    impl Compare for Index
    impl Eq for Index
    impl Hash for Index
    impl Show for Index
    impl ToJson for Index

    Index::new

    fn Index::new(name : String, columns : FixedArray[String]) -> Index

    Index::new_primary

    fn Index::new_primary(columns : FixedArray[String]) -> Index

    Index::new_unique

    fn Index::new_unique(name : String, columns : FixedArray[String]) -> Index

    IndexDiff

    pub(all) struct IndexDiff {
    added : FixedArray[Index]
    removed : FixedArray[Index]
    changed : FixedArray[(String, Index, Index)]
    }

    impl Eq for IndexDiff
    impl Show for IndexDiff
    impl ToJson for IndexDiff

    IndexType

    pub(all) enum IndexType {
    Primary
    Unique
    Index
    FullText
    Spatial
    }

    impl Eq for IndexType
    impl Hash for IndexType
    impl Show for IndexType
    impl ToJson for IndexType

    InsertQuery

    pub struct InsertQuery {
    into : String
    columns : FixedArray[String]
    values : FixedArray[
    Param
    ]
    }

    impl Eq for InsertQuery
    impl Show for InsertQuery

    InsertQuery::columns

    fn InsertQuery::columns(self : InsertQuery, columns : FixedArray[String]) -> InsertQuery

    InsertQuery::from

    InsertQuery::values

    fn InsertQuery::values(self : InsertQuery, values : FixedArray[
    Param
    ]) -> InsertQuery

    OrderBy

    pub(all) enum OrderBy {
    Asc(String)
    Desc(String)
    }

    impl Eq for OrderBy
    impl Show for OrderBy
    impl ToJson for OrderBy

    PreloadResult

    pub(all) enum PreloadResult[T] {
    One(Map[String, T])
    Many(Map[String, Array[T]])
    }

    Query

    pub struct Query {
    select : String
    from : String
    joins : FixedArray[String]
    where_ : FixedArray[Where]
    order_by : FixedArray[OrderBy]
    limit : Int?
    offset : Int?
    }

    impl Eq for Query
    impl Show for Query
    impl ToJson for Query

    Query::join

    fn Query::join(self : Query, join_sql : String) -> Query

    Query::limit

    fn Query::limit(self : Query, n : Int) -> Query

    Query::offset

    fn Query::offset(self : Query, n : Int) -> Query

    Query::order_by

    fn Query::order_by(self : Query, order_by : OrderBy) -> Query

    Query::page

    fn Query::page(self : Query, page : Int, size : Int) -> Query

    Query::where_eq

    fn[V :
    ToParam
    ] Query::where_eq(self : Query, col : String, value : V) -> Query

    Query::where_gt

    fn[V :
    ToParam
    ] Query::where_gt(self : Query, col : String, value : V) -> Query

    Query::where_gte

    fn[V :
    ToParam
    ] Query::where_gte(self : Query, col : String, value : V) -> Query

    Query::where_like

    fn[V :
    ToParam
    ] Query::where_like(self : Query, col : String, pattern : V) -> Query

    Query::where_lt

    fn[V :
    ToParam
    ] Query::where_lt(self : Query, col : String, value : V) -> Query

    Query::where_lte

    fn[V :
    ToParam
    ] Query::where_lte(self : Query, col : String, value : V) -> Query

    Query::where_ne

    fn[V :
    ToParam
    ] Query::where_ne(self : Query, col : String, value : V) -> Query

    Set

    pub struct Set {
    col : String
    value :
    Param

    }

    impl Eq for Set
    impl Show for Set
    impl ToJson for Set

    Table

    pub(all) struct Table {
    name : String
    schema : String?
    catalog : String?
    columns : FixedArray[Column]
    indexes : FixedArray[Index]
    foreign_keys : FixedArray[ForeignKey]
    temporary : Bool
    if_not_exists : Bool
    engine : String?
    charset : String?
    collation : String?
    tablespace : String?
    comment : String
    auto_increment : Int?
    engine_options : FixedArray[TableEngineOption]
    }

    impl Compare for Table
    impl Eq for Table
    impl Hash for Table
    impl Show for Table
    impl ToJson for Table

    Table::has_primary_key

    fn Table::has_primary_key(self : Table) -> Bool

    Table::new

    fn Table::new(name : String, columns? : FixedArray[Column], engine? : String) -> Table

    Table::primary_key

    fn Table::primary_key(self : Table) -> String?

    TableDiff

    pub(all) struct TableDiff {
    columns : ColumnDiff
    indexes : IndexDiff
    foreign_keys : ForeignKeyDiff
    }

    impl Eq for TableDiff
    impl Show for TableDiff
    impl ToJson for TableDiff

    TableEngineOption

    pub(all) struct TableEngineOption {
    key : String
    value : String
    }

    UpdateQuery

    pub struct UpdateQuery {
    table : String
    sets : FixedArray[Set]
    where_ : FixedArray[Where]
    }

    impl Eq for UpdateQuery
    impl Show for UpdateQuery

    UpdateQuery::from

    UpdateQuery::set

    fn[V :
    ToParam
    ] UpdateQuery::set(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpdateQuery::where_eq

    fn[V :
    ToParam
    ] UpdateQuery::where_eq(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpdateQuery::where_gt

    fn[V :
    ToParam
    ] UpdateQuery::where_gt(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpdateQuery::where_gte

    fn[V :
    ToParam
    ] UpdateQuery::where_gte(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpdateQuery::where_like

    fn[V :
    ToParam
    ] UpdateQuery::where_like(self : UpdateQuery, col : String, pattern : V) -> UpdateQuery

    UpdateQuery::where_lt

    fn[V :
    ToParam
    ] UpdateQuery::where_lt(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpdateQuery::where_lte

    fn[V :
    ToParam
    ] UpdateQuery::where_lte(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpdateQuery::where_ne

    fn[V :
    ToParam
    ] UpdateQuery::where_ne(self : UpdateQuery, col : String, value : V) -> UpdateQuery

    UpsertQuery

    pub struct UpsertQuery {
    table : String
    sets : FixedArray[Set]
    conflict_target : FixedArray[String]
    update_sets : FixedArray[Set]
    }

    impl Eq for UpsertQuery
    impl Show for UpsertQuery

    UpsertQuery::do_update_set

    fn UpsertQuery::do_update_set(self : UpsertQuery, col : String, value :
    Param
    ) -> UpsertQuery

    UpsertQuery::from

    UpsertQuery::on_conflict

    fn UpsertQuery::on_conflict(self : UpsertQuery, columns : FixedArray[String]) -> UpsertQuery

    UpsertQuery::set

    fn UpsertQuery::set(self : UpsertQuery, col : String, value :
    Param
    ) -> UpsertQuery

    Where

    pub struct Where {
    col : String
    value :
    Param

    ty : WhereType
    }

    impl Eq for Where
    impl Show for Where
    impl ToJson for Where

    WhereType

    pub enum WhereType {
    Eq
    Ne
    Gt
    Lt
    Gte
    Lte
    Like
    }

    impl Eq for WhereType
    impl Show for WhereType
    impl ToJson for WhereType

    add_column

    fn add_column(table : Table, col : Column) -> Table

    add_foreign_key

    fn add_foreign_key(table : Table, fk : ForeignKey) -> Table

    add_index

    fn add_index(table : Table, idx : Index) -> Table

    add_table_engine_option

    fn add_table_engine_option(table : Table, key : String, value : String) -> Table

    after_create

    fn[T] after_create(entity : T, callback : (T) -> T) -> T

    after_delete

    fn[T] after_delete(entity : T, callback : (T) -> T) -> T

    after_find

    fn[T] after_find(entity : T, callback : (T) -> T) -> T

    after_update

    fn[T] after_update(entity : T, callback : (T) -> T) -> T

    auto_migrate

    async fn[E :
    Engine
    ] auto_migrate(engine : E, tables : Array[Table]) -> Unit

    before_create

    fn[T] before_create(entity : T, callback : (T) -> T) -> T

    Hook callbacks helpers.

    before_delete

    fn[T] before_delete(entity : T, callback : (T) -> T) -> T

    before_update

    fn[T] before_update(entity : T, callback : (T) -> T) -> T

    belongs_to

    fn belongs_to(name : String, owner_key : String, target_table : String, target_key : String) -> Association

    current_plain_date_time_utc

    fn current_plain_date_time_utc() ->
    PlainDateTime

    current_timestamp_utc

    fn current_timestamp_utc() ->
    ZonedDateTime

    delete_from

    fn delete_from(table : String) -> DeleteQuery

    diff_table

    fn diff_table(old_table : Table, new_table : Table) -> TableDiff

    has_many

    fn has_many(name : String, owner_key : String, target_table : String, target_key : String) -> Association

    has_one

    fn has_one(name : String, owner_key : String, target_table : String, target_key : String) -> Association

    infer_column_type

    fn infer_column_type(value : Json) -> ColumnType

    insert_into

    fn insert_into(table : String) -> InsertQuery

    many_to_many

    fn many_to_many(name : String, owner_key : String, target_table : String, target_key : String, join_table : String, join_owner_key : String, join_target_key : String) -> Association

    mysql_table_compression

    fn mysql_table_compression(table : Table, compression : String) -> Table

    mysql_table_key_block_size

    fn mysql_table_key_block_size(table : Table, key_block_size : Int) -> Table

    mysql_table_row_format

    fn mysql_table_row_format(table : Table, row_format : String) -> Table

    on_delete_cascade

    fn on_delete_cascade(fk : ForeignKey) -> ForeignKey

    on_update_cascade

    fn on_update_cascade(fk : ForeignKey) -> ForeignKey

    oracle_table_on_commit

    fn oracle_table_on_commit(table : Table, on_commit : String) -> Table

    oracle_table_organization

    fn oracle_table_organization(table : Table, organization : String) -> Table

    pg_table_on_commit

    fn pg_table_on_commit(table : Table, on_commit : String) -> Table

    pg_table_unlogged

    fn pg_table_unlogged(table : Table) -> Table

    pg_table_with

    fn pg_table_with(table : Table, with_clause : String) -> Table

    preload

    async fn[E :
    Engine
    , O : ToJson, T :
    FromJson
    ] preload(engine : E, owners : FixedArray[O], association : Association) -> PreloadResult[T]

    preload_belongs_to

    async fn[E :
    Engine
    , O : ToJson, T :
    FromJson
    ] preload_belongs_to(engine : E, owners : FixedArray[O], owner_key : String, target_table : String, target_key : String) -> Map[String, T]

    preload_has_many

    async fn[E :
    Engine
    , O : ToJson, T :
    FromJson
    ] preload_has_many(engine : E, owners : FixedArray[O], owner_key : String, target_table : String, target_key : String) -> Map[String, Array[T]]

    preload_has_one

    async fn[E :
    Engine
    , O : ToJson, T :
    FromJson
    ] preload_has_one(engine : E, owners : FixedArray[O], owner_key : String, target_table : String, target_key : String) -> Map[String, T]

    preload_many_to_many

    async fn[E :
    Engine
    , O : ToJson, T :
    FromJson
    ] preload_many_to_many(engine : E, owners : FixedArray[O], owner_key : String, target_table : String, target_key : String, join_table : String, join_owner_key : String, join_target_key : String) -> Map[String, Array[T]]

    register_driver_scheme

    fn register_driver_scheme(scheme : String, driver_name : String) -> Unit

    resolve_driver_name

    fn resolve_driver_name(dsn : String) -> String?

    restore_by_id

    fn[V :
    ToParam
    ] restore_by_id(table : String, id_col : String, id : V, deleted_col? : String) -> UpdateQuery

    select_from

    fn select_from(table : String) -> Query

    select_from_scoped

    fn select_from_scoped(table : String, deleted_col? : String) -> Query

    Soft delete default scope (boolean convention): deleted = false

    select_raw

    fn select_raw(table : String, cols_expr : String) -> Query

    soft_delete_by_id

    fn[V :
    ToParam
    ] soft_delete_by_id(table : String, id_col : String, id : V, deleted_col? : String) -> UpdateQuery

    sqlite_table_strict

    fn sqlite_table_strict(table : Table) -> Table

    sqlite_table_without_rowid

    fn sqlite_table_without_rowid(table : Table) -> Table

    sqlserver_table_durability

    fn sqlserver_table_durability(table : Table, durability : String) -> Table

    sqlserver_table_filegroup

    fn sqlserver_table_filegroup(table : Table, filegroup : String) -> Table

    sqlserver_table_memory_optimized

    fn sqlserver_table_memory_optimized(table : Table) -> Table

    sqlserver_table_textimage_on

    fn sqlserver_table_textimage_on(table : Table, filegroup : String) -> Table

    table_catalog

    fn table_catalog(table : Table, catalog : String) -> Table

    table_comment

    fn table_comment(table : Table, text : String) -> Table

    table_create_suffix

    fn table_create_suffix(table : Table, suffix : String) -> Table

    table_engine

    fn table_engine(table : Table, engine : String) -> Table

    table_if_not_exists

    fn table_if_not_exists(table : Table, if_not_exists : Bool) -> Table

    table_schema

    fn table_schema(table : Table, schema : String) -> Table

    table_tablespace

    fn table_tablespace(table : Table, tablespace : String) -> Table

    table_temporary

    fn table_temporary(table : Table, temporary : Bool) -> Table

    unregister_driver_scheme

    fn unregister_driver_scheme(scheme : String) -> Unit

    update

    fn update(table : String) -> UpdateQuery

    upsert_into

    fn upsert_into(table : String) -> UpsertQuery