Skip to content

Commit 3fc3d79

Browse files
committed
Added locking clause for postgres-only
1 parent 43f90a7 commit 3fc3d79

2 files changed

Lines changed: 76 additions & 5 deletions

File tree

src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,17 @@ impl DBImpl {
299299
) -> Select<'until_build, 'post_build> {
300300
Select {
301301
db_impl: *self,
302-
join_tables: joins,
303302
resulting_columns: columns,
303+
from_clause,
304+
join_tables: joins,
305+
order_by_clause,
306+
304307
limit: None,
305308
offset: None,
306-
from_clause,
307309
where_clause: None,
308310
distinct: false,
309-
order_by_clause,
311+
#[cfg(feature = "postgres-only")]
312+
locking_clause: None,
310313
}
311314
}
312315

src/select.rs

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,54 @@ pub struct Select<'until_build, 'post_query> {
1717
pub(crate) resulting_columns: &'until_build [SelectColumnImpl<'until_build>],
1818
pub(crate) from_clause: &'until_build str,
1919
pub(crate) join_tables: &'until_build [JoinTableImpl<'until_build, 'post_query>],
20-
pub(crate) where_clause: Option<&'until_build Condition<'post_query>>,
20+
pub(crate) order_by_clause: &'until_build [OrderByEntry<'until_build>],
2121

2222
// Set by builder
23-
pub(crate) order_by_clause: &'until_build [OrderByEntry<'until_build>],
23+
pub(crate) where_clause: Option<&'until_build Condition<'post_query>>,
2424
pub(crate) distinct: bool,
2525
pub(crate) limit: Option<u64>,
2626
pub(crate) offset: Option<u64>,
27+
28+
#[cfg(feature = "postgres-only")]
29+
pub(crate) locking_clause: Option<LockingClause>,
30+
}
31+
32+
/// A `SELECT` statement's locking clause
33+
#[cfg(feature = "postgres-only")]
34+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
35+
pub struct LockingClause {
36+
/// Strength of the row lock
37+
pub strength: LockStrength,
38+
39+
/// How to acquire the row lock
40+
pub acquire: LockAcquire,
41+
}
42+
43+
#[cfg(feature = "postgres-only")]
44+
/// Strength of a `SELECT` statement's row lock
45+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
46+
pub enum LockStrength {
47+
/// `SELECT ... FOR UPDATE;`
48+
Update,
49+
/// `SELECT ... FOR NO KEY UPDATE;`
50+
NoKeyUpdate,
51+
/// `SELECT ... FOR SHARE;`
52+
Share,
53+
/// `SELECT ... FOR KEY SHARE;`
54+
KeyShare,
55+
}
56+
57+
#[cfg(feature = "postgres-only")]
58+
/// How to acquire a `SELECT` statement's row lock
59+
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
60+
pub enum LockAcquire {
61+
/// `SELECT ... FOR <strength>;`
62+
#[default]
63+
Wait,
64+
/// `SELECT ... FOR <strength> NOWAIT;`
65+
NoWait,
66+
/// `SELECT ... FOR <strength> SKIP LOCKED;`
67+
SkipLocked,
2768
}
2869

2970
impl<'until_build, 'post_build> Select<'until_build, 'post_build> {
@@ -46,6 +87,13 @@ impl<'until_build, 'post_build> Select<'until_build, 'post_build> {
4687
self
4788
}
4889

90+
/// Set a lock on the resulting rows
91+
#[cfg(feature = "postgres-only")]
92+
pub fn locking_clause(mut self, locking: LockingClause) -> Self {
93+
self.locking_clause = Some(locking);
94+
self
95+
}
96+
4997
/// Build the select query
5098
pub fn build(self) -> (String, Vec<Value<'post_build>>) {
5199
let mut sql;
@@ -166,6 +214,26 @@ impl<'until_build, 'post_build> Select<'until_build, 'post_build> {
166214
}
167215
};
168216

217+
#[cfg(feature = "postgres-only")]
218+
if let Some(locking) = self.locking_clause {
219+
write!(
220+
sql,
221+
" FOR {}{}",
222+
match locking.strength {
223+
LockStrength::Update => "UPDATE",
224+
LockStrength::NoKeyUpdate => "NO KEY UPDATE",
225+
LockStrength::Share => "SHARE",
226+
LockStrength::KeyShare => "KEY SHARE",
227+
},
228+
match locking.acquire {
229+
LockAcquire::Wait => "",
230+
LockAcquire::NoWait => " NOWAIT",
231+
LockAcquire::SkipLocked => " SKIP LOCKED",
232+
}
233+
)
234+
.unwrap();
235+
}
236+
169237
write!(sql, ";").unwrap();
170238
}
171239
}

0 commit comments

Comments
 (0)