1#![allow(unused_imports)]
2use rust_decimal::{Decimal, prelude::FromPrimitive};
3use std::{
4 borrow::Cow,
5 cell::{Cell, RefCell},
6 i128,
7 ops::Deref,
8 pin::pin,
9 sync::{Arc, LazyLock},
10};
11use tank::{
12 AsValue, Driver, DynQuery, Entity, Error, Executor, FixedDecimal, Query, QueryBuilder,
13 QueryResult, RawQuery, Result, RowsAffected, SqlWriter, Value, cols, expr,
14 stream::{StreamExt, TryStreamExt},
15};
16use time::{Date, Time, macros::date};
17use tokio::sync::Mutex;
18use uuid::Uuid;
19
20static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
21
22#[derive(Clone, Copy, PartialEq, Eq, Debug)]
23enum SomeEnum {
24 FirstValue,
25 SecondValue,
26}
27impl AsValue for SomeEnum {
28 fn as_empty_value() -> Value {
29 Value::Varchar(None)
30 }
31 fn as_value(self) -> Value {
32 match self {
33 Self::FirstValue => Value::Varchar(Some("first".into())),
34 Self::SecondValue => Value::Varchar(Some("second".into())),
35 }
36 }
37 fn try_from_value(value: Value) -> Result<Self>
38 where
39 Self: Sized,
40 {
41 if let Value::Varchar(Some(v), ..) = value.try_as(&Value::Varchar(None))? {
42 match v.deref() {
43 "first" => return Ok(Self::FirstValue),
44 "second" => return Ok(Self::SecondValue),
45 _ => {}
46 }
47 }
48 Err(Error::msg("Could not decode SomeEnum from value"))
49 }
50}
51
52#[derive(Clone, Copy, PartialEq, Eq, Debug)]
53enum AnotherEnum {
54 Alpha,
55 Bravo,
56 Charlie,
57 Delta,
58}
59impl AsValue for AnotherEnum {
60 fn as_empty_value() -> Value {
61 Value::Int8(None)
62 }
63 fn as_value(self) -> Value {
64 match self {
65 Self::Alpha => Value::Int8(Some(0)),
66 Self::Bravo => Value::Int8(Some(1)),
67 Self::Charlie => Value::Int8(Some(2)),
68 Self::Delta => Value::Int8(Some(3)),
69 }
70 }
71 fn try_from_value(value: Value) -> Result<Self>
72 where
73 Self: Sized,
74 {
75 if let Value::Int8(Some(v), ..) = value.try_as(&Value::Int8(None))? {
76 match v {
77 0 => return Ok(Self::Alpha),
78 1 => return Ok(Self::Bravo),
79 2 => return Ok(Self::Charlie),
80 3 => return Ok(Self::Delta),
81 _ => {}
82 }
83 }
84 Err(Error::msg("Could not decode AnotherEnum from value"))
85 }
86}
87
88#[derive(Debug, Entity, PartialEq)]
89#[tank(primary_key = (id, another_enum))]
90struct Entry {
91 id: i32,
92 some_enum: Option<SomeEnum>,
93 #[tank(clustering_key)]
94 another_enum: AnotherEnum,
95}
96
97pub async fn enums<E: Executor>(executor: &mut E) {
98 let _lock = MUTEX.lock().await;
99
100 Entry::drop_table(executor, true, false)
102 .await
103 .expect("Failed to drop Table table");
104 Entry::create_table(executor, true, true)
105 .await
106 .expect("Failed to create Table table");
107
108 let mut entry = Entry {
110 id: 1,
111 some_enum: Some(SomeEnum::FirstValue),
112 another_enum: AnotherEnum::Delta,
113 };
114 entry.save(executor).await.expect("Failed to save entry");
115 let value = Entry::find_one(executor, true)
116 .await
117 .expect("Failed to read entry");
118 assert_eq!(
119 value,
120 Some(Entry {
121 id: 1,
122 some_enum: Some(SomeEnum::FirstValue),
123 another_enum: AnotherEnum::Delta,
124 })
125 );
126
127 entry.some_enum = None;
128 entry
129 .save(executor)
130 .await
131 .expect("Failed to save again entry");
132 Entry::insert_many(
133 executor,
134 &[
135 Entry {
136 id: 1,
137 some_enum: Some(SomeEnum::SecondValue),
138 another_enum: AnotherEnum::Charlie,
139 },
140 Entry {
141 id: 1,
142 some_enum: None,
143 another_enum: AnotherEnum::Bravo,
144 },
145 ],
146 )
147 .await
148 .expect("Could not insert multiple entities");
149 let entries = executor
150 .fetch(
151 QueryBuilder::new()
152 .select(cols!(*))
153 .from(Entry::table())
154 .where_expr(expr!(id == 1))
155 .order_by(cols!(Entry::another_enum ASC))
156 .build(&executor.driver()),
157 )
158 .map_ok(Entry::from_row)
159 .map(Result::flatten)
160 .try_collect::<Vec<_>>()
161 .await
162 .expect("Could not query multiple entities");
163 assert_eq!(
164 entries,
165 [
166 Entry {
167 id: 1,
168 some_enum: None,
169 another_enum: AnotherEnum::Bravo,
170 },
171 Entry {
172 id: 1,
173 some_enum: Some(SomeEnum::SecondValue),
174 another_enum: AnotherEnum::Charlie,
175 },
176 Entry {
177 id: 1,
178 some_enum: None,
179 another_enum: AnotherEnum::Delta,
180 },
181 ]
182 );
183}