Skip to main content

keelson_sqlite/
select.rs

1//! Mods for [`sqlite::select`](crate::select()).
2//!
3//! Everything a SQLite `SELECT` can carry, and nothing else. There is no
4//! `returning` here, no `fetch`, no `for_update`, no `distinct_on`, no
5//! `group_by_distinct` and no `_combined` variant of anything — SQLite's grammar
6//! has none of them, and a mod for a construct a dialect lacks should not exist.
7//!
8//! ```
9//! use keelson_sqlite as sqlite;
10//! use keelson_sqlite::{Chain, arg, quote, select};
11//!
12//! let q = sqlite::select((
13//!     select::columns((quote("id"), quote("name"))),
14//!     select::from(quote("users")),
15//!     select::where_(quote("age").gte(arg(21i32))),
16//!     select::order_by(quote("name")).desc().nulls_last(),
17//!     select::limit(10),
18//!     select::offset(20),
19//! ));
20//! ```
21//!
22//! # `LIMIT` and `OFFSET` are one clause
23//!
24//! SQLite's production is `LIMIT expr [ ( OFFSET | , ) expr ]`, so [`offset`]
25//! without [`limit`] is not a statement. Building one records
26//! [`Error::Incomplete`](keelson_core::Error::Incomplete) rather than handing back
27//! SQL the database will reject.
28//!
29//! # `VALUES` is a `SELECT`
30//!
31//! [`values`] and [`rows`] fill the other alternative of SQLite's `select-core`, so
32//! `sqlite::select(select::rows([[1, 2], [3, 4]]))` is the statement
33//! `VALUES (1, 2), (3, 4)`. Compounding a `VALUES` core onto a `SELECT` one — and
34//! the reverse — is legal and is how a recursive CTE's seed row is usually written.
35
36use keelson_core::{Mod, mod_fn};
37
38use crate::statement::SelectQuery;
39
40pub use crate::shared::{
41    columns, cross_join, except, extra_from_item as from_also, from_item as from, full_join,
42    group_by, having, inner_join, intersect, left_join, limit, offset, order_by, preload_columns,
43    recursive, right_join, rows, union, union_all, values, where_, window, with,
44};
45
46/// `SELECT DISTINCT` — drop duplicate result rows.
47///
48/// `ALL` is the other alternative in the grammar and is the default; writing it adds
49/// nothing, so it is not representable.
50pub fn distinct() -> impl Mod<SelectQuery> {
51    mod_fn(|q: &mut SelectQuery| q.distinct = true)
52}