mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-01-14 01:02:55 +00:00
feat(flow): support prom ql(in tql) in flow (#6063)
* feat: support parse prom ql in create flow * refactor * fix: just run tql unmodified * refactor: determine type faster * fix: pass original query * tests: sqlness * test: fix format&chore * fix: get raw query * test: fix sqlness randomness * chore: what's the box for? * test: location_to_index * test: make sqlness more determinstic * fix: tmp add sleep 1s after flush_flow * undo test sleep 1s&rm done todo * chore: more tests
This commit is contained in:
@@ -780,8 +780,77 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_flow_tql_expr() {
|
||||
let sql = r#"
|
||||
CREATE FLOW calc_reqs SINK TO cnt_reqs AS
|
||||
TQL EVAL (0, 15, '5s') count_values("status_code", http_requests);"#;
|
||||
let stmt =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap();
|
||||
|
||||
let Statement::CreateFlow(create_flow) = stmt else {
|
||||
unreachable!()
|
||||
};
|
||||
let expr = to_create_flow_task_expr(create_flow, &QueryContext::arc()).unwrap();
|
||||
|
||||
let to_dot_sep =
|
||||
|c: TableName| format!("{}.{}.{}", c.catalog_name, c.schema_name, c.table_name);
|
||||
assert_eq!("calc_reqs", expr.flow_name);
|
||||
assert_eq!("greptime", expr.catalog_name);
|
||||
assert_eq!(
|
||||
"greptime.public.cnt_reqs",
|
||||
expr.sink_table_name.map(to_dot_sep).unwrap()
|
||||
);
|
||||
assert!(expr.source_table_names.is_empty());
|
||||
assert_eq!(
|
||||
r#"TQL EVAL (0, 15, '5s') count_values("status_code", http_requests)"#,
|
||||
expr.sql
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_flow_expr() {
|
||||
let sql = r"
|
||||
CREATE FLOW test_distinct_basic SINK TO out_distinct_basic AS
|
||||
SELECT
|
||||
DISTINCT number as dis
|
||||
FROM
|
||||
distinct_basic;";
|
||||
let stmt =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
.unwrap()
|
||||
.pop()
|
||||
.unwrap();
|
||||
|
||||
let Statement::CreateFlow(create_flow) = stmt else {
|
||||
unreachable!()
|
||||
};
|
||||
let expr = to_create_flow_task_expr(create_flow, &QueryContext::arc()).unwrap();
|
||||
|
||||
let to_dot_sep =
|
||||
|c: TableName| format!("{}.{}.{}", c.catalog_name, c.schema_name, c.table_name);
|
||||
assert_eq!("test_distinct_basic", expr.flow_name);
|
||||
assert_eq!("greptime", expr.catalog_name);
|
||||
assert_eq!(
|
||||
"greptime.public.out_distinct_basic",
|
||||
expr.sink_table_name.map(to_dot_sep).unwrap()
|
||||
);
|
||||
assert_eq!(1, expr.source_table_names.len());
|
||||
assert_eq!(
|
||||
"greptime.public.distinct_basic",
|
||||
to_dot_sep(expr.source_table_names[0].clone())
|
||||
);
|
||||
assert_eq!(
|
||||
r"SELECT
|
||||
DISTINCT number as dis
|
||||
FROM
|
||||
distinct_basic",
|
||||
expr.sql
|
||||
);
|
||||
|
||||
let sql = r"
|
||||
CREATE FLOW `task_2`
|
||||
SINK TO schema_1.table_1
|
||||
|
||||
@@ -48,7 +48,7 @@ use lazy_static::lazy_static;
|
||||
use partition::expr::{Operand, PartitionExpr, RestrictedOp};
|
||||
use partition::multi_dim::MultiDimPartitionRule;
|
||||
use partition::partition::{PartitionBound, PartitionDef};
|
||||
use query::parser::{QueryLanguageParser, QueryStatement};
|
||||
use query::parser::QueryStatement;
|
||||
use query::plan::extract_and_rewrite_full_table_names;
|
||||
use query::query_engine::DefaultSerializer;
|
||||
use query::sql::create_table_stmt;
|
||||
@@ -56,6 +56,7 @@ use regex::Regex;
|
||||
use session::context::QueryContextRef;
|
||||
use session::table_name::table_idents_to_full_name;
|
||||
use snafu::{ensure, OptionExt, ResultExt};
|
||||
use sql::parser::{ParseOptions, ParserContext};
|
||||
use sql::statements::alter::{AlterDatabase, AlterTable};
|
||||
use sql::statements::create::{
|
||||
CreateExternalTable, CreateFlow, CreateTable, CreateTableLike, CreateView, Partitions,
|
||||
@@ -440,15 +441,33 @@ impl StatementExecutor {
|
||||
}
|
||||
|
||||
let engine = &self.query_engine;
|
||||
let stmt = QueryLanguageParser::parse_sql(&expr.sql, &query_ctx)
|
||||
.map_err(BoxedError::new)
|
||||
.context(ExternalSnafu)?;
|
||||
let plan = engine
|
||||
.planner()
|
||||
.plan(&stmt, query_ctx)
|
||||
.await
|
||||
.map_err(BoxedError::new)
|
||||
.context(ExternalSnafu)?;
|
||||
let stmts = ParserContext::create_with_dialect(
|
||||
&expr.sql,
|
||||
query_ctx.sql_dialect(),
|
||||
ParseOptions::default(),
|
||||
)
|
||||
.map_err(BoxedError::new)
|
||||
.context(ExternalSnafu)?;
|
||||
|
||||
ensure!(
|
||||
stmts.len() == 1,
|
||||
InvalidSqlSnafu {
|
||||
err_msg: format!("Expect only one statement, found {}", stmts.len())
|
||||
}
|
||||
);
|
||||
let stmt = &stmts[0];
|
||||
|
||||
// support tql parse too
|
||||
let plan = match stmt {
|
||||
// prom ql is only supported in batching mode
|
||||
Statement::Tql(_) => return Ok(FlowType::Batching),
|
||||
_ => engine
|
||||
.planner()
|
||||
.plan(&QueryStatement::Sql(stmt.clone()), query_ctx)
|
||||
.await
|
||||
.map_err(BoxedError::new)
|
||||
.context(ExternalSnafu)?,
|
||||
};
|
||||
|
||||
/// Visitor to find aggregation or distinct
|
||||
struct FindAggr {
|
||||
|
||||
Reference in New Issue
Block a user