1use crate::{
2 keywords::*,
3 Alpha,
4 Brackets,
5 Caching,
6 ColumnOrder,
7 Compaction,
8 CompactionType,
9 Compression,
10 CqlType,
11 CustomToTokens,
12 If,
13 KeyspaceQualifiedName,
14 List,
15 LitStr,
16 MapLiteral,
17 Name,
18 Nothing,
19 Parens,
20 Parse,
21 Relation,
22 Replication,
23 SetLiteral,
24 SpeculativeRetry,
25 StatementStream,
26 TableOpts,
27 Tag,
28 TaggedKeyspaceQualifiedName,
29 TaggedReplication,
30 TaggedStatementOpt,
31 TaggedStatementOptValue,
32 Term,
33 TokenWrapper,
34};
35use derive_builder::Builder;
36use derive_more::{
37 From,
38 TryInto,
39};
40use scylladb_parse_macros::{
41 ParseFromStr,
42 ToTokens,
43};
44use std::{
45 convert::{
46 TryFrom,
47 TryInto,
48 },
49 fmt::{
50 Display,
51 Formatter,
52 },
53 str::FromStr,
54};
55
56mod ddl;
57pub use ddl::*;
58
59mod dml;
60pub use dml::*;
61
62mod index;
63pub use index::*;
64
65mod views;
66pub use views::*;
67
68mod function;
69pub use function::*;
70
71mod security;
72pub use security::*;
73
74mod trigger;
75pub use trigger::*;
76
77#[derive(ParseFromStr, Clone, Debug, TryInto, From, ToTokens, PartialEq)]
78#[parse_via(TaggedStatement)]
79pub enum Statement {
80 DataDefinition(DataDefinitionStatement),
81 DataManipulation(DataManipulationStatement),
82 SecondaryIndex(SecondaryIndexStatement),
83 MaterializedView(MaterializedViewStatement),
84 Role(RoleStatement),
85 Permission(PermissionStatement),
86 User(UserStatement),
87 UserDefinedFunction(UserDefinedFunctionStatement),
88 UserDefinedType(UserDefinedTypeStatement),
89 Trigger(TriggerStatement),
90}
91
92impl TryFrom<TaggedStatement> for Statement {
93 type Error = anyhow::Error;
94 fn try_from(value: TaggedStatement) -> Result<Self, Self::Error> {
95 Ok(match value {
96 TaggedStatement::DataDefinition(value) => Statement::DataDefinition(value.try_into()?),
97 TaggedStatement::DataManipulation(value) => Statement::DataManipulation(value.try_into()?),
98 TaggedStatement::SecondaryIndex(value) => Statement::SecondaryIndex(value.try_into()?),
99 TaggedStatement::MaterializedView(value) => Statement::MaterializedView(value.try_into()?),
100 TaggedStatement::Role(value) => Statement::Role(value.try_into()?),
101 TaggedStatement::Permission(value) => Statement::Permission(value.try_into()?),
102 TaggedStatement::User(value) => Statement::User(value.try_into()?),
103 TaggedStatement::UserDefinedFunction(value) => Statement::UserDefinedFunction(value.try_into()?),
104 TaggedStatement::UserDefinedType(value) => Statement::UserDefinedType(value.try_into()?),
105 TaggedStatement::Trigger(value) => Statement::Trigger(value.try_into()?),
106 })
107 }
108}
109
110macro_rules! impl_try_into_statements {
111 ($($via:ty => {$($stmt:ty),*}),*) => {
112 $($(
113 impl std::convert::TryInto<$stmt> for Statement {
114 type Error = anyhow::Error;
115
116 fn try_into(self) -> Result<$stmt, Self::Error> {
117 match <$via>::try_from(self) {
118 Ok(v) => v.try_into().map_err(|e: &str| anyhow::anyhow!(e)),
119 Err(err) => Err(anyhow::anyhow!(
120 "Could not convert Statement to {}: {}",
121 std::any::type_name::<$stmt>(),
122 err
123 )),
124 }
125 }
126 }
127
128 impl From<$stmt> for Statement {
129 fn from(v: $stmt) -> Self {
130 <$via>::from(v).into()
131 }
132 }
133 )*)*
134 };
135}
136
137impl_try_into_statements!(
138 DataDefinitionStatement => {UseStatement, CreateKeyspaceStatement, AlterKeyspaceStatement, DropKeyspaceStatement, CreateTableStatement, AlterTableStatement, DropTableStatement, TruncateStatement},
139 DataManipulationStatement => {InsertStatement, UpdateStatement, DeleteStatement, SelectStatement, BatchStatement},
140 SecondaryIndexStatement => {CreateIndexStatement, DropIndexStatement},
141 MaterializedViewStatement => {CreateMaterializedViewStatement, AlterMaterializedViewStatement, DropMaterializedViewStatement},
142 RoleStatement => {CreateRoleStatement, AlterRoleStatement, DropRoleStatement, GrantRoleStatement, RevokeRoleStatement, ListRolesStatement},
143 PermissionStatement => {GrantPermissionStatement, RevokePermissionStatement, ListPermissionsStatement},
144 UserStatement => {CreateUserStatement, AlterUserStatement, DropUserStatement, ListUsersStatement},
145 UserDefinedFunctionStatement => {CreateFunctionStatement, DropFunctionStatement, CreateAggregateFunctionStatement, DropAggregateFunctionStatement},
146 UserDefinedTypeStatement => {CreateUserDefinedTypeStatement, AlterUserDefinedTypeStatement, DropUserDefinedTypeStatement},
147 TriggerStatement => {CreateTriggerStatement, DropTriggerStatement}
148);
149
150#[derive(ParseFromStr, Clone, Debug, TryInto, From, ToTokens, PartialEq)]
151#[tokenize_as(Statement)]
152
153pub enum TaggedStatement {
154 DataDefinition(TaggedDataDefinitionStatement),
155 DataManipulation(TaggedDataManipulationStatement),
156 SecondaryIndex(TaggedSecondaryIndexStatement),
157 MaterializedView(TaggedMaterializedViewStatement),
158 Role(TaggedRoleStatement),
159 Permission(TaggedPermissionStatement),
160 User(TaggedUserStatement),
161 UserDefinedFunction(TaggedUserDefinedFunctionStatement),
162 UserDefinedType(TaggedUserDefinedTypeStatement),
163 Trigger(TaggedTriggerStatement),
164}
165
166macro_rules! impl_try_into_tagged_statements {
167 ($($via:ty => {$($stmt:ty),*}),*) => {
168 $($(
169 impl std::convert::TryInto<$stmt> for TaggedStatement {
170 type Error = anyhow::Error;
171
172 fn try_into(self) -> Result<$stmt, Self::Error> {
173 match <$via>::try_from(self) {
174 Ok(v) => v.try_into().map_err(|e: &str| anyhow::anyhow!(e)),
175 Err(err) => Err(anyhow::anyhow!(
176 "Could not convert Statement to {}: {}",
177 std::any::type_name::<$stmt>(),
178 err
179 )),
180 }
181 }
182 }
183
184 impl From<$stmt> for TaggedStatement {
185 fn from(v: $stmt) -> Self {
186 <$via>::from(v).into()
187 }
188 }
189 )*)*
190 };
191}
192
193impl_try_into_tagged_statements!(
194 TaggedDataDefinitionStatement => {TaggedUseStatement, TaggedCreateKeyspaceStatement, TaggedAlterKeyspaceStatement, TaggedDropKeyspaceStatement, TaggedCreateTableStatement, TaggedAlterTableStatement, TaggedDropTableStatement, TaggedTruncateStatement},
195 TaggedDataManipulationStatement => {TaggedInsertStatement, TaggedUpdateStatement, TaggedDeleteStatement, TaggedSelectStatement, TaggedBatchStatement},
196 TaggedSecondaryIndexStatement => {TaggedCreateIndexStatement, TaggedDropIndexStatement},
197 TaggedMaterializedViewStatement => {TaggedCreateMaterializedViewStatement, TaggedAlterMaterializedViewStatement, TaggedDropMaterializedViewStatement},
198 TaggedRoleStatement => {TaggedCreateRoleStatement, TaggedAlterRoleStatement, TaggedDropRoleStatement, TaggedGrantRoleStatement, TaggedRevokeRoleStatement, TaggedListRolesStatement},
199 TaggedPermissionStatement => {TaggedGrantPermissionStatement, TaggedRevokePermissionStatement, TaggedListPermissionsStatement},
200 TaggedUserStatement => {TaggedCreateUserStatement, TaggedAlterUserStatement, TaggedDropUserStatement, ListUsersStatement},
201 TaggedUserDefinedFunctionStatement => {TaggedCreateFunctionStatement, TaggedDropFunctionStatement, TaggedCreateAggregateFunctionStatement, TaggedDropAggregateFunctionStatement},
202 TaggedUserDefinedTypeStatement => {TaggedCreateUserDefinedTypeStatement, TaggedAlterUserDefinedTypeStatement, TaggedDropUserDefinedTypeStatement},
203 TaggedTriggerStatement => {TaggedCreateTriggerStatement, TaggedDropTriggerStatement}
204);
205
206impl Parse for TaggedStatement {
207 type Output = Self;
208 fn parse(s: &mut crate::StatementStream<'_>) -> anyhow::Result<Self::Output> {
209 Ok(if s.check::<(LIST, USERS)>() {
210 Self::User(s.parse()?)
211 } else if s.check::<(LIST, ROLES)>() {
212 Self::Role(s.parse()?)
213 } else if s.check::<LIST>() {
214 Self::Permission(s.parse()?)
215 } else if let Some(keyword) = s.find::<ReservedKeyword>() {
216 match keyword {
217 ReservedKeyword::USE | ReservedKeyword::TRUNCATE => Self::DataDefinition(s.parse()?),
218 ReservedKeyword::CREATE | ReservedKeyword::ALTER | ReservedKeyword::DROP => {
219 if let Some((_, keyword2)) = s.find::<(ReservedKeyword, ReservedKeyword)>() {
220 match keyword2 {
221 ReservedKeyword::KEYSPACE | ReservedKeyword::TABLE => Self::DataDefinition(s.parse()?),
222 ReservedKeyword::OR => Self::UserDefinedFunction(s.parse()?),
223 _ => anyhow::bail!("Unexpected keyword following {}: {}", keyword, keyword2),
224 }
225 } else if let Some((_, keyword2)) = s.find_from::<(ReservedKeyword, Alpha)>() {
226 match keyword2.to_uppercase().as_str() {
227 "INDEX" | "CUSTOM" => Self::SecondaryIndex(s.parse()?),
228 "MATERIALIZED" => Self::MaterializedView(s.parse()?),
229 "ROLE" => Self::Role(s.parse()?),
230 "USER" => Self::User(s.parse()?),
231 "FUNCTION" | "AGGREGATE" => Self::UserDefinedFunction(s.parse()?),
232 "TYPE" => Self::UserDefinedType(s.parse()?),
233 "TRIGGER" => Self::Trigger(s.parse()?),
234 _ => anyhow::bail!("Unexpected keyword following {}: {}", keyword, keyword2),
235 }
236 } else {
237 anyhow::bail!("Unexpected token following {}: {}", keyword, s.info())
238 }
239 }
240 ReservedKeyword::GRANT | ReservedKeyword::REVOKE => {
241 if let Some((_, keyword2)) = s.find_from::<(ReservedKeyword, Alpha)>() {
242 match keyword2.to_uppercase().as_str() {
243 "ROLE" => Self::Role(s.parse()?),
244 "PERMISSION" => Self::Permission(s.parse()?),
245 _ => anyhow::bail!("Unexpected keyword following {}: {}", keyword, keyword2),
246 }
247 } else {
248 anyhow::bail!("Unexpected token following {}: {}", keyword, s.info())
249 }
250 }
251 ReservedKeyword::SELECT
252 | ReservedKeyword::INSERT
253 | ReservedKeyword::UPDATE
254 | ReservedKeyword::DELETE
255 | ReservedKeyword::BEGIN => Self::DataManipulation(s.parse()?),
256 _ => anyhow::bail!("Expected statement, found {}", s.info()),
257 }
258 } else {
259 anyhow::bail!("Expected statement, found {}", s.info())
260 })
261 }
262}
263
264impl Display for Statement {
265 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
266 match self {
267 Self::DataDefinition(stmt) => stmt.fmt(f),
268 Self::DataManipulation(stmt) => stmt.fmt(f),
269 Self::SecondaryIndex(stmt) => stmt.fmt(f),
270 Self::MaterializedView(stmt) => stmt.fmt(f),
271 Self::Role(stmt) => stmt.fmt(f),
272 Self::Permission(stmt) => stmt.fmt(f),
273 Self::User(stmt) => stmt.fmt(f),
274 Self::UserDefinedFunction(stmt) => stmt.fmt(f),
275 Self::UserDefinedType(stmt) => stmt.fmt(f),
276 Self::Trigger(stmt) => stmt.fmt(f),
277 }
278 }
279}
280
281impl KeyspaceExt for Statement {
282 fn get_keyspace(&self) -> Option<String> {
283 match self {
284 Statement::DataManipulation(s) => s.get_keyspace(),
285 _ => None,
286 }
287 }
288
289 fn set_keyspace(&mut self, keyspace: impl Into<Name>) {
290 match self {
291 Statement::DataManipulation(s) => s.set_keyspace(keyspace),
292 _ => (),
293 }
294 }
295}
296
297#[derive(ParseFromStr, Clone, Debug, ToTokens, PartialEq, Eq)]
298pub struct FieldDefinition {
299 pub name: Name,
300 pub data_type: CqlType,
301}
302
303impl Parse for FieldDefinition {
304 type Output = Self;
305 fn parse(s: &mut StatementStream<'_>) -> anyhow::Result<Self> {
306 Ok(Self {
307 name: s.parse()?,
308 data_type: s.parse()?,
309 })
310 }
311}
312
313impl Display for FieldDefinition {
314 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
315 write!(f, "{} {}", self.name, self.data_type)
316 }
317}
318
319impl<N: Into<Name>, T: Into<CqlType>> From<(N, T)> for FieldDefinition {
320 fn from((name, data_type): (N, T)) -> Self {
321 Self {
322 name: name.into(),
323 data_type: data_type.into(),
324 }
325 }
326}
327
328pub trait KeyspaceExt {
330 fn get_keyspace(&self) -> Option<String>;
331
332 fn set_keyspace(&mut self, keyspace: impl Into<Name>);
333
334 fn with_keyspace(mut self, keyspace: impl Into<Name>) -> Self
335 where
336 Self: Sized,
337 {
338 self.set_keyspace(keyspace);
339 self
340 }
341}
342
343pub trait WhereExt {
344 fn iter_where(&self) -> Option<std::slice::Iter<Relation>>;
345}
346
347pub trait KeyspaceOptionsExt {
348 fn keyspace_opts(&self) -> &KeyspaceOpts;
349 fn keyspace_opts_mut(&mut self) -> &mut KeyspaceOpts;
350 fn set_replication(&mut self, replication: Replication) {
351 self.keyspace_opts_mut().replication = replication;
352 }
353 fn set_durable_writes(&mut self, durable_writes: bool) {
354 self.keyspace_opts_mut().durable_writes.replace(durable_writes);
355 }
356
357 fn with_replication(mut self, replication: Replication) -> Self
358 where
359 Self: Sized,
360 {
361 self.set_replication(replication);
362 self
363 }
364 fn with_durable_writes(mut self, durable_writes: bool) -> Self
365 where
366 Self: Sized,
367 {
368 self.set_durable_writes(durable_writes);
369 self
370 }
371
372 fn get_replication(&self) -> &Replication {
373 &self.keyspace_opts().replication
374 }
375 fn get_durable_writes(&self) -> Option<bool> {
376 self.keyspace_opts().durable_writes
377 }
378}
379
380pub trait TableOptionsExt {
381 fn table_opts(&self) -> &Option<TableOpts>;
382 fn table_opts_mut(&mut self) -> &mut Option<TableOpts>;
383 fn set_compact_storage(&mut self, compact_storage: bool) {
384 self.table_opts_mut()
385 .get_or_insert_with(Default::default)
386 .compact_storage = compact_storage;
387 }
388 fn set_clustering_order(&mut self, clustering_order: Vec<ColumnOrder>) {
389 self.table_opts_mut()
390 .get_or_insert_with(Default::default)
391 .clustering_order
392 .replace(clustering_order);
393 }
394 fn set_comment(&mut self, comment: &str) {
395 let c = comment.to_string().into();
396 self.table_opts_mut()
397 .get_or_insert_with(Default::default)
398 .comment
399 .replace(c);
400 }
401
402 fn set_speculative_retry(&mut self, speculative_retry: SpeculativeRetry) {
403 self.table_opts_mut()
404 .get_or_insert_with(Default::default)
405 .speculative_retry
406 .replace(speculative_retry);
407 }
408
409 fn set_change_data_capture(&mut self, cdc: bool) {
410 self.table_opts_mut()
411 .get_or_insert_with(Default::default)
412 .change_data_capture
413 .replace(cdc);
414 }
415
416 fn set_gc_grace_seconds(&mut self, gc_grace_seconds: i32) {
417 self.table_opts_mut()
418 .get_or_insert_with(Default::default)
419 .gc_grace_seconds
420 .replace(gc_grace_seconds);
421 }
422
423 fn set_bloom_filter_fp_chance(&mut self, bloom_filter_fp_chance: f32) {
424 self.table_opts_mut()
425 .get_or_insert_with(Default::default)
426 .bloom_filter_fp_chance
427 .replace(bloom_filter_fp_chance);
428 }
429
430 fn set_default_time_to_live(&mut self, default_time_to_live: i32) {
431 self.table_opts_mut()
432 .get_or_insert_with(Default::default)
433 .default_time_to_live
434 .replace(default_time_to_live);
435 }
436
437 fn set_compaction(&mut self, compaction: impl CompactionType) {
438 self.table_opts_mut()
439 .get_or_insert_with(Default::default)
440 .compaction
441 .replace(compaction.into());
442 }
443
444 fn set_compression(&mut self, compression: Compression) {
445 self.table_opts_mut()
446 .get_or_insert_with(Default::default)
447 .compression
448 .replace(compression);
449 }
450
451 fn set_caching(&mut self, caching: Caching) {
452 self.table_opts_mut()
453 .get_or_insert_with(Default::default)
454 .caching
455 .replace(caching);
456 }
457
458 fn set_memtable_flush_period_in_ms(&mut self, memtable_flush_period_in_ms: i32) {
459 self.table_opts_mut()
460 .get_or_insert_with(Default::default)
461 .memtable_flush_period_in_ms
462 .replace(memtable_flush_period_in_ms);
463 }
464
465 fn set_read_repair(&mut self, read_repair: bool) {
466 self.table_opts_mut()
467 .get_or_insert_with(Default::default)
468 .read_repair
469 .replace(read_repair);
470 }
471 fn set_additional_write_policy(&mut self, speculative_retry: SpeculativeRetry) {
472 self.set_speculative_retry(speculative_retry)
473 }
474
475 fn with_compact_storage(mut self, compact_storage: bool) -> Self
476 where
477 Self: Sized,
478 {
479 self.set_compact_storage(compact_storage);
480 self
481 }
482 fn with_clustering_order(mut self, clustering_order: Vec<ColumnOrder>) -> Self
483 where
484 Self: Sized,
485 {
486 self.set_clustering_order(clustering_order);
487 self
488 }
489 fn with_comment(mut self, comment: &str) -> Self
490 where
491 Self: Sized,
492 {
493 self.set_comment(comment);
494 self
495 }
496 fn with_speculative_retry(mut self, speculative_retry: SpeculativeRetry) -> Self
497 where
498 Self: Sized,
499 {
500 self.set_speculative_retry(speculative_retry);
501 self
502 }
503 fn with_change_data_capture(mut self, cdc: bool) -> Self
504 where
505 Self: Sized,
506 {
507 self.set_change_data_capture(cdc);
508 self
509 }
510 fn with_additional_write_policy(mut self, speculative_retry: SpeculativeRetry) -> Self
511 where
512 Self: Sized,
513 {
514 self.set_additional_write_policy(speculative_retry);
515 self
516 }
517 fn with_gc_grace_seconds(mut self, gc_grace_seconds: i32) -> Self
518 where
519 Self: Sized,
520 {
521 self.set_gc_grace_seconds(gc_grace_seconds);
522 self
523 }
524 fn with_bloom_filter_fp_chance(mut self, bloom_filter_fp_chance: f32) -> Self
525 where
526 Self: Sized,
527 {
528 self.set_bloom_filter_fp_chance(bloom_filter_fp_chance);
529 self
530 }
531 fn with_default_time_to_live(mut self, default_time_to_live: i32) -> Self
532 where
533 Self: Sized,
534 {
535 self.set_default_time_to_live(default_time_to_live);
536 self
537 }
538 fn with_compaction(mut self, compaction: impl CompactionType) -> Self
539 where
540 Self: Sized,
541 {
542 self.set_compaction(compaction);
543 self
544 }
545 fn with_compression(mut self, compression: Compression) -> Self
546 where
547 Self: Sized,
548 {
549 self.set_compression(compression);
550 self
551 }
552 fn with_caching(mut self, caching: Caching) -> Self
553 where
554 Self: Sized,
555 {
556 self.set_caching(caching);
557 self
558 }
559 fn with_memtable_flush_period_in_ms(mut self, memtable_flush_period_in_ms: i32) -> Self
560 where
561 Self: Sized,
562 {
563 self.set_memtable_flush_period_in_ms(memtable_flush_period_in_ms);
564 self
565 }
566 fn with_read_repair(mut self, read_repair: bool) -> Self
567 where
568 Self: Sized,
569 {
570 self.set_read_repair(read_repair);
571 self
572 }
573
574 fn get_compact_storage(&self) -> Option<&bool> {
575 self.table_opts().as_ref().map(|t| &t.compact_storage)
576 }
577 fn get_clustering_order(&self) -> Option<&Vec<ColumnOrder>> {
578 self.table_opts().as_ref().and_then(|t| t.clustering_order.as_ref())
579 }
580 fn get_comment(&self) -> Option<&String> {
581 self.table_opts()
582 .as_ref()
583 .and_then(|t| t.comment.as_ref().map(|s| &s.value))
584 }
585 fn get_speculative_retry(&self) -> Option<&SpeculativeRetry> {
586 self.table_opts().as_ref().and_then(|t| t.speculative_retry.as_ref())
587 }
588 fn get_change_data_capture(&self) -> Option<bool> {
589 self.table_opts().as_ref().and_then(|t| t.change_data_capture)
590 }
591 fn get_additional_write_policy(&self) -> Option<&SpeculativeRetry> {
592 self.table_opts().as_ref().and_then(|t| t.speculative_retry.as_ref())
593 }
594 fn get_gc_grace_seconds(&self) -> Option<i32> {
595 self.table_opts().as_ref().and_then(|t| t.gc_grace_seconds)
596 }
597 fn get_bloom_filter_fp_chance(&self) -> Option<f32> {
598 self.table_opts().as_ref().and_then(|t| t.bloom_filter_fp_chance)
599 }
600 fn get_default_time_to_live(&self) -> Option<i32> {
601 self.table_opts().as_ref().and_then(|t| t.default_time_to_live)
602 }
603 fn get_compaction(&self) -> Option<&Compaction> {
604 self.table_opts().as_ref().and_then(|t| t.compaction.as_ref())
605 }
606 fn get_compression(&self) -> Option<&Compression> {
607 self.table_opts().as_ref().and_then(|t| t.compression.as_ref())
608 }
609 fn get_caching(&self) -> Option<&Caching> {
610 self.table_opts().as_ref().and_then(|t| t.caching.as_ref())
611 }
612 fn get_memtable_flush_period_in_ms(&self) -> Option<i32> {
613 self.table_opts().as_ref().and_then(|t| t.memtable_flush_period_in_ms)
614 }
615 fn get_read_repair(&self) -> Option<bool> {
616 self.table_opts().as_ref().and_then(|t| t.read_repair)
617 }
618}