Skip to content
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
b1900cf
Condition for BinaryExpr, filter, input_ref, rexcall, and rexliteral
jdye64 Mar 26, 2022
1e48597
Updates for test_filter
jdye64 Mar 31, 2022
fd41a8c
more of test_filter.py working with the exception of some date pytests
jdye64 Mar 31, 2022
682c009
Add workflow to keep datafusion dev branch up to date (#440)
charlesbluca Mar 25, 2022
ab69dd8
Include setuptools-rust in conda build recipie, in host and run
jdye64 Apr 13, 2022
ce4c31e
Remove PyArrow dependency
jdye64 Apr 20, 2022
8785b8c
rebase with datafusion-sql-planner
jdye64 Apr 21, 2022
3e45ab8
refactor changes that were inadvertent during rebase
jdye64 Apr 21, 2022
1734b89
timestamp with loglca time zone
jdye64 Apr 21, 2022
ac7d9f6
Bump DataFusion version (#494)
andygrove Apr 21, 2022
cbf5db0
Include RelDataType work
jdye64 Apr 21, 2022
d9380a6
Include RelDataType work
jdye64 Apr 21, 2022
ad56fc2
Introduced SqlTypeName Enum in Rust and mappings for Python
jdye64 Apr 22, 2022
7b20e66
impl PyExpr.getIndex()
jdye64 Apr 22, 2022
7dd2017
add getRowType() for logical.rs
jdye64 Apr 22, 2022
984f523
Introduce DaskTypeMap for storing correlating SqlTypeName and DataTypes
jdye64 Apr 23, 2022
1405fea
use str values instead of Rust Enums, Python is unable to Hash the Ru…
jdye64 Apr 23, 2022
789aaad
linter changes, why did that work on my local pre-commit??
jdye64 Apr 23, 2022
652205e
linter changes, why did that work on my local pre-commit??
jdye64 Apr 23, 2022
5127f87
Convert final strs to SqlTypeName Enum
jdye64 Apr 24, 2022
cf568dc
removed a few print statements
jdye64 Apr 24, 2022
4fb640e
commit to share with colleague
jdye64 Apr 24, 2022
32127e5
updates
jdye64 Apr 25, 2022
f5e24fe
checkpoint
jdye64 Apr 25, 2022
11cf212
Temporarily disable conda run_test.py script since it uses features n…
jdye64 Apr 25, 2022
46dfb0a
formatting after upstream merge
jdye64 Apr 25, 2022
fa71674
expose fromString method for SqlTypeName to use Enums instead of stri…
jdye64 Apr 25, 2022
f6e86ca
expanded SqlTypeName from_string() support
jdye64 Apr 25, 2022
3d1a5ad
accept INT as INTEGER
jdye64 Apr 25, 2022
384e446
tests update
jdye64 Apr 25, 2022
199b9d2
checkpoint
jdye64 Apr 25, 2022
c9dffae
checkpoint
jdye64 Apr 27, 2022
c9aad43
Refactor PyExpr by removing From trait, and using recursion to expand…
jdye64 Apr 28, 2022
11100fa
skip test that uses create statement for gpuci
jdye64 Apr 28, 2022
643e85d
Basic DataFusion Select Functionality (#489)
jdye64 Apr 28, 2022
b36ef16
updates for expression
jdye64 Apr 28, 2022
5c94fbc
uncommented pytests
jdye64 Apr 28, 2022
bb461c8
uncommented pytests
jdye64 Apr 28, 2022
f65b1ab
code cleanup for review
jdye64 Apr 28, 2022
dc7553f
code cleanup for review
jdye64 Apr 28, 2022
f1dc0b2
Enabled more pytest that work now
jdye64 Apr 28, 2022
940e867
Enabled more pytest that work now
jdye64 Apr 28, 2022
6769ca0
Output Expression as String when BinaryExpr does not contain a named …
jdye64 Apr 29, 2022
c4ed9bd
Output Expression as String when BinaryExpr does not contain a named …
jdye64 Apr 29, 2022
05c5788
Disable 2 pytest that are causing gpuCI issues. They will be address …
jdye64 Apr 29, 2022
a33aa63
Handle Between operation for case-when
jdye64 Apr 29, 2022
20efd5c
adjust timestamp casting
jdye64 May 2, 2022
281baf7
merge with upstream
jdye64 May 6, 2022
d666bdd
merge with upstream/datafusion-sql-planner
jdye64 May 9, 2022
533f50a
Refactor projection _column_name() logic to the _column_name logic in…
jdye64 May 9, 2022
a42a133
removed println! statements
jdye64 May 9, 2022
10cd463
merge with upstream
jdye64 May 10, 2022
a1841c3
Updates from review
jdye64 May 11, 2022
a1bf8dc
refactor String::from() to .to_string()
jdye64 May 12, 2022
fb29855
When no ELSE statement is present in CASE/WHEN statement default to None
jdye64 May 12, 2022
ef4409e
Remove println
jdye64 May 12, 2022
c1c3773
Re-enable rex test that previously could not be ran
jdye64 May 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dask_planner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ rust-version = "1.59"
tokio = { version = "1.0", features = ["macros", "rt", "rt-multi-thread", "sync", "fs", "parking_lot"] }
rand = "0.7"
pyo3 = { version = "0.16", features = ["extension-module", "abi3", "abi3-py38"] }
datafusion = { git="https://github.com/apache/arrow-datafusion/", rev = "ef49d2858c2aba1ea7cd5fed3b1e5feb77fc2233" }
datafusion-expr = { git="https://github.com/apache/arrow-datafusion/", rev = "ef49d2858c2aba1ea7cd5fed3b1e5feb77fc2233" }
datafusion = { git="https://github.com/apache/arrow-datafusion/", rev = "5927bfceeba3a4eab7988289c674d925cc82ac05" }
datafusion-expr = { git="https://github.com/apache/arrow-datafusion/", rev = "5927bfceeba3a4eab7988289c674d925cc82ac05" }
uuid = { version = "0.8", features = ["v4"] }
mimalloc = { version = "*", default-features = false }
sqlparser = "0.14.0"
Expand Down
129 changes: 100 additions & 29 deletions dask_planner/src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::sql::logical;
use crate::sql::types::RexType;

use pyo3::prelude::*;
use std::convert::{From, Into};
use std::convert::From;

use datafusion::error::DataFusionError;

Expand Down Expand Up @@ -86,50 +86,47 @@ impl PyExpr {
"AGGREGATE COLUMN IS {}",
col.name
);
col.name.clone()
col.name.clone().to_ascii_uppercase()
}
_ => name.clone(),
_ => name.clone().to_ascii_uppercase(),
}
}
_ => name.clone(),
_ => name.clone().to_ascii_uppercase(),
}
}
_ => {
println!("Encountered a non-Aggregate type");

name.clone()
name.clone().to_ascii_uppercase()
}
}
}
_ => name.clone(),
_ => name.clone().to_ascii_uppercase(),
}
}
_ => {
println!("Encountered a non Expr::Column instance");
name.clone()
}
_ => name.clone().to_ascii_uppercase(),
}
}
Expr::Column(column) => column.name.clone(),
Expr::ScalarVariable(..) => unimplemented!("ScalarVariable!!!"),
Expr::Literal(..) => unimplemented!("Literal!!!"),
Expr::BinaryExpr {
left: _,
op: _,
right: _,
} => {
// /// TODO: Examine this more deeply about whether name comes from the left or right
// self.column_name(left)
unimplemented!("BinaryExpr HERE!!!")
Expr::Literal(scalar_value) => {
println!("Scalar Value: {:?}", scalar_value);
unimplemented!("Literal!!!")
}
Expr::BinaryExpr { .. } => {
// If the BinaryExpr does not have an Alias
// Ex: `df.a - Int64(1)` then use the String
// representation of the Expr to match what is
// in the DFSchemaRef instance
format!("{}", &self.expr)
}
Expr::Not(..) => unimplemented!("Not!!!"),
Expr::IsNotNull(..) => unimplemented!("IsNotNull!!!"),
Expr::Negative(..) => unimplemented!("Negative!!!"),
Expr::GetIndexedField { .. } => unimplemented!("GetIndexedField!!!"),
Expr::IsNull(..) => unimplemented!("IsNull!!!"),
Expr::Between { .. } => unimplemented!("Between!!!"),
Expr::Case { .. } => unimplemented!("Case!!!"),
Expr::Cast { .. } => unimplemented!("Cast!!!"),
Expr::Case { .. } => format!("{}", &self.expr),
Expr::Cast { .. } => format!("{}", &self.expr),
Expr::TryCast { .. } => unimplemented!("TryCast!!!"),
Expr::Sort { .. } => unimplemented!("Sort!!!"),
Expr::ScalarFunction { .. } => unimplemented!("ScalarFunction!!!"),
Expand All @@ -141,6 +138,33 @@ impl PyExpr {
_ => panic!("Nothing found!!!"),
}
}

