example_axum/
example_axum.rs1use askama::Template;
2use axum::Router;
3use axum::extract::State;
4use axum::response::Html;
5use axum::routing::get;
6
7use futures_util::{TryStreamExt, pin_mut};
8use sqlx::any::install_default_drivers;
9use sqlx::{AnyPool, Error, Row};
10use sqlx_askama_template::{PageInfo, SqlTemplate};
11
12#[derive(sqlx::prelude::FromRow, PartialEq, Eq, Debug, serde::Serialize)]
13struct User {
14 id: i64,
15 name: String,
16}
17#[derive(SqlTemplate)]
18#[template(source = r#"
19 select {{e(user_id)}} as id,{{e(user_name)}} as name
20 union all
21 {%- let id=99999_i64 %}
22 {%- let name="super man" %}
23 select {{et(id)}} as id,{{et(name)}} as name
24"#)]
25pub struct UserQuery<'a> {
26 pub user_id: i64,
27 pub user_name: &'a str,
28}
29#[derive(askama::Template)]
30#[template(
31 ext = "html",
32 source = r#"
33 <html>
34 <head>
35 <title>SQLx Askama Template</title>
36 </head>
37 <body>
38 <h1>SQLx Askama Template</h1>
39 <p>Welcome to the SQLx Askama Template!</p>
40 <h1>query database with askama template</h1>
41 <table border="1">
42 <tr>
43 <th>id</th>
44 <th>name</th>
45 </tr>
46 {% for user in users %}
47 <tr>
48 <td>{{ user.id }}</td>
49 <td>{{ user.name }}</td>
50 </tr>
51 {% endfor %}
52 </body>
53</html>"#
54)]
55struct IndexHtml {
56 users: Vec<User>,
57}
58async fn test_adapter_query(url: &str) -> Result<(), Error> {
59 let data = vec![
60 User {
61 id: 1,
62 name: "admin".to_string(),
63 },
64 User {
65 id: 99999,
66 name: "super man".to_string(),
67 },
68 ];
69 let user_query = UserQuery {
71 user_id: 1,
72 user_name: "admin",
73 };
74 let pool = AnyPool::connect(url).await?;
75
76 let mut db_adatper = user_query.adapter_render();
77
78 let count = db_adatper.count(&pool).await?;
79 assert_eq!(2, count);
80
81 let user: Option<User> = user_query
83 .adapter_render()
84 .set_page(1, 1)
85 .fetch_optional_as(&pool)
86 .await?;
87 assert_eq!(data.first(), user.as_ref());
88 let mut conn = pool.acquire().await?;
91 let user: Vec<User> = user_query
92 .adapter_render()
93 .set_page(1, 2)
94 .fetch_all_as(&mut *conn)
95 .await?;
96 assert_eq!(data[1..], user);
97 let page_info = user_query.adapter_render().count_page(1, &pool).await?;
100 assert_eq!(PageInfo::new(2, 1), page_info);
101 let mut tx = pool.begin().await?;
104
105 let rows = UserQuery {
106 user_id: 1,
107 user_name: "admin",
108 }
109 .adapter_render()
110 .fetch_all(&mut *tx)
111 .await?;
112 assert_eq!(2, rows.len());
113 let row = UserQuery {
115 user_id: 1,
116 user_name: "admin",
117 }
118 .adapter_render()
119 .fetch_optional(&mut *tx)
120 .await?;
121 assert!(row.is_some());
122 let row = UserQuery {
123 user_id: 1,
124 user_name: "admin",
125 }
126 .adapter_render()
127 .fetch_one(&mut *tx)
128 .await?;
129 assert_eq!(2, row.columns().len());
130 let users: Vec<User> = user_query.adapter_render().fetch_all_as(&pool).await?;
132 assert_eq!(data, users);
133 let u: Option<User> = UserQuery {
136 user_id: 1,
137 user_name: "admin",
138 }
139 .adapter_render()
140 .fetch_optional_as(&mut *tx)
141 .await?;
142 assert_eq!(data.first(), u.as_ref());
143 let u: User = UserQuery {
144 user_id: 1,
145 user_name: "admin",
146 }
147 .adapter_render()
148 .fetch_one_as(&mut *tx)
149 .await?;
150 assert_eq!(data.first(), Some(&u));
151
152 let mut query = user_query.adapter_render();
154 {
155 let stream = query.fetch(&mut *tx);
156 pin_mut!(stream);
157 while let Some(row) = stream.try_next().await? {
158 assert_eq!(2, row.columns().len());
159 }
160 }
161
162 tx.rollback().await?;
163
164 Ok(())
165}
166#[axum::debug_handler]
167async fn root(State(pool): State<AnyPool>) -> impl axum::response::IntoResponse {
168 test_adapter_query("sqlite://db.file?mode=memory")
169 .await
170 .unwrap();
171 let user_query = UserQuery {
173 user_id: 1,
174 user_name: "axum",
175 };
176 let count = user_query.adapter_render().count(&pool).await.unwrap();
177 println!("count: {count}");
178
179 let mut conn = pool.acquire().await.unwrap();
180 let rows = user_query
181 .adapter_render()
182 .fetch_all_as(&mut *conn)
183 .await
184 .unwrap();
185 Html(IndexHtml { users: rows }.render().unwrap())
186}
187#[tokio::main]
188async fn main() {
189 install_default_drivers();
190
191 let pool = AnyPool::connect("sqlite://db.file?mode=memory")
192 .await
193 .unwrap();
194 let app = Router::new().route("/", get(root)).with_state(pool);
195
196 let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
197 axum::serve(listener, app).await.unwrap();
198}