1use std::{pin::pin, sync::LazyLock};
2use tank::{
3 DynQuery, Entity, Executor, QueryBuilder, cols, expr,
4 stream::{StreamExt, TryStreamExt},
5};
6use tokio::sync::Mutex;
7
8static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
9
10#[derive(Entity, PartialEq, Debug)]
11pub struct ATable {
12 #[tank(primary_key)]
13 a_column: String,
14}
15
16#[derive(Entity, PartialEq, Debug)]
17pub struct CharTable {
18 #[tank(primary_key)]
19 id: i32,
20 letter: char,
21}
22
23pub async fn other(executor: &mut impl Executor) {
24 let _lock = MUTEX.lock().await;
25
26 ATable::drop_table(executor, true, false)
28 .await
29 .expect("Failed to drop ATable table");
30 ATable::create_table(executor, true, true)
31 .await
32 .expect("Failed to create ATable table");
33 ATable::insert_one(
34 executor,
35 &ATable {
36 a_column: "".into(),
37 },
38 )
39 .await
40 .expect("Could not save a row");
41
42 let stream = executor
44 .fetch(
45 QueryBuilder::new()
46 .select(cols!(NULL))
47 .from(ATable::table())
48 .where_expr(true)
49 .build(&executor.driver()),
50 )
51 .map_ok(|v| v.values.into_iter().nth(0).unwrap());
52 let value = pin!(stream)
53 .next()
54 .await
55 .expect("No result returned from the stream")
56 .expect("Could not query for NULL");
57 assert!(value.is_null());
58
59 let rows = vec![ATable {
61 a_column: "test".into(),
62 }];
63 let query = QueryBuilder::new().insert_into::<ATable>().values(&rows);
64 let from_build = query.build(&executor.driver());
65 let mut out = DynQuery::default();
66 query.build_into(&executor.driver(), &mut out);
67 let from_build_into: String = out.into();
68 assert_eq!(
69 from_build, from_build_into,
70 "build() and build_into() should produce the same SQL"
71 );
72
73 CharTable::drop_table(executor, true, false)
75 .await
76 .expect("Failed to drop CharTable");
77 CharTable::create_table(executor, true, true)
78 .await
79 .expect("Failed to create CharTable");
80 CharTable::insert_one(
81 executor,
82 &CharTable {
83 id: 1, letter: 'é'
84 },
85 )
86 .await
87 .expect("Could not insert multi-byte char");
88 let row = CharTable::find_one(executor, expr!(CharTable::id == 1))
89 .await
90 .expect("Failed to query CharTable")
91 .expect("Row with id=1 not found");
92 assert_eq!(
93 row.letter, 'é',
94 "Multi-byte char should round-trip correctly"
95 );
96}