sql/statements/
tql.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::Display;
16
17use serde::Serialize;
18use sqlparser::ast::AnalyzeFormat;
19use sqlparser_derive::{Visit, VisitMut};
20
21#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
22pub enum Tql {
23    Eval(TqlEval),
24    Explain(TqlExplain),
25    Analyze(TqlAnalyze),
26}
27
28impl Display for Tql {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        match self {
31            Tql::Eval(t) => t.fmt(f),
32            Tql::Explain(t) => t.fmt(f),
33            Tql::Analyze(t) => t.fmt(f),
34        }
35    }
36}
37
38fn format_tql(
39    f: &mut std::fmt::Formatter<'_>,
40    start: &str,
41    end: &str,
42    step: &str,
43    lookback: Option<&str>,
44    query: &str,
45) -> std::fmt::Result {
46    write!(f, "({start}, {end}, '{step}'")?;
47    if let Some(lookback) = lookback {
48        write!(f, ", {lookback}")?;
49    }
50    write!(f, ") {query}")
51}
52
53/// TQL EVAL (<start>, <end>, <step>, [lookback]) <promql>
54#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
55pub struct TqlEval {
56    pub start: String,
57    pub end: String,
58    pub step: String,
59    pub lookback: Option<String>,
60    pub query: String,
61}
62
63impl Display for TqlEval {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        write!(f, "TQL EVAL ")?;
66        format_tql(
67            f,
68            &self.start,
69            &self.end,
70            &self.step,
71            self.lookback.as_deref(),
72            &self.query,
73        )
74    }
75}
76
77/// TQL EXPLAIN [VERBOSE] [FORMAT format] [<start>, <end>, <step>, [lookback]] <promql>
78/// doesn't execute the query but tells how the query would be executed (similar to SQL EXPLAIN).
79#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
80pub struct TqlExplain {
81    pub start: String,
82    pub end: String,
83    pub step: String,
84    pub lookback: Option<String>,
85    pub query: String,
86    pub is_verbose: bool,
87    pub format: Option<AnalyzeFormat>,
88}
89
90impl Display for TqlExplain {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        write!(f, "TQL EXPLAIN ")?;
93        if self.is_verbose {
94            write!(f, "VERBOSE ")?;
95        }
96        if let Some(format) = &self.format {
97            write!(f, "FORMAT {} ", format)?;
98        }
99        format_tql(
100            f,
101            &self.start,
102            &self.end,
103            &self.step,
104            self.lookback.as_deref(),
105            &self.query,
106        )
107    }
108}
109
110/// TQL ANALYZE [VERBOSE] [FORMAT format] (<start>, <end>, <step>, [lookback]) <promql>
111/// executes the plan and tells the detailed per-step execution time (similar to SQL ANALYZE).
112#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
113pub struct TqlAnalyze {
114    pub start: String,
115    pub end: String,
116    pub step: String,
117    pub lookback: Option<String>,
118    pub query: String,
119    pub is_verbose: bool,
120    pub format: Option<AnalyzeFormat>,
121}
122
123impl Display for TqlAnalyze {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        write!(f, "TQL ANALYZE ")?;
126        if self.is_verbose {
127            write!(f, "VERBOSE ")?;
128        }
129        if let Some(format) = &self.format {
130            write!(f, "FORMAT {} ", format)?;
131        }
132        format_tql(
133            f,
134            &self.start,
135            &self.end,
136            &self.step,
137            self.lookback.as_deref(),
138            &self.query,
139        )
140    }
141}
142
143/// Intermediate structure used to unify parameter mappings for various TQL operations.
144///
145/// This struct serves as a common parameter container for parsing TQL queries
146/// and constructing corresponding TQL operations: `TqlEval`, `TqlAnalyze` or `TqlExplain`.
147#[derive(Debug)]
148pub struct TqlParameters {
149    start: String,
150    end: String,
151    step: String,
152    lookback: Option<String>,
153    query: String,
154    pub is_verbose: bool,
155    pub format: Option<AnalyzeFormat>,
156}
157
158impl TqlParameters {
159    pub fn new(
160        start: String,
161        end: String,
162        step: String,
163        lookback: Option<String>,
164        query: String,
165    ) -> Self {
166        TqlParameters {
167            start,
168            end,
169            step,
170            lookback,
171            query,
172            is_verbose: false,
173            format: None,
174        }
175    }
176}
177
178impl From<TqlParameters> for TqlEval {
179    fn from(params: TqlParameters) -> Self {
180        TqlEval {
181            start: params.start,
182            end: params.end,
183            step: params.step,
184            lookback: params.lookback,
185            query: params.query,
186        }
187    }
188}
189
190impl From<TqlParameters> for TqlExplain {
191    fn from(params: TqlParameters) -> Self {
192        TqlExplain {
193            start: params.start,
194            end: params.end,
195            step: params.step,
196            query: params.query,
197            lookback: params.lookback,
198            is_verbose: params.is_verbose,
199            format: params.format,
200        }
201    }
202}
203
204impl From<TqlParameters> for TqlAnalyze {
205    fn from(params: TqlParameters) -> Self {
206        TqlAnalyze {
207            start: params.start,
208            end: params.end,
209            step: params.step,
210            query: params.query,
211            lookback: params.lookback,
212            is_verbose: params.is_verbose,
213            format: params.format,
214        }
215    }
216}