Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(planner_v2): support standalone VALUES clause #726

Merged
merged 13 commits into from
Nov 7, 2022
1 change: 1 addition & 0 deletions src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ macro_rules! impl_array_builder {
use DataTypeKind::*;
match ty.kind() {
Null => Self::Int32(I32ArrayBuilder::with_capacity(capacity)),
Struct(_) => todo!("array of Struct type"),
$(
$Type => Self::$Abc(<$AbcArrayBuilder>::with_capacity(capacity)),
)*
Expand Down
8 changes: 4 additions & 4 deletions src/binder/expression/binary_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ impl Binder {
let left_data_type_kind = {
let left_kind = left_bound_expr.return_type().kind();
let right_kind = right_bound_expr.return_type().kind();
let mut return_type_tmp = left_kind;
let mut return_type_tmp = left_kind.clone();
// Check if implicit type conversion is needed
if left_kind != right_kind {
// Insert type cast expr
match (left_kind, right_kind) {
match (&left_kind, &right_kind) {
(Float64 | Decimal(_, _), Int32 | Int64)
| (Int64, Int32)
| (Date, String)
Expand All @@ -68,12 +68,12 @@ impl Binder {
| (Float64, Decimal(_, _)) => {
left_bound_expr = BoundExpr::TypeCast(BoundTypeCast {
expr: Box::new(left_bound_expr),
ty: right_kind,
ty: right_kind.clone(),
});
return_type_tmp = right_kind;
}
(Date, Interval) => {}
_ => todo!(
(left_kind, right_kind) => todo!(
"Support implicit conversion of {:?} and {:?}",
left_kind,
right_kind
Expand Down
26 changes: 13 additions & 13 deletions src/binder/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ impl BoundExpr {
pub fn return_type(&self) -> DataType {
match self {
Self::Constant(v) => v.data_type(),
Self::ColumnRef(expr) => *expr.desc.datatype(),
Self::BinaryOp(expr) => expr.return_type,
Self::UnaryOp(expr) => expr.return_type,
Self::TypeCast(expr) => expr.ty.nullable(),
Self::AggCall(expr) => expr.return_type,
Self::InputRef(expr) => expr.return_type,
Self::ColumnRef(expr) => expr.desc.datatype().clone(),
Self::BinaryOp(expr) => expr.return_type.clone(),
Self::UnaryOp(expr) => expr.return_type.clone(),
Self::TypeCast(expr) => expr.ty.clone().nullable(),
Self::AggCall(expr) => expr.return_type.clone(),
Self::InputRef(expr) => expr.return_type.clone(),
Self::IsNull(_) => DataTypeKind::Bool.not_null(),
Self::ExprWithAlias(expr) => expr.expr.return_type(),
Self::Alias(expr) => expr.expr.return_type(),
Expand Down Expand Up @@ -334,9 +334,9 @@ mod tests {
let data_type = DataType::new(DataTypeKind::Int32, true);
let expr = BoundExpr::InputRef(BoundInputRef {
index: 0,
return_type: data_type,
return_type: data_type.clone(),
});
let child_schema = vec![ColumnDesc::new(data_type, "a".to_string(), false)];
let child_schema = vec![ColumnDesc::new(data_type.clone(), "a".to_string(), false)];
let expr = BoundExpr::UnaryOp(BoundUnaryOp {
op: UnaryOperator::Minus,
expr: Box::new(expr),
Expand All @@ -353,7 +353,7 @@ mod tests {
let left_data_type = DataType::new(DataTypeKind::Int32, true);
let left_expr = BoundExpr::InputRef(BoundInputRef {
index: 0,
return_type: left_data_type,
return_type: left_data_type.clone(),
});
let right_expr = BoundExpr::Constant(DataValue::Int64(1));
let child_schema = vec![ColumnDesc::new(left_data_type, "a".to_string(), false)];
Expand All @@ -370,15 +370,15 @@ mod tests {
let data_type = DataType::new(DataTypeKind::Int32, true);
let left_expr = BoundExpr::InputRef(BoundInputRef {
index: 0,
return_type: data_type,
return_type: data_type.clone(),
});
let right_expr = BoundExpr::InputRef(BoundInputRef {
index: 1,
return_type: data_type,
return_type: data_type.clone(),
});
let child_schema = vec![
ColumnDesc::new(data_type, "a".to_string(), false),
ColumnDesc::new(data_type, "b".to_string(), false),
ColumnDesc::new(data_type.clone(), "a".to_string(), false),
ColumnDesc::new(data_type.clone(), "b".to_string(), false),
];

let expr = BoundExpr::BinaryOp(BoundBinaryOp {
Expand Down
96 changes: 15 additions & 81 deletions src/binder_v2/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ use std::str::FromStr;
use serde::{Deserialize, Serialize};

use super::*;
use crate::catalog::{ColumnCatalog, ColumnDesc, TableCatalog};
use crate::types::ColumnIndex;

#[derive(Debug, PartialEq, PartialOrd, Ord, Hash, Eq, Clone, Serialize, Deserialize)]
pub struct BoundExtSource {
pub struct ExtSource {
pub path: String,
pub format: FileFormat,
pub colums_desc: Vec<ColumnDesc>,
}

/// File format.
Expand All @@ -29,34 +26,19 @@ pub enum FileFormat {
},
}

impl std::fmt::Display for BoundExtSource {
impl std::fmt::Display for ExtSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"path: {}, format: {}, desc: {:?}",
self.path, self.format, self.colums_desc
)
write!(f, "{self:?}")
}
}

impl std::fmt::Display for FileFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FileFormat::Csv {
delimiter,
quote,
header,
..
} => write!(
f,
"CSV: delimiter: {}, quote:{}, header:{}",
delimiter, quote, header
),
}
write!(f, "{self:?}")
}
}

impl FromStr for BoundExtSource {
impl FromStr for ExtSource {
type Err = ();

fn from_str(_s: &str) -> RawResult<Self, Self::Err> {
Expand All @@ -73,76 +55,28 @@ impl Binder {
target: CopyTarget,
options: &[CopyOption],
) -> Result {
let path = match target {
CopyTarget::File { filename } => filename,
t => todo!("unsupported copy target: {:?}", t),
};

let (_, _, columns) = self.bind_table_columns(&table_name, columns)?;
let cols = self.bind_table_columns(table_name, columns)?;

let ext_source = self.egraph.add(Node::BoundExtSource(BoundExtSource {
path,
let ext_source = self.egraph.add(Node::ExtSource(ExtSource {
path: match target {
CopyTarget::File { filename } => filename,
t => todo!("unsupported copy target: {:?}", t),
},
format: FileFormat::from_options(options),
colums_desc: columns.iter().map(|col| col.desc().clone()).collect(),
}));

let name = lower_case_name(table_name);
let (database_name, schema_name, table_name) = split_name(&name)?;
let table_scan = self.bind_table_name(database_name, schema_name, table_name)?;

let copy = if to {
// COPY <source_table> TO <[dest_file]>
self.egraph.add(Node::CopyTo([table_scan, ext_source]))
// COPY <source_table> TO <dest_file>
let scan = self.egraph.add(Node::Scan(cols));
self.egraph.add(Node::CopyTo([ext_source, scan]))
} else {
// COPY <dest_table> FROM <source_file>
let column_ids = columns
.iter()
.map(|col| self.egraph.add(Node::ColumnIndex(ColumnIndex(col.id()))))
.collect();

let cols_id = self.egraph.add(Node::List(column_ids));

let copy = self.egraph.add(Node::CopyFrom(ext_source));

self.egraph.add(Node::Insert([cols_id, copy]))
self.egraph.add(Node::Insert([cols, copy]))
};

Ok(copy)
}

fn bind_table_columns(
&mut self,
table_name: &ObjectName,
columns: &[Ident],
) -> Result<(TableRefId, Arc<TableCatalog>, Vec<ColumnCatalog>)> {
let name = lower_case_name(table_name.clone());
let (database_name, schema_name, table_name) = split_name(&name)?;

let table_ref_id = self
.catalog
.get_table_id_by_name(database_name, schema_name, table_name)
.ok_or_else(|| BindError::InvalidTable(table_name.into()))?;

let table = self
.catalog
.get_table(&table_ref_id)
.ok_or_else(|| BindError::InvalidTable(table_name.into()))?;

let columns = if columns.is_empty() {
table.all_columns().values().cloned().collect_vec()
} else {
let mut column_catalogs = vec![];
for col in columns.iter() {
let col_name = col.value.to_lowercase();
let col = table
.get_column_by_name(&col_name)
.ok_or_else(|| BindError::InvalidColumn(col_name.clone()))?;
column_catalogs.push(col);
}
column_catalogs
};
Ok((table_ref_id, table, columns))
}
}

impl FileFormat {
Expand Down
11 changes: 5 additions & 6 deletions src/binder_v2/create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use crate::catalog::{ColumnCatalog, ColumnDesc};
use crate::types::{ColumnId, DatabaseId, SchemaId};

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
pub struct BoundTable {
pub struct CreateTable {
pub database_id: DatabaseId,
pub schema_id: SchemaId,
pub table_name: String,
pub columns_desc: Vec<ColumnDesc>,
pub ordered_pk_ids: Vec<ColumnId>,
}

impl std::fmt::Display for BoundTable {
impl std::fmt::Display for CreateTable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
Expand All @@ -31,7 +31,7 @@ impl std::fmt::Display for BoundTable {
}
}

impl FromStr for BoundTable {
impl FromStr for CreateTable {
type Err = ();

fn from_str(_s: &str) -> RawResult<Self, Self::Err> {
Expand Down Expand Up @@ -105,7 +105,7 @@ impl Binder {
columns[index as usize].set_nullable(false);
}

let table = self.egraph.add(Node::BoundTable(BoundTable {
let create = self.egraph.add(Node::CreateTable(CreateTable {
database_id: db.id(),
schema_id: schema.id(),
table_name: table_name.into(),
Expand All @@ -116,8 +116,7 @@ impl Binder {
.collect::<Vec<ColumnDesc>>(),
ordered_pk_ids,
}));

Ok(self.egraph.add(Node::Create(table)))
Ok(create)
}

/// get primary keys' id in declared order。
Expand Down
6 changes: 4 additions & 2 deletions src/binder_v2/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ impl Binder {
table_name: TableFactor,
selection: Option<Expr>,
) -> Result {
let table = self.bind_table(table_name)?;
let table_id = self.bind_table_id(table_name.clone())?;
let scan = self.bind_table(table_name)?;
let cond = self.bind_condition(selection)?;
Ok(self.egraph.add(Node::Delete([table, cond])))
let filter = self.egraph.add(Node::Filter([cond, scan]));
Ok(self.egraph.add(Node::Delete([table_id, filter])))
}
}
4 changes: 2 additions & 2 deletions src/binder_v2/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl std::fmt::Display for BoundDrop {
impl std::fmt::Display for Object {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Object::Table(table_id_ref) => write!(f, "{}", table_id_ref),
Object::Table(table_id_ref) => write!(f, "table {}", table_id_ref),
}
}
}
Expand Down Expand Up @@ -60,7 +60,7 @@ impl Binder {
.get_table_id_by_name(database_name, schema_name, table_name)
.ok_or_else(|| BindError::InvalidTable(table_name.into()))?;

Ok(self.egraph.add(Node::BoundDrop(BoundDrop {
Ok(self.egraph.add(Node::Drop(BoundDrop {
object: Object::Table(table_ref_id),
if_exists,
cascade,
Expand Down
4 changes: 1 addition & 3 deletions src/binder_v2/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ impl Binder {
} => self.bind_between(*expr, negated, *low, *high),
_ => todo!("bind expression: {:?}", expr),
}?;
if let Err(e) = &self.egraph[id].data.type_ {
return Err(e.clone().into());
}
self.check_type(id)?;
Ok(id)
}

Expand Down
18 changes: 18 additions & 0 deletions src/binder_v2/insert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2022 RisingLight Project Authors. Licensed under Apache-2.0.

use super::*;
use crate::parser::Query;

impl Binder {
pub fn bind_insert(
&mut self,
table_name: ObjectName,
columns: Vec<Ident>,
source: Box<Query>,
) -> Result {
let cols = self.bind_table_columns(table_name, &columns)?;
let source = self.bind_query(*source)?;
let id = self.egraph.add(Node::Insert([cols, source]));
Ok(id)
}
}
16 changes: 14 additions & 2 deletions src/binder_v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod create_table;
mod delete;
mod drop;
mod expr;
mod insert;
mod select;
mod table;

Expand All @@ -25,6 +26,7 @@ pub use self::create_table::*;
pub use self::delete::*;
pub use self::drop::*;
pub use self::expr::*;
pub use self::insert::*;
pub use self::select::*;
pub use self::table::*;

Expand Down Expand Up @@ -92,7 +94,7 @@ impl Binder {
Binder {
egraph: egg::EGraph::default(),
catalog,
contexts: vec![],
contexts: vec![Context::default()],
}
}

Expand All @@ -119,7 +121,12 @@ impl Binder {
cascade,
..
} => self.bind_drop(object_type, if_exists, names, cascade),
Statement::Insert { .. } => todo!(),
Statement::Insert {
table_name,
columns,
source,
..
} => self.bind_insert(table_name, columns, source),
Statement::Delete {
table_name,
selection,
Expand Down Expand Up @@ -166,6 +173,11 @@ impl Binder {
Ok(())
}

fn check_type(&self, id: Id) -> Result<()> {
self.egraph[id].data.type_.clone()?;
Ok(())
}

fn bind_explain(&mut self, query: Statement) -> Result {
let id = self.bind_stmt(query)?;
let id = self.egraph.add(Node::Explain(id));
Expand Down
Loading