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    alias: &Option<String>,
46) -> std::fmt::Result {
47    write!(f, "({start}, {end}, '{step}'")?;
48    if let Some(lookback) = lookback {
49        write!(f, ", {lookback}")?;
50    }
51    if let Some(alias) = alias {
52        write!(f, ") {query} AS {alias}")
53    } else {
54        write!(f, ") {query}")
55    }
56}
57
58/// TQL EVAL (<start>, <end>, <step>, [lookback]) <promql> [AS alias]
59#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
60pub struct TqlEval {
61    pub start: String,
62    pub end: String,
63    pub step: String,
64    pub lookback: Option<String>,
65    pub query: String,
66    pub alias: Option<String>,
67}
68
69impl Display for TqlEval {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        write!(f, "TQL EVAL ")?;
72        format_tql(
73            f,
74            &self.start,
75            &self.end,
76            &self.step,
77            self.lookback.as_deref(),
78            &self.query,
79            &self.alias,
80        )
81    }
82}
83
84/// TQL EXPLAIN [VERBOSE] [FORMAT format] [<start>, <end>, <step>, [lookback]] <promql> [AS alias]
85/// doesn't execute the query but tells how the query would be executed (similar to SQL EXPLAIN).
86#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
87pub struct TqlExplain {
88    pub start: String,
89    pub end: String,
90    pub step: String,
91    pub lookback: Option<String>,
92    pub query: String,
93    pub alias: Option<String>,
94    pub is_verbose: bool,
95    pub format: Option<AnalyzeFormat>,
96}
97
98impl Display for TqlExplain {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        write!(f, "TQL EXPLAIN ")?;
101        if self.is_verbose {
102            write!(f, "VERBOSE ")?;
103        }
104        if let Some(format) = &self.format {
105            write!(f, "FORMAT {} ", format)?;
106        }
107        format_tql(
108            f,
109            &self.start,
110            &self.end,
111            &self.step,
112            self.lookback.as_deref(),
113            &self.query,
114            &self.alias,
115        )
116    }
117}
118
119/// TQL ANALYZE [VERBOSE] [FORMAT format] (<start>, <end>, <step>, [lookback]) <promql> [AS alias]
120/// executes the plan and tells the detailed per-step execution time (similar to SQL ANALYZE).
121#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
122pub struct TqlAnalyze {
123    pub start: String,
124    pub end: String,
125    pub step: String,
126    pub lookback: Option<String>,
127    pub query: String,
128    pub alias: Option<String>,
129    pub is_verbose: bool,
130    pub format: Option<AnalyzeFormat>,
131}
132
133impl Display for TqlAnalyze {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        write!(f, "TQL ANALYZE ")?;
136        if self.is_verbose {
137            write!(f, "VERBOSE ")?;
138        }
139        if let Some(format) = &self.format {
140            write!(f, "FORMAT {} ", format)?;
141        }
142        format_tql(
143            f,
144            &self.start,
145            &self.end,
146            &self.step,
147            self.lookback.as_deref(),
148            &self.query,
149            &self.alias,
150        )
151    }
152}
153
154/// Intermediate structure used to unify parameter mappings for various TQL operations.
155///
156/// This struct serves as a common parameter container for parsing TQL queries
157/// and constructing corresponding TQL operations: `TqlEval`, `TqlAnalyze` or `TqlExplain`.
158#[derive(Debug)]
159pub struct TqlParameters {
160    start: String,
161    end: String,
162    step: String,
163    lookback: Option<String>,
164    query: String,
165    alias: Option<String>,
166    pub is_verbose: bool,
167    pub format: Option<AnalyzeFormat>,
168}
169
170impl TqlParameters {
171    pub fn new(
172        start: String,
173        end: String,
174        step: String,
175        lookback: Option<String>,
176        query: String,
177        alias: Option<String>,
178    ) -> Self {
179        TqlParameters {
180            start,
181            end,
182            step,
183            lookback,
184            query,
185            alias,
186            is_verbose: false,
187            format: None,
188        }
189    }
190}
191
192impl From<TqlParameters> for TqlEval {
193    fn from(params: TqlParameters) -> Self {
194        TqlEval {
195            start: params.start,
196            end: params.end,
197            step: params.step,
198            lookback: params.lookback,
199            query: params.query,
200            alias: params.alias,
201        }
202    }
203}
204
205impl From<TqlParameters> for TqlExplain {
206    fn from(params: TqlParameters) -> Self {
207        TqlExplain {
208            start: params.start,
209            end: params.end,
210            step: params.step,
211            query: params.query,
212            alias: params.alias,
213            lookback: params.lookback,
214            is_verbose: params.is_verbose,
215            format: params.format,
216        }
217    }
218}
219
220impl From<TqlParameters> for TqlAnalyze {
221    fn from(params: TqlParameters) -> Self {
222        TqlAnalyze {
223            start: params.start,
224            end: params.end,
225            step: params.step,
226            query: params.query,
227            alias: params.alias,
228            lookback: params.lookback,
229            is_verbose: params.is_verbose,
230            format: params.format,
231        }
232    }
233}