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#[derive(PartialEq, Debug, Clone)]
17pub struct ColumnDefinition {
18 pub name: Identifier,
20 pub data_type: DataType,
22 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#[derive(PartialEq, Debug, Clone)]
40pub struct DataType {
41 pub name: DataTypeName,
43 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#[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 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#[derive(PartialEq, Debug, Clone, Eq, Ord, PartialOrd)]
158pub enum Operand {
159 Const(String),
161 Map(Vec<(String, String)>),
163 Set(Vec<String>),
165 List(Vec<String>),
167 Tuple(Vec<Operand>),
169 Column(Identifier),
171 Func(String),
173 Param(String),
175 Null,
177}
178
179impl 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 fn from_hex(hex_str: &str) -> Operand {
297 Operand::Const(format!("0x{}", hex_str))
298 }
299
300 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 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 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#[derive(PartialEq, Debug, Clone)]
387pub struct Privilege {
388 pub privilege: PrivilegeType,
390 pub resource: Option<Resource>,
392 pub role: Option<String>,
394}
395
396#[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 pub obj: Operand,
430 pub oper: RelationOperator,
432 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 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#[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 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#[derive(PartialEq, Debug, Clone)]
499pub struct TtlTimestamp {
500 pub ttl: Option<u64>,
502 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#[derive(PartialEq, Debug, Clone)]
528pub enum WithItem {
529 Option { key: String, value: OptionValue },
531 ClusterOrder(OrderClause),
533 ID(String),
535 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#[derive(PartialEq, Debug, Clone)]
552pub struct OrderClause {
553 pub name: Identifier,
555 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#[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#[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#[derive(PartialEq, Debug, Clone)]
626pub enum Resource {
627 AllFunctions(Option<String>),
629 AllKeyspaces,
631 AllRoles,
633 Function(FQName),
635 Keyspace(Identifier),
637 Role(String),
639 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 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 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#[derive(PartialEq, Debug, Clone, Hash, Eq, Deserialize)]
698pub struct FQName {
699 pub keyspace: Option<Identifier>,
700 pub name: Identifier,
701}
702
703impl FQName {
704 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#[derive(Debug, Clone, Eq, Ord, PartialOrd, Deserialize)]
784pub enum Identifier {
785 Quoted(String),
788 Unquoted(String),
792}
793
794impl Identifier {
795 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#[derive(Debug)]
866pub enum IdentifierRef<'a> {
867 Quoted(&'a str),
870 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("e_in_quoted, "e_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}