Skip to content

Commit 3771d9a

Browse files
committed
implement #17
1 parent 277eb0d commit 3771d9a

File tree

7 files changed

+60
-12
lines changed

7 files changed

+60
-12
lines changed

example-postgres/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ async fn main() -> anyhow::Result<()> {
5555

5656
log::info!("use the improved query macro for searching users");
5757
let search_result = query2::query_users(&db, Some("NewFirstName"), None).await?;
58-
println!("{:?}", search_result);
58+
log::info!("search result: {:?}", search_result);
59+
60+
log::info!("load all users in the order specified by the 'order_by' attribute");
61+
let all = User::all_paginated(&db, 0, 100).await?;
62+
log::info!("all users: {all:?}");
5963

6064
log::info!("delete the user from the database");
6165
new.delete(&db).await?;
@@ -64,7 +68,7 @@ async fn main() -> anyhow::Result<()> {
6468
}
6569

6670
#[derive(Debug, ormx::Table)]
67-
#[ormx(table = "users", id = user_id, insertable, deletable)]
71+
#[ormx(table = "users", id = user_id, insertable, deletable, order_by = "email ASC")]
6872
struct User {
6973
// map this field to the column "id"
7074
#[ormx(column = "id")]

ormx-macros/src/attrs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub enum TableAttr {
1313
Insertable(Option<Insertable>),
1414
// deletable
1515
Deletable(()),
16+
// order_by = <string>
17+
OrderBy(String),
1618
}
1719

1820
pub struct Insertable {
@@ -144,7 +146,8 @@ impl_parse!(TableAttr {
144146
"table" => Table(= String),
145147
"id" => Id(= Ident),
146148
"insertable" => Insertable((= Insertable)?),
147-
"deletable" => Deletable()
149+
"deletable" => Deletable(),
150+
"order_by" => OrderBy(= String)
148151
});
149152

150153
impl_parse!(TableFieldAttr {

ormx-macros/src/backend/common/table.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,15 @@ fn update<B: Backend>(table: &Table<B>) -> TokenStream {
101101

102102
fn stream_all<B: Backend>(table: &Table<B>, column_list: &str) -> TokenStream {
103103
let return_type = crate::utils::stream!(sqlx::Result<Self>);
104-
let all_sql = format!("SELECT {} FROM {}", column_list, table.name());
104+
let order_by = match &table.order_by {
105+
None => &format!("{} DESC", table.id.column()),
106+
Some(by) => by,
107+
};
108+
let all_sql = format!(
109+
"SELECT {} FROM {} ORDER BY {order_by}",
110+
column_list,
111+
table.name()
112+
);
105113

106114
quote! {
107115
fn stream_all<'a, 'c: 'a>(
@@ -116,8 +124,12 @@ fn stream_all<B: Backend>(table: &Table<B>, column_list: &str) -> TokenStream {
116124
fn stream_all_paginated<B: Backend>(table: &Table<B>, column_list: &str) -> TokenStream {
117125
let return_type = crate::utils::stream!(sqlx::Result<Self>);
118126
let mut bindings = B::Bindings::default();
127+
let order_by = match &table.order_by {
128+
None => &format!("{} DESC", table.id.column()),
129+
Some(by) => by,
130+
};
119131
let all_sql = format!(
120-
"SELECT {} FROM {} LIMIT {} OFFSET {}",
132+
"SELECT {} FROM {} ORDER BY {order_by} LIMIT {} OFFSET {} ",
121133
column_list,
122134
table.name(),
123135
bindings.next().unwrap(),

ormx-macros/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
#![cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite", feature = "mariadb"))]
1+
#![cfg(any(
2+
feature = "mysql",
3+
feature = "postgres",
4+
feature = "sqlite",
5+
feature = "mariadb"
6+
))]
27

38
mod attrs;
49
mod backend;

ormx-macros/src/table/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub struct Table<B: Backend> {
2020
pub fields: Vec<TableField<B>>,
2121
pub insertable: Option<Insertable>,
2222
pub deletable: bool,
23+
pub order_by: Option<String>,
2324
}
2425

2526
#[derive(Clone)]
@@ -70,7 +71,12 @@ impl<B: Backend> TableField<B> {
7071
let q = B::QUOTE;
7172

7273
if self.custom_type {
73-
format!("{q}{}{q} AS {q}{}: {}{q}", self.column_name, self.field.to_string(), self.ty.to_token_stream())
74+
format!(
75+
"{q}{}{q} AS {q}{}: {}{q}",
76+
self.column_name,
77+
self.field.to_string(),
78+
self.ty.to_token_stream()
79+
)
7480
} else if self.field == self.column_name {
7581
self.column()
7682
} else {

ormx-macros/src/table/parse.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::{convert::TryFrom, marker::PhantomData};
22

33
use proc_macro2::Span;
4-
use syn::{Data, DeriveInput, Error, Ident, Result};
5-
use syn::ext::IdentExt;
4+
use syn::{ext::IdentExt, Data, DeriveInput, Error, Ident, Result};
5+
66
use super::{Table, TableField};
77
use crate::{
88
attrs::{parse_attrs, Insertable, TableAttr, TableFieldAttr},
@@ -40,7 +40,8 @@ impl<B: Backend> TryFrom<&syn::Field> for TableField<B> {
4040
TableFieldAttr::GetOptional(g) => set_once(&mut get_optional, g)?,
4141
TableFieldAttr::GetMany(g) => set_once(&mut get_many, g)?,
4242
TableFieldAttr::Set(s) => {
43-
let default = || Ident::new(&format!("set_{}", ident.unraw()), Span::call_site());
43+
let default =
44+
|| Ident::new(&format!("set_{}", ident.unraw()), Span::call_site());
4445
set_once(&mut set, s.unwrap_or_else(default))?
4546
}
4647
TableFieldAttr::Default(..) => set_once(&mut default, true)?,
@@ -80,7 +81,7 @@ impl<B: Backend> TryFrom<&DeriveInput> for Table<B> {
8081
.map(TableField::try_from)
8182
.collect::<Result<Vec<_>>>()?;
8283

83-
none!(table, id, insertable, deletable);
84+
none!(table, id, insertable, deletable, order_by);
8485
for attr in parse_attrs::<TableAttr>(&value.attrs)? {
8586
match attr {
8687
TableAttr::Table(x) => set_once(&mut table, x)?,
@@ -93,6 +94,7 @@ impl<B: Backend> TryFrom<&DeriveInput> for Table<B> {
9394
set_once(&mut insertable, x.unwrap_or_else(default))?;
9495
}
9596
TableAttr::Deletable(_) => set_once(&mut deletable, true)?,
97+
TableAttr::OrderBy(by) => set_once(&mut order_by, by)?,
9698
}
9799
}
98100

@@ -123,6 +125,7 @@ impl<B: Backend> TryFrom<&DeriveInput> for Table<B> {
123125
insertable,
124126
fields,
125127
deletable: deletable.unwrap_or(false),
128+
order_by,
126129
})
127130
}
128131
}

ormx/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
#![cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite", feature = "mariadb"))]
1+
#![cfg(any(
2+
feature = "mysql",
3+
feature = "postgres",
4+
feature = "sqlite",
5+
feature = "mariadb"
6+
))]
27
//! Lightweight derive macros for bringing orm-like features to sqlx.
38
//!
49
//! # Example: Table
@@ -80,23 +85,33 @@ where
8085
) -> impl Future<Output = Result<Self>> + Send + 'a;
8186

8287
/// Stream all rows from this table.
88+
/// By default, results are ordered in descending order according to their ID column.
89+
/// This can be configured using `#[ormx(order_by = "some_column ASC")]`.
8390
fn stream_all<'a, 'c: 'a>(
8491
db: impl Executor<'c, Database = Db> + 'a,
8592
) -> impl Stream<Item = Result<Self>> + Send + 'a;
8693

94+
/// Streams at most `limit` rows from this table, skipping the first `offset` rows.
95+
/// By default, results are ordered in descending order according to their ID column.
96+
/// This can be configured using `#[ormx(order_by = "some_column ASC")]`.
8797
fn stream_all_paginated<'a, 'c: 'a>(
8898
db: impl Executor<'c, Database = Db> + 'a,
8999
offset: i64,
90100
limit: i64,
91101
) -> impl Stream<Item = Result<Self>> + Send + 'a;
92102

93103
/// Load all rows from this table.
104+
/// By default, results are ordered in descending order according to their ID column.
105+
/// This can be configured using `#[ormx(order_by = "some_column ASC")]`.
94106
fn all<'a, 'c: 'a>(
95107
db: impl Executor<'c, Database = Db> + 'a,
96108
) -> impl Future<Output = Result<Vec<Self>>> + Send + 'a {
97109
Self::stream_all(db).try_collect()
98110
}
99111

112+
/// Load at most `limit` rows from this table, skipping the first `offset`.
113+
/// By default, results are ordered in descending order according to their ID column.
114+
/// This can be configured using `#[ormx(order_by = "some_column ASC")]`.
100115
fn all_paginated<'a, 'c: 'a>(
101116
db: impl Executor<'c, Database = Db> + 'a,
102117
offset: i64,

0 commit comments

Comments
 (0)