cql3_parser/
common.rs

1use bigdecimal::BigDecimal;
2use bytes::Bytes;
3use hex;
4use itertools::Itertools;
5use num_bigint::BigInt;
6use serde::Deserialize;
7use std::collections::{BTreeMap, HashSet};
8use std::fmt::{Display, Formatter};
9use std::hash::{Hash, Hasher};
10use std::net::IpAddr;
11use uuid::Uuid;
12
13/// A column definition.
14/// This is used in many places, however the primary_key value should only be used in
15/// the `create table` calls.  In all other cases it will yield an invalid statement.
16#[derive(PartialEq, Debug, Clone)]
17pub struct ColumnDefinition {
18    /// the name of the column
19    pub name: Identifier,
20    /// the data type for the column
21    pub data_type: DataType,
22    /// if set this column is the primary key.
23    pub primary_key: bool,
24}
25
26impl Display for ColumnDefinition {
27    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28        write!(
29            f,
30            "{} {}{}",
31            self.name,
32            self.data_type,
33            if self.primary_key { " PRIMARY KEY" } else { "" }
34        )
35    }
36}
37
38/// the definition of a data type
39#[derive(PartialEq, Debug, Clone)]
40pub struct DataType {
41    /// the name of the data type.
42    pub name: DataTypeName,
43    /// the definition of the data type.  Normally this is empty but may contain data types that
44    /// comprise the named type. (e.g. `FROZEN<foo>` will have foo in the definition)
45    pub definition: Vec<DataTypeName>,
46}
47
48impl Display for DataType {
49    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50        if self.definition.is_empty() {
51            write!(f, "{}", self.name)
52        } else {
53            write!(f, "{}<{}>", self.name, self.definition.iter().join(", "))
54        }
55    }
56}
57
58/// An enumeration of data types.
59#[derive(PartialEq, Debug, Clone)]
60pub enum DataTypeName {
61    Timestamp,
62    Set,
63    Ascii,
64    BigInt,
65    Blob,
66    Boolean,
67    Counter,
68    Date,
69    Decimal,
70    Double,
71    Float,
72    Frozen,
73    Inet,
74    Int,
75    List,
76    Map,
77    SmallInt,
78    Text,
79    Time,
80    TimeUuid,
81    TinyInt,
82    Tuple,
83    VarChar,
84    VarInt,
85    Uuid,
86    /// defines a custom type.  Where the name is the name of the type.
87    Custom(String),
88}
89
90impl Display for DataTypeName {
91    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
92        match self {
93            DataTypeName::Timestamp => write!(f, "TIMESTAMP"),
94            DataTypeName::Set => write!(f, "SET"),
95            DataTypeName::Ascii => write!(f, "ASCII"),
96            DataTypeName::BigInt => write!(f, "BIGINT"),
97            DataTypeName::Blob => write!(f, "BLOB"),
98            DataTypeName::Boolean => write!(f, "BOOLEAN"),
99            DataTypeName::Counter => write!(f, "COUNTER"),
100            DataTypeName::Date => write!(f, "DATE"),
101            DataTypeName::Decimal => write!(f, "DECIMAL"),
102            DataTypeName::Double => write!(f, "DOUBLE"),
103            DataTypeName::Float => write!(f, "FLOAT"),
104            DataTypeName::Frozen => write!(f, "FROZEN"),
105            DataTypeName::Inet => write!(f, "INET"),
106            DataTypeName::Int => write!(f, "INT"),
107            DataTypeName::List => write!(f, "LIST"),
108            DataTypeName::Map => write!(f, "MAP"),
109            DataTypeName::SmallInt => write!(f, "SMALLINT"),
110            DataTypeName::Text => write!(f, "TEXT"),
111            DataTypeName::Time => write!(f, "TIME"),
112            DataTypeName::TimeUuid => write!(f, "TIMEUUID"),
113            DataTypeName::TinyInt => write!(f, "TINYINT"),
114            DataTypeName::Tuple => write!(f, "TUPLE"),
115            DataTypeName::VarChar => write!(f, "VARCHAR"),
116            DataTypeName::VarInt => write!(f, "VARINT"),
117            DataTypeName::Uuid => write!(f, "UUID"),
118            DataTypeName::Custom(name) => write!(f, "{}", name),
119        }
120    }
121}
122
123impl DataTypeName {
124    pub fn from(name: &str) -> DataTypeName {
125        match name.to_uppercase().as_str() {
126            "ASCII" => DataTypeName::Ascii,
127            "BIGINT" => DataTypeName::BigInt,
128            "BLOB" => DataTypeName::Blob,
129            "BOOLEAN" => DataTypeName::Boolean,
130            "COUNTER" => DataTypeName::Counter,
131            "DATE" => DataTypeName::Date,
132            "DECIMAL" => DataTypeName::Decimal,
133            "DOUBLE" => DataTypeName::Double,
134            "FLOAT" => DataTypeName::Float,
135            "FROZEN" => DataTypeName::Frozen,
136            "INET" => DataTypeName::Inet,
137            "INT" => DataTypeName::Int,
138            "LIST" => DataTypeName::List,
139            "MAP" => DataTypeName::Map,
140            "SET" => DataTypeName::Set,
141            "SMALLINT" => DataTypeName::SmallInt,
142            "TEXT" => DataTypeName::Text,
143            "TIME" => DataTypeName::Time,
144            "TIMESTAMP" => DataTypeName::Timestamp,
145            "TIMEUUID" => DataTypeName::TimeUuid,
146            "TINYINT" => DataTypeName::TinyInt,
147            "TUPLE" => DataTypeName::Tuple,
148            "UUID" => DataTypeName::Uuid,
149            "VARCHAR" => DataTypeName::VarChar,
150            "VARINT" => DataTypeName::VarInt,
151            _ => DataTypeName::Custom(name.to_string()),
152        }
153    }
154}
155
156/// An object that can be on either side of an `Operator`
157#[derive(PartialEq, Debug, Clone, Eq, Ord, PartialOrd)]
158pub enum Operand {
159    /// A constant
160    Const(String),
161    /// a map displays as `{ String:String, String:String, ... }`
162    Map(Vec<(String, String)>),
163    /// a set of values.  Displays as `( String, String, ...)`
164    Set(Vec<String>),
165    /// a list of values.  Displays as `[String, String, ...]`
166    List(Vec<String>),
167    /// a tuple of values.  Displays as `{ Operand, Operand, ... }`
168    Tuple(Vec<Operand>),
169    /// A column name
170    Column(Identifier),
171    /// A function call e.g. foo(bar)
172    Func(String),
173    /// A parameter.  The string will either be '?' or ':name'
174    Param(String),
175    /// the `NULL` value.
176    Null,
177}
178
179/// this is _NOT_ the same as `Operand::Const(string)`  This conversion encloses the value in
180/// single quotes.
181impl From<&str> for Operand {
182    fn from(txt: &str) -> Self {
183        Operand::Const(format!("'{}'", txt))
184    }
185}
186
187impl From<&Bytes> for Operand {
188    fn from(b: &Bytes) -> Self {
189        Operand::from_hex(&hex::encode(b))
190    }
191}
192
193impl From<&bool> for Operand {
194    fn from(b: &bool) -> Self {
195        Operand::Const(if *b {
196            "TRUE".to_string()
197        } else {
198            "FALSE".to_string()
199        })
200    }
201}
202
203impl From<&u128> for Operand {
204    fn from(i: &u128) -> Self {
205        Operand::Const(i.to_string())
206    }
207}
208impl From<&u64> for Operand {
209    fn from(i: &u64) -> Self {
210        Operand::Const(i.to_string())
211    }
212}
213impl From<&u32> for Operand {
214    fn from(i: &u32) -> Self {
215        Operand::Const(i.to_string())
216    }
217}
218
219impl From<&u16> for Operand {
220    fn from(i: &u16) -> Self {
221        Operand::Const(i.to_string())
222    }
223}
224
225impl From<&u8> for Operand {
226    fn from(i: &u8) -> Self {
227        Operand::Const(i.to_string())
228    }
229}
230impl From<&i128> for Operand {
231    fn from(i: &i128) -> Self {
232        Operand::Const(i.to_string())
233    }
234}
235
236impl From<&i64> for Operand {
237    fn from(i: &i64) -> Self {
238        Operand::Const(i.to_string())
239    }
240}
241impl From<&i32> for Operand {
242    fn from(i: &i32) -> Self {
243        Operand::Const(i.to_string())
244    }
245}
246
247impl From<&i16> for Operand {
248    fn from(i: &i16) -> Self {
249        Operand::Const(i.to_string())
250    }
251}
252
253impl From<&i8> for Operand {
254    fn from(i: &i8) -> Self {
255        Operand::Const(i.to_string())
256    }
257}
258
259impl From<&f64> for Operand {
260    fn from(i: &f64) -> Self {
261        Operand::Const(i.to_string())
262    }
263}
264impl From<&f32> for Operand {
265    fn from(i: &f32) -> Self {
266        Operand::Const(i.to_string())
267    }
268}
269
270impl From<&BigInt> for Operand {
271    fn from(b: &BigInt) -> Self {
272        Operand::Const(b.to_string())
273    }
274}
275
276impl From<&BigDecimal> for Operand {
277    fn from(b: &BigDecimal) -> Self {
278        Operand::Const(b.to_string())
279    }
280}
281
282impl From<&IpAddr> for Operand {
283    fn from(addr: &IpAddr) -> Self {
284        Operand::from(addr.to_string().as_str())
285    }
286}
287
288impl From<&Uuid> for Operand {
289    fn from(uuid: &Uuid) -> Self {
290        Operand::from(uuid.to_string().as_str())
291    }
292}
293
294impl Operand {
295    /// creates creates a properly formatted Operand::Const for a hex string.
296    fn from_hex(hex_str: &str) -> Operand {
297        Operand::Const(format!("0x{}", hex_str))
298    }
299
300    /// unescapes a CQL string
301    /// Specifically converts `''` to `'` and removes the leading and
302    /// trailing delimiters.  For all other strings this is method returns
303    /// the argument.  Valid delimiters are `'` and `$$`
304    pub fn unescape(value: &str) -> String {
305        if value.starts_with('\'') {
306            let mut chars = value.chars();
307            chars.next();
308            chars.next_back();
309            chars.as_str().replace("''", "'")
310        } else if value.starts_with("$$") {
311            /* to convert to a VarChar type we have to strip the delimiters off the front and back
312            of the string.  Soe remove one char (front and back) in the case of `'` and two in the case of `$$`
313             */
314            let mut chars = value.chars();
315            chars.next();
316            chars.next();
317            chars.next_back();
318            chars.next_back();
319            chars.as_str().to_string()
320        } else {
321            value.to_string()
322        }
323    }
324
325    /// creates an Operand::Const from an unquoted string.
326    /// if the string contains a `'` it will be quoted by the `$$` pattern.  if it contains `$$` and `'`
327    /// it will be quoted by the `'` pattern and all existing `'` will be replaced with `''` (two single quotes).
328    pub fn escape(txt: &str) -> Operand {
329        if txt.contains('\'') {
330            if txt.contains("$$") {
331                Operand::Const(format!("'{}'", txt.replace('\'', "''")))
332            } else {
333                Operand::Const(format!("$${}$$", txt))
334            }
335        } else {
336            Operand::Const(txt.to_string())
337        }
338    }
339}
340
341impl Display for Operand {
342    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
343        match self {
344            Operand::Column(id) => {
345                write!(f, "{}", id)
346            }
347            Operand::Const(text) | Operand::Param(text) | Operand::Func(text) => {
348                write!(f, "{}", text)
349            }
350            Operand::Map(entries) => {
351                let mut result = String::from('{');
352                result.push_str(
353                    entries
354                        .iter()
355                        .map(|(x, y)| format!("{}:{}", x, y))
356                        .join(", ")
357                        .as_str(),
358                );
359                result.push('}');
360                write!(f, "{}", result)
361            }
362            Operand::Set(values) => {
363                let mut result = String::from('{');
364                result.push_str(values.iter().join(", ").as_str());
365                result.push('}');
366                write!(f, "{}", result)
367            }
368            Operand::List(values) => {
369                let mut result = String::from('[');
370                result.push_str(values.iter().join(", ").as_str());
371                result.push(']');
372                write!(f, "{}", result)
373            }
374            Operand::Tuple(values) => {
375                let mut result = String::from('(');
376                result.push_str(values.iter().join(", ").as_str());
377                result.push(')');
378                write!(f, "{}", result)
379            }
380            Operand::Null => write!(f, "NULL"),
381        }
382    }
383}
384
385/// data item used in `Grant`, `ListPermissions` and `Revoke` statements.
386#[derive(PartialEq, Debug, Clone)]
387pub struct Privilege {
388    /// the privilege that is being manipulated
389    pub privilege: PrivilegeType,
390    /// the resource on which the permission is applied
391    pub resource: Option<Resource>,
392    /// the role name that tis being modified.
393    pub role: Option<String>,
394}
395
396/// the list of privileges recognized by the system.
397#[derive(PartialEq, Debug, Clone)]
398pub enum PrivilegeType {
399    All,
400    Alter,
401    Authorize,
402    Describe,
403    Execute,
404    Create,
405    Drop,
406    Modify,
407    Select,
408}
409
410impl Display for PrivilegeType {
411    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
412        match self {
413            PrivilegeType::All => write!(f, "ALL PERMISSIONS"),
414            PrivilegeType::Alter => write!(f, "ALTER"),
415            PrivilegeType::Authorize => write!(f, "AUTHORIZE"),
416            PrivilegeType::Describe => write!(f, "DESCRIBE"),
417            PrivilegeType::Execute => write!(f, "EXECUTE"),
418            PrivilegeType::Create => write!(f, "CREATE"),
419            PrivilegeType::Drop => write!(f, "DROP"),
420            PrivilegeType::Modify => write!(f, "MODIFY"),
421            PrivilegeType::Select => write!(f, "SELECT"),
422        }
423    }
424}
425
426#[derive(PartialEq, Debug, Clone, Eq, Ord, PartialOrd)]
427pub struct RelationElement {
428    /// the column, function or column list on the left side
429    pub obj: Operand,
430    /// the relational operator
431    pub oper: RelationOperator,
432    /// the value, func, argument list, tuple list or tuple
433    pub value: Operand,
434}
435
436impl Display for RelationElement {
437    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
438        write!(f, "{} {} {}", self.obj, self.oper, self.value)
439    }
440}
441
442impl RelationOperator {
443    /// evaluates the expression for any PartialOrd implementation
444    pub fn eval<T>(&self, left: &T, right: &T) -> bool
445    where
446        T: PartialOrd,
447    {
448        match self {
449            RelationOperator::LessThan => left.lt(right),
450            RelationOperator::LessThanOrEqual => left.le(right),
451            RelationOperator::Equal => left.eq(right),
452            RelationOperator::NotEqual => !left.eq(right),
453            RelationOperator::GreaterThanOrEqual => left.ge(right),
454            RelationOperator::GreaterThan => left.gt(right),
455            RelationOperator::In => false,
456            RelationOperator::Contains => false,
457            RelationOperator::ContainsKey => false,
458            RelationOperator::IsNot => false,
459        }
460    }
461}
462
463/// A relation operator used in `WHERE` and `IF` clauses.
464#[derive(PartialEq, Debug, Clone, Eq, PartialOrd, Ord)]
465pub enum RelationOperator {
466    LessThan,
467    LessThanOrEqual,
468    Equal,
469    NotEqual,
470    GreaterThanOrEqual,
471    GreaterThan,
472    In,
473    Contains,
474    ContainsKey,
475    /// this is not used in normal cases it is used in the MaterializedView to specify
476    /// a collumn that must not be null.
477    IsNot,
478}
479
480impl Display for RelationOperator {
481    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
482        match self {
483            RelationOperator::LessThan => write!(f, "<"),
484            RelationOperator::LessThanOrEqual => write!(f, "<="),
485            RelationOperator::Equal => write!(f, "="),
486            RelationOperator::NotEqual => write!(f, "<>"),
487            RelationOperator::GreaterThanOrEqual => write!(f, ">="),
488            RelationOperator::GreaterThan => write!(f, ">"),
489            RelationOperator::In => write!(f, "IN"),
490            RelationOperator::Contains => write!(f, "CONTAINS"),
491            RelationOperator::ContainsKey => write!(f, "CONTAINS KEY"),
492            RelationOperator::IsNot => write!(f, "IS NOT"),
493        }
494    }
495}
496
497/// the structure of the TTL / Timestamp option.
498#[derive(PartialEq, Debug, Clone)]
499pub struct TtlTimestamp {
500    /// the optional time-to-live value
501    pub ttl: Option<u64>,
502    /// the optional timestamp value
503    pub timestamp: Option<u64>,
504}
505
506impl Display for TtlTimestamp {
507    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
508        let tl = match self.ttl {
509            Some(t) => format!("TTL {}", t),
510            _ => "".to_string(),
511        };
512
513        let tm = match self.timestamp {
514            Some(t) => format!("TIMESTAMP {}", t),
515            _ => "".to_string(),
516        };
517
518        if self.ttl.is_some() && self.timestamp.is_some() {
519            write!(f, " USING {} AND {}", tl, tm)
520        } else {
521            write!(f, " USING {}", if self.ttl.is_some() { tl } else { tm })
522        }
523    }
524}
525
526/// The definition of the items in a WithElement
527#[derive(PartialEq, Debug, Clone)]
528pub enum WithItem {
529    /// an option comprising the key (name) and the value for the option.
530    Option { key: String, value: OptionValue },
531    /// A clustering order clause.
532    ClusterOrder(OrderClause),
533    /// the ID the ID for the table/view.
534    ID(String),
535    /// use compact storage.
536    CompactStorage,
537}
538
539impl Display for WithItem {
540    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
541        match self {
542            WithItem::Option { key, value } => write!(f, "{} = {}", key, value),
543            WithItem::ClusterOrder(order) => write!(f, "CLUSTERING ORDER BY ({})", order),
544            WithItem::ID(txt) => write!(f, "ID = {}", txt),
545            WithItem::CompactStorage => write!(f, "COMPACT STORAGE"),
546        }
547    }
548}
549
550/// the order clause
551#[derive(PartialEq, Debug, Clone)]
552pub struct OrderClause {
553    /// the column to order by.
554    pub name: Identifier,
555    /// if `true` then the order is descending,
556    pub desc: bool,
557}
558
559impl Display for OrderClause {
560    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
561        write!(
562            f,
563            "{} {}",
564            self.name,
565            if self.desc { "DESC" } else { "ASC" }
566        )
567    }
568}
569
570/// the definition of an option value, is either literal string or a map of Key,value pairs.
571#[derive(PartialEq, Debug, Clone)]
572pub enum OptionValue {
573    Literal(String),
574    Map(Vec<(String, String)>),
575}
576
577impl Display for OptionValue {
578    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
579        match self {
580            OptionValue::Literal(txt) => write!(f, "{}", txt),
581            OptionValue::Map(items) => write!(
582                f,
583                "{{{}}}",
584                items.iter().map(|(x, y)| format!("{}:{}", x, y)).join(", ")
585            ),
586        }
587    }
588}
589
590/// The definition of a primary key.
591/// There must be at least one column specified in the partition.
592#[derive(PartialEq, Debug, Clone)]
593pub struct PrimaryKey {
594    pub partition: Vec<Identifier>,
595    pub clustering: Vec<Identifier>,
596}
597
598impl Display for PrimaryKey {
599    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
600        if self.partition.is_empty() && self.clustering.is_empty() {
601            write!(f, "")
602        } else if self.partition.len() == 1 {
603            if self.clustering.is_empty() {
604                write!(f, "PRIMARY KEY ({})", self.partition[0])
605            } else {
606                write!(
607                    f,
608                    "PRIMARY KEY ({}, {})",
609                    self.partition[0],
610                    self.clustering.iter().map(|c| c.to_string()).join(", ")
611                )
612            }
613        } else {
614            write!(
615                f,
616                "PRIMARY KEY (({}), {})",
617                self.partition.iter().map(|c| c.to_string()).join(", "),
618                self.clustering.iter().map(|c| c.to_string()).join(", ")
619            )
620        }
621    }
622}
623
624/// A list of resource types recognized by the system
625#[derive(PartialEq, Debug, Clone)]
626pub enum Resource {
627    /// all the functions optionally within a keyspace
628    AllFunctions(Option<String>),
629    /// all the keyspaces
630    AllKeyspaces,
631    /// all the roles
632    AllRoles,
633    /// the specific function.
634    Function(FQName),
635    /// the specific keyspace
636    Keyspace(Identifier),
637    /// the specified role.
638    Role(String),
639    /// the specified table.
640    Table(FQName),
641}
642
643impl Display for Resource {
644    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
645        match self {
646            Resource::AllFunctions(str) => {
647                if let Some(str) = str {
648                    write!(f, "ALL FUNCTIONS IN KEYSPACE {}", str)
649                } else {
650                    write!(f, "ALL FUNCTIONS")
651                }
652            }
653            Resource::AllKeyspaces => write!(f, "ALL KEYSPACES"),
654            Resource::AllRoles => write!(f, "ALL ROLES"),
655            Resource::Function(func) => write!(f, "FUNCTION {}", func),
656            Resource::Keyspace(keyspace) => write!(f, "KEYSPACE {}", keyspace),
657            Resource::Role(role) => write!(f, "ROLE {}", role),
658            Resource::Table(table) => write!(f, "TABLE {}", table),
659        }
660    }
661}
662
663pub struct WhereClause {}
664impl WhereClause {
665    /// return a map of column names to relation elements
666    pub fn get_column_relation_element_map(
667        where_clause: &[RelationElement],
668    ) -> BTreeMap<Identifier, Vec<RelationElement>> {
669        let mut result: BTreeMap<Identifier, Vec<RelationElement>> = BTreeMap::new();
670
671        for relation_element in where_clause {
672            if let Operand::Column(key) = &relation_element.obj {
673                if let Some(value) = result.get_mut(key) {
674                    value.push(relation_element.clone());
675                } else {
676                    result.insert(key.clone(), vec![relation_element.clone()]);
677                }
678            }
679        }
680
681        result
682    }
683
684    /// get the unordered set of column names for found in the where clause
685    pub fn get_column_list(where_clause: Vec<RelationElement>) -> HashSet<Identifier> {
686        where_clause
687            .into_iter()
688            .filter_map(|relation_element| match relation_element.obj {
689                Operand::Column(name) => Some(name),
690                _ => None,
691            })
692            .collect()
693    }
694}
695
696/// a fully qualified name.
697#[derive(PartialEq, Debug, Clone, Hash, Eq, Deserialize)]
698pub struct FQName {
699    pub keyspace: Option<Identifier>,
700    pub name: Identifier,
701}
702
703impl FQName {
704    /// parses the FQName from a string.  Breaks the string at the first dot (`.`) and makes the left
705    /// string the keyspace and the second string the name. If no dot is present the entire string
706    /// is the name.
707    pub fn parse(txt: &str) -> FQName {
708        let parts = txt.split('.').collect_vec();
709        if parts.len() > 1 {
710            FQName::new(parts[0], parts[1])
711        } else {
712            FQName::simple(txt)
713        }
714    }
715
716    pub fn simple(name: &str) -> FQName {
717        FQName {
718            keyspace: None,
719            name: Identifier::parse(name),
720        }
721    }
722
723    pub fn new(keyspace: &str, name: &str) -> FQName {
724        FQName {
725            keyspace: Some(Identifier::parse(keyspace)),
726            name: Identifier::parse(name),
727        }
728    }
729}
730
731impl Display for FQName {
732    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
733        if let Some(keyspace) = &self.keyspace {
734            write!(f, "{}.{}", keyspace, self.name)
735        } else {
736            write!(f, "{}", self.name)
737        }
738    }
739}
740
741impl From<&FQName> for std::string::String {
742    fn from(fqname: &FQName) -> Self {
743        fqname.to_string()
744    }
745}
746
747impl From<FQName> for std::string::String {
748    fn from(fqname: FQName) -> Self {
749        fqname.to_string()
750    }
751}
752
753#[derive(Debug, PartialEq)]
754pub struct FQNameRef<'a> {
755    pub keyspace: Option<IdentifierRef<'a>>,
756    pub name: IdentifierRef<'a>,
757}
758
759impl PartialEq<FQName> for FQNameRef<'_> {
760    fn eq(&self, other: &FQName) -> bool {
761        self.keyspace == other.keyspace.as_ref().map(|x| x.as_ref()) && self.name == other.name
762    }
763}
764
765impl PartialEq<FQNameRef<'_>> for FQName {
766    fn eq(&self, other: &FQNameRef<'_>) -> bool {
767        self.keyspace.as_ref().map(|x| x.as_ref()) == other.keyspace && self.name == other.name
768    }
769}
770
771/// Identifers are either Quoted or Unquoted.
772///  * Unquoted Identifiers:  are case insensitive
773///  * Quoted Identifiers: are case sensitive.  double quotes appearing within the quoted string are escaped by doubling (i.e. `"foo""bar" is interpreted as `foo"bar`)
774///
775/// Quoted lower lower case is equivalent to unquoted mixed case.
776/// Quoted( myid ) == Unquoted( myid )
777/// Quoted( myid ) == Unquoted( "myId" )
778/// Quoted( myid ) != Quoted( "myId" )
779///
780/// It is possible to create an Unquoted identifier with an embedded quote (e.g. `Identifier::Unquoted( "foo\"bar" )`).
781/// *Note* that a quote as the first character in an Unquoted Identifier can cause problems if the Identifier is converted
782/// to a string and then parsed again as the second parse will create a Quoted identifier.
783#[derive(Debug, Clone, Eq, Ord, PartialOrd, Deserialize)]
784pub enum Identifier {
785    /// This variant is case sensitive
786    /// "fOo""bAr""" is stored as fOo"bAr"
787    Quoted(String),
788    /// This variant is case insensitive
789    /// Only ascii alphanumeric and _ characters are allowed in this variant
790    /// fOo_bAr is stored as fOo_bAr
791    Unquoted(String),
792}
793
794impl Identifier {
795    /// parses strings as returned by the parser into Quoted or Unquoted Identifiers.
796    ///  * Unquoted Identifiers:  are case insensitive
797    ///  * Quoted Identifiers: are case sensitive.  double quotes appearing within the quoted string
798    ///    are escaped by doubling (i.e. `"foo""bar" is interpreted as `foo"bar`)
799    ///
800    /// If the string starts with `"` it is assumed to be a quoted identifier, the leading and trailing quotes are removed
801    /// and the internal doubled quotes (`""`) are converted to simple quotes (`"`).
802    pub fn parse(text: &str) -> Identifier {
803        if text.starts_with('"') {
804            let mut chars = text.chars();
805            chars.next();
806            chars.next_back();
807            Identifier::Quoted(chars.as_str().replace("\"\"", "\""))
808        } else {
809            Identifier::Unquoted(text.to_string())
810        }
811    }
812
813    fn as_ref(&'_ self) -> IdentifierRef<'_> {
814        match self {
815            Self::Quoted(x) => IdentifierRef::Quoted(x),
816            Self::Unquoted(x) => IdentifierRef::Unquoted(x),
817        }
818    }
819}
820
821impl PartialEq for Identifier {
822    fn eq(&self, other: &Self) -> bool {
823        self.as_ref() == other.as_ref()
824    }
825}
826
827impl Hash for Identifier {
828    fn hash<H: Hasher>(&self, state: &mut H) {
829        match self {
830            Identifier::Quoted(a) => a.hash(state),
831            Identifier::Unquoted(a) => a.to_lowercase().hash(state),
832        }
833    }
834}
835
836impl Display for Identifier {
837    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
838        match &self {
839            Identifier::Quoted(txt) => write!(f, "\"{}\"", txt.replace('\"', "\"\"")),
840            Identifier::Unquoted(txt) => write!(f, "{}", txt),
841        }
842    }
843}
844
845impl Default for Identifier {
846    fn default() -> Self {
847        Identifier::Unquoted("".to_string())
848    }
849}
850
851impl From<&str> for Identifier {
852    fn from(txt: &str) -> Self {
853        Identifier::parse(txt)
854    }
855}
856
857impl From<&String> for Identifier {
858    fn from(txt: &String) -> Self {
859        Identifier::parse(txt)
860    }
861}
862
863/// An alternative to [Identifier] that holds &str instead of String.
864/// Allows for allocationless comparison of [Identifier].
865#[derive(Debug)]
866pub enum IdentifierRef<'a> {
867    /// This variant is case sensitive
868    /// "fOo""bAr""" is stored as fOo"bAr"
869    Quoted(&'a str),
870    /// This variant is case insensitive
871    /// Only ascii alphanumeric and _ characters are allowed in this variant
872    /// fOo_bAr is stored as fOo_bAr
873    Unquoted(&'a str),
874}
875
876impl PartialEq for IdentifierRef<'_> {
877    fn eq(&self, other: &Self) -> bool {
878        match (self, other) {
879            (IdentifierRef::Quoted(a), IdentifierRef::Quoted(b)) => a == b,
880            (IdentifierRef::Unquoted(a), IdentifierRef::Unquoted(b)) => {
881                a.to_lowercase() == b.to_lowercase()
882            }
883            (IdentifierRef::Quoted(a), IdentifierRef::Unquoted(b)) => a == &b.to_lowercase(),
884            (IdentifierRef::Unquoted(a), IdentifierRef::Quoted(b)) => &a.to_lowercase() == b,
885        }
886    }
887}
888
889impl PartialEq<Identifier> for IdentifierRef<'_> {
890    fn eq(&self, other: &Identifier) -> bool {
891        self == &other.as_ref()
892    }
893}
894
895impl PartialEq<IdentifierRef<'_>> for Identifier {
896    fn eq(&self, other: &IdentifierRef<'_>) -> bool {
897        &self.as_ref() == other
898    }
899}
900
901#[cfg(test)]
902mod tests {
903    use crate::common::{FQName, Identifier, Operand};
904    use std::collections::hash_map::DefaultHasher;
905    use std::hash::{Hash, Hasher};
906
907    #[test]
908    pub fn test_operand_unescape() {
909        let tests = [
910            (
911                "'Women''s Tour of New Zealand'",
912                "Women's Tour of New Zealand",
913            ),
914            (
915                "$$Women's Tour of New Zealand$$",
916                "Women's Tour of New Zealand",
917            ),
918            (
919                "$$Women''s Tour of New Zealand$$",
920                "Women''s Tour of New Zealand",
921            ),
922            ("55", "55"),
923        ];
924        for (arg, expected) in tests {
925            assert_eq!(expected, Operand::unescape(arg).as_str());
926        }
927        assert_eq!(
928            Operand::Null.to_string(),
929            Operand::unescape(Operand::Null.to_string().as_str())
930        );
931    }
932
933    #[test]
934    pub fn test_operand_escape() {
935        let tests = [
936            (
937                "$$Women's Tour of New Zealand$$",
938                "Women's Tour of New Zealand",
939            ),
940            (
941                "'Women''s Tour of New Zealand makes big $$'",
942                "Women's Tour of New Zealand makes big $$",
943            ),
944            ("55", "55"),
945        ];
946        for (expected, arg) in tests {
947            assert_eq!(Operand::Const(expected.to_string()), Operand::escape(arg));
948        }
949    }
950
951    #[test]
952    pub fn test_identifier_parse_quoted() {
953        let args = [
954            (r#""""hello"", she said""#, r#""hello", she said"#),
955            (r#""CaseSpecific""#, "CaseSpecific"),
956        ];
957
958        for (arg, expected) in args {
959            let x = Identifier::parse(arg);
960            assert_eq!(arg, x.to_string());
961            if let Identifier::Quoted(txt) = x {
962                assert_eq!(expected, txt);
963            } else {
964                panic!("Should  be quoted");
965            }
966        }
967    }
968
969    #[test]
970    pub fn test_identifier_parse_unquoted() {
971        let args = ["just_A_name", "CaseSpecific"];
972
973        for arg in args {
974            let x = Identifier::parse(arg);
975            assert_eq!(arg, x.to_string());
976            if let Identifier::Unquoted(txt) = x {
977                assert_eq!(arg, txt);
978            } else {
979                panic!("Should  be unquoted");
980            }
981        }
982    }
983
984    fn assert_identifier_equality(left: &Identifier, right: &Identifier) {
985        assert_eq!(left, right);
986        assert_eq!(right, left);
987        let mut left_hasher = DefaultHasher::new();
988        left.hash(&mut left_hasher);
989
990        let mut right_hasher = DefaultHasher::new();
991        right.hash(&mut right_hasher);
992        assert_eq!(left_hasher.finish(), right_hasher.finish());
993    }
994
995    fn assert_identifier_inequality(left: &Identifier, right: &Identifier) {
996        assert!(!left.eq(right));
997        assert!(!right.eq(left));
998    }
999
1000    #[test]
1001    pub fn test_identifier_equality() {
1002        let lower_case_unquoted = Identifier::Unquoted("myid".to_string());
1003        let mixed_case_unquoted = Identifier::Unquoted("myId".to_string());
1004        let lower_case_quoted = Identifier::Quoted("myid".to_string());
1005        let mixed_case_quoted = Identifier::Quoted("MyId".to_string());
1006
1007        let quote_in_unquoted = Identifier::Unquoted("\"now\"".to_string());
1008        let quote_in_quoted = Identifier::Quoted("\"now\"".to_string());
1009
1010        assert_identifier_equality(&lower_case_unquoted, &mixed_case_unquoted);
1011
1012        assert_identifier_equality(&lower_case_unquoted, &lower_case_quoted);
1013        assert_identifier_inequality(&mixed_case_quoted, &mixed_case_unquoted);
1014        assert_identifier_inequality(&mixed_case_quoted, &lower_case_unquoted);
1015        assert_identifier_inequality(&mixed_case_quoted, &lower_case_quoted);
1016
1017        assert_identifier_equality(&quote_in_quoted, &quote_in_unquoted);
1018    }
1019
1020    #[test]
1021    pub fn test_fqname_parse() {
1022        let name = FQName::parse("myid");
1023        assert_eq!(FQName::simple("myid"), name);
1024
1025        let name = FQName::parse("myId");
1026        assert_eq!(FQName::simple("myId"), name);
1027        assert_eq!(Identifier::Unquoted("myId".to_string()), name.name);
1028
1029        let name = FQName::parse(r#""myId""#);
1030        assert_eq!(FQName::simple("\"myId\""), name);
1031        assert_eq!(Identifier::Quoted("myId".to_string()), name.name);
1032
1033        assert_eq!(FQName::new("myid", "name"), FQName::parse("myid.name"));
1034
1035        let name = FQName::parse("myId.Name");
1036        assert_eq!(FQName::new("myId", "Name"), name);
1037        assert_eq!(
1038            Some(Identifier::Unquoted("MyId".to_string())),
1039            name.keyspace
1040        );
1041        assert_eq!(Identifier::Unquoted("Name".to_string()), name.name);
1042
1043        let name = FQName::parse("\"myId\".Name");
1044        assert_eq!(FQName::new("\"myId\"", "Name"), name);
1045        assert_eq!(Some(Identifier::Quoted("myId".to_string())), name.keyspace);
1046        assert_eq!(Identifier::Unquoted("Name".to_string()), name.name);
1047
1048        let name = FQName::parse("\"myId\".\"Name\"");
1049        assert_eq!(FQName::new("\"myId\"", "\"Name\""), name);
1050        assert_eq!(Some(Identifier::Quoted("myId".to_string())), name.keyspace);
1051        assert_eq!(Identifier::Quoted("Name".to_string()), name.name);
1052    }
1053}