scylladb_parse/statements/
mod.rs

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
328// TODO: Add more usability APIs
329pub 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}