#postgresql #sql-database #sql #orm #database-schema #connect-database

bin+lib sql_db_mapper

将 SQL 数据库映射到 Rust 结构体和函数

4 个版本

0.1.0 2021 年 1 月 29 日
0.0.3 2020 年 1 月 14 日
0.0.2 2020 年 1 月 13 日
0.0.1 2020 年 1 月 4 日

#2425数据库接口

MIT/Apache

76KB
1.5K SLoC

sql_db_mapper

生成 Rust 数据库映射的命令行工具。

连接到 PostgreSQL 数据库,并创建一个 Rust 模块,表示所有模式,包括存储函数/过程的映射

使用 tokio-postgrespostgres 将 SQL 表、视图和函数映射到 Rust 结构体和函数

注意

一旦生成,生成的代码不包含检查数据库模式是否已更改的额外检查。尽管一些类型转换在调用时可能会失败,但应同时更新生成的代码和数据库

所有生成的函数都接受用作数据库连接客户端的第一个参数

重载的 SQL 程序/函数(具有相同名称和不同参数的两个)被映射到接受单个元组的函数,即 my_func((client, id, "hello"))my_func((client, id)) 这意味着重载以前未重载的 SQL 程序将破坏生成的代码(除非使用具有 all 或 one 选项的 use-tuples)

帮助

sql_db_mapper 0.1.0
Generate a rust wrapper for a PostgreSQL database

USAGE:
    sql_db_mapper [FLAGS] [OPTIONS] --conn <conn> [--] [output]

FLAGS:
    -d, --debug           Activate debug mode
        --dir             Program will treat output as a directory name rather than a file and generate a whole crate.
                          If output is not provided code is printed as usual
    -h, --help            Prints help information
        --no-functions    Only make mappings for tables and views
        --rust-case       Convert names from the database to rust standard (i.e. table names in CamelCase, fields and
                          functions in snake_case)
    -u, --ugly            Skip running output through rustfmt
    -V, --version         Prints version information

OPTIONS:
        --conn <conn>
            String to connect to database, see tokio_postgres::Config for details. If not provided environment variable
            DATABASE_URL is checked instead
        --rustfmt-config <rustfmt-config>              string passed to rustfmt --config
        --rustfmt-config-path <rustfmt-config-path>    string passed to rustfmt --config-path
        --third-party <third-party>...
            A comma seperated list of third party crates which contain types that will be mapped to and from sql types.
            Valid values are "bit_vec,chrono,eui48,geo_types,rust_decimal,serde_json,time,uuid"
        --use-tuples <use-tuples>
            How to use tuples (used by default for just overloads). Options: overloads (the default, use tuples to
            represent function overloading). all (Have all functions take a tuple for consitency). none (skip mapping
            overloaded procs at all). one_overload (avoid tuples by only mapping the oldest sql proc in the database)
            [default: overloads]

ARGS:
    <output>    Output file, stdout if not present

常见错误

| 在模块 `super::pg_catalog` 中找不到类型 `????`
指定的类型只能由第三方 crate 之一映射。`postgres_types::FromSql` 列出所有可以映射的类型,除了 `Numeric`,它使用 `rust_decimal::Decimal` 映射


sql_db_mapper_core

包含从 tokio-postgres Rows 转换到 Rust 类型的 trait TryFromRow,并为几种常见类型实现了它
重新导出可转换为/从 sql 类型转换的类型

sql_db_mapper_derive

提供了一个来自 TryFromRow 的 derive 宏(在 sql_db_mapper_core 中定义),


build.rs 脚本中使用

创建一个新的库 crate,并使 Cargo.toml 看起来如下

[package]
name = "rust_test"
version = "0.1.0"
edition = "2018"

[dependencies]
sql_db_mapper_core = { version = "0.1", features = ["with-bit-vec-0_6", "with-chrono-0_4", "with-eui48-0_4", "with-geo-types-0_6", "with-rust_decimal-1", "with-serde_json-1", "with-time-0_2", "with-uuid-0_8", ] }
postgres-types = { version = "0.2", features = ["derive"] }
async-trait = { version = "0.1", optional = true }

serde = { version = "1.0", features = ["derive"] }

[build-dependencies]
sql_db_mapper = { path = "../sql_db_mapper/sql_db_mapper" }

[features]
sync = []
async = ["async-trait"]

修改crate的名称、版本以及sql_db_mapper_core的功能,使其符合您的需求

创建一个名为build.rs的文件,并包含以下内容

use sql_db_mapper::{ Opt, Tuples, ThirdParty };

fn main() {
	let options = Opt {
		debug: false,
		ugly: false,
		dir: false, // this should be false
		rust_case: true,
		rustfmt_config: None,
		rustfmt_config_path: None,
		no_functions: false,
		use_tuples: Tuples::ForOverloads,
		third_party: vec![
			ThirdParty::Chrono,
			ThirdParty::Time,
			ThirdParty::Eui48,
			ThirdParty::GeoTypes,
			ThirdParty::SerdeJson,
			ThirdParty::Uuid,
			ThirdParty::BitVec,
			ThirdParty::RustDecimal,
		],
		conn: std::env::var("DATABASE_URL").expect("Must provide connection string in environment variable 'DATABASE_URL'"),
		output: Some("./src/lib.rs".into())
	};

	let mut client = options.get_client();
	let full_db = client.get_all(options.no_functions);

	full_db.make_output(&options);
}

这样应该足以开始使用了。


可能未来的工作

  • 更多关于代码生成方式的选择
    • COMMENT ON获取文本,并将其放入文档注释中
    • 允许函数接收(例如)&varchar类型的参数,也可以接收&str类型的参数(varchar是String的一个typedef,因此函数可能需要像HashMap的get一样进行泛型化)
  • 考虑增加对其他流行数据库的支持,或者Rust数据库库的支持
    • sqlx和diesel代码生成器将非常有用

许可证

根据您的选择,许可协议为以下之一

由您选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的任何有意提交给作品并由您包含的贡献,将按照上述方式双许可,不附加任何额外的条款或条件。

依赖项

~9–20MB
~276K SLoC