mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-01-14 17:23:09 +00:00
feat: frontend instance (#238)
* feat: frontend instance * no need to carry column length in `Column` proto * add more tests * rebase develop * create a new variant with already provisioned RecordBatches in Output * resolve code review comments * new frontend instance does not connect datanode grpc * add more tests * add more tests * rebase develop Co-authored-by: luofucong <luofucong@greptime.com>
This commit is contained in:
@@ -7,6 +7,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
common-error = { path = "../common/error" }
|
||||
datatypes = { path = "../datatypes" }
|
||||
snafu = { version = "0.7", features = ["backtraces"] }
|
||||
sqlparser = "0.15.0"
|
||||
table-engine = { path = "../table-engine" }
|
||||
|
||||
@@ -4,6 +4,8 @@ use common_error::prelude::*;
|
||||
use sqlparser::parser::ParserError;
|
||||
use sqlparser::tokenizer::TokenizerError;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// SQL parser errors.
|
||||
// Now the error in parser does not contains backtrace to avoid generating backtrace
|
||||
// every time the parser parses an invalid SQL.
|
||||
@@ -39,6 +41,15 @@ pub enum Error {
|
||||
sql
|
||||
))]
|
||||
InvalidTimeIndex { sql: String, backtrace: Backtrace },
|
||||
|
||||
#[snafu(display("Invalid SQL, error: {}", msg))]
|
||||
InvalidSql { msg: String, backtrace: Backtrace },
|
||||
|
||||
#[snafu(display("SQL data type not supported yet: {:?}", t))]
|
||||
SqlTypeNotSupported {
|
||||
t: crate::ast::DataType,
|
||||
backtrace: Backtrace,
|
||||
},
|
||||
}
|
||||
|
||||
impl ErrorExt for Error {
|
||||
@@ -47,9 +58,12 @@ impl ErrorExt for Error {
|
||||
|
||||
match self {
|
||||
Unsupported { .. } => StatusCode::Unsupported,
|
||||
Unexpected { .. } | Syntax { .. } | InvalidTimeIndex { .. } | Tokenizer { .. } => {
|
||||
StatusCode::InvalidSyntax
|
||||
}
|
||||
Unexpected { .. }
|
||||
| Syntax { .. }
|
||||
| InvalidTimeIndex { .. }
|
||||
| Tokenizer { .. }
|
||||
| InvalidSql { .. }
|
||||
| SqlTypeNotSupported { .. } => StatusCode::InvalidSyntax,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +82,7 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
fn throw_sp_error() -> Result<(), ParserError> {
|
||||
fn throw_sp_error() -> std::result::Result<(), ParserError> {
|
||||
Err(ParserError::ParserError("parser error".to_string()))
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,11 @@ use sqlparser::parser::Parser;
|
||||
use sqlparser::parser::ParserError;
|
||||
use sqlparser::tokenizer::{Token, Tokenizer};
|
||||
|
||||
use crate::error::{self, Error, SyntaxSnafu, TokenizerSnafu};
|
||||
use crate::error::{self, Result, SyntaxSnafu, TokenizerSnafu};
|
||||
use crate::statements::show_database::SqlShowDatabase;
|
||||
use crate::statements::show_kind::ShowKind;
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// GrepTime SQL parser context, a simple wrapper for Datafusion SQL parser.
|
||||
pub struct ParserContext<'a> {
|
||||
pub(crate) parser: Parser<'a>,
|
||||
|
||||
@@ -2,9 +2,8 @@ use snafu::ResultExt;
|
||||
use sqlparser::keywords::Keyword;
|
||||
use sqlparser::parser::ParserError;
|
||||
|
||||
use crate::error;
|
||||
use crate::error::{self, Result};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::parser::Result;
|
||||
use crate::statements::alter::{AlterTable, AlterTableOperation};
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
|
||||
@@ -5,10 +5,8 @@ use sqlparser::{dialect::keywords::Keyword, tokenizer::Token};
|
||||
use table_engine::engine;
|
||||
|
||||
use crate::ast::{ColumnDef, Ident, TableConstraint};
|
||||
use crate::error;
|
||||
use crate::error::{InvalidTimeIndexSnafu, SyntaxSnafu};
|
||||
use crate::error::{self, InvalidTimeIndexSnafu, Result, SyntaxSnafu};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::parser::Result;
|
||||
use crate::statements::create_table::{CreateTable, TIME_INDEX};
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use snafu::ResultExt;
|
||||
use sqlparser::ast::Statement as SpStatement;
|
||||
|
||||
use crate::error;
|
||||
use crate::error::{self, Result};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::parser::Result;
|
||||
use crate::statements::insert::Insert;
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use snafu::prelude::*;
|
||||
|
||||
use crate::error;
|
||||
use crate::error::{self, Result};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::parser::Result;
|
||||
use crate::statements::query::Query;
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
|
||||
@@ -5,3 +5,129 @@ pub mod query;
|
||||
pub mod show_database;
|
||||
pub mod show_kind;
|
||||
pub mod statement;
|
||||
|
||||
use datatypes::prelude::ConcreteDataType;
|
||||
use datatypes::schema::ColumnSchema;
|
||||
use datatypes::types::DateTimeType;
|
||||
|
||||
use crate::ast::{ColumnDef, ColumnOption, DataType as SqlDataType, ObjectName};
|
||||
use crate::error::{self, Result};
|
||||
|
||||
/// Converts maybe fully-qualified table name (`<catalog>.<schema>.<table>` or `<table>` when
|
||||
/// catalog and schema are default) to tuple.
|
||||
pub fn table_idents_to_full_name(
|
||||
obj_name: &ObjectName,
|
||||
) -> Result<(Option<String>, Option<String>, String)> {
|
||||
match &obj_name.0[..] {
|
||||
[table] => Ok((None, None, table.value.clone())),
|
||||
[catalog, schema, table] => Ok((
|
||||
Some(catalog.value.clone()),
|
||||
Some(schema.value.clone()),
|
||||
table.value.clone(),
|
||||
)),
|
||||
_ => error::InvalidSqlSnafu {
|
||||
msg: format!(
|
||||
"expect table name to be <catalog>.<schema>.<table> or <table>, actual: {}",
|
||||
obj_name
|
||||
),
|
||||
}
|
||||
.fail(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn column_def_to_schema(column_def: &ColumnDef) -> Result<ColumnSchema> {
|
||||
let is_nullable = column_def
|
||||
.options
|
||||
.iter()
|
||||
.any(|o| matches!(o.option, ColumnOption::Null));
|
||||
Ok(ColumnSchema {
|
||||
name: column_def.name.value.clone(),
|
||||
data_type: sql_data_type_to_concrete_data_type(&column_def.data_type)?,
|
||||
is_nullable,
|
||||
})
|
||||
}
|
||||
|
||||
fn sql_data_type_to_concrete_data_type(data_type: &SqlDataType) -> Result<ConcreteDataType> {
|
||||
match data_type {
|
||||
SqlDataType::BigInt(_) => Ok(ConcreteDataType::int64_datatype()),
|
||||
SqlDataType::Int(_) => Ok(ConcreteDataType::int32_datatype()),
|
||||
SqlDataType::SmallInt(_) => Ok(ConcreteDataType::int16_datatype()),
|
||||
SqlDataType::Char(_)
|
||||
| SqlDataType::Varchar(_)
|
||||
| SqlDataType::Text
|
||||
| SqlDataType::String => Ok(ConcreteDataType::string_datatype()),
|
||||
SqlDataType::Float(_) => Ok(ConcreteDataType::float32_datatype()),
|
||||
SqlDataType::Double => Ok(ConcreteDataType::float64_datatype()),
|
||||
SqlDataType::Boolean => Ok(ConcreteDataType::boolean_datatype()),
|
||||
SqlDataType::Date => Ok(ConcreteDataType::date_datatype()),
|
||||
SqlDataType::Custom(obj_name) => match &obj_name.0[..] {
|
||||
[type_name] => {
|
||||
if type_name.value.eq_ignore_ascii_case(DateTimeType::name()) {
|
||||
Ok(ConcreteDataType::datetime_datatype())
|
||||
} else {
|
||||
error::SqlTypeNotSupportedSnafu {
|
||||
t: data_type.clone(),
|
||||
}
|
||||
.fail()
|
||||
}
|
||||
}
|
||||
_ => error::SqlTypeNotSupportedSnafu {
|
||||
t: data_type.clone(),
|
||||
}
|
||||
.fail(),
|
||||
},
|
||||
SqlDataType::Timestamp => Ok(ConcreteDataType::timestamp_millis_datatype()),
|
||||
_ => error::SqlTypeNotSupportedSnafu {
|
||||
t: data_type.clone(),
|
||||
}
|
||||
.fail(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ast::Ident;
|
||||
|
||||
fn check_type(sql_type: SqlDataType, data_type: ConcreteDataType) {
|
||||
assert_eq!(
|
||||
data_type,
|
||||
sql_data_type_to_concrete_data_type(&sql_type).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sql_data_type_to_concrete_data_type() {
|
||||
check_type(
|
||||
SqlDataType::BigInt(None),
|
||||
ConcreteDataType::int64_datatype(),
|
||||
);
|
||||
check_type(SqlDataType::Int(None), ConcreteDataType::int32_datatype());
|
||||
check_type(
|
||||
SqlDataType::SmallInt(None),
|
||||
ConcreteDataType::int16_datatype(),
|
||||
);
|
||||
check_type(SqlDataType::Char(None), ConcreteDataType::string_datatype());
|
||||
check_type(
|
||||
SqlDataType::Varchar(None),
|
||||
ConcreteDataType::string_datatype(),
|
||||
);
|
||||
check_type(SqlDataType::Text, ConcreteDataType::string_datatype());
|
||||
check_type(SqlDataType::String, ConcreteDataType::string_datatype());
|
||||
check_type(
|
||||
SqlDataType::Float(None),
|
||||
ConcreteDataType::float32_datatype(),
|
||||
);
|
||||
check_type(SqlDataType::Double, ConcreteDataType::float64_datatype());
|
||||
check_type(SqlDataType::Boolean, ConcreteDataType::boolean_datatype());
|
||||
check_type(SqlDataType::Date, ConcreteDataType::date_datatype());
|
||||
check_type(
|
||||
SqlDataType::Custom(ObjectName(vec![Ident::new("datetime")])),
|
||||
ConcreteDataType::datetime_datatype(),
|
||||
);
|
||||
check_type(
|
||||
SqlDataType::Timestamp,
|
||||
ConcreteDataType::timestamp_millis_datatype(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user