keelson_psql/statement/
table.rs1use keelson_core::clause::{
2 Combines, Fetch, HasCombines, HasFetch, HasLimit, HasLocks, HasOffset, HasOrderBy, HasTableRef,
3 HasWith, Limit, Locks, Offset, OrderBy, TableRef, With,
4};
5use keelson_core::expr::{Expr, IntoExpr, IntoExprList};
6use keelson_core::{Dialect, Error, Expression, Mod, Query, QueryExtensions, QueryType, SqlWriter};
7
8use crate::Psql;
9
10#[derive(Debug, Clone, Default)]
24pub struct TableQuery {
25 pub with: With,
27 pub table: TableRef,
30 pub order_by: OrderBy,
32 pub limit: Limit,
34 pub offset: Offset,
36 pub fetch: Fetch,
38 pub locks: Locks,
40 pub combines: Combines,
42}
43
44impl TableQuery {
45 pub fn new() -> TableQuery {
47 TableQuery::default()
48 }
49
50 pub fn apply(&mut self, mods: impl Mod<TableQuery>) {
52 mods.apply(self);
53 }
54
55 fn has_tail_clauses(&self) -> bool {
59 !self.order_by.is_empty()
60 || !self.limit.is_empty()
61 || !self.offset.is_empty()
62 || !self.fetch.is_empty()
63 || !self.locks.is_empty()
64 }
65}
66
67impl Expression for TableQuery {
68 fn write_sql(&self, w: &mut SqlWriter<'_>) {
69 if !self.limit.is_empty() && !self.fetch.is_empty() {
71 w.record_error(Error::conflicting_clauses("LIMIT", "FETCH"));
72 return;
73 }
74 if self.table.is_empty() {
75 w.record_error(Error::Incomplete("the table of a TABLE statement"));
76 return;
77 }
78
79 w.write_if(!self.with.is_empty(), "", &self.with, " ");
80
81 let parens = self
82 .combines
83 .parenthesises_leading_query(self.has_tail_clauses());
84 if parens {
85 w.push_str("(");
86 }
87
88 w.push_str("TABLE ");
89 w.write_expr(&self.table);
90
91 w.write_if(!self.order_by.is_empty(), " ", &self.order_by, "");
92 w.write_if(!self.limit.is_empty(), " ", &self.limit, "");
93 w.write_if(!self.offset.is_empty(), " ", &self.offset, "");
94 w.write_if(!self.fetch.is_empty(), " ", &self.fetch, "");
95 w.write_if(!self.locks.is_empty(), " ", &self.locks, "");
96
97 if parens {
98 w.push_str(")");
99 }
100
101 w.write_if(!self.combines.is_empty(), " ", &self.combines, "");
102 }
103}
104
105impl Query for TableQuery {
106 fn query_type(&self) -> QueryType {
107 QueryType::Select
109 }
110
111 fn dialect(&self) -> &dyn Dialect {
112 &Psql
113 }
114}
115
116impl<H, L, M> QueryExtensions<H, L, M> for TableQuery {}
117
118impl IntoExpr for TableQuery {
119 fn into_expr(self) -> Expr {
120 crate::query(self)
121 }
122}
123
124impl IntoExprList for TableQuery {
125 fn into_expr_list(self) -> Vec<Expr> {
126 vec![self.into_expr()]
127 }
128}
129
130impl HasWith for TableQuery {
131 fn with_mut(&mut self) -> &mut With {
132 &mut self.with
133 }
134}
135
136impl HasTableRef for TableQuery {
137 fn table_ref_mut(&mut self) -> &mut TableRef {
138 &mut self.table
139 }
140}
141
142impl HasOrderBy for TableQuery {
143 fn order_by_mut(&mut self) -> &mut OrderBy {
144 &mut self.order_by
145 }
146}
147
148impl HasLimit for TableQuery {
149 fn limit_mut(&mut self) -> &mut Limit {
150 &mut self.limit
151 }
152}
153
154impl HasOffset for TableQuery {
155 fn offset_mut(&mut self) -> &mut Offset {
156 &mut self.offset
157 }
158}
159
160impl HasFetch for TableQuery {
161 fn fetch_mut(&mut self) -> &mut Fetch {
162 &mut self.fetch
163 }
164}
165
166impl HasLocks for TableQuery {
167 fn locks_mut(&mut self) -> &mut Locks {
168 &mut self.locks
169 }
170}
171
172impl HasCombines for TableQuery {
173 fn combines_mut(&mut self) -> &mut Combines {
174 &mut self.combines
175 }
176}