Skip to content

Commit

Permalink
Update to sqlx 0.8, eliminate most allocations (#40)
Browse files Browse the repository at this point in the history
Release v0.11
  • Loading branch information
NyxCode authored Sep 8, 2024
1 parent 5c66ce6 commit bec3ab2
Show file tree
Hide file tree
Showing 37 changed files with 754 additions and 305 deletions.
117 changes: 117 additions & 0 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Examples

on:
pull_request:
push:
branches:
- main
- '*-dev'

jobs:
mysql:
name: MySQL Example
runs-on: ubuntu-latest

services:
mysql:
image: mysql:latest
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: ormx
ports:
- 3307:3306

steps:
- uses: actions/checkout@v4

- uses: Swatinem/rust-cache@v2
with:
key: mysql-example

- name: Install sqlx-cli
run: |
cargo install sqlx-cli
sleep 5
- name: Setup
working-directory: example-mysql
env:
DATABASE_URL: mysql://root:password@localhost:3307/ormx?ssl-mode=disabled
run: sqlx db setup

- name: Run
working-directory: example-mysql
env:
DATABASE_URL: mysql://root:password@localhost:3307/ormx?ssl-mode=disabled
run: cargo run


mariadb:
name: MariaDB Example
runs-on: ubuntu-latest

services:
mysql:
image: mariadb:latest
env:
MYSQL_ROOT_PASSWORD: password
ports:
- 3306:3306

steps:
- uses: actions/checkout@v4

- uses: Swatinem/rust-cache@v2
with:
key: mariadb-example

- name: Install sqlx-cli
run: |
cargo install sqlx-cli
sleep 5
- name: Setup
working-directory: example-mariadb
env:
DATABASE_URL: mysql://root:password@localhost:3306/ormx?ssl-mode=disabled
run: sqlx db setup

- name: Run
working-directory: example-mariadb
env:
DATABASE_URL: mysql://root:password@localhost:3306/ormx?ssl-mode=disabled
run: cargo run

postgres:
name: PostgreSQL Example
runs-on: ubuntu-latest

services:
postgres:
image: postgres:latest
env:
POSTGRES_PASSWORD: password
ports:
- 5432:5432

steps:
- uses: actions/checkout@v4

- uses: Swatinem/rust-cache@v2
with:
key: postgres-example

- name: Install sqlx-cli
run: cargo install sqlx-cli

- name: Setup
working-directory: example-postgres
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/ormx
run: sqlx db setup

- name: Run
working-directory: example-postgres
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/ormx
run: cargo run
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[workspace]
members = ["ormx-macros", "ormx", "example-postgres", "example-mysql"]
members = ["ormx-macros", "ormx", "example-postgres", "example-mariadb", "example-mysql"]
resolver = "2"
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@
Add ormx and sqlx to your `Cargo.toml`
```toml
[dependencies.ormx]
version = "0.7"
version = "0.11"
features = ["mysql"]

[dependencies.sqlx]
version = "0.5"
version = "0.8"
default-features = false
features = ["macros", "mysql", "runtime-tokio-rustls"]
```
Right now, ormx supports mysql/mariadb and postgres.
Right now, ormx supports mysql, mariadb and postgres.

## what does it do?
ormx provides macros for generating commonly used sql queries at compile time.
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.
Expand All @@ -57,8 +58,9 @@ is not what you are looking for.
if you encounter an issue or have questions, feel free to ask in [`#ormx` on the sqlx discord](https://discord.gg/mrZz4Wv8r2).
The documentation currently is not what it should be, so don't be afraid to ask for help.

## [mysql example](https://github.com/NyxCode/ormx/tree/master/example-mysql/src/main.rs)
## [postgres example](https://github.com/NyxCode/ormx/tree/master/example-postgres/src/main.rs)
## [mariadb example](https://github.com/NyxCode/ormx/tree/master/example-mariadb/src/main.rs)
## [mysql example](https://github.com/NyxCode/ormx/tree/master/example-mysql/src/main.rs)
## features
- `mysql` - enable support for mysql/mariadb
- `postgres` - enable support for postgres
Expand Down
19 changes: 19 additions & 0 deletions example-mariadb/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "example-mariadb"
version = "0.1.0"
authors = ["moritz"]
edition = "2021"

[dependencies]
ormx = { path = "../ormx", features = ["mariadb"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1"
dotenv = "0.15"
chrono = "0.4"
env_logger = "0.11.5"
log = "0.4"

[dependencies.sqlx]
version = "0.8"
default-features = false
features = ["macros", "mysql", "runtime-tokio-rustls", "chrono"]
File renamed without changes.
91 changes: 91 additions & 0 deletions example-mariadb/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use chrono::{NaiveDateTime, Utc};
use log::LevelFilter;
use ormx::{Delete, Insert, Table};
use sqlx::MySqlPool;

// To run this example, first run `/scripts/mariadb.sh` to start mariadb in a docker container and
// write the database URL to `.env`. Then, source `.env` (`. .env`) and run `cargo run`

mod query2;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
env_logger::builder()
.filter_level(LevelFilter::Debug)
.init();

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

log::info!("insert a new row into the database");
let mut new = InsertUser {
first_name: "Moritz".to_owned(),
last_name: "Bischof".to_owned(),
email: "[email protected]".to_owned(),
disabled: None,
}
.insert(&db)
.await?;

log::info!("update a single field");
new.set_last_login(&db, Some(Utc::now().naive_utc()))
.await?;

log::info!("update all fields at once");
new.email = "asdf".to_owned();
new.update(&db).await?;

log::info!("apply a patch to the user, updating its first and last name");
new.patch(
&db,
UpdateName {
first_name: "NewFirstName".to_owned(),
last_name: "NewLastName".to_owned(),
disabled: Some("Reason".to_owned()),
},
)
.await?;

log::info!("reload the user, in case it has been modified");
new.reload(&db).await?;

log::info!("use the improved query macro for searching users");
let search_result = query2::query_users(&db, Some("NewFirstName"), None).await?;
println!("{:?}", search_result);

log::info!("delete the user from the database");
new.delete(&db).await?;

Ok(())
}

#[derive(Debug, ormx::Table)]
#[ormx(table = "users", id = user_id, insertable, deletable)]
struct User {
// map this field to the column "id"
#[ormx(column = "id")]
// generate `User::get_by_user_id(u32) -> Result<Self>`
#[ormx(get_one = get_by_user_id(u32))]
// this column is database-generated.
#[ormx(default)]
user_id: u32,
first_name: String,
last_name: String,
// generate `User::by_email(&str) -> Result<Option<Self>>`
#[ormx(get_optional(&str))]
email: String,
disabled: Option<String>,
// don't include this field into `InsertUser` since it has a default value
// generate `User::set_last_login(Option<NaiveDateTime>) -> Result<()>`
#[ormx(default, set)]
last_login: Option<NaiveDateTime>,
}

// Patches can be used to update multiple fields at once (in diesel, they're called "ChangeSets").
#[derive(ormx::Patch)]
#[ormx(table_name = "users", table = crate::User, id = "id")]
struct UpdateName {
first_name: String,
last_name: String,
disabled: Option<String>,
}
27 changes: 27 additions & 0 deletions example-mariadb/src/query2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use sqlx::MySqlPool;

use crate::User;

pub(crate) async fn query_users(
db: &MySqlPool,
filter: Option<&str>,
limit: Option<usize>,
) -> anyhow::Result<Vec<User>> {
let result = ormx::conditional_query_as!(
User,
r#"SELECT id AS user_id, first_name, last_name, email, disabled, last_login"#
"FROM users"
Some(f) = filter => {
"WHERE first_name LIKE" ?(f)
"OR last_name LIKE" ?(f)
}
"ORDER BY first_name DESC"
Some(l) = limit => {
"LIMIT" ?(l as i64)
}
)
.fetch_all(db)
.await?;

Ok(result)
}
10 changes: 5 additions & 5 deletions example-mysql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
name = "example-mysql"
version = "0.1.0"
authors = ["moritz"]
edition = "2018"
edition = "2021"

[dependencies]
ormx = { path = "../ormx", features = ["mysql"] }
tokio = { version = "1.1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1"
dotenv = "0.15"
chrono = "0.4"
simple_logger = "1"
env_logger = "0.11.5"
log = "0.4"

[dependencies.sqlx]
version = "0.6"
version = "0.8"
default-features = false
features = ["macros", "mysql", "runtime-tokio-rustls", "chrono", "offline"]
features = ["macros", "mysql", "runtime-tokio-rustls", "chrono"]
9 changes: 9 additions & 0 deletions example-mysql/migrations/20240908062140_schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE users
(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(128) NOT NULL,
last_name VARCHAR(128) NOT NULL,
email VARCHAR(128) NOT NULL UNIQUE,
disabled VARCHAR(128),
last_login DATETIME DEFAULT NULL
)
18 changes: 8 additions & 10 deletions example-mysql/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
// #![feature(trace_macros)]
use chrono::{NaiveDateTime, Utc};
use ormx::{Insert, Table};
use log::LevelFilter;
use ormx::{Delete, Insert, Table};
use sqlx::MySqlPool;

// trace_macros!(true);

// To run this example-postgres, first run `/scripts/postgres.sh` to start postgres in a docker container and
// To run this example, first run `/scripts/mariadb.sh` to start mariadb in a docker container and
// write the database URL to `.env`. Then, source `.env` (`. .env`) and run `cargo run`

mod query2;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
simple_logger::SimpleLogger::new()
.with_level(log::LevelFilter::Info)
.init()?;
env_logger::builder()
.filter_level(LevelFilter::Debug)
.init();

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

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

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

#[derive(Debug, ormx::Table)]
#[ormx(table = "users", id = user_id, insertable)]
#[ormx(table = "users", id = user_id, insertable, deletable)]
struct User {
// map this field to the column "id"
#[ormx(column = "id")]
Expand Down
Loading

0 comments on commit bec3ab2

Please sign in to comment.