fn _rex_type(&self, expr: Expr) -> RexType {
match &expr {
Expr::Alias(expr, name) => RexType::Reference,
Comment thread
jdye64 marked this conversation as resolved.
Outdated
Expr::Column(..) => RexType::Reference,
Expr::ScalarVariable(..) => RexType::Literal,
Expr::Literal(..) => RexType::Literal,
Expr::BinaryExpr { .. } => RexType::Call,
Expr::Not(..) => RexType::Call,
Expr::IsNotNull(..) => RexType::Call,
Expr::Negative(..) => RexType::Call,
Expr::GetIndexedField { .. } => RexType::Reference,
Expr::IsNull(..) => RexType::Call,
Expr::Between { .. } => RexType::Call,
Expr::Case { .. } => RexType::Call,
Expr::Cast { .. } => RexType::Call,
Expr::TryCast { .. } => RexType::Call,
Expr::Sort { .. } => RexType::Call,
Expr::ScalarFunction { .. } => RexType::Call,
Expr::AggregateFunction { .. } => RexType::Call,
Expr::WindowFunction { .. } => RexType::Call,
Expr::AggregateUDF { .. } => RexType::Call,
Expr::InList { .. } => RexType::Call,
Expr::Wildcard => RexType::Call,
_ => RexType::Other,
}
}
}

