feat: AST traversal using Visitor pattern (#5796)
* feat: Partition implementation of Visitable for InfluxQL AST * feat: Added consistent structures for each clause to simplify visitor Continued to expand `accept` and `pre` / `post` visit implementations. * feat: Added insta and tests using snapshots (thanks @crepererum) The insta crate simplifies the process of validating the combination of visitor and accept implementations are called and in the correct order. * chore: Run cargo hakari tasks * feat: Added remaining snapshot tests Some tests are failing as some minor type changes must be added along with the addition of related visitor functions. * feat: Add types to represent each clause in numerous statements These clauses permit distinct visit functions on the `Visitor` type. * chore: Reformat `SELECT` * chore: Explicitly specify access to export selected types only This required completing all the missing documentation for the exported types. * chore: Update Cargo.lock * chore: macro to implement common traits and hide 0th tuple element Co-authored-by: CircleCI[bot] <circleci@influxdata.com>pull/24376/head
parent
9134ccd6c3
commit
81722dc19b
|
|
@ -667,9 +667,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.14"
|
||||
version = "4.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ea54a38e4bce14ff6931c72e5b3c43da7051df056913d4e7e1fcdb1c03df69d"
|
||||
checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
|
|
@ -684,7 +684,7 @@ dependencies = [
|
|||
name = "clap_blocks"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"data_types",
|
||||
"futures",
|
||||
"humantime",
|
||||
|
|
@ -834,6 +834,19 @@ dependencies = [
|
|||
"workspace-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"terminal_size",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console-api"
|
||||
version = "0.4.0"
|
||||
|
|
@ -1432,6 +1445,12 @@ version = "1.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.31"
|
||||
|
|
@ -1699,7 +1718,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-english",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"clap_blocks",
|
||||
"data_types",
|
||||
"filetime",
|
||||
|
|
@ -2171,6 +2190,7 @@ name = "influxdb_influxql_parser"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"insta",
|
||||
"nom",
|
||||
"test_helpers",
|
||||
"workspace-hack",
|
||||
|
|
@ -2185,7 +2205,7 @@ dependencies = [
|
|||
"assert_cmd",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"clap_blocks",
|
||||
"compactor",
|
||||
"console-subscriber",
|
||||
|
|
@ -2373,6 +2393,20 @@ dependencies = [
|
|||
"write_summary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581d4e3314cae4536e5d22ffd23189d4a374696c5ef733eadafae0ed273fd303"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
"linked-hash-map",
|
||||
"serde",
|
||||
"similar",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
|
|
@ -2430,7 +2464,7 @@ dependencies = [
|
|||
"bytes",
|
||||
"chrono",
|
||||
"chrono-english",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"criterion",
|
||||
"futures",
|
||||
"handlebars",
|
||||
|
|
@ -2524,7 +2558,7 @@ dependencies = [
|
|||
"async-trait",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"clap_blocks",
|
||||
"data_types",
|
||||
"flate2",
|
||||
|
|
@ -2680,7 +2714,7 @@ name = "ioxd_test"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"hyper",
|
||||
"ioxd_common",
|
||||
"metric",
|
||||
|
|
@ -2854,6 +2888,12 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.0.46"
|
||||
|
|
@ -5200,6 +5240,16 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termtree"
|
||||
version = "0.2.4"
|
||||
|
|
@ -5606,7 +5656,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"futures",
|
||||
"observability_deps",
|
||||
"snafu",
|
||||
|
|
@ -5745,7 +5795,7 @@ name = "trogging"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"clap 4.0.14",
|
||||
"clap 4.0.15",
|
||||
"logfmt",
|
||||
"observability_deps",
|
||||
"regex",
|
||||
|
|
@ -6158,6 +6208,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"similar",
|
||||
"smallvec",
|
||||
"sqlx",
|
||||
"sqlx-core",
|
||||
|
|
@ -6234,6 +6285,15 @@ dependencies = [
|
|||
"workspace-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
|
|
|
|||
|
|
@ -121,3 +121,10 @@ inherits = "release"
|
|||
codegen-units = 16
|
||||
lto = false
|
||||
incremental = true
|
||||
|
||||
# Per insta docs: https://insta.rs/docs/quickstart/#optional-faster-runs
|
||||
[profile.dev.package.insta]
|
||||
opt-level = 3
|
||||
|
||||
[profile.dev.package.similar]
|
||||
opt-level = 3
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ workspace-hack = { path = "../workspace-hack"}
|
|||
|
||||
[dev-dependencies] # In alphabetical order
|
||||
test_helpers = { path = "../test_helpers" }
|
||||
assert_matches = "1"
|
||||
assert_matches = "1"
|
||||
insta = { version = "1.21.0", features = ["yaml"] }
|
||||
|
|
@ -11,6 +11,7 @@ use nom::combinator::{map, opt, value};
|
|||
use nom::multi::separated_list1;
|
||||
use nom::sequence::{pair, preceded, terminated};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// Represents a measurement name as either an identifier or a regular expression.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
|
@ -44,8 +45,13 @@ impl Display for MeasurementName {
|
|||
/// Represents a fully-qualified, 3-part measurement name.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct QualifiedMeasurementName {
|
||||
/// An optional database name.
|
||||
pub database: Option<Identifier>,
|
||||
|
||||
/// An optional retention policy.
|
||||
pub retention_policy: Option<Identifier>,
|
||||
|
||||
/// The measurement name.
|
||||
pub name: MeasurementName,
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +93,7 @@ impl Display for QualifiedMeasurementName {
|
|||
/// policy_name ::= identifier
|
||||
/// measurement_name ::= identifier | regex_lit
|
||||
/// ```
|
||||
pub fn qualified_measurement_name(i: &str) -> ParseResult<&str, QualifiedMeasurementName> {
|
||||
pub(crate) fn qualified_measurement_name(i: &str) -> ParseResult<&str, QualifiedMeasurementName> {
|
||||
let (remaining_input, (opt_db_rp, name)) = pair(
|
||||
opt(alt((
|
||||
// database "." retention_policy "."
|
||||
|
|
@ -122,49 +128,153 @@ pub fn qualified_measurement_name(i: &str) -> ParseResult<&str, QualifiedMeasure
|
|||
))
|
||||
}
|
||||
|
||||
/// Implements common behaviour for u64 tuple-struct types
|
||||
#[macro_export]
|
||||
macro_rules! impl_tuple_clause {
|
||||
($NAME:ident, $FOR:ty) => {
|
||||
impl $NAME {
|
||||
/// Create a new instance with the specified value.
|
||||
pub fn new(value: $FOR) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for $NAME {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for $NAME {
|
||||
type Target = $FOR;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$FOR> for $NAME {
|
||||
fn from(value: $FOR) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Represents the value for a `LIMIT` clause.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct LimitClause(pub(crate) u64);
|
||||
|
||||
impl_tuple_clause!(LimitClause, u64);
|
||||
|
||||
impl Display for LimitClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "LIMIT {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a `LIMIT <n>` clause.
|
||||
pub fn limit_clause(i: &str) -> ParseResult<&str, u64> {
|
||||
pub(crate) fn limit_clause(i: &str) -> ParseResult<&str, LimitClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("LIMIT"), multispace1),
|
||||
expect(
|
||||
"invalid LIMIT clause, expected unsigned integer",
|
||||
unsigned_integer,
|
||||
map(unsigned_integer, LimitClause),
|
||||
),
|
||||
)(i)
|
||||
}
|
||||
|
||||
/// Represents the value for a `OFFSET` clause.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct OffsetClause(pub(crate) u64);
|
||||
|
||||
impl_tuple_clause!(OffsetClause, u64);
|
||||
|
||||
impl Display for OffsetClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "OFFSET {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an `OFFSET <n>` clause.
|
||||
pub fn offset_clause(i: &str) -> ParseResult<&str, u64> {
|
||||
pub(crate) fn offset_clause(i: &str) -> ParseResult<&str, OffsetClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("OFFSET"), multispace1),
|
||||
expect(
|
||||
"invalid OFFSET clause, expected unsigned integer",
|
||||
unsigned_integer,
|
||||
map(unsigned_integer, OffsetClause),
|
||||
),
|
||||
)(i)
|
||||
}
|
||||
|
||||
/// Parse a terminator that ends a SQL statement.
|
||||
pub fn statement_terminator(i: &str) -> ParseResult<&str, ()> {
|
||||
pub(crate) fn statement_terminator(i: &str) -> ParseResult<&str, ()> {
|
||||
value((), char(';'))(i)
|
||||
}
|
||||
|
||||
/// Represents the `WHERE` clause of a statement.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct WhereClause(pub(crate) ConditionalExpression);
|
||||
|
||||
impl WhereClause {
|
||||
/// Create an instance of a `WhereClause` using `expr`
|
||||
pub fn new(expr: ConditionalExpression) -> Self {
|
||||
Self(expr)
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for WhereClause {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for WhereClause {
|
||||
type Target = ConditionalExpression;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for WhereClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "WHERE {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a `WHERE` clause.
|
||||
pub fn where_clause(i: &str) -> ParseResult<&str, ConditionalExpression> {
|
||||
pub(crate) fn where_clause(i: &str) -> ParseResult<&str, WhereClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("WHERE"), multispace1),
|
||||
conditional_expression,
|
||||
map(conditional_expression, WhereClause),
|
||||
)(i)
|
||||
}
|
||||
|
||||
/// Represents an InfluxQL `ORDER BY` clause.
|
||||
#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum OrderByClause {
|
||||
/// Signals the `ORDER BY` is in ascending order.
|
||||
#[default]
|
||||
Ascending,
|
||||
|
||||
/// Signals the `ORDER BY` is in descending order.
|
||||
Descending,
|
||||
}
|
||||
|
||||
impl Display for OrderByClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"ORDER BY TIME {}",
|
||||
match self {
|
||||
Self::Ascending => "ASC",
|
||||
Self::Descending => "DESC",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an InfluxQL `ORDER BY` clause.
|
||||
///
|
||||
/// An `ORDER BY` in InfluxQL is limited when compared to the equivalent
|
||||
|
|
@ -187,7 +297,7 @@ pub enum OrderByClause {
|
|||
/// ```
|
||||
///
|
||||
/// [EBNF]: https://www.w3.org/TR/2010/REC-xquery-20101214/#EBNFNotation
|
||||
pub fn order_by_clause(i: &str) -> ParseResult<&str, OrderByClause> {
|
||||
pub(crate) fn order_by_clause(i: &str) -> ParseResult<&str, OrderByClause> {
|
||||
let order = || {
|
||||
preceded(
|
||||
multispace1,
|
||||
|
|
@ -221,29 +331,18 @@ pub fn order_by_clause(i: &str) -> ParseResult<&str, OrderByClause> {
|
|||
|
||||
/// Parser is a trait that allows a type to parse itself.
|
||||
pub trait Parser: Sized {
|
||||
/// Parse this type from the string `i`.
|
||||
fn parse(i: &str) -> ParseResult<&str, Self>;
|
||||
}
|
||||
|
||||
/// `OneOrMore` is a container for representing a minimum of one `T`.
|
||||
///
|
||||
/// `OneOrMore` provides a default implementation of [`fmt::Display`],
|
||||
/// which displays the contents separated by commas.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OneOrMore<T: Display + Parser> {
|
||||
contents: Vec<T>,
|
||||
pub struct OneOrMore<T> {
|
||||
pub(crate) contents: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Display + Parser> Display for OneOrMore<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self.first(), f)?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display + Parser> OneOrMore<T> {
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<T> OneOrMore<T> {
|
||||
/// Construct a new `OneOrMore<T>` with `contents`.
|
||||
///
|
||||
/// **NOTE:** that `new` panics if contents is empty.
|
||||
|
|
@ -272,11 +371,11 @@ impl<T: Display + Parser> OneOrMore<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Display + Parser> OneOrMore<T> {
|
||||
impl<T: Parser> OneOrMore<T> {
|
||||
/// Parse a list of one or more `T`, separated by commas.
|
||||
///
|
||||
/// Returns an error using `msg` if `separated_list1` fails to parse any elements.
|
||||
pub fn separated_list1<'a>(
|
||||
pub(crate) fn separated_list1<'a>(
|
||||
msg: &'static str,
|
||||
) -> impl FnMut(&'a str) -> ParseResult<&'a str, Self> {
|
||||
move |i: &str| {
|
||||
|
|
@ -303,7 +402,7 @@ mod tests {
|
|||
impl From<&str> for MeasurementName {
|
||||
/// Convert a `str` to [`MeasurementName::Name`].
|
||||
fn from(s: &str) -> Self {
|
||||
Self::Name(Identifier(s.into()))
|
||||
Self::Name(Identifier::new(s.into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,15 +507,15 @@ mod tests {
|
|||
#[test]
|
||||
fn test_limit_clause() {
|
||||
let (_, got) = limit_clause("LIMIT 587").unwrap();
|
||||
assert_eq!(got, 587);
|
||||
assert_eq!(*got, 587);
|
||||
|
||||
// case insensitive
|
||||
let (_, got) = limit_clause("limit 587").unwrap();
|
||||
assert_eq!(got, 587);
|
||||
assert_eq!(*got, 587);
|
||||
|
||||
// extra spaces between tokens
|
||||
let (_, got) = limit_clause("LIMIT 123").unwrap();
|
||||
assert_eq!(got, 123);
|
||||
assert_eq!(*got, 123);
|
||||
|
||||
// not digits
|
||||
assert_expect_error!(
|
||||
|
|
@ -440,15 +539,15 @@ mod tests {
|
|||
#[test]
|
||||
fn test_offset_clause() {
|
||||
let (_, got) = offset_clause("OFFSET 587").unwrap();
|
||||
assert_eq!(got, 587);
|
||||
assert_eq!(*got, 587);
|
||||
|
||||
// case insensitive
|
||||
let (_, got) = offset_clause("offset 587").unwrap();
|
||||
assert_eq!(got, 587);
|
||||
assert_eq!(*got, 587);
|
||||
|
||||
// extra spaces between tokens
|
||||
let (_, got) = offset_clause("OFFSET 123").unwrap();
|
||||
assert_eq!(got, 123);
|
||||
assert_eq!(*got, 123);
|
||||
|
||||
// not digits
|
||||
assert_expect_error!(
|
||||
|
|
@ -537,6 +636,16 @@ mod tests {
|
|||
|
||||
type OneOrMoreString = OneOrMore<String>;
|
||||
|
||||
impl Display for OneOrMoreString {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self.first(), f)?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "OneOrMore requires elements")]
|
||||
fn test_one_or_more() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::common::where_clause;
|
||||
use crate::expression::conditional::ConditionalExpression;
|
||||
use crate::common::{where_clause, WhereClause};
|
||||
use crate::internal::{expect, ParseResult};
|
||||
use crate::simple_from_clause::{delete_from_clause, DeleteFromClause};
|
||||
use nom::branch::alt;
|
||||
|
|
@ -9,17 +8,21 @@ use nom::combinator::{map, opt};
|
|||
use nom::sequence::{pair, preceded};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
/// Represents a `DELETE` statement.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum DeleteStatement {
|
||||
/// A DELETE with a measurement or measurements and an optional conditional expression
|
||||
/// to restrict which series are deleted.
|
||||
/// A DELETE with a `FROM` clause specifying one or more measurements
|
||||
/// and an optional `WHERE` clause to restrict which series are deleted.
|
||||
FromWhere {
|
||||
/// Represents the `FROM` clause.
|
||||
from: DeleteFromClause,
|
||||
condition: Option<ConditionalExpression>,
|
||||
|
||||
/// Represents the optional `WHERE` clause.
|
||||
condition: Option<WhereClause>,
|
||||
},
|
||||
|
||||
/// A `DELETE` with a conditional expression to restrict which series are deleted.
|
||||
Where(ConditionalExpression),
|
||||
/// A `DELETE` with a `WHERE` clause to restrict which series are deleted.
|
||||
Where(WhereClause),
|
||||
}
|
||||
|
||||
impl Display for DeleteStatement {
|
||||
|
|
@ -28,12 +31,12 @@ impl Display for DeleteStatement {
|
|||
|
||||
match self {
|
||||
Self::FromWhere { from, condition } => {
|
||||
write!(f, " FROM {}", from)?;
|
||||
if let Some(condition) = condition {
|
||||
write!(f, " WHERE {}", condition)?;
|
||||
write!(f, " {}", from)?;
|
||||
if let Some(where_clause) = condition {
|
||||
write!(f, " {}", where_clause)?;
|
||||
}
|
||||
}
|
||||
Self::Where(condition) => write!(f, " WHERE {}", condition)?,
|
||||
Self::Where(where_clause) => write!(f, " {}", where_clause)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
|
@ -41,7 +44,7 @@ impl Display for DeleteStatement {
|
|||
}
|
||||
|
||||
/// Parse a `DELETE` statement.
|
||||
pub fn delete_statement(i: &str) -> ParseResult<&str, DeleteStatement> {
|
||||
pub(crate) fn delete_statement(i: &str) -> ParseResult<&str, DeleteStatement> {
|
||||
// delete ::= "DELETE" ( from_clause where_clause? | where_clause )
|
||||
preceded(
|
||||
tag_no_case("DELETE"),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl Display for DropMeasurementStatement {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn drop_statement(i: &str) -> ParseResult<&str, DropMeasurementStatement> {
|
||||
pub(crate) fn drop_statement(i: &str) -> ParseResult<&str, DropMeasurementStatement> {
|
||||
preceded(
|
||||
pair(tag_no_case("DROP"), multispace1),
|
||||
expect(
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use nom::sequence::{preceded, tuple};
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
/// Represents various options for an `EXPLAIN` statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ExplainOption {
|
||||
/// `EXPLAIN VERBOSE statement`
|
||||
Verbose,
|
||||
|
|
@ -38,8 +38,11 @@ impl Display for ExplainOption {
|
|||
/// ```
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ExplainStatement {
|
||||
options: Option<ExplainOption>,
|
||||
select: Box<SelectStatement>,
|
||||
/// Represents any options specified for the `EXPLAIN` statement.
|
||||
pub options: Option<ExplainOption>,
|
||||
|
||||
/// Represents the `SELECT` statement to be explained and / or analyzed.
|
||||
pub select: Box<SelectStatement>,
|
||||
}
|
||||
|
||||
impl Display for ExplainStatement {
|
||||
|
|
@ -53,7 +56,7 @@ impl Display for ExplainStatement {
|
|||
}
|
||||
|
||||
/// Parse an `EXPLAIN` statement.
|
||||
pub fn explain_statement(i: &str) -> ParseResult<&str, ExplainStatement> {
|
||||
pub(crate) fn explain_statement(i: &str) -> ParseResult<&str, ExplainStatement> {
|
||||
map(
|
||||
tuple((
|
||||
tag_no_case("EXPLAIN"),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
pub use arithmetic::*;
|
||||
pub use conditional::*;
|
||||
|
||||
/// Provides arithmetic expression parsing.
|
||||
pub mod arithmetic;
|
||||
/// Provides conditional expression parsing.
|
||||
pub mod conditional;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -68,12 +68,21 @@ pub enum Expr {
|
|||
UnaryOp(UnaryOperator, Box<Expr>),
|
||||
|
||||
/// Function call
|
||||
Call { name: String, args: Vec<Expr> },
|
||||
Call {
|
||||
/// Represents the name of the function call.
|
||||
name: String,
|
||||
|
||||
/// Represents the list of arguments to the function call.
|
||||
args: Vec<Expr>,
|
||||
},
|
||||
|
||||
/// Binary operations, such as `1 + 2`.
|
||||
Binary {
|
||||
/// Represents the left-hand side of the binary expression.
|
||||
lhs: Box<Expr>,
|
||||
/// Represents the operator to apply to the binary expression.
|
||||
op: BinaryOperator,
|
||||
/// Represents the right-hand side of the binary expression.
|
||||
rhs: Box<Expr>,
|
||||
},
|
||||
|
||||
|
|
@ -142,7 +151,10 @@ impl Display for Expr {
|
|||
/// Specifies the data type of a wildcard (`*`) when using the `::` operator.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum WildcardType {
|
||||
/// Indicates the wildcard refers to tags only.
|
||||
Tag,
|
||||
|
||||
/// Indicates the wildcard refers to fields only.
|
||||
Field,
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +175,17 @@ impl Display for WildcardType {
|
|||
/// [cast]: https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/#cast-operations
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum VarRefDataType {
|
||||
/// Represents a 64-bit float.
|
||||
Float,
|
||||
/// Represents a 64-bit integer.
|
||||
Integer,
|
||||
/// Represents a UTF-8 string.
|
||||
String,
|
||||
/// Represents a boolean.
|
||||
Boolean,
|
||||
/// Represents a tag.
|
||||
Tag,
|
||||
/// Represents a field.
|
||||
Field,
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +205,9 @@ impl Display for VarRefDataType {
|
|||
/// An InfluxQL unary operator.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum UnaryOperator {
|
||||
/// Represents the unary `+` operator.
|
||||
Plus,
|
||||
/// Represents the unary `-` operator.
|
||||
Minus,
|
||||
}
|
||||
|
||||
|
|
@ -203,14 +223,22 @@ impl Display for UnaryOperator {
|
|||
/// An InfluxQL binary operators.
|
||||
#[derive(Clone, Debug, Copy, PartialEq, Eq)]
|
||||
pub enum BinaryOperator {
|
||||
Add, // +
|
||||
Sub, // -
|
||||
Mul, // *
|
||||
Div, // /
|
||||
Mod, // %
|
||||
BitwiseAnd, // &
|
||||
BitwiseOr, // |
|
||||
BitwiseXor, // ^
|
||||
/// Represents the `+` operator.
|
||||
Add,
|
||||
/// Represents the `-` operator.
|
||||
Sub,
|
||||
/// Represents the `*` operator.
|
||||
Mul,
|
||||
/// Represents the `/` operator.
|
||||
Div,
|
||||
/// Represents the `%` or modulus operator.
|
||||
Mod,
|
||||
/// Represents the `&` or bitwise-and operator.
|
||||
BitwiseAnd,
|
||||
/// Represents the `|` or bitwise-or operator.
|
||||
BitwiseOr,
|
||||
/// Represents the `^` or bitwise-xor operator.
|
||||
BitwiseXor,
|
||||
}
|
||||
|
||||
impl Display for BinaryOperator {
|
||||
|
|
@ -259,7 +287,7 @@ where
|
|||
}
|
||||
|
||||
/// Parse a function call expression
|
||||
pub fn call_expression<T>(i: &str) -> ParseResult<&str, Expr>
|
||||
pub(crate) fn call_expression<T>(i: &str) -> ParseResult<&str, Expr>
|
||||
where
|
||||
T: ArithmeticParsers,
|
||||
{
|
||||
|
|
@ -283,7 +311,7 @@ where
|
|||
}
|
||||
|
||||
/// Parse a variable reference, which is an identifier followed by an optional cast expression.
|
||||
pub fn var_ref(i: &str) -> ParseResult<&str, Expr> {
|
||||
pub(crate) fn var_ref(i: &str) -> ParseResult<&str, Expr> {
|
||||
map(
|
||||
pair(
|
||||
identifier,
|
||||
|
|
@ -342,7 +370,7 @@ where
|
|||
/// Parse an arithmetic expression.
|
||||
///
|
||||
/// This includes the addition, subtraction, bitwise or, and bitwise xor operators.
|
||||
pub fn arithmetic<T>(i: &str) -> ParseResult<&str, Expr>
|
||||
pub(crate) fn arithmetic<T>(i: &str) -> ParseResult<&str, Expr>
|
||||
where
|
||||
T: ArithmeticParsers,
|
||||
{
|
||||
|
|
@ -363,7 +391,7 @@ where
|
|||
}
|
||||
|
||||
/// A trait for customizing arithmetic parsers.
|
||||
pub trait ArithmeticParsers {
|
||||
pub(crate) trait ArithmeticParsers {
|
||||
/// Parse an operand of an arithmetic expression.
|
||||
fn operand(i: &str) -> ParseResult<&str, Expr>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,19 +13,31 @@ use nom::sequence::{delimited, preceded, tuple};
|
|||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter, Write};
|
||||
|
||||
/// Represents on of the conditional operators supported by [`ConditionalExpression::Binary`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ConditionalOperator {
|
||||
Eq, // =
|
||||
NotEq, // !=
|
||||
EqRegex, // =~
|
||||
NotEqRegex, // !~
|
||||
Lt, // <
|
||||
LtEq, // <=
|
||||
Gt, // >
|
||||
GtEq, // >=
|
||||
In, // IN
|
||||
And, // AND
|
||||
Or, // OR
|
||||
/// Represents the `=` operator.
|
||||
Eq,
|
||||
/// Represents the `!=` operator.
|
||||
NotEq,
|
||||
/// Represents the `=~` (regular expression equals) operator.
|
||||
EqRegex,
|
||||
/// Represents the `!~` (regular expression not equals) operator.
|
||||
NotEqRegex,
|
||||
/// Represents the `<` operator.
|
||||
Lt,
|
||||
/// Represents the `<=` operator.
|
||||
LtEq,
|
||||
/// Represents the `>` operator.
|
||||
Gt,
|
||||
/// Represents the `>=` operator.
|
||||
GtEq,
|
||||
/// Represents the `IN` operator.
|
||||
In,
|
||||
/// Represents the `AND` operator.
|
||||
And,
|
||||
/// Represents the `OR` operator.
|
||||
Or,
|
||||
}
|
||||
|
||||
impl Display for ConditionalOperator {
|
||||
|
|
@ -46,6 +58,7 @@ impl Display for ConditionalOperator {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents a conditional expression.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ConditionalExpression {
|
||||
/// Represents an arithmetic expression.
|
||||
|
|
@ -53,8 +66,11 @@ pub enum ConditionalExpression {
|
|||
|
||||
/// Binary operations, such as `foo = 'bar'` or `true AND false`.
|
||||
Binary {
|
||||
/// Represents the left-hand side of the conditional binary expression.
|
||||
lhs: Box<ConditionalExpression>,
|
||||
/// Represents the operator to apply to the conditional binary expression.
|
||||
op: ConditionalOperator,
|
||||
/// Represents the right-hand side of the conditional binary expression.
|
||||
rhs: Box<ConditionalExpression>,
|
||||
},
|
||||
|
||||
|
|
@ -162,7 +178,7 @@ fn disjunction(i: &str) -> ParseResult<&str, ConditionalExpression> {
|
|||
}
|
||||
|
||||
/// Parse an InfluxQL conditional expression.
|
||||
pub fn conditional_expression(i: &str) -> ParseResult<&str, ConditionalExpression> {
|
||||
pub(crate) fn conditional_expression(i: &str) -> ParseResult<&str, ConditionalExpression> {
|
||||
disjunction(i)
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +197,7 @@ fn reduce_expr(
|
|||
}
|
||||
|
||||
/// Returns true if `expr` is a valid [`Expr::Call`] expression for the `now` function.
|
||||
pub fn is_valid_now_call(expr: &Expr) -> bool {
|
||||
pub(crate) fn is_valid_now_call(expr: &Expr) -> bool {
|
||||
match expr {
|
||||
Expr::Call { name, args } => name.to_lowercase() == "now" && args.is_empty(),
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ macro_rules! regex {
|
|||
macro_rules! param {
|
||||
($EXPR: expr) => {
|
||||
$crate::expression::arithmetic::Expr::BindParameter(
|
||||
$crate::parameter::BindParameter($EXPR.into()).into(),
|
||||
$crate::parameter::BindParameter::new($EXPR.into()).into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
use crate::internal::ParseResult;
|
||||
use crate::keywords::sql_keyword;
|
||||
use crate::string::double_quoted_string;
|
||||
use crate::write_quoted_string;
|
||||
use crate::{impl_tuple_clause, write_quoted_string};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::{alpha1, alphanumeric1};
|
||||
|
|
@ -25,7 +25,7 @@ use std::fmt;
|
|||
use std::fmt::{Display, Formatter, Write};
|
||||
|
||||
/// Parse an unquoted InfluxQL identifier.
|
||||
pub fn unquoted_identifier(i: &str) -> ParseResult<&str, &str> {
|
||||
pub(crate) fn unquoted_identifier(i: &str) -> ParseResult<&str, &str> {
|
||||
preceded(
|
||||
not(sql_keyword),
|
||||
recognize(pair(
|
||||
|
|
@ -37,13 +37,9 @@ pub fn unquoted_identifier(i: &str) -> ParseResult<&str, &str> {
|
|||
|
||||
/// A type that represents an InfluxQL identifier.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Identifier(pub String);
|
||||
pub struct Identifier(pub(crate) String);
|
||||
|
||||
impl From<String> for Identifier {
|
||||
fn from(s: String) -> Self {
|
||||
Self(s)
|
||||
}
|
||||
}
|
||||
impl_tuple_clause!(Identifier, String);
|
||||
|
||||
impl From<&str> for Identifier {
|
||||
fn from(s: &str) -> Self {
|
||||
|
|
@ -59,7 +55,7 @@ impl Display for Identifier {
|
|||
}
|
||||
|
||||
/// Parses an InfluxQL [Identifier].
|
||||
pub fn identifier(i: &str) -> ParseResult<&str, Identifier> {
|
||||
pub(crate) fn identifier(i: &str) -> ParseResult<&str, Identifier> {
|
||||
// See: https://github.com/influxdata/influxql/blob/df51a45762be9c1b578f01718fa92d286a843fe9/scanner.go#L358-L362
|
||||
alt((
|
||||
map(unquoted_identifier, Into::into),
|
||||
|
|
|
|||
|
|
@ -109,4 +109,4 @@ impl<I> NomParseError<I> for Error<I> {
|
|||
|
||||
/// ParseResult is a type alias for [`nom::IResult`] used by nom combinator
|
||||
/// functions for parsing InfluxQL.
|
||||
pub type ParseResult<I, T, E = Error<I>> = nom::IResult<I, T, E>;
|
||||
pub(crate) type ParseResult<I, T, E = Error<I>> = nom::IResult<I, T, E>;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ fn keyword_show_to_write(i: &str) -> ParseResult<&str, &str> {
|
|||
}
|
||||
|
||||
/// Matches any InfluxQL reserved keyword.
|
||||
pub fn sql_keyword(i: &str) -> ParseResult<&str, &str> {
|
||||
pub(crate) fn sql_keyword(i: &str) -> ParseResult<&str, &str> {
|
||||
// NOTE that the alt function takes a tuple with a maximum arity of 21, hence
|
||||
// the reason these are broken into groups
|
||||
alt((
|
||||
|
|
|
|||
|
|
@ -14,10 +14,29 @@
|
|||
clippy::dbg_macro
|
||||
)]
|
||||
|
||||
pub use crate::common::*;
|
||||
pub use crate::delete::*;
|
||||
pub use crate::drop::*;
|
||||
pub use crate::explain::*;
|
||||
pub use crate::expression::*;
|
||||
pub use crate::identifier::*;
|
||||
pub use crate::literal::*;
|
||||
pub use crate::parameter::*;
|
||||
pub use crate::select::*;
|
||||
pub use crate::show::*;
|
||||
pub use crate::show_field_keys::*;
|
||||
pub use crate::show_measurements::*;
|
||||
pub use crate::show_retention_policies::*;
|
||||
pub use crate::show_tag_keys::*;
|
||||
pub use crate::show_tag_values::*;
|
||||
pub use crate::simple_from_clause::*;
|
||||
pub use crate::statement::*;
|
||||
pub use crate::string::*;
|
||||
pub use crate::visit::*;
|
||||
|
||||
use crate::common::statement_terminator;
|
||||
use crate::internal::Error as InternalError;
|
||||
use crate::statement::statement;
|
||||
pub use crate::statement::Statement;
|
||||
use nom::character::complete::multispace0;
|
||||
use nom::combinator::eof;
|
||||
use nom::Offset;
|
||||
|
|
@ -46,6 +65,7 @@ mod show_tag_values;
|
|||
mod simple_from_clause;
|
||||
mod statement;
|
||||
mod string;
|
||||
mod visit;
|
||||
|
||||
/// A error returned when parsing an InfluxQL query using
|
||||
/// [`parse_statements`] fails.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::internal::{map_fail, ParseResult};
|
||||
use crate::string::{regex, single_quoted_string, Regex};
|
||||
use crate::write_escaped;
|
||||
use crate::{impl_tuple_clause, write_escaped};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::{tag, tag_no_case};
|
||||
use nom::character::complete::{char, digit1, multispace0};
|
||||
|
|
@ -25,7 +25,7 @@ const NANOS_PER_DAY: i64 = 24 * NANOS_PER_HOUR;
|
|||
/// Number of nanoseconds in a week.
|
||||
const NANOS_PER_WEEK: i64 = 7 * NANOS_PER_DAY;
|
||||
|
||||
// Primitive InfluxQL literal values, such as strings and regular expressions.
|
||||
/// Primitive InfluxQL literal values, such as strings and regular expressions.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Literal {
|
||||
/// Unsigned integer literal.
|
||||
|
|
@ -118,7 +118,7 @@ fn integer(i: &str) -> ParseResult<&str, i64> {
|
|||
/// ```text
|
||||
/// INTEGER ::= [0-9]+
|
||||
/// ```
|
||||
pub fn unsigned_integer(i: &str) -> ParseResult<&str, u64> {
|
||||
pub(crate) fn unsigned_integer(i: &str) -> ParseResult<&str, u64> {
|
||||
map_fail("unable to parse unsigned integer", digit1, &str::parse)(i)
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,9 @@ fn float(i: &str) -> ParseResult<&str, f64> {
|
|||
/// Represents any signed number.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Number {
|
||||
/// Contains a 64-bit integer.
|
||||
Integer(i64),
|
||||
/// Contains a 64-bit float.
|
||||
Float(f64),
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +169,7 @@ impl From<i64> for Number {
|
|||
}
|
||||
|
||||
/// Parse a signed [`Number`].
|
||||
pub fn number(i: &str) -> ParseResult<&str, Number> {
|
||||
pub(crate) fn number(i: &str) -> ParseResult<&str, Number> {
|
||||
let (remaining, sign) = opt(alt((char('-'), char('+'))))(i)?;
|
||||
preceded(
|
||||
multispace0,
|
||||
|
|
@ -204,13 +206,9 @@ enum DurationUnit {
|
|||
|
||||
/// Represents an InfluxQL duration in nanoseconds.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Duration(i64);
|
||||
pub struct Duration(pub(crate) i64);
|
||||
|
||||
impl From<i64> for Duration {
|
||||
fn from(v: i64) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
impl_tuple_clause!(Duration, i64);
|
||||
|
||||
static DIVISORS: [(i64, &str); 8] = [
|
||||
(NANOS_PER_WEEK, "w"),
|
||||
|
|
@ -276,7 +274,7 @@ fn single_duration(i: &str) -> ParseResult<&str, i64> {
|
|||
}
|
||||
|
||||
/// Parse the input for an InfluxQL duration.
|
||||
pub fn duration(i: &str) -> ParseResult<&str, Duration> {
|
||||
pub(crate) fn duration(i: &str) -> ParseResult<&str, Duration> {
|
||||
map(
|
||||
fold_many1(single_duration, || 0, |acc, fragment| acc + fragment),
|
||||
Duration,
|
||||
|
|
@ -286,7 +284,7 @@ pub fn duration(i: &str) -> ParseResult<&str, Duration> {
|
|||
/// Parse an InfluxQL literal, except a [`Regex`].
|
||||
///
|
||||
/// Use [`literal`] for parsing any literals, excluding regular expressions.
|
||||
pub fn literal_no_regex(i: &str) -> ParseResult<&str, Literal> {
|
||||
pub(crate) fn literal_no_regex(i: &str) -> ParseResult<&str, Literal> {
|
||||
alt((
|
||||
// NOTE: order is important, as floats should be tested before durations and integers.
|
||||
map(float, Literal::Float),
|
||||
|
|
@ -298,12 +296,12 @@ pub fn literal_no_regex(i: &str) -> ParseResult<&str, Literal> {
|
|||
}
|
||||
|
||||
/// Parse any InfluxQL literal.
|
||||
pub fn literal(i: &str) -> ParseResult<&str, Literal> {
|
||||
pub(crate) fn literal(i: &str) -> ParseResult<&str, Literal> {
|
||||
alt((literal_no_regex, map(regex, Literal::Regex)))(i)
|
||||
}
|
||||
|
||||
/// Parse an InfluxQL literal regular expression.
|
||||
pub fn literal_regex(i: &str) -> ParseResult<&str, Literal> {
|
||||
pub(crate) fn literal_regex(i: &str) -> ParseResult<&str, Literal> {
|
||||
map(regex, Literal::Regex)(i)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use crate::internal::ParseResult;
|
||||
use crate::string::double_quoted_string;
|
||||
use crate::write_quoted_string;
|
||||
use crate::{impl_tuple_clause, write_quoted_string};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::{alphanumeric1, char};
|
||||
|
|
@ -26,13 +26,9 @@ fn unquoted_parameter(i: &str) -> ParseResult<&str, &str> {
|
|||
|
||||
/// A type that represents an InfluxQL bind parameter.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct BindParameter(pub String);
|
||||
pub struct BindParameter(pub(crate) String);
|
||||
|
||||
impl From<String> for BindParameter {
|
||||
fn from(s: String) -> Self {
|
||||
Self(s)
|
||||
}
|
||||
}
|
||||
impl_tuple_clause!(BindParameter, String);
|
||||
|
||||
impl From<&str> for BindParameter {
|
||||
fn from(s: &str) -> Self {
|
||||
|
|
@ -49,7 +45,7 @@ impl Display for BindParameter {
|
|||
}
|
||||
|
||||
/// Parses an InfluxQL [BindParameter].
|
||||
pub fn parameter(i: &str) -> ParseResult<&str, BindParameter> {
|
||||
pub(crate) fn parameter(i: &str) -> ParseResult<&str, BindParameter> {
|
||||
// See: https://github.com/influxdata/influxql/blob/df51a45762be9c1b578f01718fa92d286a843fe9/scanner.go#L358-L362
|
||||
preceded(
|
||||
char('$'),
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
use crate::common::{
|
||||
limit_clause, offset_clause, order_by_clause, qualified_measurement_name, where_clause,
|
||||
OneOrMore, OrderByClause, Parser, QualifiedMeasurementName,
|
||||
LimitClause, OffsetClause, OneOrMore, OrderByClause, Parser, QualifiedMeasurementName,
|
||||
WhereClause,
|
||||
};
|
||||
use crate::expression::arithmetic::Expr::Wildcard;
|
||||
use crate::expression::arithmetic::{
|
||||
arithmetic, call_expression, var_ref, ArithmeticParsers, Expr, WildcardType,
|
||||
};
|
||||
use crate::expression::conditional::{is_valid_now_call, ConditionalExpression};
|
||||
use crate::expression::conditional::is_valid_now_call;
|
||||
use crate::identifier::{identifier, Identifier};
|
||||
use crate::internal::{expect, verify, ParseResult};
|
||||
use crate::literal::{duration, literal, number, unsigned_integer, Literal, Number};
|
||||
use crate::parameter::parameter;
|
||||
use crate::select::MeasurementSelection::Subquery;
|
||||
use crate::string::{regex, single_quoted_string, Regex};
|
||||
use crate::write_escaped;
|
||||
use crate::{impl_tuple_clause, write_escaped};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::{tag, tag_no_case};
|
||||
use nom::character::complete::{char, multispace0, multispace1};
|
||||
|
|
@ -22,6 +23,7 @@ use nom::sequence::{delimited, pair, preceded, tuple};
|
|||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter, Write};
|
||||
|
||||
/// Represents a `SELECT` statement.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SelectStatement {
|
||||
/// Expressions returned by the selection.
|
||||
|
|
@ -31,85 +33,83 @@ pub struct SelectStatement {
|
|||
pub from: FromMeasurementClause,
|
||||
|
||||
/// A conditional expression to filter the selection.
|
||||
pub condition: Option<ConditionalExpression>,
|
||||
pub condition: Option<WhereClause>,
|
||||
|
||||
/// Expressions used for grouping the selection.
|
||||
pub group_by: Option<GroupByList>,
|
||||
pub group_by: Option<GroupByClause>,
|
||||
|
||||
/// The [fill option][fill] specified for the selection. If the value is [`None`],
|
||||
/// The [fill clause] specifies the fill behaviour for the selection. If the value is [`None`],
|
||||
/// it is the same behavior as `fill(none)`.
|
||||
///
|
||||
/// [fill]: https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/#group-by-time-intervals-and-fill
|
||||
pub fill_option: Option<FillOption>,
|
||||
pub fill: Option<FillClause>,
|
||||
|
||||
/// Configures the ordering of the selection by time.
|
||||
pub order_by: Option<OrderByClause>,
|
||||
|
||||
/// A value to restrict the number of rows returned.
|
||||
pub limit: Option<u64>,
|
||||
pub limit: Option<LimitClause>,
|
||||
|
||||
/// A value to specify an offset to start retrieving rows.
|
||||
pub offset: Option<u64>,
|
||||
pub offset: Option<OffsetClause>,
|
||||
|
||||
/// A value to restrict the number of series returned.
|
||||
pub series_limit: Option<u64>,
|
||||
pub series_limit: Option<SLimitClause>,
|
||||
|
||||
/// A value to specify an offset to start retrieving series.
|
||||
pub series_offset: Option<u64>,
|
||||
pub series_offset: Option<SOffsetClause>,
|
||||
|
||||
/// The timezone for the query, specified as [`tz('<time zone>')`][time_zone_clause].
|
||||
///
|
||||
/// [time_zone_clause]: https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/#the-time-zone-clause
|
||||
pub timezone: Option<String>,
|
||||
pub timezone: Option<TimeZoneClause>,
|
||||
}
|
||||
|
||||
impl Display for SelectStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SELECT {} FROM {}", self.fields, self.from)?;
|
||||
write!(f, "SELECT {} {}", self.fields, self.from)?;
|
||||
|
||||
if let Some(condition) = &self.condition {
|
||||
write!(f, " WHERE {}", condition)?;
|
||||
if let Some(where_clause) = &self.condition {
|
||||
write!(f, " {}", where_clause)?;
|
||||
}
|
||||
|
||||
if let Some(group_by) = &self.group_by {
|
||||
write!(f, " GROUP BY {}", group_by)?;
|
||||
write!(f, " {}", group_by)?;
|
||||
}
|
||||
|
||||
if let Some(fill_option) = &self.fill_option {
|
||||
write!(f, " FILL({})", fill_option)?;
|
||||
if let Some(fill_clause) = &self.fill {
|
||||
write!(f, " {}", fill_clause)?;
|
||||
}
|
||||
|
||||
if let Some(OrderByClause::Descending) = &self.order_by {
|
||||
write!(f, " ORDER BY TIME DESC")?;
|
||||
if let Some(order_by) = &self.order_by {
|
||||
write!(f, " {}", order_by)?;
|
||||
}
|
||||
|
||||
if let Some(limit) = &self.limit {
|
||||
write!(f, " LIMIT {}", limit)?;
|
||||
write!(f, " {}", limit)?;
|
||||
}
|
||||
|
||||
if let Some(offset) = &self.offset {
|
||||
write!(f, " OFFSET {}", offset)?;
|
||||
write!(f, " {}", offset)?;
|
||||
}
|
||||
|
||||
if let Some(slimit) = &self.series_limit {
|
||||
write!(f, " SLIMIT {}", slimit)?;
|
||||
write!(f, " {}", slimit)?;
|
||||
}
|
||||
|
||||
if let Some(soffset) = &self.series_offset {
|
||||
write!(f, " SOFFSET {}", soffset)?;
|
||||
write!(f, " {}", soffset)?;
|
||||
}
|
||||
|
||||
if let Some(tz) = &self.timezone {
|
||||
f.write_str(" TZ('")?;
|
||||
write_escaped!(f, tz, '\n' => "\\n", '\\' => "\\\\", '\'' => "\\'", '"' => "\\\"");
|
||||
f.write_str("')")?;
|
||||
if let Some(tz_clause) = &self.timezone {
|
||||
write!(f, " {}", tz_clause)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_statement(i: &str) -> ParseResult<&str, SelectStatement> {
|
||||
pub(crate) fn select_statement(i: &str) -> ParseResult<&str, SelectStatement> {
|
||||
let (
|
||||
remaining,
|
||||
(
|
||||
|
|
@ -150,7 +150,7 @@ pub fn select_statement(i: &str) -> ParseResult<&str, SelectStatement> {
|
|||
from,
|
||||
condition,
|
||||
group_by,
|
||||
fill_option,
|
||||
fill: fill_option,
|
||||
order_by,
|
||||
limit,
|
||||
offset,
|
||||
|
|
@ -161,10 +161,13 @@ pub fn select_statement(i: &str) -> ParseResult<&str, SelectStatement> {
|
|||
))
|
||||
}
|
||||
|
||||
/// Represents a single measurement selection found in a `FROM` clause.
|
||||
/// Represents a single measurement selection for a `FROM` clause.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum MeasurementSelection {
|
||||
/// The measurement selection is measurement name or regular expression.
|
||||
Name(QualifiedMeasurementName),
|
||||
|
||||
/// The measurement selection is a subquery.
|
||||
Subquery(Box<SelectStatement>),
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +199,16 @@ impl Parser for MeasurementSelection {
|
|||
/// Represents a `FROM` clause for a `SELECT` statement.
|
||||
pub type FromMeasurementClause = OneOrMore<MeasurementSelection>;
|
||||
|
||||
impl Display for FromMeasurementClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FROM {}", self.first())?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn from_clause(i: &str) -> ParseResult<&str, FromMeasurementClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("FROM"), multispace1),
|
||||
|
|
@ -205,7 +218,18 @@ fn from_clause(i: &str) -> ParseResult<&str, FromMeasurementClause> {
|
|||
)(i)
|
||||
}
|
||||
|
||||
pub type GroupByList = OneOrMore<Dimension>;
|
||||
/// Represents the collection of dimensions for a `GROUP BY` clause.
|
||||
pub type GroupByClause = OneOrMore<Dimension>;
|
||||
|
||||
impl Display for GroupByClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "GROUP BY {}", self.first())?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to parse the interval argument of the TIME function
|
||||
struct TimeCallIntervalArgument;
|
||||
|
|
@ -251,11 +275,14 @@ impl ArithmeticParsers for TimeCallOffsetArgument {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents a dimension of a `GROUP BY` clause.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Dimension {
|
||||
/// Represents a `TIME` call in a `GROUP BY` clause.
|
||||
Time {
|
||||
/// The first argument of the `TIME` call.
|
||||
interval: Expr,
|
||||
/// An optional second argument to specify the offset applied to the `TIME` call.
|
||||
offset: Option<Expr>,
|
||||
},
|
||||
|
||||
|
|
@ -336,7 +363,7 @@ fn time_call_expression(i: &str) -> ParseResult<&str, Dimension> {
|
|||
/// ```text
|
||||
/// group_by_clause ::= dimension ( "," dimension )*
|
||||
/// ```
|
||||
fn group_by_clause(i: &str) -> ParseResult<&str, GroupByList> {
|
||||
fn group_by_clause(i: &str) -> ParseResult<&str, GroupByClause> {
|
||||
preceded(
|
||||
tuple((
|
||||
tag_no_case("GROUP"),
|
||||
|
|
@ -344,15 +371,15 @@ fn group_by_clause(i: &str) -> ParseResult<&str, GroupByList> {
|
|||
expect("invalid GROUP BY clause, expected BY", tag_no_case("BY")),
|
||||
multispace1,
|
||||
)),
|
||||
GroupByList::separated_list1(
|
||||
GroupByClause::separated_list1(
|
||||
"invalid GROUP BY clause, expected wildcard, TIME, identifier or regular expression",
|
||||
),
|
||||
)(i)
|
||||
}
|
||||
|
||||
/// Represents all cases of an option argument of a `FILL` clause.
|
||||
/// Represents a `FILL` clause, and specifies all possible cases of the argument to the `FILL` clause.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum FillOption {
|
||||
pub enum FillClause {
|
||||
/// Empty aggregate windows will contain null values and is specified as `fill(null)`
|
||||
Null,
|
||||
|
||||
|
|
@ -372,22 +399,27 @@ pub enum FillOption {
|
|||
Linear,
|
||||
}
|
||||
|
||||
impl Display for FillOption {
|
||||
impl Display for FillClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("FILL(")?;
|
||||
match self {
|
||||
Self::Null => f.write_str("NULL"),
|
||||
Self::None => f.write_str("NONE"),
|
||||
Self::Value(v) => fmt::Display::fmt(v, f),
|
||||
Self::Previous => f.write_str("PREVIOUS"),
|
||||
Self::Linear => f.write_str("LINEAR"),
|
||||
Self::Null => f.write_str("NULL")?,
|
||||
Self::None => f.write_str("NONE")?,
|
||||
Self::Value(v) => fmt::Display::fmt(v, f)?,
|
||||
Self::Previous => f.write_str("PREVIOUS")?,
|
||||
Self::Linear => f.write_str("LINEAR")?,
|
||||
}
|
||||
f.write_str(")")
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an expression specified in the projection list of a `SELECT` statement.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Field {
|
||||
/// The expression which represents the field projection.
|
||||
pub expr: Expr,
|
||||
|
||||
/// An optional alias for the field projection.
|
||||
pub alias: Option<Identifier>,
|
||||
}
|
||||
|
||||
|
|
@ -440,8 +472,19 @@ fn wildcard(i: &str) -> ParseResult<&str, Option<WildcardType>> {
|
|||
)(i)
|
||||
}
|
||||
|
||||
/// Represents the field projection list of a `SELECT` statement.
|
||||
pub type FieldList = OneOrMore<Field>;
|
||||
|
||||
impl Display for FieldList {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(self.first(), f)?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a field expression.
|
||||
///
|
||||
/// A field expression is an arithmetic expression accepting
|
||||
|
|
@ -495,7 +538,7 @@ fn field_list(i: &str) -> ParseResult<&str, FieldList> {
|
|||
/// fill_option ::= "NULL" | "NONE" | "PREVIOUS" | "LINEAR" | number
|
||||
/// number ::= signed_integer | signed_float
|
||||
/// ```
|
||||
fn fill_clause(i: &str) -> ParseResult<&str, FillOption> {
|
||||
fn fill_clause(i: &str) -> ParseResult<&str, FillClause> {
|
||||
preceded(
|
||||
tag_no_case("FILL"),
|
||||
delimited(
|
||||
|
|
@ -505,11 +548,11 @@ fn fill_clause(i: &str) -> ParseResult<&str, FillOption> {
|
|||
preceded(
|
||||
multispace0,
|
||||
alt((
|
||||
value(FillOption::Null, tag_no_case("NULL")),
|
||||
value(FillOption::None, tag_no_case("NONE")),
|
||||
map(number, FillOption::Value),
|
||||
value(FillOption::Previous, tag_no_case("PREVIOUS")),
|
||||
value(FillOption::Linear, tag_no_case("LINEAR")),
|
||||
value(FillClause::Null, tag_no_case("NULL")),
|
||||
value(FillClause::None, tag_no_case("NONE")),
|
||||
map(number, FillClause::Value),
|
||||
value(FillClause::Previous, tag_no_case("PREVIOUS")),
|
||||
value(FillClause::Linear, tag_no_case("LINEAR")),
|
||||
)),
|
||||
),
|
||||
),
|
||||
|
|
@ -518,49 +561,87 @@ fn fill_clause(i: &str) -> ParseResult<&str, FillOption> {
|
|||
)(i)
|
||||
}
|
||||
|
||||
/// Represents the value for a `SLIMIT` clause.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct SLimitClause(pub(crate) u64);
|
||||
|
||||
impl_tuple_clause!(SLimitClause, u64);
|
||||
|
||||
impl Display for SLimitClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SLIMIT {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a series limit (`SLIMIT <n>`) clause.
|
||||
///
|
||||
/// ```text
|
||||
/// slimit_clause ::= "SLIMIT" unsigned_integer
|
||||
/// ```
|
||||
fn slimit_clause(i: &str) -> ParseResult<&str, u64> {
|
||||
fn slimit_clause(i: &str) -> ParseResult<&str, SLimitClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("SLIMIT"), multispace1),
|
||||
expect(
|
||||
"invalid SLIMIT clause, expected unsigned integer",
|
||||
unsigned_integer,
|
||||
map(unsigned_integer, SLimitClause),
|
||||
),
|
||||
)(i)
|
||||
}
|
||||
|
||||
/// Represents the value for a `SOFFSET` clause.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct SOffsetClause(pub(crate) u64);
|
||||
|
||||
impl_tuple_clause!(SOffsetClause, u64);
|
||||
|
||||
impl Display for SOffsetClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SOFFSET {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a series offset (`SOFFSET <n>`) clause.
|
||||
///
|
||||
/// ```text
|
||||
/// soffset_clause ::= "SOFFSET" unsigned_integer
|
||||
/// ```
|
||||
fn soffset_clause(i: &str) -> ParseResult<&str, u64> {
|
||||
fn soffset_clause(i: &str) -> ParseResult<&str, SOffsetClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("SOFFSET"), multispace1),
|
||||
expect(
|
||||
"invalid SLIMIT clause, expected unsigned integer",
|
||||
unsigned_integer,
|
||||
map(unsigned_integer, SOffsetClause),
|
||||
),
|
||||
)(i)
|
||||
}
|
||||
|
||||
/// Represents the value of the time zone string of a `TZ` clause.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TimeZoneClause(pub(crate) String);
|
||||
|
||||
impl_tuple_clause!(TimeZoneClause, String);
|
||||
|
||||
impl Display for TimeZoneClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("TZ('")?;
|
||||
write_escaped!(f, self.0, '\n' => "\\n", '\\' => "\\\\", '\'' => "\\'", '"' => "\\\"");
|
||||
f.write_str("')")
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a timezone clause.
|
||||
///
|
||||
/// ```text
|
||||
/// timezone_clause ::= "TZ" "(" single_quoted_string ")"
|
||||
/// ```
|
||||
fn timezone_clause(i: &str) -> ParseResult<&str, String> {
|
||||
fn timezone_clause(i: &str) -> ParseResult<&str, TimeZoneClause> {
|
||||
preceded(
|
||||
tag_no_case("TZ"),
|
||||
delimited(
|
||||
preceded(multispace0, char('(')),
|
||||
expect(
|
||||
"invalid TZ clause, expected string",
|
||||
preceded(multispace0, single_quoted_string),
|
||||
preceded(multispace0, map(single_quoted_string, TimeZoneClause)),
|
||||
),
|
||||
preceded(multispace0, char(')')),
|
||||
),
|
||||
|
|
@ -608,7 +689,10 @@ mod test {
|
|||
);
|
||||
|
||||
let (_, got) = select_statement("SELECT value FROM foo ORDER BY TIME ASC").unwrap();
|
||||
assert_eq!(format!("{}", got), r#"SELECT value FROM foo"#);
|
||||
assert_eq!(
|
||||
format!("{}", got),
|
||||
r#"SELECT value FROM foo ORDER BY TIME ASC"#
|
||||
);
|
||||
|
||||
let (_, got) = select_statement("SELECT value FROM foo LIMIT 5").unwrap();
|
||||
assert_eq!(format!("{}", got), r#"SELECT value FROM foo LIMIT 5"#);
|
||||
|
|
@ -958,26 +1042,26 @@ mod test {
|
|||
#[test]
|
||||
fn test_fill_clause() {
|
||||
let (_, got) = fill_clause("FILL(null)").unwrap();
|
||||
assert_matches!(got, FillOption::Null);
|
||||
assert_matches!(got, FillClause::Null);
|
||||
|
||||
let (_, got) = fill_clause("FILL(NONE)").unwrap();
|
||||
assert_matches!(got, FillOption::None);
|
||||
assert_matches!(got, FillClause::None);
|
||||
|
||||
let (_, got) = fill_clause("FILL(53)").unwrap();
|
||||
assert_matches!(got, FillOption::Value(v) if v == 53.into());
|
||||
assert_matches!(got, FillClause::Value(v) if v == 53.into());
|
||||
|
||||
let (_, got) = fill_clause("FILL(-18.9)").unwrap();
|
||||
assert_matches!(got, FillOption::Value(v) if v == (-18.9).into());
|
||||
assert_matches!(got, FillClause::Value(v) if v == (-18.9).into());
|
||||
|
||||
let (_, got) = fill_clause("FILL(previous)").unwrap();
|
||||
assert_matches!(got, FillOption::Previous);
|
||||
assert_matches!(got, FillClause::Previous);
|
||||
|
||||
let (_, got) = fill_clause("FILL(linear)").unwrap();
|
||||
assert_matches!(got, FillOption::Linear);
|
||||
assert_matches!(got, FillClause::Linear);
|
||||
|
||||
// unnecessary whitespace
|
||||
let (_, got) = fill_clause("FILL ( null )").unwrap();
|
||||
assert_matches!(got, FillOption::Null);
|
||||
assert_matches!(got, FillClause::Null);
|
||||
|
||||
// Fallible cases
|
||||
|
||||
|
|
@ -990,7 +1074,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_timezone_clause() {
|
||||
let (_, got) = timezone_clause("TZ('Australia/Hobart')").unwrap();
|
||||
assert_eq!(got, "Australia/Hobart");
|
||||
assert_eq!(*got, "Australia/Hobart");
|
||||
|
||||
// Fallible cases
|
||||
assert_expect_error!(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::show_measurements::show_measurements;
|
|||
use crate::show_retention_policies::show_retention_policies;
|
||||
use crate::show_tag_keys::show_tag_keys;
|
||||
use crate::show_tag_values::show_tag_values;
|
||||
use crate::Statement;
|
||||
use crate::{impl_tuple_clause, Statement};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag_no_case;
|
||||
use nom::character::complete::multispace1;
|
||||
|
|
@ -14,7 +14,7 @@ use nom::sequence::{pair, preceded};
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
/// Parse a SHOW statement.
|
||||
pub fn show_statement(i: &str) -> ParseResult<&str, Statement> {
|
||||
pub(crate) fn show_statement(i: &str) -> ParseResult<&str, Statement> {
|
||||
preceded(
|
||||
pair(tag_no_case("SHOW"), multispace1),
|
||||
expect(
|
||||
|
|
@ -54,12 +54,26 @@ fn show_databases(i: &str) -> ParseResult<&str, ShowDatabasesStatement> {
|
|||
value(ShowDatabasesStatement, tag_no_case("DATABASES"))(i)
|
||||
}
|
||||
|
||||
/// Parse an `ON` clause for `SHOW TAG KEYS`, `SHOW TAG VALUES` and `SHOW FIELD KEYS`
|
||||
/// statements.
|
||||
pub fn on_clause(i: &str) -> ParseResult<&str, Identifier> {
|
||||
/// Represents an `ON` clause for the case where the database is a single [`Identifier`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OnClause(pub(crate) Identifier);
|
||||
|
||||
impl_tuple_clause!(OnClause, Identifier);
|
||||
|
||||
impl Display for OnClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ON {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an `ON` clause for statements such as `SHOW TAG KEYS` and `SHOW FIELD KEYS`.
|
||||
pub(crate) fn on_clause(i: &str) -> ParseResult<&str, OnClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("ON"), multispace1),
|
||||
expect("invalid ON clause, expected identifier", identifier),
|
||||
expect(
|
||||
"invalid ON clause, expected identifier",
|
||||
map(identifier, OnClause),
|
||||
),
|
||||
)(i)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::common::{limit_clause, offset_clause};
|
||||
use crate::identifier::Identifier;
|
||||
use crate::common::{limit_clause, offset_clause, LimitClause, OffsetClause};
|
||||
use crate::internal::{expect, ParseResult};
|
||||
use crate::show::on_clause;
|
||||
use crate::show::{on_clause, OnClause};
|
||||
use crate::simple_from_clause::{show_from_clause, ShowFromClause};
|
||||
use nom::bytes::complete::tag_no_case;
|
||||
use nom::character::complete::multispace1;
|
||||
|
|
@ -15,37 +14,37 @@ use std::fmt::Formatter;
|
|||
pub struct ShowFieldKeysStatement {
|
||||
/// The name of the database to query. If `None`, a default
|
||||
/// database will be used.
|
||||
pub database: Option<Identifier>,
|
||||
pub database: Option<OnClause>,
|
||||
|
||||
/// The measurement or measurements to restrict which field keys
|
||||
/// are retrieved.
|
||||
pub from: Option<ShowFromClause>,
|
||||
|
||||
/// A value to restrict the number of field keys returned.
|
||||
pub limit: Option<u64>,
|
||||
pub limit: Option<LimitClause>,
|
||||
|
||||
/// A value to specify an offset to start retrieving field keys.
|
||||
pub offset: Option<u64>,
|
||||
pub offset: Option<OffsetClause>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ShowFieldKeysStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SHOW FIELD KEYS")?;
|
||||
f.write_str("SHOW FIELD KEYS")?;
|
||||
|
||||
if let Some(ref expr) = self.database {
|
||||
write!(f, " ON {}", expr)?;
|
||||
if let Some(ref on_clause) = self.database {
|
||||
write!(f, " {}", on_clause)?;
|
||||
}
|
||||
|
||||
if let Some(ref expr) = self.from {
|
||||
write!(f, " FROM {}", expr)?;
|
||||
write!(f, " {}", expr)?;
|
||||
}
|
||||
|
||||
if let Some(limit) = self.limit {
|
||||
write!(f, " LIMIT {}", limit)?;
|
||||
if let Some(ref limit) = self.limit {
|
||||
write!(f, " {}", limit)?;
|
||||
}
|
||||
|
||||
if let Some(offset) = self.offset {
|
||||
write!(f, " OFFSET {}", offset)?;
|
||||
if let Some(ref offset) = self.offset {
|
||||
write!(f, " {}", offset)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -53,7 +52,7 @@ impl fmt::Display for ShowFieldKeysStatement {
|
|||
}
|
||||
|
||||
/// Parse a `SHOW FIELD KEYS` statement, starting from the `FIELD` token.
|
||||
pub fn show_field_keys(i: &str) -> ParseResult<&str, ShowFieldKeysStatement> {
|
||||
pub(crate) fn show_field_keys(i: &str) -> ParseResult<&str, ShowFieldKeysStatement> {
|
||||
let (
|
||||
remaining_input,
|
||||
(
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
//! [sql]: https://docs.influxdata.com/influxdb/v1.8/query_language/explore-schema/#show-measurements
|
||||
|
||||
use crate::common::{
|
||||
limit_clause, offset_clause, qualified_measurement_name, where_clause, QualifiedMeasurementName,
|
||||
limit_clause, offset_clause, qualified_measurement_name, where_clause, LimitClause,
|
||||
OffsetClause, QualifiedMeasurementName, WhereClause,
|
||||
};
|
||||
use crate::expression::conditional::ConditionalExpression;
|
||||
use crate::identifier::{identifier, Identifier};
|
||||
use crate::internal::{expect, ParseResult};
|
||||
use nom::branch::alt;
|
||||
|
|
@ -17,18 +17,24 @@ use nom::sequence::{pair, preceded, terminated};
|
|||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
/// OnExpression represents an InfluxQL database or retention policy name
|
||||
/// or a wildcard.
|
||||
/// Represents an `ON` clause for a `SHOW MEASUREMENTS` statement to specify
|
||||
/// which database the statement applies to.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum OnExpression {
|
||||
pub enum ExtendedOnClause {
|
||||
/// Represents a specific database and the default retention policy.
|
||||
Database(Identifier),
|
||||
/// Represents a specific database and retention policy.
|
||||
DatabaseRetentionPolicy(Identifier, Identifier),
|
||||
/// Represents all databases and their default retention policies.
|
||||
AllDatabases,
|
||||
/// Represents all databases and all their retention policies.
|
||||
AllDatabasesAndRetentionPolicies,
|
||||
}
|
||||
|
||||
impl fmt::Display for OnExpression {
|
||||
impl fmt::Display for ExtendedOnClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("ON ")?;
|
||||
|
||||
match self {
|
||||
Self::Database(db) => write!(f, "{}", db),
|
||||
Self::DatabaseRetentionPolicy(db, rp) => write!(f, "{}.{}", db, rp),
|
||||
|
|
@ -39,19 +45,22 @@ impl fmt::Display for OnExpression {
|
|||
}
|
||||
|
||||
/// Parse the `ON` clause of the `SHOW MEASUREMENTS` statement.
|
||||
fn on_clause(i: &str) -> ParseResult<&str, OnExpression> {
|
||||
fn extended_on_clause(i: &str) -> ParseResult<&str, ExtendedOnClause> {
|
||||
preceded(
|
||||
pair(tag_no_case("ON"), multispace1),
|
||||
expect(
|
||||
"invalid ON clause, expected wildcard or identifier",
|
||||
alt((
|
||||
value(OnExpression::AllDatabasesAndRetentionPolicies, tag("*.*")),
|
||||
value(OnExpression::AllDatabases, tag("*")),
|
||||
value(
|
||||
ExtendedOnClause::AllDatabasesAndRetentionPolicies,
|
||||
tag("*.*"),
|
||||
),
|
||||
value(ExtendedOnClause::AllDatabases, tag("*")),
|
||||
map(
|
||||
pair(opt(terminated(identifier, tag("."))), identifier),
|
||||
|tup| match tup {
|
||||
(None, db) => OnExpression::Database(db),
|
||||
(Some(db), rp) => OnExpression::DatabaseRetentionPolicy(db, rp),
|
||||
(None, db) => ExtendedOnClause::Database(db),
|
||||
(Some(db), rp) => ExtendedOnClause::DatabaseRetentionPolicy(db, rp),
|
||||
},
|
||||
),
|
||||
)),
|
||||
|
|
@ -59,60 +68,72 @@ fn on_clause(i: &str) -> ParseResult<&str, OnExpression> {
|
|||
)(i)
|
||||
}
|
||||
|
||||
/// Represents a `SHOW MEASUREMENTS` statement.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct ShowMeasurementsStatement {
|
||||
/// Limit the search to databases matching the expression.
|
||||
pub on_expression: Option<OnExpression>,
|
||||
/// Represents the `ON` clause, which limits the search
|
||||
/// to databases matching the expression.
|
||||
pub on: Option<ExtendedOnClause>,
|
||||
|
||||
/// Limit the search to measurements matching the expression.
|
||||
pub measurement_expression: Option<MeasurementExpression>,
|
||||
/// Represents the `WITH MEASUREMENT` clause, which limits
|
||||
/// the search to measurements matching the expression.
|
||||
pub with_measurement: Option<WithMeasurementClause>,
|
||||
|
||||
/// A conditional expression to filter the measurement list.
|
||||
pub condition: Option<ConditionalExpression>,
|
||||
/// Represents the `WHERE` clause, which holds a conditional
|
||||
/// expression to filter the measurement list.
|
||||
pub condition: Option<WhereClause>,
|
||||
|
||||
/// A value to restrict the number of tag keys returned.
|
||||
pub limit: Option<u64>,
|
||||
/// Represents the `LIMIT` clause, which holds a value to
|
||||
/// restrict the number of tag keys returned.
|
||||
pub limit: Option<LimitClause>,
|
||||
|
||||
/// A value to specify an offset to start retrieving tag keys.
|
||||
pub offset: Option<u64>,
|
||||
/// Represents the `OFFSET` clause.
|
||||
///
|
||||
/// The `OFFSET` clause holds value to specify an offset to start retrieving tag keys.
|
||||
pub offset: Option<OffsetClause>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ShowMeasurementsStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SHOW MEASUREMENTS")?;
|
||||
|
||||
if let Some(ref expr) = self.on_expression {
|
||||
write!(f, " ON {}", expr)?;
|
||||
if let Some(ref on_clause) = self.on {
|
||||
write!(f, " {}", on_clause)?;
|
||||
}
|
||||
|
||||
if let Some(ref expr) = self.measurement_expression {
|
||||
write!(f, " WITH MEASUREMENT {}", expr)?;
|
||||
if let Some(ref with_clause) = self.with_measurement {
|
||||
write!(f, " {}", with_clause)?;
|
||||
}
|
||||
|
||||
if let Some(ref cond) = self.condition {
|
||||
write!(f, " WHERE {}", cond)?;
|
||||
if let Some(ref where_clause) = self.condition {
|
||||
write!(f, " {}", where_clause)?;
|
||||
}
|
||||
|
||||
if let Some(limit) = self.limit {
|
||||
write!(f, " LIMIT {}", limit)?;
|
||||
if let Some(ref limit) = self.limit {
|
||||
write!(f, " {}", limit)?;
|
||||
}
|
||||
|
||||
if let Some(offset) = self.offset {
|
||||
write!(f, " OFFSET {}", offset)?;
|
||||
if let Some(ref offset) = self.offset {
|
||||
write!(f, " {}", offset)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the expression of a `WITH MEASUREMENT` clause.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum MeasurementExpression {
|
||||
pub enum WithMeasurementClause {
|
||||
/// Limit the measurements identified by the measurement name using an equals operator.
|
||||
Equals(QualifiedMeasurementName),
|
||||
/// Limit the measurements identified by the measurement name using a
|
||||
/// regular expression equals operator.
|
||||
Regex(QualifiedMeasurementName),
|
||||
}
|
||||
|
||||
impl fmt::Display for MeasurementExpression {
|
||||
impl fmt::Display for WithMeasurementClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("WITH MEASUREMENT ")?;
|
||||
match self {
|
||||
Self::Equals(ref name) => write!(f, "= {}", name),
|
||||
Self::Regex(ref re) => write!(f, "=~ {}", re),
|
||||
|
|
@ -120,7 +141,7 @@ impl fmt::Display for MeasurementExpression {
|
|||
}
|
||||
}
|
||||
|
||||
fn with_measurement_clause(i: &str) -> ParseResult<&str, MeasurementExpression> {
|
||||
fn with_measurement_clause(i: &str) -> ParseResult<&str, WithMeasurementClause> {
|
||||
preceded(
|
||||
tuple((
|
||||
tag_no_case("WITH"),
|
||||
|
|
@ -136,14 +157,14 @@ fn with_measurement_clause(i: &str) -> ParseResult<&str, MeasurementExpression>
|
|||
alt((
|
||||
map(
|
||||
preceded(pair(tag("=~"), multispace0), qualified_measurement_name),
|
||||
MeasurementExpression::Regex,
|
||||
WithMeasurementClause::Regex,
|
||||
),
|
||||
map(
|
||||
preceded(
|
||||
pair(tag("="), multispace0),
|
||||
expect("expected measurement name", qualified_measurement_name),
|
||||
),
|
||||
MeasurementExpression::Equals,
|
||||
WithMeasurementClause::Equals,
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
|
@ -151,7 +172,7 @@ fn with_measurement_clause(i: &str) -> ParseResult<&str, MeasurementExpression>
|
|||
}
|
||||
|
||||
/// Parse a `SHOW MEASUREMENTS` statement after `SHOW` and any whitespace has been consumed.
|
||||
pub fn show_measurements(i: &str) -> ParseResult<&str, ShowMeasurementsStatement> {
|
||||
pub(crate) fn show_measurements(i: &str) -> ParseResult<&str, ShowMeasurementsStatement> {
|
||||
let (
|
||||
remaining_input,
|
||||
(
|
||||
|
|
@ -164,7 +185,7 @@ pub fn show_measurements(i: &str) -> ParseResult<&str, ShowMeasurementsStatement
|
|||
),
|
||||
) = tuple((
|
||||
tag_no_case("MEASUREMENTS"),
|
||||
opt(preceded(multispace1, on_clause)),
|
||||
opt(preceded(multispace1, extended_on_clause)),
|
||||
opt(preceded(multispace1, with_measurement_clause)),
|
||||
opt(preceded(multispace1, where_clause)),
|
||||
opt(preceded(multispace1, limit_clause)),
|
||||
|
|
@ -174,8 +195,8 @@ pub fn show_measurements(i: &str) -> ParseResult<&str, ShowMeasurementsStatement
|
|||
Ok((
|
||||
remaining_input,
|
||||
ShowMeasurementsStatement {
|
||||
on_expression,
|
||||
measurement_expression,
|
||||
on: on_expression,
|
||||
with_measurement: measurement_expression,
|
||||
condition,
|
||||
limit,
|
||||
offset,
|
||||
|
|
@ -197,7 +218,7 @@ mod test {
|
|||
assert_eq!(
|
||||
got,
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: None,
|
||||
on: None,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
|
@ -206,7 +227,7 @@ mod test {
|
|||
assert_eq!(
|
||||
got,
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::Database("foo".into())),
|
||||
on: Some(ExtendedOnClause::Database("foo".into())),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
|
@ -218,17 +239,15 @@ mod test {
|
|||
assert_eq!(
|
||||
got,
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::Database("foo".into())),
|
||||
measurement_expression: Some(MeasurementExpression::Equals(
|
||||
QualifiedMeasurementName {
|
||||
database: None,
|
||||
retention_policy: None,
|
||||
name: "bar".into(),
|
||||
}
|
||||
)),
|
||||
condition: Some(Expr::Literal(true.into()).into()),
|
||||
limit: Some(10),
|
||||
offset: Some(20)
|
||||
on: Some(ExtendedOnClause::Database("foo".into())),
|
||||
with_measurement: Some(WithMeasurementClause::Equals(QualifiedMeasurementName {
|
||||
database: None,
|
||||
retention_policy: None,
|
||||
name: "bar".into(),
|
||||
})),
|
||||
condition: Some(WhereClause::new(Expr::Literal(true.into()).into())),
|
||||
limit: Some(10.into()),
|
||||
offset: Some(20.into())
|
||||
},
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -242,11 +261,11 @@ mod test {
|
|||
assert_eq!(
|
||||
got,
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::Database("foo".into())),
|
||||
measurement_expression: Some(MeasurementExpression::Regex(
|
||||
on: Some(ExtendedOnClause::Database("foo".into())),
|
||||
with_measurement: Some(WithMeasurementClause::Regex(
|
||||
QualifiedMeasurementName::new(MeasurementName::Regex("bar".into()))
|
||||
)),
|
||||
condition: Some(Expr::Literal(true.into()).into()),
|
||||
condition: Some(WhereClause::new(Expr::Literal(true.into()).into())),
|
||||
limit: None,
|
||||
offset: None
|
||||
},
|
||||
|
|
@ -262,7 +281,7 @@ mod test {
|
|||
let got = format!(
|
||||
"{}",
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: None,
|
||||
on: None,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
|
|
@ -271,7 +290,7 @@ mod test {
|
|||
let got = format!(
|
||||
"{}",
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::Database("foo".into())),
|
||||
on: Some(ExtendedOnClause::Database("foo".into())),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
|
|
@ -280,7 +299,7 @@ mod test {
|
|||
let got = format!(
|
||||
"{}",
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::DatabaseRetentionPolicy(
|
||||
on: Some(ExtendedOnClause::DatabaseRetentionPolicy(
|
||||
"foo".into(),
|
||||
"bar".into()
|
||||
)),
|
||||
|
|
@ -292,7 +311,7 @@ mod test {
|
|||
let got = format!(
|
||||
"{}",
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::AllDatabases),
|
||||
on: Some(ExtendedOnClause::AllDatabases),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
|
|
@ -301,7 +320,7 @@ mod test {
|
|||
let got = format!(
|
||||
"{}",
|
||||
ShowMeasurementsStatement {
|
||||
on_expression: Some(OnExpression::AllDatabasesAndRetentionPolicies),
|
||||
on: Some(ExtendedOnClause::AllDatabasesAndRetentionPolicies),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
|
|
@ -309,24 +328,24 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_on_clause() {
|
||||
let (_, got) = on_clause("ON cpu").unwrap();
|
||||
assert_eq!(got, OnExpression::Database("cpu".into()));
|
||||
fn test_extended_on_clause() {
|
||||
let (_, got) = extended_on_clause("ON cpu").unwrap();
|
||||
assert_eq!(got, ExtendedOnClause::Database("cpu".into()));
|
||||
|
||||
let (_, got) = on_clause("ON cpu.autogen").unwrap();
|
||||
let (_, got) = extended_on_clause("ON cpu.autogen").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
OnExpression::DatabaseRetentionPolicy("cpu".into(), "autogen".into())
|
||||
ExtendedOnClause::DatabaseRetentionPolicy("cpu".into(), "autogen".into())
|
||||
);
|
||||
|
||||
let (_, got) = on_clause("ON *").unwrap();
|
||||
assert_matches!(got, OnExpression::AllDatabases);
|
||||
let (_, got) = extended_on_clause("ON *").unwrap();
|
||||
assert_matches!(got, ExtendedOnClause::AllDatabases);
|
||||
|
||||
let (_, got) = on_clause("ON *.*").unwrap();
|
||||
assert_matches!(got, OnExpression::AllDatabasesAndRetentionPolicies);
|
||||
let (_, got) = extended_on_clause("ON *.*").unwrap();
|
||||
assert_matches!(got, ExtendedOnClause::AllDatabasesAndRetentionPolicies);
|
||||
|
||||
assert_expect_error!(
|
||||
on_clause("ON WHERE cpu = 'test'"),
|
||||
extended_on_clause("ON WHERE cpu = 'test'"),
|
||||
"invalid ON clause, expected wildcard or identifier"
|
||||
)
|
||||
}
|
||||
|
|
@ -338,13 +357,13 @@ mod test {
|
|||
let (_, got) = with_measurement_clause("WITH measurement = foo").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
MeasurementExpression::Equals(QualifiedMeasurementName::new(Name("foo".into())))
|
||||
WithMeasurementClause::Equals(QualifiedMeasurementName::new(Name("foo".into())))
|
||||
);
|
||||
|
||||
let (_, got) = with_measurement_clause("WITH measurement =~ /foo/").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
MeasurementExpression::Regex(QualifiedMeasurementName::new(Regex("foo".into())))
|
||||
WithMeasurementClause::Regex(QualifiedMeasurementName::new(Regex("foo".into())))
|
||||
);
|
||||
|
||||
// Expressions are still valid when whitespace is omitted
|
||||
|
|
@ -352,7 +371,7 @@ mod test {
|
|||
let (_, got) = with_measurement_clause("WITH measurement=foo..bar").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
MeasurementExpression::Equals(QualifiedMeasurementName::new_db(
|
||||
WithMeasurementClause::Equals(QualifiedMeasurementName::new_db(
|
||||
Name("bar".into()),
|
||||
"foo".into()
|
||||
))
|
||||
|
|
@ -361,7 +380,7 @@ mod test {
|
|||
let (_, got) = with_measurement_clause("WITH measurement=~/foo/").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
MeasurementExpression::Regex(QualifiedMeasurementName::new(Regex("foo".into())))
|
||||
WithMeasurementClause::Regex(QualifiedMeasurementName::new(Regex("foo".into())))
|
||||
);
|
||||
|
||||
// Quirks of InfluxQL per https://github.com/influxdata/influxdb_iox/issues/5662
|
||||
|
|
@ -369,13 +388,13 @@ mod test {
|
|||
let (_, got) = with_measurement_clause("WITH measurement =~ foo").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
MeasurementExpression::Regex(QualifiedMeasurementName::new(Name("foo".into())))
|
||||
WithMeasurementClause::Regex(QualifiedMeasurementName::new(Name("foo".into())))
|
||||
);
|
||||
|
||||
let (_, got) = with_measurement_clause("WITH measurement = /foo/").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
MeasurementExpression::Equals(QualifiedMeasurementName::new(Regex("foo".into())))
|
||||
WithMeasurementClause::Equals(QualifiedMeasurementName::new(Regex("foo".into())))
|
||||
);
|
||||
|
||||
// Fallible cases
|
||||
|
|
|
|||
|
|
@ -1,36 +1,31 @@
|
|||
use crate::identifier::{identifier, Identifier};
|
||||
use crate::internal::{expect, ParseResult};
|
||||
use crate::show::{on_clause, OnClause};
|
||||
use nom::bytes::complete::tag_no_case;
|
||||
use nom::character::complete::multispace1;
|
||||
use nom::combinator::opt;
|
||||
use nom::sequence::{pair, preceded, tuple};
|
||||
use nom::sequence::{preceded, tuple};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
/// Represents a `SHOW RETENTION POLICIES` statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ShowRetentionPoliciesStatement {
|
||||
/// Name of the database to list the retention policies, or all if this is `None`.
|
||||
database: Option<Identifier>,
|
||||
pub database: Option<OnClause>,
|
||||
}
|
||||
|
||||
impl Display for ShowRetentionPoliciesStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SHOW RETENTION POLICIES")?;
|
||||
if let Some(ref database) = self.database {
|
||||
write!(f, " ON {}", database)?;
|
||||
write!(f, " {}", database)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn on_clause(i: &str) -> ParseResult<&str, Identifier> {
|
||||
preceded(
|
||||
pair(tag_no_case("ON"), multispace1),
|
||||
expect("invalid ON clause, expected identifier", identifier),
|
||||
)(i)
|
||||
}
|
||||
|
||||
pub fn show_retention_policies(i: &str) -> ParseResult<&str, ShowRetentionPoliciesStatement> {
|
||||
pub(crate) fn show_retention_policies(
|
||||
i: &str,
|
||||
) -> ParseResult<&str, ShowRetentionPoliciesStatement> {
|
||||
let (remaining, (_, _, _, database)) = tuple((
|
||||
tag_no_case("RETENTION"),
|
||||
multispace1,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::common::{limit_clause, offset_clause, where_clause};
|
||||
use crate::expression::conditional::ConditionalExpression;
|
||||
use crate::identifier::Identifier;
|
||||
use crate::common::{
|
||||
limit_clause, offset_clause, where_clause, LimitClause, OffsetClause, WhereClause,
|
||||
};
|
||||
use crate::internal::ParseResult;
|
||||
use crate::show::on_clause;
|
||||
use crate::show::{on_clause, OnClause};
|
||||
use crate::simple_from_clause::{show_from_clause, ShowFromClause};
|
||||
use nom::bytes::complete::tag_no_case;
|
||||
use nom::character::complete::multispace1;
|
||||
|
|
@ -16,44 +16,44 @@ use std::fmt::Formatter;
|
|||
pub struct ShowTagKeysStatement {
|
||||
/// The name of the database to query. If `None`, a default
|
||||
/// database will be used.
|
||||
pub database: Option<Identifier>,
|
||||
pub database: Option<OnClause>,
|
||||
|
||||
/// The measurement or measurements to restrict which tag keys
|
||||
/// are retrieved.
|
||||
pub from: Option<ShowFromClause>,
|
||||
|
||||
/// A conditional expression to filter the tag keys.
|
||||
pub condition: Option<ConditionalExpression>,
|
||||
pub condition: Option<WhereClause>,
|
||||
|
||||
/// A value to restrict the number of tag keys returned.
|
||||
pub limit: Option<u64>,
|
||||
pub limit: Option<LimitClause>,
|
||||
|
||||
/// A value to specify an offset to start retrieving tag keys.
|
||||
pub offset: Option<u64>,
|
||||
pub offset: Option<OffsetClause>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ShowTagKeysStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SHOW TAG KEYS")?;
|
||||
|
||||
if let Some(ref expr) = self.database {
|
||||
write!(f, " ON {}", expr)?;
|
||||
if let Some(ref on_clause) = self.database {
|
||||
write!(f, " {}", on_clause)?;
|
||||
}
|
||||
|
||||
if let Some(ref expr) = self.from {
|
||||
write!(f, " FROM {}", expr)?;
|
||||
write!(f, " {}", expr)?;
|
||||
}
|
||||
|
||||
if let Some(ref cond) = self.condition {
|
||||
write!(f, " WHERE {}", cond)?;
|
||||
write!(f, " {}", cond)?;
|
||||
}
|
||||
|
||||
if let Some(limit) = self.limit {
|
||||
write!(f, " LIMIT {}", limit)?;
|
||||
if let Some(ref limit) = self.limit {
|
||||
write!(f, " {}", limit)?;
|
||||
}
|
||||
|
||||
if let Some(offset) = self.offset {
|
||||
write!(f, " OFFSET {}", offset)?;
|
||||
if let Some(ref offset) = self.offset {
|
||||
write!(f, " {}", offset)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -61,7 +61,7 @@ impl fmt::Display for ShowTagKeysStatement {
|
|||
}
|
||||
|
||||
/// Parse a `SHOW TAG KEYS` statement, starting from the `KEYS` token.
|
||||
pub fn show_tag_keys(i: &str) -> ParseResult<&str, ShowTagKeysStatement> {
|
||||
pub(crate) fn show_tag_keys(i: &str) -> ParseResult<&str, ShowTagKeysStatement> {
|
||||
let (
|
||||
remaining_input,
|
||||
(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use crate::common::{limit_clause, offset_clause, where_clause, OneOrMore};
|
||||
use crate::expression::conditional::ConditionalExpression;
|
||||
use crate::common::{
|
||||
limit_clause, offset_clause, where_clause, LimitClause, OffsetClause, OneOrMore, WhereClause,
|
||||
};
|
||||
use crate::identifier::{identifier, Identifier};
|
||||
use crate::internal::{expect, ParseResult};
|
||||
use crate::show::on_clause;
|
||||
use crate::show::{on_clause, OnClause};
|
||||
use crate::simple_from_clause::{show_from_clause, ShowFromClause};
|
||||
use crate::string::{regex, Regex};
|
||||
use nom::branch::alt;
|
||||
|
|
@ -18,50 +19,50 @@ use std::fmt::{Display, Formatter};
|
|||
pub struct ShowTagValuesStatement {
|
||||
/// The name of the database to query. If `None`, a default
|
||||
/// database will be used.
|
||||
pub database: Option<Identifier>,
|
||||
pub database: Option<OnClause>,
|
||||
|
||||
/// The measurement or measurements to restrict which tag keys
|
||||
/// are retrieved.
|
||||
pub from: Option<ShowFromClause>,
|
||||
|
||||
/// `WITH KEY` expression, to limit the values retrieved to
|
||||
/// Represents the `WITH KEY` clause, to restrict the tag values to
|
||||
/// the matching tag keys.
|
||||
pub with_key: WithKeyExpression,
|
||||
pub with_key: WithKeyClause,
|
||||
|
||||
/// A conditional expression to filter the tag keys.
|
||||
pub condition: Option<ConditionalExpression>,
|
||||
pub condition: Option<WhereClause>,
|
||||
|
||||
/// A value to restrict the number of tag keys returned.
|
||||
pub limit: Option<u64>,
|
||||
pub limit: Option<LimitClause>,
|
||||
|
||||
/// A value to specify an offset to start retrieving tag keys.
|
||||
pub offset: Option<u64>,
|
||||
pub offset: Option<OffsetClause>,
|
||||
}
|
||||
|
||||
impl Display for ShowTagValuesStatement {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SHOW TAG VALUES")?;
|
||||
|
||||
if let Some(ref expr) = self.database {
|
||||
write!(f, " ON {}", expr)?;
|
||||
if let Some(ref on_clause) = self.database {
|
||||
write!(f, " {}", on_clause)?;
|
||||
}
|
||||
|
||||
if let Some(ref expr) = self.from {
|
||||
write!(f, " FROM {}", expr)?;
|
||||
if let Some(ref from_clause) = self.from {
|
||||
write!(f, " {}", from_clause)?;
|
||||
}
|
||||
|
||||
write!(f, " {}", self.with_key)?;
|
||||
|
||||
if let Some(ref cond) = self.condition {
|
||||
write!(f, " WHERE {}", cond)?;
|
||||
if let Some(ref where_clause) = self.condition {
|
||||
write!(f, " {}", where_clause)?;
|
||||
}
|
||||
|
||||
if let Some(limit) = self.limit {
|
||||
write!(f, " LIMIT {}", limit)?;
|
||||
if let Some(ref limit) = self.limit {
|
||||
write!(f, " {}", limit)?;
|
||||
}
|
||||
|
||||
if let Some(offset) = self.offset {
|
||||
write!(f, " OFFSET {}", offset)?;
|
||||
if let Some(ref offset) = self.offset {
|
||||
write!(f, " {}", offset)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -69,7 +70,7 @@ impl Display for ShowTagValuesStatement {
|
|||
}
|
||||
|
||||
/// Parse a `SHOW TAG VALUES` statement, starting from the `VALUES` token.
|
||||
pub fn show_tag_values(i: &str) -> ParseResult<&str, ShowTagValuesStatement> {
|
||||
pub(crate) fn show_tag_values(i: &str) -> ParseResult<&str, ShowTagValuesStatement> {
|
||||
let (
|
||||
remaining_input,
|
||||
(
|
||||
|
|
@ -107,19 +108,36 @@ pub fn show_tag_values(i: &str) -> ParseResult<&str, ShowTagValuesStatement> {
|
|||
))
|
||||
}
|
||||
|
||||
/// Represents a list of identifiers when the `WITH KEY` clause
|
||||
/// specifies the `IN` operator.
|
||||
pub type InList = OneOrMore<Identifier>;
|
||||
|
||||
impl Display for InList {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(self.first(), f)?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a `WITH KEY` clause.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum WithKeyExpression {
|
||||
pub enum WithKeyClause {
|
||||
/// Select a single tag key that equals the identifier.
|
||||
Eq(Identifier),
|
||||
/// Select all tag keys that do not equal the identifier.
|
||||
NotEq(Identifier),
|
||||
/// Select any tag keys that pass the regular expression.
|
||||
EqRegex(Regex),
|
||||
/// Select the tag keys that do not pass the regular expression.
|
||||
NotEqRegex(Regex),
|
||||
/// IN expression
|
||||
/// Select the tag keys matching each of the identifiers in the list.
|
||||
In(InList),
|
||||
}
|
||||
|
||||
impl Display for WithKeyExpression {
|
||||
impl Display for WithKeyClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("WITH KEY ")?;
|
||||
|
||||
|
|
@ -145,7 +163,7 @@ fn identifier_list(i: &str) -> ParseResult<&str, InList> {
|
|||
)(i)
|
||||
}
|
||||
|
||||
fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyExpression> {
|
||||
fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyClause> {
|
||||
preceded(
|
||||
tuple((
|
||||
tag_no_case("WITH"),
|
||||
|
|
@ -163,7 +181,7 @@ fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyExpression> {
|
|||
regex,
|
||||
),
|
||||
),
|
||||
WithKeyExpression::EqRegex,
|
||||
WithKeyClause::EqRegex,
|
||||
),
|
||||
map(
|
||||
preceded(
|
||||
|
|
@ -173,7 +191,7 @@ fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyExpression> {
|
|||
regex,
|
||||
),
|
||||
),
|
||||
WithKeyExpression::NotEqRegex,
|
||||
WithKeyClause::NotEqRegex,
|
||||
),
|
||||
map(
|
||||
preceded(
|
||||
|
|
@ -183,7 +201,7 @@ fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyExpression> {
|
|||
identifier,
|
||||
),
|
||||
),
|
||||
WithKeyExpression::Eq,
|
||||
WithKeyClause::Eq,
|
||||
),
|
||||
map(
|
||||
preceded(
|
||||
|
|
@ -193,7 +211,7 @@ fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyExpression> {
|
|||
identifier,
|
||||
),
|
||||
),
|
||||
WithKeyExpression::NotEq,
|
||||
WithKeyClause::NotEq,
|
||||
),
|
||||
map(
|
||||
preceded(
|
||||
|
|
@ -203,7 +221,7 @@ fn with_key_clause(i: &str) -> ParseResult<&str, WithKeyExpression> {
|
|||
identifier_list,
|
||||
),
|
||||
),
|
||||
WithKeyExpression::In,
|
||||
WithKeyClause::In,
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
|
@ -286,24 +304,24 @@ mod test {
|
|||
#[test]
|
||||
fn test_with_key_clause() {
|
||||
let (_, got) = with_key_clause("WITH KEY = foo").unwrap();
|
||||
assert_eq!(got, WithKeyExpression::Eq("foo".into()));
|
||||
assert_eq!(got, WithKeyClause::Eq("foo".into()));
|
||||
|
||||
let (_, got) = with_key_clause("WITH KEY != foo").unwrap();
|
||||
assert_eq!(got, WithKeyExpression::NotEq("foo".into()));
|
||||
assert_eq!(got, WithKeyClause::NotEq("foo".into()));
|
||||
|
||||
let (_, got) = with_key_clause("WITH KEY =~ /foo/").unwrap();
|
||||
assert_eq!(got, WithKeyExpression::EqRegex("foo".into()));
|
||||
assert_eq!(got, WithKeyClause::EqRegex("foo".into()));
|
||||
|
||||
let (_, got) = with_key_clause("WITH KEY !~ /foo/").unwrap();
|
||||
assert_eq!(got, WithKeyExpression::NotEqRegex("foo".into()));
|
||||
assert_eq!(got, WithKeyClause::NotEqRegex("foo".into()));
|
||||
|
||||
let (_, got) = with_key_clause("WITH KEY IN (foo)").unwrap();
|
||||
assert_eq!(got, WithKeyExpression::In(InList::new(vec!["foo".into()])));
|
||||
assert_eq!(got, WithKeyClause::In(InList::new(vec!["foo".into()])));
|
||||
|
||||
let (_, got) = with_key_clause("WITH KEY IN (foo, bar, \"foo bar\")").unwrap();
|
||||
assert_eq!(
|
||||
got,
|
||||
WithKeyExpression::In(InList::new(vec![
|
||||
WithKeyClause::In(InList::new(vec![
|
||||
"foo".into(),
|
||||
"bar".into(),
|
||||
"foo bar".into()
|
||||
|
|
@ -312,7 +330,7 @@ mod test {
|
|||
|
||||
// Expressions are still valid when whitespace is omitted
|
||||
let (_, got) = with_key_clause("WITH KEY=foo").unwrap();
|
||||
assert_eq!(got, WithKeyExpression::Eq("foo".into()));
|
||||
assert_eq!(got, WithKeyClause::Eq("foo".into()));
|
||||
|
||||
// Fallible cases
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use nom::bytes::complete::tag_no_case;
|
|||
use nom::character::complete::multispace1;
|
||||
use nom::sequence::{pair, preceded};
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
/// Represents a `FROM` clause of a `DELETE` or `SHOW` statement.
|
||||
///
|
||||
|
|
@ -64,8 +65,18 @@ impl Parser for QualifiedMeasurementName {
|
|||
/// ```
|
||||
pub type ShowFromClause = FromMeasurementClause<QualifiedMeasurementName>;
|
||||
|
||||
impl Display for ShowFromClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FROM {}", self.first())?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a `FROM` clause for various `SHOW` statements.
|
||||
pub fn show_from_clause(i: &str) -> ParseResult<&str, ShowFromClause> {
|
||||
pub(crate) fn show_from_clause(i: &str) -> ParseResult<&str, ShowFromClause> {
|
||||
from_clause(i)
|
||||
}
|
||||
|
||||
|
|
@ -78,8 +89,18 @@ impl Parser for Identifier {
|
|||
/// Represents a `FROM` clause for a `DELETE` statement.
|
||||
pub type DeleteFromClause = FromMeasurementClause<MeasurementName>;
|
||||
|
||||
impl Display for DeleteFromClause {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FROM {}", self.first())?;
|
||||
for arg in self.rest() {
|
||||
write!(f, ", {}", arg)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a `FROM` clause for a `DELETE` statement.
|
||||
pub fn delete_from_clause(i: &str) -> ParseResult<&str, DeleteFromClause> {
|
||||
pub(crate) fn delete_from_clause(i: &str) -> ParseResult<&str, DeleteFromClause> {
|
||||
from_clause(i)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"DELETE WHERE 'foo bar' =~ /foo/\")"
|
||||
---
|
||||
- "pre_visit_statement: Delete(Where(WhereClause(Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) })))"
|
||||
- "pre_visit_delete_statement: Where(WhereClause(Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) }))"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) }"
|
||||
- "pre_visit_conditional_expression: Expr(Literal(String(\"foo bar\")))"
|
||||
- "pre_visit_expr: Literal(String(\"foo bar\"))"
|
||||
- "post_visit_expr: Literal(String(\"foo bar\"))"
|
||||
- "post_visit_conditional_expression: Expr(Literal(String(\"foo bar\")))"
|
||||
- "pre_visit_conditional_expression: Expr(Literal(Regex(Regex(\"foo\"))))"
|
||||
- "pre_visit_expr: Literal(Regex(Regex(\"foo\")))"
|
||||
- "post_visit_expr: Literal(Regex(Regex(\"foo\")))"
|
||||
- "post_visit_conditional_expression: Expr(Literal(Regex(Regex(\"foo\"))))"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) })"
|
||||
- "post_visit_delete_statement: Where(WhereClause(Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) }))"
|
||||
- "post_visit_statement: Delete(Where(WhereClause(Binary { lhs: Expr(Literal(String(\"foo bar\"))), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"foo\")))) })))"
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"DELETE FROM cpu\")"
|
||||
---
|
||||
- "pre_visit_statement: Delete(FromWhere { from: OneOrMore { contents: [Name(Identifier(\"cpu\"))] }, condition: None })"
|
||||
- "pre_visit_delete_statement: FromWhere { from: OneOrMore { contents: [Name(Identifier(\"cpu\"))] }, condition: None }"
|
||||
- "pre_visit_delete_from: OneOrMore { contents: [Name(Identifier(\"cpu\"))] }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_delete_from: OneOrMore { contents: [Name(Identifier(\"cpu\"))] }"
|
||||
- "post_visit_delete_statement: FromWhere { from: OneOrMore { contents: [Name(Identifier(\"cpu\"))] }, condition: None }"
|
||||
- "post_visit_statement: Delete(FromWhere { from: OneOrMore { contents: [Name(Identifier(\"cpu\"))] }, condition: None })"
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"DELETE FROM /^cpu/\")"
|
||||
---
|
||||
- "pre_visit_statement: Delete(FromWhere { from: OneOrMore { contents: [Regex(Regex(\"^cpu\"))] }, condition: None })"
|
||||
- "pre_visit_delete_statement: FromWhere { from: OneOrMore { contents: [Regex(Regex(\"^cpu\"))] }, condition: None }"
|
||||
- "pre_visit_delete_from: OneOrMore { contents: [Regex(Regex(\"^cpu\"))] }"
|
||||
- "pre_visit_measurement_name: Regex(Regex(\"^cpu\"))"
|
||||
- "post_visit_measurement_name: Regex(Regex(\"^cpu\"))"
|
||||
- "post_visit_delete_from: OneOrMore { contents: [Regex(Regex(\"^cpu\"))] }"
|
||||
- "post_visit_delete_statement: FromWhere { from: OneOrMore { contents: [Regex(Regex(\"^cpu\"))] }, condition: None }"
|
||||
- "post_visit_statement: Delete(FromWhere { from: OneOrMore { contents: [Regex(Regex(\"^cpu\"))] }, condition: None })"
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"DELETE FROM a WHERE b = \\\"c\\\"\")"
|
||||
---
|
||||
- "pre_visit_statement: Delete(FromWhere { from: OneOrMore { contents: [Name(Identifier(\"a\"))] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) })) })"
|
||||
- "pre_visit_delete_statement: FromWhere { from: OneOrMore { contents: [Name(Identifier(\"a\"))] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) })) }"
|
||||
- "pre_visit_delete_from: OneOrMore { contents: [Name(Identifier(\"a\"))] }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"a\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"a\"))"
|
||||
- "post_visit_delete_from: OneOrMore { contents: [Name(Identifier(\"a\"))] }"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"b\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"b\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"b\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"b\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"c\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"c\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"c\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"c\"), data_type: None })"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) })"
|
||||
- "post_visit_delete_statement: FromWhere { from: OneOrMore { contents: [Name(Identifier(\"a\"))] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) })) }"
|
||||
- "post_visit_statement: Delete(FromWhere { from: OneOrMore { contents: [Name(Identifier(\"a\"))] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"b\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"c\"), data_type: None }) })) })"
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"DROP MEASUREMENT cpu\")"
|
||||
---
|
||||
- "pre_visit_statement: DropMeasurement(DropMeasurementStatement { name: Identifier(\"cpu\") })"
|
||||
- "pre_visit_drop_measurement_statement: DropMeasurementStatement { name: Identifier(\"cpu\") }"
|
||||
- "post_visit_drop_measurement_statement: DropMeasurementStatement { name: Identifier(\"cpu\") }"
|
||||
- "post_visit_statement: DropMeasurement(DropMeasurementStatement { name: Identifier(\"cpu\") })"
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"EXPLAIN SELECT * FROM cpu\")"
|
||||
---
|
||||
- "pre_visit_statement: Explain(ExplainStatement { options: None, select: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None } })"
|
||||
- "pre_visit_explain_statement: ExplainStatement { options: None, select: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None } }"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: Wildcard(None), alias: None }"
|
||||
- "pre_visit_expr: Wildcard(None)"
|
||||
- "post_visit_expr: Wildcard(None)"
|
||||
- "post_visit_select_field: Field { expr: Wildcard(None), alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_explain_statement: ExplainStatement { options: None, select: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None } }"
|
||||
- "post_visit_statement: Explain(ExplainStatement { options: None, select: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None } })"
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(r#\"SELECT DISTINCT value FROM temp\"#)"
|
||||
---
|
||||
- "pre_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Distinct(Identifier(\"value\")), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Distinct(Identifier(\"value\")), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: Distinct(Identifier(\"value\")), alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: Distinct(Identifier(\"value\")), alias: None }"
|
||||
- "pre_visit_expr: Distinct(Identifier(\"value\"))"
|
||||
- "post_visit_expr: Distinct(Identifier(\"value\"))"
|
||||
- "post_visit_select_field: Field { expr: Distinct(Identifier(\"value\")), alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: Distinct(Identifier(\"value\")), alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Distinct(Identifier(\"value\")), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Distinct(Identifier(\"value\")), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(r#\"SELECT COUNT(value) FROM temp\"#)"
|
||||
---
|
||||
- "pre_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }"
|
||||
- "pre_visit_expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }"
|
||||
- "post_visit_select_field: Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [VarRef { name: Identifier(\"value\"), data_type: None }] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(r#\"SELECT COUNT(DISTINCT value) FROM temp\"#)"
|
||||
---
|
||||
- "pre_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }"
|
||||
- "pre_visit_expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }"
|
||||
- "pre_visit_expr: Distinct(Identifier(\"value\"))"
|
||||
- "post_visit_expr: Distinct(Identifier(\"value\"))"
|
||||
- "post_visit_expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }"
|
||||
- "post_visit_select_field: Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Call { name: \"COUNT\", args: [Distinct(Identifier(\"value\"))] }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(r#\"SELECT * FROM /cpu/, memory\"#)"
|
||||
---
|
||||
- "pre_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }), Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }), Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: Wildcard(None), alias: None }"
|
||||
- "pre_visit_expr: Wildcard(None)"
|
||||
- "post_visit_expr: Wildcard(None)"
|
||||
- "post_visit_select_field: Field { expr: Wildcard(None), alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }), Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Regex(Regex(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Regex(Regex(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) })"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"memory\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"memory\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }), Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })] }"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }), Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: Wildcard(None), alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }), Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"memory\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(r#\"SELECT value FROM (SELECT usage FROM cpu WHERE host = \"node1\")\n WHERE region =~ /west/ AND value > 5\n GROUP BY TIME(5m), host FILL(previous)\n ORDER BY TIME DESC\n LIMIT 1 OFFSET 2\n SLIMIT 3 SOFFSET 4\n TZ('Australia/Hobart')\n \"#)"
|
||||
---
|
||||
- "pre_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })] }, condition: Some(WhereClause(Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } })), group_by: Some(OneOrMore { contents: [Time { interval: Literal(Duration(Duration(300000000000))), offset: None }, Tag(Identifier(\"host\"))] }), fill: Some(Previous), order_by: Some(Descending), limit: Some(LimitClause(1)), offset: Some(OffsetClause(2)), series_limit: Some(SLimitClause(3)), series_offset: Some(SOffsetClause(4)), timezone: Some(TimeZoneClause(\"Australia/Hobart\")) })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })] }, condition: Some(WhereClause(Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } })), group_by: Some(OneOrMore { contents: [Time { interval: Literal(Duration(Duration(300000000000))), offset: None }, Tag(Identifier(\"host\"))] }), fill: Some(Previous), order_by: Some(Descending), limit: Some(LimitClause(1)), offset: Some(OffsetClause(2)), series_limit: Some(SLimitClause(3)), series_offset: Some(SOffsetClause(4)), timezone: Some(TimeZoneClause(\"Australia/Hobart\")) }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_select_field: Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })] }"
|
||||
- "pre_visit_select_measurement_selection: Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"usage\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"usage\"), data_type: None }"
|
||||
- "post_visit_select_field: Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"node1\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"node1\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"node1\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"node1\"), data_type: None })"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_select_measurement_selection: Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })] }"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } }"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"region\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"region\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"region\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"region\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(Literal(Regex(Regex(\"west\"))))"
|
||||
- "pre_visit_expr: Literal(Regex(Regex(\"west\")))"
|
||||
- "post_visit_expr: Literal(Regex(Regex(\"west\")))"
|
||||
- "post_visit_conditional_expression: Expr(Literal(Regex(Regex(\"west\"))))"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"value\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"value\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(Literal(Unsigned(5)))"
|
||||
- "pre_visit_expr: Literal(Unsigned(5))"
|
||||
- "post_visit_expr: Literal(Unsigned(5))"
|
||||
- "post_visit_conditional_expression: Expr(Literal(Unsigned(5)))"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) }"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } })"
|
||||
- "pre_visit_group_by_clause: OneOrMore { contents: [Time { interval: Literal(Duration(Duration(300000000000))), offset: None }, Tag(Identifier(\"host\"))] }"
|
||||
- "pre_visit_select_dimension: Time { interval: Literal(Duration(Duration(300000000000))), offset: None }"
|
||||
- "pre_visit_expr: Literal(Duration(Duration(300000000000)))"
|
||||
- "post_visit_expr: Literal(Duration(Duration(300000000000)))"
|
||||
- "post_visit_select_dimension: Time { interval: Literal(Duration(Duration(300000000000))), offset: None }"
|
||||
- "pre_visit_select_dimension: Tag(Identifier(\"host\"))"
|
||||
- "post_visit_select_dimension: Tag(Identifier(\"host\"))"
|
||||
- "post_visit_group_by_clause: OneOrMore { contents: [Time { interval: Literal(Duration(Duration(300000000000))), offset: None }, Tag(Identifier(\"host\"))] }"
|
||||
- "pre_visit_fill_clause: Previous"
|
||||
- "post_visit_fill_clause: Previous"
|
||||
- "pre_visit_order_by_clause: Descending"
|
||||
- "post_visit_order_by_clause: Descending"
|
||||
- "pre_visit_limit_clause: LimitClause(1)"
|
||||
- "post_visit_limit_clause: LimitClause(1)"
|
||||
- "pre_visit_offset_clause: OffsetClause(2)"
|
||||
- "post_visit_offset_clause: OffsetClause(2)"
|
||||
- "pre_visit_slimit_clause: SLimitClause(3)"
|
||||
- "post_visit_slimit_clause: SLimitClause(3)"
|
||||
- "pre_visit_soffset_clause: SOffsetClause(4)"
|
||||
- "post_visit_soffset_clause: SOffsetClause(4)"
|
||||
- "pre_visit_timezone_clause: TimeZoneClause(\"Australia/Hobart\")"
|
||||
- "post_visit_timezone_clause: TimeZoneClause(\"Australia/Hobart\")"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })] }, condition: Some(WhereClause(Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } })), group_by: Some(OneOrMore { contents: [Time { interval: Literal(Duration(Duration(300000000000))), offset: None }, Tag(Identifier(\"host\"))] }), fill: Some(Previous), order_by: Some(Descending), limit: Some(LimitClause(1)), offset: Some(OffsetClause(2)), series_limit: Some(SLimitClause(3)), series_offset: Some(SOffsetClause(4)), timezone: Some(TimeZoneClause(\"Australia/Hobart\")) }"
|
||||
- "post_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Subquery(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"usage\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })] }, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"node1\"), data_type: None }) })), group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })] }, condition: Some(WhereClause(Binary { lhs: Binary { lhs: Expr(VarRef { name: Identifier(\"region\"), data_type: None }), op: EqRegex, rhs: Expr(Literal(Regex(Regex(\"west\")))) }, op: And, rhs: Binary { lhs: Expr(VarRef { name: Identifier(\"value\"), data_type: None }), op: Gt, rhs: Expr(Literal(Unsigned(5))) } })), group_by: Some(OneOrMore { contents: [Time { interval: Literal(Duration(Duration(300000000000))), offset: None }, Tag(Identifier(\"host\"))] }), fill: Some(Previous), order_by: Some(Descending), limit: Some(LimitClause(1)), offset: Some(OffsetClause(2)), series_limit: Some(SLimitClause(3)), series_offset: Some(SOffsetClause(4)), timezone: Some(TimeZoneClause(\"Australia/Hobart\")) })"
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(r#\"SELECT value FROM temp\"#)"
|
||||
---
|
||||
- "pre_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
- "pre_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "pre_visit_select_field_list: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }"
|
||||
- "pre_visit_select_field: Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"value\"), data_type: None }"
|
||||
- "post_visit_select_field: Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }"
|
||||
- "post_visit_select_field_list: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }"
|
||||
- "pre_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "pre_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"temp\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) }"
|
||||
- "post_visit_select_measurement_selection: Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })"
|
||||
- "post_visit_select_from_clause: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }"
|
||||
- "post_visit_select_statement: SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None }"
|
||||
- "post_visit_statement: Select(SelectStatement { fields: OneOrMore { contents: [Field { expr: VarRef { name: Identifier(\"value\"), data_type: None }, alias: None }] }, from: OneOrMore { contents: [Name(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"temp\")) })] }, condition: None, group_by: None, fill: None, order_by: None, limit: None, offset: None, series_limit: None, series_offset: None, timezone: None })"
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW DATABASES\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowDatabases(ShowDatabasesStatement)"
|
||||
- "pre_visit_show_databases_statement: ShowDatabasesStatement"
|
||||
- "post_visit_show_databases_statement: ShowDatabasesStatement"
|
||||
- "post_visit_statement: ShowDatabases(ShowDatabasesStatement)"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW FIELD KEYS ON telegraf\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_field_keys_statement: ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: None, limit: None, offset: None }"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "post_visit_show_field_keys_statement: ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW FIELD KEYS FROM cpu\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: None, from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), limit: None, offset: None })"
|
||||
- "pre_visit_show_field_keys_statement: ShowFieldKeysStatement { database: None, from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), limit: None, offset: None }"
|
||||
- "pre_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "post_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }"
|
||||
- "post_visit_show_field_keys_statement: ShowFieldKeysStatement { database: None, from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: None, from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW FIELD KEYS ON telegraf FROM /cpu/\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }] }), limit: None, offset: None })"
|
||||
- "pre_visit_show_field_keys_statement: ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }] }), limit: None, offset: None }"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }] }"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Regex(Regex(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Regex(Regex(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }"
|
||||
- "post_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }] }"
|
||||
- "post_visit_show_field_keys_statement: ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }] }), limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"cpu\")) }] }), limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW FIELD KEYS\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: None, from: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_field_keys_statement: ShowFieldKeysStatement { database: None, from: None, limit: None, offset: None }"
|
||||
- "post_visit_show_field_keys_statement: ShowFieldKeysStatement { database: None, from: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowFieldKeys(ShowFieldKeysStatement { database: None, from: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS ON db.rp\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: Some(DatabaseRetentionPolicy(Identifier(\"db\"), Identifier(\"rp\"))), with_measurement: None, condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: Some(DatabaseRetentionPolicy(Identifier(\"db\"), Identifier(\"rp\"))), with_measurement: None, condition: None, limit: None, offset: None }"
|
||||
- "pre_visit_extended_on_clause: DatabaseRetentionPolicy(Identifier(\"db\"), Identifier(\"rp\"))"
|
||||
- "post_visit_extended_on_clause: DatabaseRetentionPolicy(Identifier(\"db\"), Identifier(\"rp\"))"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: Some(DatabaseRetentionPolicy(Identifier(\"db\"), Identifier(\"rp\"))), with_measurement: None, condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: Some(DatabaseRetentionPolicy(Identifier(\"db\"), Identifier(\"rp\"))), with_measurement: None, condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS WITH MEASUREMENT = \\\"cpu\\\"\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: Some(Equals(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })), condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: Some(Equals(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })), condition: None, limit: None, offset: None }"
|
||||
- "pre_visit_with_measurement_clause: Equals(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "post_visit_with_measurement_clause: Equals(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: Some(Equals(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })), condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: Some(Equals(QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) })), condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS WHERE host = 'west'\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: None, offset: None })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: None, offset: None }"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(Literal(String(\"west\")))"
|
||||
- "pre_visit_expr: Literal(String(\"west\"))"
|
||||
- "post_visit_expr: Literal(String(\"west\"))"
|
||||
- "post_visit_conditional_expression: Expr(Literal(String(\"west\")))"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS LIMIT 5\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: Some(LimitClause(5)), offset: None })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: Some(LimitClause(5)), offset: None }"
|
||||
- "pre_visit_limit_clause: LimitClause(5)"
|
||||
- "post_visit_limit_clause: LimitClause(5)"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: Some(LimitClause(5)), offset: None }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: Some(LimitClause(5)), offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS OFFSET 10\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: Some(OffsetClause(10)) })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: Some(OffsetClause(10)) }"
|
||||
- "pre_visit_offset_clause: OffsetClause(10)"
|
||||
- "post_visit_offset_clause: OffsetClause(10)"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: Some(OffsetClause(10)) }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: Some(OffsetClause(10)) })"
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS ON * WITH MEASUREMENT =~ /foo/ WHERE host = 'west' LIMIT 10 OFFSET 20\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: Some(AllDatabases), with_measurement: Some(Regex(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) })), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: Some(LimitClause(10)), offset: Some(OffsetClause(20)) })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: Some(AllDatabases), with_measurement: Some(Regex(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) })), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: Some(LimitClause(10)), offset: Some(OffsetClause(20)) }"
|
||||
- "pre_visit_extended_on_clause: AllDatabases"
|
||||
- "post_visit_extended_on_clause: AllDatabases"
|
||||
- "pre_visit_with_measurement_clause: Regex(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) })"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) }"
|
||||
- "pre_visit_measurement_name: Regex(Regex(\"foo\"))"
|
||||
- "post_visit_measurement_name: Regex(Regex(\"foo\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) }"
|
||||
- "post_visit_with_measurement_clause: Regex(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) })"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(Literal(String(\"west\")))"
|
||||
- "pre_visit_expr: Literal(String(\"west\"))"
|
||||
- "post_visit_expr: Literal(String(\"west\"))"
|
||||
- "post_visit_conditional_expression: Expr(Literal(String(\"west\")))"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })"
|
||||
- "pre_visit_limit_clause: LimitClause(10)"
|
||||
- "post_visit_limit_clause: LimitClause(10)"
|
||||
- "pre_visit_offset_clause: OffsetClause(20)"
|
||||
- "post_visit_offset_clause: OffsetClause(20)"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: Some(AllDatabases), with_measurement: Some(Regex(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) })), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: Some(LimitClause(10)), offset: Some(OffsetClause(20)) }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: Some(AllDatabases), with_measurement: Some(Regex(QualifiedMeasurementName { database: None, retention_policy: None, name: Regex(Regex(\"foo\")) })), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(Literal(String(\"west\"))) })), limit: Some(LimitClause(10)), offset: Some(OffsetClause(20)) })"
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW MEASUREMENTS\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: None }"
|
||||
- "post_visit_show_measurements_statement: ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowMeasurements(ShowMeasurementsStatement { on: None, with_measurement: None, condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW RETENTION POLICIES ON telegraf\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowRetentionPolicies(ShowRetentionPoliciesStatement { database: Some(OnClause(Identifier(\"telegraf\"))) })"
|
||||
- "pre_visit_show_retention_policies_statement: ShowRetentionPoliciesStatement { database: Some(OnClause(Identifier(\"telegraf\"))) }"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "post_visit_show_retention_policies_statement: ShowRetentionPoliciesStatement { database: Some(OnClause(Identifier(\"telegraf\"))) }"
|
||||
- "post_visit_statement: ShowRetentionPolicies(ShowRetentionPoliciesStatement { database: Some(OnClause(Identifier(\"telegraf\"))) })"
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW RETENTION POLICIES\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowRetentionPolicies(ShowRetentionPoliciesStatement { database: None })"
|
||||
- "pre_visit_show_retention_policies_statement: ShowRetentionPoliciesStatement { database: None }"
|
||||
- "post_visit_show_retention_policies_statement: ShowRetentionPoliciesStatement { database: None }"
|
||||
- "post_visit_statement: ShowRetentionPolicies(ShowRetentionPoliciesStatement { database: None })"
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW TAG KEYS ON telegraf FROM cpu WHERE host = \\\"west\\\" LIMIT 5 OFFSET 10\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowTagKeys(ShowTagKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) })"
|
||||
- "pre_visit_show_tag_keys_statement: ShowTagKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) }"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "post_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"west\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"west\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"west\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"west\"), data_type: None })"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })"
|
||||
- "pre_visit_limit_clause: LimitClause(5)"
|
||||
- "post_visit_limit_clause: LimitClause(5)"
|
||||
- "pre_visit_offset_clause: OffsetClause(10)"
|
||||
- "post_visit_offset_clause: OffsetClause(10)"
|
||||
- "post_visit_show_tag_keys_statement: ShowTagKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) }"
|
||||
- "post_visit_statement: ShowTagKeys(ShowTagKeysStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) })"
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW TAG KEYS\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowTagKeys(ShowTagKeysStatement { database: None, from: None, condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_tag_keys_statement: ShowTagKeysStatement { database: None, from: None, condition: None, limit: None, offset: None }"
|
||||
- "post_visit_show_tag_keys_statement: ShowTagKeysStatement { database: None, from: None, condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowTagKeys(ShowTagKeysStatement { database: None, from: None, condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW TAG VALUES WITH KEY =~ /host|region/\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowTagValues(ShowTagValuesStatement { database: None, from: None, with_key: EqRegex(Regex(\"host|region\")), condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_tag_values_statement: ShowTagValuesStatement { database: None, from: None, with_key: EqRegex(Regex(\"host|region\")), condition: None, limit: None, offset: None }"
|
||||
- "pre_visit_with_key_clause: EqRegex(Regex(\"host|region\"))"
|
||||
- "post_visit_with_key_clause: EqRegex(Regex(\"host|region\"))"
|
||||
- "post_visit_show_tag_values_statement: ShowTagValuesStatement { database: None, from: None, with_key: EqRegex(Regex(\"host|region\")), condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowTagValues(ShowTagValuesStatement { database: None, from: None, with_key: EqRegex(Regex(\"host|region\")), condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW TAG VALUES WITH KEY IN (host, region)\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowTagValues(ShowTagValuesStatement { database: None, from: None, with_key: In(OneOrMore { contents: [Identifier(\"host\"), Identifier(\"region\")] }), condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_tag_values_statement: ShowTagValuesStatement { database: None, from: None, with_key: In(OneOrMore { contents: [Identifier(\"host\"), Identifier(\"region\")] }), condition: None, limit: None, offset: None }"
|
||||
- "pre_visit_with_key_clause: In(OneOrMore { contents: [Identifier(\"host\"), Identifier(\"region\")] })"
|
||||
- "post_visit_with_key_clause: In(OneOrMore { contents: [Identifier(\"host\"), Identifier(\"region\")] })"
|
||||
- "post_visit_show_tag_values_statement: ShowTagValuesStatement { database: None, from: None, with_key: In(OneOrMore { contents: [Identifier(\"host\"), Identifier(\"region\")] }), condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowTagValues(ShowTagValuesStatement { database: None, from: None, with_key: In(OneOrMore { contents: [Identifier(\"host\"), Identifier(\"region\")] }), condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW TAG VALUES ON telegraf FROM cpu WITH KEY = host WHERE host = \\\"west\\\" LIMIT 5 OFFSET 10\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowTagValues(ShowTagValuesStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), with_key: Eq(Identifier(\"host\")), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) })"
|
||||
- "pre_visit_show_tag_values_statement: ShowTagValuesStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), with_key: Eq(Identifier(\"host\")), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) }"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_on_clause: OnClause(Identifier(\"telegraf\"))"
|
||||
- "pre_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }"
|
||||
- "pre_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "pre_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_measurement_name: Name(Identifier(\"cpu\"))"
|
||||
- "post_visit_qualified_measurement_name: QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }"
|
||||
- "post_visit_show_from_clause: OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }"
|
||||
- "pre_visit_with_key_clause: Eq(Identifier(\"host\"))"
|
||||
- "post_visit_with_key_clause: Eq(Identifier(\"host\"))"
|
||||
- "pre_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })"
|
||||
- "pre_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) }"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"host\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"host\"), data_type: None })"
|
||||
- "pre_visit_conditional_expression: Expr(VarRef { name: Identifier(\"west\"), data_type: None })"
|
||||
- "pre_visit_expr: VarRef { name: Identifier(\"west\"), data_type: None }"
|
||||
- "post_visit_expr: VarRef { name: Identifier(\"west\"), data_type: None }"
|
||||
- "post_visit_conditional_expression: Expr(VarRef { name: Identifier(\"west\"), data_type: None })"
|
||||
- "post_visit_conditional_expression: Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) }"
|
||||
- "post_visit_where_clause: WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })"
|
||||
- "pre_visit_limit_clause: LimitClause(5)"
|
||||
- "post_visit_limit_clause: LimitClause(5)"
|
||||
- "pre_visit_offset_clause: OffsetClause(10)"
|
||||
- "post_visit_offset_clause: OffsetClause(10)"
|
||||
- "post_visit_show_tag_values_statement: ShowTagValuesStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), with_key: Eq(Identifier(\"host\")), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) }"
|
||||
- "post_visit_statement: ShowTagValues(ShowTagValuesStatement { database: Some(OnClause(Identifier(\"telegraf\"))), from: Some(OneOrMore { contents: [QualifiedMeasurementName { database: None, retention_policy: None, name: Name(Identifier(\"cpu\")) }] }), with_key: Eq(Identifier(\"host\")), condition: Some(WhereClause(Binary { lhs: Expr(VarRef { name: Identifier(\"host\"), data_type: None }), op: Eq, rhs: Expr(VarRef { name: Identifier(\"west\"), data_type: None }) })), limit: Some(LimitClause(5)), offset: Some(OffsetClause(10)) })"
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
source: influxdb_influxql_parser/src/visit.rs
|
||||
expression: "visit_statement!(\"SHOW TAG VALUES WITH KEY = host\")"
|
||||
---
|
||||
- "pre_visit_statement: ShowTagValues(ShowTagValuesStatement { database: None, from: None, with_key: Eq(Identifier(\"host\")), condition: None, limit: None, offset: None })"
|
||||
- "pre_visit_show_tag_values_statement: ShowTagValuesStatement { database: None, from: None, with_key: Eq(Identifier(\"host\")), condition: None, limit: None, offset: None }"
|
||||
- "pre_visit_with_key_clause: Eq(Identifier(\"host\"))"
|
||||
- "post_visit_with_key_clause: Eq(Identifier(\"host\"))"
|
||||
- "post_visit_show_tag_values_statement: ShowTagValuesStatement { database: None, from: None, with_key: Eq(Identifier(\"host\")), condition: None, limit: None, offset: None }"
|
||||
- "post_visit_statement: ShowTagValues(ShowTagValuesStatement { database: None, from: None, with_key: Eq(Identifier(\"host\")), condition: None, limit: None, offset: None })"
|
||||
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
// Taken liberally from https://github.com/Geal/nom/blob/main/examples/string.rs and
|
||||
// amended for InfluxQL.
|
||||
|
||||
use crate::impl_tuple_clause;
|
||||
use crate::internal::{expect, ParseError, ParseResult};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::{is_not, tag};
|
||||
|
|
@ -61,7 +62,7 @@ enum StringFragment<'a> {
|
|||
}
|
||||
|
||||
/// Parse a single-quoted literal string.
|
||||
pub fn single_quoted_string(i: &str) -> ParseResult<&str, String> {
|
||||
pub(crate) fn single_quoted_string(i: &str) -> ParseResult<&str, String> {
|
||||
let escaped = preceded(
|
||||
char('\\'),
|
||||
expect(
|
||||
|
|
@ -79,7 +80,7 @@ pub fn single_quoted_string(i: &str) -> ParseResult<&str, String> {
|
|||
}
|
||||
|
||||
/// Parse a double-quoted identifier string.
|
||||
pub fn double_quoted_string(i: &str) -> ParseResult<&str, String> {
|
||||
pub(crate) fn double_quoted_string(i: &str) -> ParseResult<&str, String> {
|
||||
let escaped = preceded(
|
||||
char('\\'),
|
||||
expect(
|
||||
|
|
@ -158,7 +159,9 @@ fn regex_literal(i: &str) -> ParseResult<&str, &str> {
|
|||
|
||||
/// An unescaped regular expression.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Regex(pub String);
|
||||
pub struct Regex(pub(crate) String);
|
||||
|
||||
impl_tuple_clause!(Regex, String);
|
||||
|
||||
impl Display for Regex {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
|
|
@ -168,12 +171,6 @@ impl Display for Regex {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<String> for Regex {
|
||||
fn from(v: String) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Regex {
|
||||
fn from(v: &str) -> Self {
|
||||
Self(v.into())
|
||||
|
|
@ -181,7 +178,7 @@ impl From<&str> for Regex {
|
|||
}
|
||||
|
||||
/// Parse a regular expression, delimited by `/`.
|
||||
pub fn regex(i: &str) -> ParseResult<&str, Regex> {
|
||||
pub(crate) fn regex(i: &str) -> ParseResult<&str, Regex> {
|
||||
map(
|
||||
string(
|
||||
'/',
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -58,6 +58,7 @@ ring = { version = "0.16", features = ["alloc", "dev_urandom_fallback", "once_ce
|
|||
serde = { version = "1", features = ["derive", "rc", "serde_derive", "std"] }
|
||||
serde_json = { version = "1", features = ["raw_value", "std"] }
|
||||
sha2 = { version = "0.10", features = ["std"] }
|
||||
similar = { version = "2", features = ["inline", "text"] }
|
||||
smallvec = { version = "1", default-features = false, features = ["union"] }
|
||||
sqlx = { version = "0.6", features = ["_rt-tokio", "json", "macros", "migrate", "postgres", "runtime-tokio-rustls", "sqlx-macros", "tls", "uuid"] }
|
||||
sqlx-core = { version = "0.6", default-features = false, features = ["_rt-tokio", "_tls-rustls", "any", "base64", "crc", "dirs", "hkdf", "hmac", "json", "md-5", "migrate", "postgres", "rand", "runtime-tokio-rustls", "rustls", "rustls-pemfile", "serde", "serde_json", "sha1", "sha2", "tokio-stream", "uuid", "webpki-roots", "whoami"] }
|
||||
|
|
|
|||
Loading…
Reference in New Issue