Skip to main content

uqa_sql/ast/
pattern_operator.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Native pattern syntax retains its operator identity independently of routine names.
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12pub enum PatternOperator {
13    Like,
14    NotLike,
15    ILike,
16    NotILike,
17    Regex,
18    NotRegex,
19    RegexInsensitive,
20    NotRegexInsensitive,
21}
22
23impl PatternOperator {
24    #[must_use]
25    pub fn from_symbol(symbol: &str) -> Option<Self> {
26        Some(match symbol {
27            "~~" => Self::Like,
28            "!~~" => Self::NotLike,
29            "~~*" => Self::ILike,
30            "!~~*" => Self::NotILike,
31            "~" => Self::Regex,
32            "!~" => Self::NotRegex,
33            "~*" => Self::RegexInsensitive,
34            "!~*" => Self::NotRegexInsensitive,
35            _ => return None,
36        })
37    }
38
39    /// The selected binary operator after any SQL escape helper.
40    #[must_use]
41    pub const fn symbol(self) -> &'static str {
42        match self {
43            Self::Like => "~~",
44            Self::NotLike => "!~~",
45            Self::ILike => "~~*",
46            Self::NotILike => "!~~*",
47            Self::Regex => "~",
48            Self::NotRegex => "!~",
49            Self::RegexInsensitive => "~*",
50            Self::NotRegexInsensitive => "!~*",
51        }
52    }
53
54    #[must_use]
55    pub const fn syntax(self) -> &'static str {
56        match self {
57            Self::Like => "LIKE",
58            Self::NotLike => "NOT LIKE",
59            Self::ILike => "ILIKE",
60            Self::NotILike => "NOT ILIKE",
61            _ => self.symbol(),
62        }
63    }
64
65    #[must_use]
66    pub const fn is_like(self) -> bool {
67        matches!(
68            self,
69            Self::Like | Self::NotLike | Self::ILike | Self::NotILike
70        )
71    }
72
73    #[must_use]
74    pub const fn case_insensitive(self) -> bool {
75        matches!(
76            self,
77            Self::ILike | Self::NotILike | Self::RegexInsensitive | Self::NotRegexInsensitive
78        )
79    }
80
81    #[must_use]
82    pub const fn negated(self) -> bool {
83        matches!(
84            self,
85            Self::NotLike | Self::NotILike | Self::NotRegex | Self::NotRegexInsensitive
86        )
87    }
88}