#[pymethods]
Expand Down Expand Up @@ -222,7 +246,7 @@ impl PyExpr {
#[pyo3(name = "getRexType")]
pub fn rex_type(&self) -> RexType {
match &self.expr {
Comment thread
jdye64 marked this conversation as resolved.
Outdated
Expr::Alias(expr, name) => RexType::Reference,
Expr::Alias(..) => RexType::Reference,
Expr::Column(..) => RexType::Reference,
Expr::ScalarVariable(..) => RexType::Literal,
Expr::Literal(..) => RexType::Literal,
Expand Down Expand Up @@ -281,9 +305,44 @@ impl PyExpr {
operands.push(py_ex);
Ok(operands)
}
_ => Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(
"unknown Expr type encountered",
)),
Expr::Case {
Comment thread
jdye64 marked this conversation as resolved.
expr,
when_then_expr,
else_expr,
} => {
let mut operands: Vec<PyExpr> = Vec::new();
match expr {
Some(e) => operands.push(PyExpr::from(*e.clone(), self.input_plan.clone())),
None => (),
};

for (when, then) in when_then_expr {
operands.push(PyExpr::from(*when.clone(), self.input_plan.clone()));
operands.push(PyExpr::from(*then.clone(), self.input_plan.clone()));
}

match else_expr {
Some(e) => operands.push(PyExpr::from(*e.clone(), self.input_plan.clone())),
None => (),
}
Ok(operands)
}
Expr::Between {
expr,
negated: _,
Comment thread
jdye64 marked this conversation as resolved.
low,
high,
} => {
let mut operands: Vec<PyExpr> = Vec::new();
operands.push(PyExpr::from(*expr.clone(), self.input_plan.clone()));
operands.push(PyExpr::from(*low.clone(), self.input_plan.clone()));
operands.push(PyExpr::from(*high.clone(), self.input_plan.clone()));
Ok(operands)
}
_ => Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(format!(
"unknown Expr type {:?} encountered",
&self.expr
))),
}
}

