mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-01-03 11:52:54 +00:00
feat: implement v1/sql/parse endpoint to parse GreptimeDB's SQL dialect (#5144)
* derive ser/de Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * impl method Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * fix typo Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * remove deserialize Signed-off-by: Ruihang Xia <waynestxia@gmail.com> --------- Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -11295,6 +11295,7 @@ dependencies = [
|
||||
"jsonb",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snafu 0.8.5",
|
||||
"sqlparser 0.45.0 (git+https://github.com/GreptimeTeam/sqlparser-rs.git?rev=54a267ac89c09b11c0c88934690530807185d3e7)",
|
||||
@@ -11371,6 +11372,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"regex",
|
||||
"serde",
|
||||
"sqlparser 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sqlparser_derive 0.2.2 (git+https://github.com/GreptimeTeam/sqlparser-rs.git?rev=54a267ac89c09b11c0c88934690530807185d3e7)",
|
||||
]
|
||||
|
||||
@@ -180,6 +180,7 @@ sysinfo = "0.30"
|
||||
# on branch v0.44.x
|
||||
sqlparser = { git = "https://github.com/GreptimeTeam/sqlparser-rs.git", rev = "54a267ac89c09b11c0c88934690530807185d3e7", features = [
|
||||
"visitor",
|
||||
"serde",
|
||||
] }
|
||||
strum = { version = "0.25", features = ["derive"] }
|
||||
tempfile = "3"
|
||||
|
||||
@@ -189,6 +189,13 @@ pub enum Error {
|
||||
location: Location,
|
||||
},
|
||||
|
||||
#[snafu(display("Failed to parse query"))]
|
||||
FailedToParseQuery {
|
||||
#[snafu(implicit)]
|
||||
location: Location,
|
||||
source: sql::error::Error,
|
||||
},
|
||||
|
||||
#[snafu(display("Failed to parse InfluxDB line protocol"))]
|
||||
InfluxdbLineProtocol {
|
||||
#[snafu(implicit)]
|
||||
@@ -651,7 +658,8 @@ impl ErrorExt for Error {
|
||||
| OpenTelemetryLog { .. }
|
||||
| UnsupportedJsonDataTypeForTag { .. }
|
||||
| InvalidTableName { .. }
|
||||
| PrepareStatementNotFound { .. } => StatusCode::InvalidArguments,
|
||||
| PrepareStatementNotFound { .. }
|
||||
| FailedToParseQuery { .. } => StatusCode::InvalidArguments,
|
||||
|
||||
Catalog { source, .. } => source.status_code(),
|
||||
RowWriter { source, .. } => source.status_code(),
|
||||
|
||||
@@ -755,6 +755,10 @@ impl HttpServer {
|
||||
fn route_sql<S>(api_state: ApiState) -> Router<S> {
|
||||
Router::new()
|
||||
.route("/sql", routing::get(handler::sql).post(handler::sql))
|
||||
.route(
|
||||
"/sql/parse",
|
||||
routing::get(handler::sql_parse).post(handler::sql_parse),
|
||||
)
|
||||
.route(
|
||||
"/promql",
|
||||
routing::get(handler::promql).post(handler::promql),
|
||||
|
||||
@@ -30,8 +30,13 @@ use query::parser::{PromQuery, DEFAULT_LOOKBACK_STRING};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use session::context::{Channel, QueryContext, QueryContextRef};
|
||||
use snafu::ResultExt;
|
||||
use sql::dialect::GreptimeDbDialect;
|
||||
use sql::parser::{ParseOptions, ParserContext};
|
||||
use sql::statements::statement::Statement;
|
||||
|
||||
use super::header::collect_plan_metrics;
|
||||
use crate::error::{FailedToParseQuerySnafu, InvalidQuerySnafu, Result};
|
||||
use crate::http::result::arrow_result::ArrowResponse;
|
||||
use crate::http::result::csv_result::CsvResponse;
|
||||
use crate::http::result::error_result::ErrorResponse;
|
||||
@@ -146,10 +151,31 @@ pub async fn sql(
|
||||
resp.with_execution_time(start.elapsed().as_millis() as u64)
|
||||
}
|
||||
|
||||
/// Handler to parse sql
|
||||
#[axum_macros::debug_handler]
|
||||
#[tracing::instrument(skip_all, fields(protocol = "http", request_type = "sql"))]
|
||||
pub async fn sql_parse(
|
||||
Query(query_params): Query<SqlQuery>,
|
||||
Form(form_params): Form<SqlQuery>,
|
||||
) -> Result<Json<Vec<Statement>>> {
|
||||
let Some(sql) = query_params.sql.or(form_params.sql) else {
|
||||
return InvalidQuerySnafu {
|
||||
reason: "sql parameter is required.",
|
||||
}
|
||||
.fail();
|
||||
};
|
||||
|
||||
let stmts =
|
||||
ParserContext::create_with_dialect(&sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
.context(FailedToParseQuerySnafu)?;
|
||||
|
||||
Ok(stmts.into())
|
||||
}
|
||||
|
||||
/// Create a response from query result
|
||||
pub async fn from_output(
|
||||
outputs: Vec<crate::error::Result<Output>>,
|
||||
) -> Result<(Vec<GreptimeQueryOutput>, HashMap<String, Value>), ErrorResponse> {
|
||||
) -> std::result::Result<(Vec<GreptimeQueryOutput>, HashMap<String, Value>), ErrorResponse> {
|
||||
// TODO(sunng87): this api response structure cannot represent error well.
|
||||
// It hides successful execution results from error response
|
||||
let mut results = Vec::with_capacity(outputs.len());
|
||||
|
||||
@@ -30,6 +30,7 @@ itertools.workspace = true
|
||||
jsonb.workspace = true
|
||||
lazy_static.workspace = true
|
||||
regex.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
snafu.workspace = true
|
||||
sqlparser.workspace = true
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::ast::Function;
|
||||
|
||||
/// `ADMIN` statement to execute some administration commands.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum Admin {
|
||||
/// Run a admin function.
|
||||
Func(Function),
|
||||
|
||||
@@ -18,10 +18,11 @@ use api::v1;
|
||||
use common_query::AddColumnLocation;
|
||||
use datatypes::schema::FulltextOptions;
|
||||
use itertools::Itertools;
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::{ColumnDef, DataType, Ident, ObjectName, TableConstraint};
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct AlterTable {
|
||||
pub table_name: ObjectName,
|
||||
pub alter_operation: AlterTableOperation,
|
||||
@@ -56,7 +57,7 @@ impl Display for AlterTable {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum AlterTableOperation {
|
||||
/// `ADD <table_constraint>`
|
||||
AddConstraint(TableConstraint),
|
||||
@@ -151,7 +152,7 @@ impl Display for AlterTableOperation {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct KeyValueOption {
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
@@ -166,7 +167,7 @@ impl From<KeyValueOption> for v1::Option {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct AlterDatabase {
|
||||
pub database_name: ObjectName,
|
||||
pub alter_operation: AlterDatabaseOperation,
|
||||
@@ -197,7 +198,7 @@ impl Display for AlterDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum AlterDatabaseOperation {
|
||||
SetDatabaseOption { options: Vec<KeyValueOption> },
|
||||
UnsetDatabaseOption { keys: Vec<String> },
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::ObjectName;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::statements::OptionMap;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum Copy {
|
||||
CopyTable(CopyTable),
|
||||
CopyDatabase(CopyDatabase),
|
||||
@@ -34,7 +35,7 @@ impl Display for Copy {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum CopyTable {
|
||||
To(CopyTableArgument),
|
||||
From(CopyTableArgument),
|
||||
@@ -65,7 +66,7 @@ impl Display for CopyTable {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum CopyDatabase {
|
||||
To(CopyDatabaseArgument),
|
||||
From(CopyDatabaseArgument),
|
||||
@@ -96,7 +97,7 @@ impl Display for CopyDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct CopyDatabaseArgument {
|
||||
pub database_name: ObjectName,
|
||||
pub with: OptionMap,
|
||||
@@ -104,7 +105,7 @@ pub struct CopyDatabaseArgument {
|
||||
pub location: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct CopyTableArgument {
|
||||
pub table_name: ObjectName,
|
||||
pub with: OptionMap,
|
||||
|
||||
@@ -18,6 +18,7 @@ use std::fmt::{Display, Formatter};
|
||||
use common_catalog::consts::FILE_ENGINE;
|
||||
use datatypes::schema::FulltextOptions;
|
||||
use itertools::Itertools;
|
||||
use serde::Serialize;
|
||||
use snafu::ResultExt;
|
||||
use sqlparser::ast::{ColumnOptionDef, DataType, Expr, Query};
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
@@ -58,7 +59,7 @@ fn format_table_constraint(constraints: &[TableConstraint]) -> String {
|
||||
}
|
||||
|
||||
/// Table constraint for create table statement.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub enum TableConstraint {
|
||||
/// Primary key constraint.
|
||||
PrimaryKey { columns: Vec<Ident> },
|
||||
@@ -84,7 +85,7 @@ impl Display for TableConstraint {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct CreateTable {
|
||||
/// Create if not exists
|
||||
pub if_not_exists: bool,
|
||||
@@ -100,7 +101,7 @@ pub struct CreateTable {
|
||||
}
|
||||
|
||||
/// Column definition in `CREATE TABLE` statement.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct Column {
|
||||
/// `ColumnDef` from `sqlparser::ast`
|
||||
pub column_def: ColumnDef,
|
||||
@@ -109,7 +110,7 @@ pub struct Column {
|
||||
}
|
||||
|
||||
/// Column extensions for greptimedb dialect.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Default)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Default, Serialize)]
|
||||
pub struct ColumnExtensions {
|
||||
/// Fulltext options.
|
||||
pub fulltext_options: Option<OptionMap>,
|
||||
@@ -172,7 +173,7 @@ impl ColumnExtensions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct Partitions {
|
||||
pub column_list: Vec<Ident>,
|
||||
pub exprs: Vec<Expr>,
|
||||
@@ -244,7 +245,7 @@ impl Display for CreateTable {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct CreateDatabase {
|
||||
pub name: ObjectName,
|
||||
/// Create if not exists
|
||||
@@ -278,7 +279,7 @@ impl Display for CreateDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct CreateExternalTable {
|
||||
/// Table name
|
||||
pub name: ObjectName,
|
||||
@@ -309,7 +310,7 @@ impl Display for CreateExternalTable {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct CreateTableLike {
|
||||
/// Table name
|
||||
pub table_name: ObjectName,
|
||||
@@ -325,7 +326,7 @@ impl Display for CreateTableLike {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct CreateFlow {
|
||||
/// Flow name
|
||||
pub flow_name: ObjectName,
|
||||
@@ -367,7 +368,7 @@ impl Display for CreateFlow {
|
||||
}
|
||||
|
||||
/// Create SQL view statement.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Visit, VisitMut, Serialize)]
|
||||
pub struct CreateView {
|
||||
/// View name
|
||||
pub name: ObjectName,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::ObjectName;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
@@ -22,7 +23,7 @@ use super::query::Query;
|
||||
/// Represents a DECLARE CURSOR statement
|
||||
///
|
||||
/// This statement will carry a SQL query
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct DeclareCursor {
|
||||
pub cursor_name: ObjectName,
|
||||
pub query: Box<Query>,
|
||||
@@ -35,7 +36,7 @@ impl Display for DeclareCursor {
|
||||
}
|
||||
|
||||
/// Represents a FETCH FROM cursor statement
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct FetchCursor {
|
||||
pub cursor_name: ObjectName,
|
||||
pub fetch_size: u64,
|
||||
@@ -48,7 +49,7 @@ impl Display for FetchCursor {
|
||||
}
|
||||
|
||||
/// Represents a CLOSE cursor statement
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct CloseCursor {
|
||||
pub cursor_name: ObjectName,
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::Statement;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct Delete {
|
||||
pub inner: Statement,
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::ObjectName;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
/// SQL structure for `DESCRIBE TABLE`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct DescribeTable {
|
||||
name: ObjectName,
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::ObjectName;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
/// DROP TABLE statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct DropTable {
|
||||
table_names: Vec<ObjectName>,
|
||||
|
||||
@@ -62,7 +63,7 @@ impl Display for DropTable {
|
||||
}
|
||||
|
||||
/// DROP DATABASE statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct DropDatabase {
|
||||
name: ObjectName,
|
||||
/// drop table if exists
|
||||
@@ -99,7 +100,7 @@ impl Display for DropDatabase {
|
||||
}
|
||||
|
||||
/// DROP FLOW statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct DropFlow {
|
||||
flow_name: ObjectName,
|
||||
/// drop flow if exists
|
||||
@@ -138,7 +139,7 @@ impl Display for DropFlow {
|
||||
}
|
||||
|
||||
/// `DROP VIEW` statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct DropView {
|
||||
// The view name
|
||||
pub view_name: ObjectName,
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::Statement as SpStatement;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
/// Explain statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct Explain {
|
||||
pub inner: SpStatement,
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::{ObjectName, Query, SetExpr, Statement, UnaryOperator, Values};
|
||||
use sqlparser::parser::ParserError;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
@@ -20,7 +21,7 @@ use crate::ast::{Expr, Value};
|
||||
use crate::error::Result;
|
||||
use crate::statements::query::Query as GtQuery;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct Insert {
|
||||
// Can only be sqlparser::ast::Statement::Insert variant
|
||||
pub inner: Statement,
|
||||
|
||||
@@ -16,14 +16,16 @@ use std::collections::{BTreeMap, HashMap};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use common_base::secrets::{ExposeSecret, ExposeSecretMut, SecretString};
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::{Visit, VisitMut, Visitor, VisitorMut};
|
||||
|
||||
const REDACTED_OPTIONS: [&str; 2] = ["access_key_id", "secret_access_key"];
|
||||
|
||||
/// Options hashmap.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Debug, Default, Serialize)]
|
||||
pub struct OptionMap {
|
||||
options: BTreeMap<String, String>,
|
||||
#[serde(skip_serializing)]
|
||||
secrets: BTreeMap<String, SecretString>,
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::Query as SpQuery;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
/// Query statement instance.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct Query {
|
||||
pub inner: SpQuery,
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::{Expr, ObjectName};
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
/// SET variables statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct SetVariables {
|
||||
pub variable: ObjectName,
|
||||
pub value: Vec<Expr>,
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::ast::{Expr, Ident, ObjectName};
|
||||
|
||||
/// Show kind for SQL expressions like `SHOW DATABASE` or `SHOW TABLE`
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum ShowKind {
|
||||
All,
|
||||
Like(Ident),
|
||||
@@ -46,14 +47,14 @@ macro_rules! format_kind {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW DATABASES`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowDatabases {
|
||||
pub kind: ShowKind,
|
||||
pub full: bool,
|
||||
}
|
||||
|
||||
/// The SQL `SHOW COLUMNS` statement
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowColumns {
|
||||
pub kind: ShowKind,
|
||||
pub table: String,
|
||||
@@ -77,7 +78,7 @@ impl Display for ShowColumns {
|
||||
}
|
||||
|
||||
/// The SQL `SHOW INDEX` statement
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowIndex {
|
||||
pub kind: ShowKind,
|
||||
pub table: String,
|
||||
@@ -118,7 +119,7 @@ impl Display for ShowDatabases {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW TABLES`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowTables {
|
||||
pub kind: ShowKind,
|
||||
pub database: Option<String>,
|
||||
@@ -142,7 +143,7 @@ impl Display for ShowTables {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW TABLE STATUS`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowTableStatus {
|
||||
pub kind: ShowKind,
|
||||
pub database: Option<String>,
|
||||
@@ -162,7 +163,7 @@ impl Display for ShowTableStatus {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW CREATE DATABASE`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowCreateDatabase {
|
||||
pub database_name: ObjectName,
|
||||
}
|
||||
@@ -175,7 +176,7 @@ impl Display for ShowCreateDatabase {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW CREATE TABLE`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowCreateTable {
|
||||
pub table_name: ObjectName,
|
||||
}
|
||||
@@ -188,7 +189,7 @@ impl Display for ShowCreateTable {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW CREATE FLOW`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowCreateFlow {
|
||||
pub flow_name: ObjectName,
|
||||
}
|
||||
@@ -201,7 +202,7 @@ impl Display for ShowCreateFlow {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW FLOWS`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowFlows {
|
||||
pub kind: ShowKind,
|
||||
pub database: Option<String>,
|
||||
@@ -220,7 +221,7 @@ impl Display for ShowFlows {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW CREATE VIEW`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowCreateView {
|
||||
pub view_name: ObjectName,
|
||||
}
|
||||
@@ -233,7 +234,7 @@ impl Display for ShowCreateView {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW VIEWS`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowViews {
|
||||
pub kind: ShowKind,
|
||||
pub database: Option<String>,
|
||||
@@ -252,7 +253,7 @@ impl Display for ShowViews {
|
||||
}
|
||||
|
||||
/// SQL structure for `SHOW VARIABLES xxx`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowVariables {
|
||||
pub variable: ObjectName,
|
||||
}
|
||||
@@ -265,7 +266,7 @@ impl Display for ShowVariables {
|
||||
}
|
||||
|
||||
/// SQL structure for "SHOW STATUS"
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct ShowStatus {}
|
||||
|
||||
impl Display for ShowStatus {
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use datafusion_sql::parser::Statement as DfStatement;
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::Statement as SpStatement;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::error::{ConvertToDfStatementSnafu, Error};
|
||||
use crate::statements::admin::Admin;
|
||||
use crate::statements::alter::{AlterDatabase, AlterTable};
|
||||
use crate::statements::copy::Copy;
|
||||
use crate::statements::create::{
|
||||
CreateDatabase, CreateExternalTable, CreateFlow, CreateTable, CreateTableLike, CreateView,
|
||||
};
|
||||
@@ -42,7 +44,7 @@ use crate::statements::truncate::TruncateTable;
|
||||
|
||||
/// Tokens parsed by `DFParser` are converted into these values.
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum Statement {
|
||||
// Query
|
||||
Query(Box<Query>),
|
||||
@@ -107,7 +109,8 @@ pub enum Statement {
|
||||
// EXPLAIN QUERY
|
||||
Explain(Explain),
|
||||
// COPY
|
||||
Copy(crate::statements::copy::Copy),
|
||||
Copy(Copy),
|
||||
// Telemetry Query Language
|
||||
Tql(Tql),
|
||||
// TRUNCATE TABLE
|
||||
TruncateTable(TruncateTable),
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub enum Tql {
|
||||
Eval(TqlEval),
|
||||
Explain(TqlExplain),
|
||||
@@ -49,7 +50,7 @@ fn format_tql(
|
||||
}
|
||||
|
||||
/// TQL EVAL (<start>, <end>, <step>, [lookback]) <promql>
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct TqlEval {
|
||||
pub start: String,
|
||||
pub end: String,
|
||||
@@ -74,7 +75,7 @@ impl Display for TqlEval {
|
||||
|
||||
/// TQL EXPLAIN [VERBOSE] [<start>, <end>, <step>, [lookback]] <promql>
|
||||
/// doesn't execute the query but tells how the query would be executed (similar to SQL EXPLAIN).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct TqlExplain {
|
||||
pub start: String,
|
||||
pub end: String,
|
||||
@@ -103,7 +104,7 @@ impl Display for TqlExplain {
|
||||
|
||||
/// TQL ANALYZE [VERBOSE] (<start>, <end>, <step>, [lookback]) <promql>
|
||||
/// executes the plan and tells the detailed per-step execution time (similar to SQL ANALYZE).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct TqlAnalyze {
|
||||
pub start: String,
|
||||
pub end: String,
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Serialize;
|
||||
use sqlparser::ast::ObjectName;
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
/// TRUNCATE TABLE statement.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
|
||||
pub struct TruncateTable {
|
||||
table_name: ObjectName,
|
||||
}
|
||||
|
||||
@@ -361,6 +361,14 @@ pub async fn test_sql_api(store_type: StorageType) {
|
||||
let body = serde_json::from_str::<ErrorResponse>(&res.text().await).unwrap();
|
||||
assert_eq!(body.code(), ErrorCode::DatabaseNotFound as u32);
|
||||
|
||||
// test parse method
|
||||
let res = client.get("/v1/sql/parse?sql=desc table t").send().await;
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
res.text().await,
|
||||
"[{\"DescribeTable\":{\"name\":[{\"value\":\"t\",\"quote_style\":null}]}}]"
|
||||
);
|
||||
|
||||
// test timezone header
|
||||
let res = client
|
||||
.get("/v1/sql?&sql=show variables system_time_zone")
|
||||
|
||||
Reference in New Issue
Block a user