Skip to main content

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