Expand All @@ -300,9 +359,21 @@ impl PyExpr {
expr: _,
data_type: _,
} => Ok(String::from("cast")),
_ => Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(
"Catch all triggered ....",
)),
Expr::Between {
expr: _,
negated: _,
low: _,
high: _,
} => Ok(String::from("between")),
Comment thread
jdye64 marked this conversation as resolved.
Outdated
Expr::Case {
expr: _,
when_then_expr: _,
else_expr: _,
} => Ok(String::from("case")),
Comment thread
jdye64 marked this conversation as resolved.
Outdated
_ => Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(format!(
"Catch all triggered for get_operator_name: {:?}",
&self.expr
))),
}
}

Expand Down
49 changes: 29 additions & 20 deletions dask_planner/src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub mod types;
use crate::sql::exceptions::ParsingException;

use datafusion::arrow::datatypes::{Field, Schema};
use datafusion::catalog::TableReference;
use datafusion::catalog::{ResolvedTableReference, TableReference};
use datafusion::error::DataFusionError;
use datafusion::physical_plan::udaf::AggregateUDF;
use datafusion::physical_plan::udf::ScalarUDF;
Expand Down Expand Up @@ -46,12 +46,18 @@ use pyo3::prelude::*;
#[pyclass(name = "DaskSQLContext", module = "dask_planner", subclass)]
#[derive(Debug, Clone)]
pub struct DaskSQLContext {
default_catalog_name: String,
default_schema_name: String,
schemas: HashMap<String, schema::DaskSchema>,
}

