tank_tests/readme.rs
1use std::{borrow::Cow, collections::HashSet, sync::LazyLock};
2use tank::{Entity, Executor, Result, expr, stream::TryStreamExt};
3use tokio::sync::Mutex;
4
5#[derive(Entity)]
6#[tank(schema = "army")]
7pub struct Tank {
8 #[tank(primary_key)]
9 pub name: String,
10 pub country: Cow<'static, str>,
11 #[tank(name = "caliber")]
12 pub caliber_mm: u16,
13 #[tank(name = "speed")]
14 pub speed_kmh: f32,
15 pub is_operational: bool,
16 pub units_produced: Option<u32>,
17}
18static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
19
20pub async fn readme<E: Executor>(connection: &mut E) -> Result<()> {
21 let _lock = MUTEX.lock();
22
23 let my_tank = Tank {
24 name: "Tiger I".into(),
25 country: "Germany".into(),
26 caliber_mm: 88,
27 speed_kmh: 45.4,
28 is_operational: false,
29 units_produced: Some(1_347),
30 };
31
32 /*
33 * DROP TABLE IF EXISTS "army"."tank";
34 */
35 Tank::drop_table(connection, true, false).await?;
36
37 /*
38 * CREATE SCHEMA IF NOT EXISTS "army";
39 * CREATE TABLE IF NOT EXISTS "army"."tank" (
40 * "name" VARCHAR PRIMARY KEY,
41 * "country" VARCHAR NOT NULL,
42 * "caliber" USMALLINT NOT NULL,
43 * "speed" FLOAT NOT NULL,
44 * "is_operational" BOOLEAN NOT NULL,
45 * "units_produced" UINTEGER);
46 */
47 Tank::create_table(connection, true, true).await?;
48
49 /*
50 * INSERT INTO "army"."tank" ("name", "country", "caliber", "speed", "is_operational", "units_produced") VALUES
51 * ('Tiger I', 'Germany', 88, 45.4, false, 1347)
52 * ON CONFLICT ("name") DO UPDATE SET
53 * "country" = EXCLUDED."country",
54 * "caliber" = EXCLUDED."caliber",
55 * "speed" = EXCLUDED."speed",
56 * "is_operational" = EXCLUDED."is_operational",
57 * "units_produced" = EXCLUDED."units_produced";
58 */
59 my_tank.save(connection).await?;
60
61 /*
62 * In the case of DuckDB, it uses the appender API, in other cases the resulting query is:
63 * INSERT INTO "army"."tank" ("name", "country", "caliber", "speed", "is_operational", "units_produced") VALUES
64 * ('T-34/85', 'Soviet Union', 85, 53.0, false, 49200),
65 * ('M1 Abrams', 'USA', 120, 72.0, true, NULL);
66 */
67 Tank::insert_many(
68 connection,
69 &[
70 Tank {
71 name: "T-34/85".into(),
72 country: "Soviet Union".into(),
73 caliber_mm: 85,
74 speed_kmh: 53.0,
75 is_operational: false,
76 units_produced: Some(49_200),
77 },
78 Tank {
79 name: "M1 Abrams".into(),
80 country: "USA".into(),
81 caliber_mm: 120,
82 speed_kmh: 72.0,
83 is_operational: true,
84 units_produced: None,
85 },
86 ],
87 )
88 .await?;
89
90 /*
91 * SELECT "name", "country", "caliber", "speed", "is_operational", "units_produced"
92 * FROM "army"."tank"
93 * WHERE "is_operational" = false
94 * LIMIT 1000;
95 */
96 let tanks = Tank::find_many(
97 connection,
98 &expr!(Tank::is_operational == false),
99 Some(1000),
100 )
101 .try_collect::<Vec<_>>()
102 .await?;
103
104 assert_eq!(
105 tanks
106 .iter()
107 .map(|t| t.name.to_string())
108 .collect::<HashSet<_>>(),
109 HashSet::from_iter(["Tiger I".into(), "T-34/85".into()])
110 );
111 Ok(())
112}