Skip to content

Commit

Permalink
Introduce a binders crate
Browse files Browse the repository at this point in the history
Fixes #273
  • Loading branch information
nitnelave committed May 23, 2022
1 parent 58e11cc commit 445b660
Show file tree
Hide file tree
Showing 20 changed files with 951 additions and 109 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ members = [
".",
"sea-query-derive",
"sea-query-driver",
"sea-query-binders",
"examples/postgres",
"examples/postgres_json",
"examples/cockroach",
"examples/cockroach_json",
"examples/rusqlite",
"examples/sqlx_any",
"examples/sqlx_mysql",
"examples/sqlx_postgres",
"examples/sqlx_sqlite",
Expand Down
10 changes: 5 additions & 5 deletions examples/rusqlite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ sea-query = { path = "../../", features = [
# NOTE: if you are copying this example into your own project, use the following line instead:
# sea-query = { version = "^0", features = [
# "rusqlite",
# "with-chrono",
# "with-json",
# "with-uuid",
# "with-time",
# "sqlx-chrono",
# "sqlx-json",
# "sqlx-uuid",
# "sqlx-time",
# ] }

[dependencies.rusqlite]
Expand All @@ -32,4 +32,4 @@ features = [
"serde_json",
"uuid",
"time",
]
]
44 changes: 44 additions & 0 deletions examples/sqlx_any/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[package]
name = "sea-query-sqlx-any-example"
version = "0.1.0"
edition = "2021"

[dependencies]
chrono = "^0"
time = "^0.2"
uuid = { version = "^0", features = ["serde", "v4"] }
serde_json = "^1"
rust_decimal = { version = "^1" }
bigdecimal = { version = "^0.2" }
async-std = { version = "1.8", features = [ "attributes" ] }
sea-query = { path = "../../" }
# NOTE: if you are copying this example into your own project, use the following line instead:
# sea-query = { version = "^0", features = [...] }
sea-query-binders = { path = "../../sea-query-binders", features = [
"sqlx-postgres",
"sqlx-sqlite",
"sqlx-mysql",
"sqlx-any",
"with-chrono",
"with-json",
"with-rust_decimal",
"with-bigdecimal",
"with-uuid",
"with-time",
] }

[dependencies.sqlx]
version = "^0.5"
default-features = false
features = [
"runtime-async-std-native-tls",
"macros",
"any",
"tls",
"chrono",
"json",
"decimal",
"bigdecimal",
"uuid",
"time",
]
30 changes: 30 additions & 0 deletions examples/sqlx_any/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SeaQuery SQLx Any example

Running:
```sh
cargo run
```

Example output:
```
Create table character: Ok(AnyQueryResult { rows_affected: 0, last_insert_id: Some(0) })
Insert into character: last_insert_id = 1
Select one from character:
CharacterStructChrono { id: 1, character: "A", font_size: 12, created: 2020-08-20T00:00:00 }
Update character: Ok(AnyQueryResult { rows_affected: 1, last_insert_id: Some(1) })
Select one from character:
CharacterStructChrono { id: 1, character: "A", font_size: 24, created: 2020-08-20T00:00:00 }
Count character: 1
Insert into character (with upsert): Ok(AnyQueryResult { rows_affected: 1, last_insert_id: Some(1) })
Select all characters:
CharacterStructChrono { id: 1, character: "B", font_size: 16, created: 2020-08-20T00:00:00 }
Delete character: Ok(AnyQueryResult { rows_affected: 1, last_insert_id: Some(1) })
```
240 changes: 240 additions & 0 deletions examples/sqlx_any/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
use chrono::{NaiveDate, NaiveDateTime};
use sea_query::{
ColumnDef, Expr, Func, Iden, MysqlQueryBuilder, OnConflict, Order, PostgresQueryBuilder, Query,
QueryBuilder, SchemaBuilder, SqliteQueryBuilder, Table,
};
use sqlx::{AnyPool, Row};
use std::env;

use sea_query_binders::SqlxBinder;

#[async_std::main]
async fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 2 || (args[1] != "postgres" && args[1] != "mysql" && args[1] != "sqlite") {
println!(
"Expected a single argument out of {{postgres, mysql, sqlite}}, got {}",
args.split_at(1).1.join(", ")
);
return;
}
let (url, box_query_builder, box_schema_builder): (
&str,
Box<dyn QueryBuilder>,
Box<dyn SchemaBuilder>,
) = if args[1] == "postgres" {
(
"postgres://sea:sea@127.0.0.1/query",
Box::new(PostgresQueryBuilder {}),
Box::new(PostgresQueryBuilder {}),
)
} else if args[1] == "sqlite" {
(
"sqlite::memory:",
Box::new(SqliteQueryBuilder {}),
Box::new(SqliteQueryBuilder {}),
)
} else if args[1] == "mysql" {
(
"mysql://sea:sea@127.0.0.1/query",
Box::new(MysqlQueryBuilder {}),
Box::new(MysqlQueryBuilder {}),
)
} else {
panic!()
};
let query_builder = &*box_query_builder;
let schema_builder = &*box_schema_builder;
let connection = AnyPool::connect(url).await.unwrap();
let mut pool = connection.try_acquire().unwrap();

// Schema

let sql = Table::create()
.table(Character::Table)
.if_not_exists()
.col(
ColumnDef::new(Character::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Character::FontSize).integer())
.col(ColumnDef::new(Character::Character).string())
.col(ColumnDef::new(Character::Created).date_time())
.build_any(schema_builder);

let result = sqlx::query(&sql).execute(&mut pool).await;
println!("Create table character: {:?}\n", result);

// Create

let (sql, values) = Query::insert()
.into_table(Character::Table)
.columns(vec![
Character::FontSize,
Character::Character,
Character::Created,
])
.values_panic(vec![
12.into(),
"A".into(),
NaiveDate::from_ymd(2020, 8, 20).and_hms(0, 0, 0).into(),
])
.returning_col(Character::Id)
.build_any_sqlx(query_builder);

let row = sqlx::query_with(&sql, values)
.fetch_one(&mut pool)
.await
.unwrap();
let id: i32 = row.try_get(0).unwrap();
println!("Insert into character: last_insert_id = {}\n", id);

// Read

let (sql, values) = Query::select()
.columns(vec![
Character::Id,
Character::Character,
Character::FontSize,
Character::Created,
])
.from(Character::Table)
.order_by(Character::Id, Order::Desc)
.limit(1)
.build_any_sqlx(query_builder);

let rows = sqlx::query_as_with::<_, CharacterStructChrono, _>(&sql, values)
.fetch_all(&mut pool)
.await
.unwrap();
println!("Select one from character:");
for row in rows.iter() {
println!("{:?}", row);
}
println!();

// Update

let (sql, values) = Query::update()
.table(Character::Table)
.values(vec![(Character::FontSize, 24.into())])
.and_where(Expr::col(Character::Id).eq(id))
.build_any_sqlx(query_builder);

let result = sqlx::query_with(&sql, values).execute(&mut pool).await;
println!("Update character: {:?}\n", result);

// Read

let (sql, values) = Query::select()
.columns(vec![
Character::Id,
Character::Character,
Character::FontSize,
Character::Created,
])
.from(Character::Table)
.order_by(Character::Id, Order::Desc)
.limit(1)
.build_any_sqlx(query_builder);

let rows = sqlx::query_as_with::<_, CharacterStructChrono, _>(&sql, values)
.fetch_all(&mut pool)
.await
.unwrap();
println!("Select one from character:");
for row in rows.iter() {
println!("{:?}", row);
}
println!();

// Count

let (sql, values) = Query::select()
.from(Character::Table)
.expr(Func::count(Expr::col(Character::Id)))
.build_any_sqlx(query_builder);

let row = sqlx::query_with(&sql, values)
.fetch_one(&mut pool)
.await
.unwrap();
print!("Count character: ");
let count: i64 = row.try_get(0).unwrap();
println!("{}", count);
println!();

// Upsert

let (sql, values) = Query::insert()
.into_table(Character::Table)
.columns(vec![
Character::Id,
Character::FontSize,
Character::Character,
])
.values_panic(vec![1.into(), 16.into(), "B".into()])
.on_conflict(
OnConflict::column(Character::Id)
.update_columns([Character::FontSize, Character::Character])
.to_owned(),
)
.build_any_sqlx(query_builder);

let result = sqlx::query_with(&sql, values).execute(&mut pool).await;
println!("Insert into character (with upsert): {:?}\n", result);

// Read

let (sql, values) = Query::select()
.columns(vec![
Character::Id,
Character::Character,
Character::FontSize,
Character::Created,
])
.from(Character::Table)
.order_by(Character::Id, Order::Desc)
.build_any_sqlx(query_builder);

let rows = sqlx::query_as_with::<_, CharacterStructChrono, _>(&sql, values)
.fetch_all(&mut pool)
.await
.unwrap();
println!("Select all characters:");
for row in rows.iter() {
println!("{:?}", row);
}
println!();

// Delete

let (sql, values) = Query::delete()
.from_table(Character::Table)
.and_where(Expr::col(Character::Id).eq(id))
.build_any_sqlx(query_builder);

let result = sqlx::query_with(&sql, values).execute(&mut pool).await;
println!("Delete character: {:?}", result);
}

#[derive(Iden)]
enum Character {
Table,
Id,
Character,
FontSize,
Created,
}

#[derive(sqlx::FromRow, Debug)]
#[allow(dead_code)]
struct CharacterStructChrono {
id: i32,
character: String,
font_size: i32,
created: NaiveDateTime,
}
15 changes: 4 additions & 11 deletions examples/sqlx_mysql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ serde_json = "^1"
rust_decimal = { version = "^1" }
bigdecimal = { version = "^0.2" }
async-std = { version = "1.8", features = [ "attributes" ] }
sea-query = { path = "../../", features = [
sea-query = { path = "../../" }
# NOTE: if you are copying this example into your own project, use the following line instead:
# sea-query = { version = "^0", features = [...] }
sea-query-binders = { path = "../../sea-query-binders", features = [
"sqlx-mysql",
"with-chrono",
"with-json",
Expand All @@ -20,16 +23,6 @@ sea-query = { path = "../../", features = [
"with-uuid",
"with-time",
] }
# NOTE: if you are copying this example into your own project, use the following line instead:
# sea-query = { version = "^0", features = [
# "sqlx-mysql",
# "with-chrono",
# "with-json",
# "with-rust_decimal",
# "with-bigdecimal",
# "with-uuid",
# "with-time",
# ] }

# To fix sqlx on unstable Rust:
# lexical-core = { version = "0.7.5" }
Expand Down
Loading

0 comments on commit 445b660

Please sign in to comment.