Skip to content

Commit bec3ab2

Browse files
authored
Update to sqlx 0.8, eliminate most allocations (#40)
Release v0.11
1 parent 5c66ce6 commit bec3ab2

File tree

37 files changed

+754
-305
lines changed

37 files changed

+754
-305
lines changed

.github/workflows/examples.yml

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Examples
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
- '*-dev'
9+
10+
jobs:
11+
mysql:
12+
name: MySQL Example
13+
runs-on: ubuntu-latest
14+
15+
services:
16+
mysql:
17+
image: mysql:latest
18+
env:
19+
MYSQL_ROOT_PASSWORD: password
20+
MYSQL_DATABASE: ormx
21+
ports:
22+
- 3307:3306
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: Swatinem/rust-cache@v2
28+
with:
29+
key: mysql-example
30+
31+
- name: Install sqlx-cli
32+
run: |
33+
cargo install sqlx-cli
34+
sleep 5
35+
36+
- name: Setup
37+
working-directory: example-mysql
38+
env:
39+
DATABASE_URL: mysql://root:password@localhost:3307/ormx?ssl-mode=disabled
40+
run: sqlx db setup
41+
42+
- name: Run
43+
working-directory: example-mysql
44+
env:
45+
DATABASE_URL: mysql://root:password@localhost:3307/ormx?ssl-mode=disabled
46+
run: cargo run
47+
48+
49+
mariadb:
50+
name: MariaDB Example
51+
runs-on: ubuntu-latest
52+
53+
services:
54+
mysql:
55+
image: mariadb:latest
56+
env:
57+
MYSQL_ROOT_PASSWORD: password
58+
ports:
59+
- 3306:3306
60+
61+
steps:
62+
- uses: actions/checkout@v4
63+
64+
- uses: Swatinem/rust-cache@v2
65+
with:
66+
key: mariadb-example
67+
68+
- name: Install sqlx-cli
69+
run: |
70+
cargo install sqlx-cli
71+
sleep 5
72+
73+
- name: Setup
74+
working-directory: example-mariadb
75+
env:
76+
DATABASE_URL: mysql://root:password@localhost:3306/ormx?ssl-mode=disabled
77+
run: sqlx db setup
78+
79+
- name: Run
80+
working-directory: example-mariadb
81+
env:
82+
DATABASE_URL: mysql://root:password@localhost:3306/ormx?ssl-mode=disabled
83+
run: cargo run
84+
85+
postgres:
86+
name: PostgreSQL Example
87+
runs-on: ubuntu-latest
88+
89+
services:
90+
postgres:
91+
image: postgres:latest
92+
env:
93+
POSTGRES_PASSWORD: password
94+
ports:
95+
- 5432:5432
96+
97+
steps:
98+
- uses: actions/checkout@v4
99+
100+
- uses: Swatinem/rust-cache@v2
101+
with:
102+
key: postgres-example
103+
104+
- name: Install sqlx-cli
105+
run: cargo install sqlx-cli
106+
107+
- name: Setup
108+
working-directory: example-postgres
109+
env:
110+
DATABASE_URL: postgres://postgres:password@localhost:5432/ormx
111+
run: sqlx db setup
112+
113+
- name: Run
114+
working-directory: example-postgres
115+
env:
116+
DATABASE_URL: postgres://postgres:password@localhost:5432/ormx
117+
run: cargo run

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[workspace]
2-
members = ["ormx-macros", "ormx", "example-postgres", "example-mysql"]
2+
members = ["ormx-macros", "ormx", "example-postgres", "example-mariadb", "example-mysql"]
3+
resolver = "2"

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,16 @@
3333
Add ormx and sqlx to your `Cargo.toml`
3434
```toml
3535
[dependencies.ormx]
36-
version = "0.7"
36+
version = "0.11"
3737
features = ["mysql"]
3838

3939
[dependencies.sqlx]
40-
version = "0.5"
40+
version = "0.8"
4141
default-features = false
4242
features = ["macros", "mysql", "runtime-tokio-rustls"]
4343
```
44-
Right now, ormx supports mysql/mariadb and postgres.
44+
Right now, ormx supports mysql, mariadb and postgres.
45+
4546
## what does it do?
4647
ormx provides macros for generating commonly used sql queries at compile time.
4748
ormx is meant to be used together with sqlx. Everything it generates uses `sqlx::query!` under the hood, so every generated query will be checked against your database at compile time.
@@ -57,8 +58,9 @@ is not what you are looking for.
5758
if you encounter an issue or have questions, feel free to ask in [`#ormx` on the sqlx discord](https://discord.gg/mrZz4Wv8r2).
5859
The documentation currently is not what it should be, so don't be afraid to ask for help.
5960

60-
## [mysql example](https://github.com/NyxCode/ormx/tree/master/example-mysql/src/main.rs)
6161
## [postgres example](https://github.com/NyxCode/ormx/tree/master/example-postgres/src/main.rs)
62+
## [mariadb example](https://github.com/NyxCode/ormx/tree/master/example-mariadb/src/main.rs)
63+
## [mysql example](https://github.com/NyxCode/ormx/tree/master/example-mysql/src/main.rs)
6264
## features
6365
- `mysql` - enable support for mysql/mariadb
6466
- `postgres` - enable support for postgres

example-mariadb/Cargo.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "example-mariadb"
3+
version = "0.1.0"
4+
authors = ["moritz"]
5+
edition = "2021"
6+
7+
[dependencies]
8+
ormx = { path = "../ormx", features = ["mariadb"] }
9+
tokio = { version = "1", features = ["full"] }
10+
anyhow = "1"
11+
dotenv = "0.15"
12+
chrono = "0.4"
13+
env_logger = "0.11.5"
14+
log = "0.4"
15+
16+
[dependencies.sqlx]
17+
version = "0.8"
18+
default-features = false
19+
features = ["macros", "mysql", "runtime-tokio-rustls", "chrono"]

example-mariadb/src/main.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use chrono::{NaiveDateTime, Utc};
2+
use log::LevelFilter;
3+
use ormx::{Delete, Insert, Table};
4+
use sqlx::MySqlPool;
5+
6+
// To run this example, first run `/scripts/mariadb.sh` to start mariadb in a docker container and
7+
// write the database URL to `.env`. Then, source `.env` (`. .env`) and run `cargo run`
8+
9+
mod query2;
10+
11+
#[tokio::main]
12+
async fn main() -> anyhow::Result<()> {
13+
dotenv::dotenv().ok();
14+
env_logger::builder()
15+
.filter_level(LevelFilter::Debug)
16+
.init();
17+
18+
let db = MySqlPool::connect(&dotenv::var("DATABASE_URL")?).await?;
19+
20+
log::info!("insert a new row into the database");
21+
let mut new = InsertUser {
22+
first_name: "Moritz".to_owned(),
23+
last_name: "Bischof".to_owned(),
24+
email: "[email protected]".to_owned(),
25+
disabled: None,
26+
}
27+
.insert(&db)
28+
.await?;
29+
30+
log::info!("update a single field");
31+
new.set_last_login(&db, Some(Utc::now().naive_utc()))
32+
.await?;
33+
34+
log::info!("update all fields at once");
35+
new.email = "asdf".to_owned();
36+
new.update(&db).await?;
37+
38+
log::info!("apply a patch to the user, updating its first and last name");
39+
new.patch(
40+
&db,
41+
UpdateName {
42+
first_name: "NewFirstName".to_owned(),
43+
last_name: "NewLastName".to_owned(),
44+
disabled: Some("Reason".to_owned()),
45+
},
46+
)
47+
.await?;
48+
49+
log::info!("reload the user, in case it has been modified");
50+
new.reload(&db).await?;
51+
52+
log::info!("use the improved query macro for searching users");
53+
let search_result = query2::query_users(&db, Some("NewFirstName"), None).await?;
54+
println!("{:?}", search_result);
55+
56+
log::info!("delete the user from the database");
57+
new.delete(&db).await?;
58+
59+
Ok(())
60+
}
61+
62+
#[derive(Debug, ormx::Table)]
63+
#[ormx(table = "users", id = user_id, insertable, deletable)]
64+
struct User {
65+
// map this field to the column "id"
66+
#[ormx(column = "id")]
67+
// generate `User::get_by_user_id(u32) -> Result<Self>`
68+
#[ormx(get_one = get_by_user_id(u32))]
69+
// this column is database-generated.
70+
#[ormx(default)]
71+
user_id: u32,
72+
first_name: String,
73+
last_name: String,
74+
// generate `User::by_email(&str) -> Result<Option<Self>>`
75+
#[ormx(get_optional(&str))]
76+
email: String,
77+
disabled: Option<String>,
78+
// don't include this field into `InsertUser` since it has a default value
79+
// generate `User::set_last_login(Option<NaiveDateTime>) -> Result<()>`
80+
#[ormx(default, set)]
81+
last_login: Option<NaiveDateTime>,
82+
}
83+
84+
// Patches can be used to update multiple fields at once (in diesel, they're called "ChangeSets").
85+
#[derive(ormx::Patch)]
86+
#[ormx(table_name = "users", table = crate::User, id = "id")]
87+
struct UpdateName {
88+
first_name: String,
89+
last_name: String,
90+
disabled: Option<String>,
91+
}

example-mariadb/src/query2.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use sqlx::MySqlPool;
2+
3+
use crate::User;
4+
5+
pub(crate) async fn query_users(
6+
db: &MySqlPool,
7+
filter: Option<&str>,
8+
limit: Option<usize>,
9+
) -> anyhow::Result<Vec<User>> {
10+
let result = ormx::conditional_query_as!(
11+
User,
12+
r#"SELECT id AS user_id, first_name, last_name, email, disabled, last_login"#
13+
"FROM users"
14+
Some(f) = filter => {
15+
"WHERE first_name LIKE" ?(f)
16+
"OR last_name LIKE" ?(f)
17+
}
18+
"ORDER BY first_name DESC"
19+
Some(l) = limit => {
20+
"LIMIT" ?(l as i64)
21+
}
22+
)
23+
.fetch_all(db)
24+
.await?;
25+
26+
Ok(result)
27+
}

example-mysql/Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
name = "example-mysql"
33
version = "0.1.0"
44
authors = ["moritz"]
5-
edition = "2018"
5+
edition = "2021"
66

77
[dependencies]
88
ormx = { path = "../ormx", features = ["mysql"] }
9-
tokio = { version = "1.1", features = ["full"] }
9+
tokio = { version = "1", features = ["full"] }
1010
anyhow = "1"
1111
dotenv = "0.15"
1212
chrono = "0.4"
13-
simple_logger = "1"
13+
env_logger = "0.11.5"
1414
log = "0.4"
1515

1616
[dependencies.sqlx]
17-
version = "0.6"
17+
version = "0.8"
1818
default-features = false
19-
features = ["macros", "mysql", "runtime-tokio-rustls", "chrono", "offline"]
19+
features = ["macros", "mysql", "runtime-tokio-rustls", "chrono"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CREATE TABLE users
2+
(
3+
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
4+
first_name VARCHAR(128) NOT NULL,
5+
last_name VARCHAR(128) NOT NULL,
6+
email VARCHAR(128) NOT NULL UNIQUE,
7+
disabled VARCHAR(128),
8+
last_login DATETIME DEFAULT NULL
9+
)

example-mysql/src/main.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
// #![feature(trace_macros)]
21
use chrono::{NaiveDateTime, Utc};
3-
use ormx::{Insert, Table};
2+
use log::LevelFilter;
3+
use ormx::{Delete, Insert, Table};
44
use sqlx::MySqlPool;
55

6-
// trace_macros!(true);
7-
8-
// To run this example-postgres, first run `/scripts/postgres.sh` to start postgres in a docker container and
6+
// To run this example, first run `/scripts/mariadb.sh` to start mariadb in a docker container and
97
// write the database URL to `.env`. Then, source `.env` (`. .env`) and run `cargo run`
108

119
mod query2;
1210

1311
#[tokio::main]
1412
async fn main() -> anyhow::Result<()> {
1513
dotenv::dotenv().ok();
16-
simple_logger::SimpleLogger::new()
17-
.with_level(log::LevelFilter::Info)
18-
.init()?;
14+
env_logger::builder()
15+
.filter_level(LevelFilter::Debug)
16+
.init();
1917

2018
let db = MySqlPool::connect(&dotenv::var("DATABASE_URL")?).await?;
2119

@@ -26,7 +24,7 @@ async fn main() -> anyhow::Result<()> {
2624
email: "[email protected]".to_owned(),
2725
disabled: None,
2826
}
29-
.insert(&db)
27+
.insert(&mut *db.acquire().await?)
3028
.await?;
3129

3230
log::info!("update a single field");
@@ -62,7 +60,7 @@ async fn main() -> anyhow::Result<()> {
6260
}
6361

6462
#[derive(Debug, ormx::Table)]
65-
#[ormx(table = "users", id = user_id, insertable)]
63+
#[ormx(table = "users", id = user_id, insertable, deletable)]
6664
struct User {
6765
// map this field to the column "id"
6866
#[ormx(column = "id")]

0 commit comments

Comments
 (0)