Skip to main content

example_axum/
example_axum.rs

1use 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    //  test count
70    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    // test pagination
82    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    // println!("{user:?}");
89
90    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    // println!("{user:?}");
98
99    let page_info = user_query.adapter_render().count_page(1, &pool).await?;
100    assert_eq!(PageInfo::new(2, 1), page_info);
101    // println!("{page_info:?}");
102    //fecth
103    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    //println!("{:?}", rows.len());
114    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    // fetch_as
131    let users: Vec<User> = user_query.adapter_render().fetch_all_as(&pool).await?;
132    assert_eq!(data, users);
133    //println!("{:?}", users);
134
135    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    // stream
153    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    //  test count
172    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}