1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
//! Static constructor methods for Qail.
//!
//! Methods like get(), set(), add(), del(), make(), etc.
use crate::ast::{Action, Qail};
impl Qail {
/// SELECT — query rows.
pub fn get(table: impl Into<String>) -> Self {
Self {
action: Action::Get,
table: table.into(),
..Default::default()
}
}
/// UPDATE — modify rows.
pub fn set(table: impl Into<String>) -> Self {
Self {
action: Action::Set,
table: table.into(),
..Default::default()
}
}
/// DELETE — remove rows.
pub fn del(table: impl Into<String>) -> Self {
Self {
action: Action::Del,
table: table.into(),
..Default::default()
}
}
/// INSERT — add rows.
pub fn add(table: impl Into<String>) -> Self {
Self {
action: Action::Add,
table: table.into(),
..Default::default()
}
}
/// UPSERT — insert or update.
pub fn put(table: impl Into<String>) -> Self {
Self {
action: Action::Put,
table: table.into(),
..Default::default()
}
}
/// COPY … TO — export data.
pub fn export(table: impl Into<String>) -> Self {
Self {
action: Action::Export,
table: table.into(),
..Default::default()
}
}
/// CREATE TABLE.
pub fn make(table: impl Into<String>) -> Self {
Self {
action: Action::Make,
table: table.into(),
..Default::default()
}
}
/// TRUNCATE — empty a table.
pub fn truncate(table: impl Into<String>) -> Self {
Self {
action: Action::Truncate,
table: table.into(),
..Default::default()
}
}
/// EXPLAIN — show query plan.
pub fn explain(table: impl Into<String>) -> Self {
Self {
action: Action::Explain,
table: table.into(),
..Default::default()
}
}
/// EXPLAIN ANALYZE — show query plan with execution stats.
pub fn explain_analyze(table: impl Into<String>) -> Self {
Self {
action: Action::ExplainAnalyze,
table: table.into(),
..Default::default()
}
}
/// LOCK TABLE.
pub fn lock(table: impl Into<String>) -> Self {
Self {
action: Action::Lock,
table: table.into(),
..Default::default()
}
}
/// CREATE MATERIALIZED VIEW.
pub fn create_materialized_view(name: impl Into<String>, query: Qail) -> Self {
Self {
action: Action::CreateMaterializedView,
table: name.into(),
source_query: Some(Box::new(query)),
..Default::default()
}
}
/// REFRESH MATERIALIZED VIEW.
pub fn refresh_materialized_view(name: impl Into<String>) -> Self {
Self {
action: Action::RefreshMaterializedView,
table: name.into(),
..Default::default()
}
}
/// DROP MATERIALIZED VIEW.
pub fn drop_materialized_view(name: impl Into<String>) -> Self {
Self {
action: Action::DropMaterializedView,
table: name.into(),
..Default::default()
}
}
// PostgreSQL Pub/Sub (LISTEN/NOTIFY)
/// Create a LISTEN command to subscribe to a channel.
///
/// # Example
/// ```ignore
/// let cmd = Qail::listen("orders");
/// // Generates: LISTEN orders
/// ```
pub fn listen(channel: impl Into<String>) -> Self {
Self {
action: Action::Listen,
channel: Some(channel.into()),
..Default::default()
}
}
/// Create an UNLISTEN command to unsubscribe from a channel.
///
/// # Example
/// ```ignore
/// let cmd = Qail::unlisten("orders");
/// // Generates: UNLISTEN orders
/// ```
pub fn unlisten(channel: impl Into<String>) -> Self {
Self {
action: Action::Unlisten,
channel: Some(channel.into()),
..Default::default()
}
}
/// Create a NOTIFY command to send a message to a channel.
///
/// # Example
/// ```ignore
/// let cmd = Qail::notify("orders", "new_order:123");
/// // Generates: NOTIFY orders, 'new_order:123'
/// ```
pub fn notify(channel: impl Into<String>, payload: impl Into<String>) -> Self {
Self {
action: Action::Notify,
channel: Some(channel.into()),
payload: Some(payload.into()),
..Default::default()
}
}
// PostgreSQL Procedural Commands
/// Create a CALL command to invoke a stored procedure.
///
/// # Example
/// ```ignore
/// let cmd = Qail::call("refresh_materialized_views()");
/// // Generates: CALL refresh_materialized_views()
/// ```
pub fn call(procedure: impl Into<String>) -> Self {
Self {
action: Action::Call,
table: procedure.into(),
..Default::default()
}
}
/// Create a DO command to execute an anonymous code block.
///
/// # Example
/// ```ignore
/// let cmd = Qail::do_block("BEGIN RAISE NOTICE 'hello'; END;", "plpgsql");
/// // Generates: DO $$ BEGIN RAISE NOTICE 'hello'; END; $$ LANGUAGE plpgsql
/// ```
pub fn do_block(body: impl Into<String>, language: impl Into<String>) -> Self {
Self {
action: Action::Do,
payload: Some(body.into()),
table: language.into(),
..Default::default()
}
}
// PostgreSQL Session Commands
/// Create a SET command for session variables.
///
/// # Example
/// ```ignore
/// let cmd = Qail::session_set("statement_timeout", "5000");
/// // Generates: SET statement_timeout = '5000'
/// ```
pub fn session_set(key: impl Into<String>, value: impl Into<String>) -> Self {
Self {
action: Action::SessionSet,
table: key.into(),
payload: Some(value.into()),
..Default::default()
}
}
/// Create a SHOW command to inspect a session variable.
///
/// # Example
/// ```ignore
/// let cmd = Qail::session_show("statement_timeout");
/// // Generates: SHOW statement_timeout
/// ```
pub fn session_show(key: impl Into<String>) -> Self {
Self {
action: Action::SessionShow,
table: key.into(),
..Default::default()
}
}
/// Create a RESET command to restore a session variable to default.
///
/// # Example
/// ```ignore
/// let cmd = Qail::session_reset("statement_timeout");
/// // Generates: RESET statement_timeout
/// ```
pub fn session_reset(key: impl Into<String>) -> Self {
Self {
action: Action::SessionReset,
table: key.into(),
..Default::default()
}
}
/// Create a CREATE DATABASE command.
pub fn create_database(name: impl Into<String>) -> Self {
Self {
action: Action::CreateDatabase,
table: name.into(),
..Default::default()
}
}
/// Create a DROP DATABASE command.
pub fn drop_database(name: impl Into<String>) -> Self {
Self {
action: Action::DropDatabase,
table: name.into(),
..Default::default()
}
}
}