impl ContextProvider for DaskSQLContext {
fn get_table_provider(&self, name: TableReference) -> Option<Arc<dyn table::TableProvider>> {
fn get_table_provider(
&self,
name: TableReference,
) -> Result<Arc<dyn table::TableProvider>, DataFusionError> {
let reference: ResolvedTableReference =
name.resolve(&self.default_catalog_name, &self.default_schema_name);
match self.schemas.get(&self.default_schema_name) {
Some(schema) => {
let mut resp = None;
Expand All @@ -67,17 +73,22 @@ impl ContextProvider for DaskSQLContext {
resp = Some(Schema::new(fields));
}
}
Some(Arc::new(DaskTableProvider::new(Arc::new(
table::DaskTableSource::new(Arc::new(resp.unwrap())),
))))
}
None => {
DataFusionError::Execution(format!(
"Schema with name {} not found",
&self.default_schema_name
));
None

// If the Table is not found return None. DataFusion will handle the error propagation
match resp {
Some(e) => Ok(Arc::new(DaskTableProvider::new(Arc::new(
table::DaskTableSource::new(Arc::new(e)),
)))),
None => Err(DataFusionError::Plan(format!(
"Table '{}.{}.{}' not found",
reference.catalog, reference.schema, reference.table
))),
}
}
None => Err(DataFusionError::Plan(format!(
"Unable to located Schema: '{}.{}'",
reference.catalog, reference.schema
))),
}
}

Expand All @@ -99,8 +110,9 @@ impl ContextProvider for DaskSQLContext {
#[pymethods]
impl DaskSQLContext {
#[new]
pub fn new(default_schema_name: String) -> Self {
pub fn new(default_catalog_name: String, default_schema_name: String) -> Self {
Self {
default_catalog_name,
default_schema_name,
schemas: HashMap::new(),
}
Expand Down Expand Up @@ -159,13 +171,10 @@ impl DaskSQLContext {
) -> PyResult<logical::PyLogicalPlan> {
let planner = SqlToRel::new(self);
match planner.statement_to_plan(statement.statement) {
Ok(k) => {
println!("\nLogicalPlan: {:?}\n\n", k);
Ok(logical::PyLogicalPlan {
original_plan: k,
current_node: None,
})
}
Ok(k) => Ok(logical::PyLogicalPlan {
original_plan: k,
current_node: None,
}),
Err(e) => Err(PyErr::new::<ParsingException, _>(format!("{}", e))),
}
}
Expand Down
2 changes: 0 additions & 2 deletions dask_planner/src/sql/logical.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::sql::table;
use crate::sql::types::rel_data_type::RelDataType;
use crate::sql::types::rel_data_type_field::RelDataTypeField;
use datafusion::logical_plan::DFField;

mod aggregate;
mod filter;
Expand All @@ -12,7 +11,6 @@ pub use datafusion_expr::LogicalPlan;

use datafusion::common::Result;
use datafusion::prelude::Column;
use pyo3::ffi::Py_FatalError;

use crate::sql::exceptions::py_type_err;
use pyo3::prelude::*;
Expand Down
13 changes: 8 additions & 5 deletions dask_planner/src/sql/logical/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ pub struct PyProjection {
impl PyProjection {
/// Projection: Gets the names of the fields that should be projected
fn projected_expressions(&mut self, local_expr: &PyExpr) -> Vec<PyExpr> {
println!("Exprs: {:?}", &self.projection.expr);
println!("Input: {:?}", &self.projection.input);
println!("Schema: {:?}", &self.projection.schema);
println!("Alias: {:?}", &self.projection.alias);
let mut projs: Vec<PyExpr> = Vec::new();
match &local_expr.expr {
Expr::Alias(expr, _name) => {
let ex: Expr = *expr.clone();
let mut py_expr: PyExpr = PyExpr::from(ex, Some(self.projection.input.clone()));
py_expr.input_plan = local_expr.input_plan.clone();
let py_expr: PyExpr =
PyExpr::from(*expr.clone(), Some(self.projection.input.clone()));
projs.extend_from_slice(self.projected_expressions(&py_expr).as_slice());
}
_ => projs.push(local_expr.clone()),
Expand All @@ -34,7 +37,7 @@ impl PyProjection {
fn column_name(&mut self, expr: PyExpr) -> PyResult<String> {
let mut val: String = String::from("OK");
match expr.expr {
Expr::Alias(expr, _alias) => match expr.as_ref() {
Expr::Alias(expr, name) => match expr.as_ref() {
Expr::Column(col) => {
let index = self.projection.input.schema().index_of_column(col).unwrap();
match self.projection.input.as_ref() {
Expand Down Expand Up @@ -63,7 +66,7 @@ impl PyProjection {
val = self.column_name(py_type).unwrap();
println!("Setting col name to: {:?}", val);
}
_ => panic!("not supported: {:?}", expr),
_ => val = name.clone().to_ascii_uppercase(),
},
Expr::Column(col) => val = col.name.clone(),
Expr::Cast { expr, data_type: _ } => {
Expand Down
5 changes: 4 additions & 1 deletion dask_sql/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Context:

"""

DEFAULT_CATALOG_NAME = "dask_sql"
DEFAULT_SCHEMA_NAME = "root"

def __init__(self, logging_level=logging.INFO):
Expand All @@ -79,6 +80,8 @@ def __init__(self, logging_level=logging.INFO):
# Set the logging level for this SQL context
logging.basicConfig(level=logging_level)

# Name of the root catalog
self.catalog_name = self.DEFAULT_CATALOG_NAME
# Name of the root schema
self.schema_name = self.DEFAULT_SCHEMA_NAME
# All schema information
Expand All @@ -87,7 +90,7 @@ def __init__(self, logging_level=logging.INFO):
self.sql_server = None

# Create the `DaskSQLContext` Rust context
self.context = DaskSQLContext(self.schema_name)
self.context = DaskSQLContext(self.catalog_name, self.schema_name)
self.context.register_schema(self.schema_name, DaskSchema(self.schema_name))

# # Register any default plugins, if nothing was registered before.
Expand Down
8 changes: 3 additions & 5 deletions dask_sql/physical/rel/logical/limit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

if TYPE_CHECKING:
import dask_sql
from dask_sql.java import org
from dask_planner.rust import LogicalPlan


class DaskLimitPlugin(BaseRelPlugin):
Expand All @@ -18,11 +18,9 @@ class DaskLimitPlugin(BaseRelPlugin):
(LIMIT).
"""

class_name = "com.dask.sql.nodes.DaskLimit"
class_name = "Limit"

def convert(
self, rel: "org.apache.calcite.rel.RelNode", context: "dask_sql.Context"
) -> DataContainer:
def convert(self, rel: "LogicalPlan", context: "dask_sql.Context") -> DataContainer:
(dc,) = self.assert_inputs(rel, 1, context)
df = dc.df
cc = dc.column_container
Expand Down
Loading