Merge pull request #1602 from influxdata/ntran/pushdown_explain
refactor: macro and tests for explainspull/24376/head
commit
fdb6c98c8e
|
@ -145,6 +145,7 @@ impl IOxExecutionContext {
|
||||||
/// Prepare a SQL statement for execution. This assumes that any
|
/// Prepare a SQL statement for execution. This assumes that any
|
||||||
/// tables referenced in the SQL have been registered with this context
|
/// tables referenced in the SQL have been registered with this context
|
||||||
pub fn prepare_sql(&mut self, sql: &str) -> Result<Arc<dyn ExecutionPlan>> {
|
pub fn prepare_sql(&mut self, sql: &str) -> Result<Arc<dyn ExecutionPlan>> {
|
||||||
|
debug!(text=%sql, "SQL");
|
||||||
let logical_plan = self.inner.sql(sql)?.to_logical_plan();
|
let logical_plan = self.inner.sql(sql)?.to_logical_plan();
|
||||||
self.prepare_plan(&logical_plan)
|
self.prepare_plan(&logical_plan)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use datafusion::{
|
||||||
physical_plan::ExecutionPlan,
|
physical_plan::ExecutionPlan,
|
||||||
};
|
};
|
||||||
use internal_types::schema::{builder::SchemaMerger, Schema};
|
use internal_types::schema::{builder::SchemaMerger, Schema};
|
||||||
|
use observability_deps::tracing::debug;
|
||||||
|
|
||||||
use crate::{predicate::PredicateBuilder, util::project_schema, PartitionChunk};
|
use crate::{predicate::PredicateBuilder, util::project_schema, PartitionChunk};
|
||||||
|
|
||||||
|
@ -198,6 +199,8 @@ impl<C: PartitionChunk + 'static> TableProvider for ChunkTableProvider<C> {
|
||||||
filters: &[Expr],
|
filters: &[Expr],
|
||||||
_limit: Option<usize>,
|
_limit: Option<usize>,
|
||||||
) -> std::result::Result<Arc<dyn ExecutionPlan>, DataFusionError> {
|
) -> std::result::Result<Arc<dyn ExecutionPlan>, DataFusionError> {
|
||||||
|
debug!("Input Filters to Scan: {:#?}", filters);
|
||||||
|
|
||||||
// Note that `filters` don't actually need to be evaluated in
|
// Note that `filters` don't actually need to be evaluated in
|
||||||
// the scan for the plans to be correct, they are an extra
|
// the scan for the plans to be correct, they are an extra
|
||||||
// optimization for providers which can offer them
|
// optimization for providers which can offer them
|
||||||
|
|
|
@ -287,6 +287,8 @@ impl PartitionChunk for DbChunk {
|
||||||
// Predicate is not required to be applied for correctness. We only pushed it down
|
// Predicate is not required to be applied for correctness. We only pushed it down
|
||||||
// when possible for performance gain
|
// when possible for performance gain
|
||||||
|
|
||||||
|
debug!("Input Predicate to read_filter: {:#?}", predicate);
|
||||||
|
|
||||||
match &self.state {
|
match &self.state {
|
||||||
State::MutableBuffer { chunk, .. } => {
|
State::MutableBuffer { chunk, .. } => {
|
||||||
let batch = chunk
|
let batch = chunk
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use super::scenarios::*;
|
use super::scenarios::*;
|
||||||
use arrow::record_batch::RecordBatch;
|
use arrow::record_batch::RecordBatch;
|
||||||
use arrow_util::assert_batches_sorted_eq;
|
use arrow_util::{assert_batches_eq, assert_batches_sorted_eq};
|
||||||
use query::frontend::sql::SqlQueryPlanner;
|
use query::frontend::sql::SqlQueryPlanner;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -40,6 +40,35 @@ macro_rules! run_sql_test_case {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// runs table_names(predicate) and compares it to the expected
|
||||||
|
/// output
|
||||||
|
macro_rules! run_sql_explain_test_case {
|
||||||
|
($DB_SETUP:expr, $SQL:expr, $EXPECTED_LINES:expr) => {
|
||||||
|
test_helpers::maybe_start_logging();
|
||||||
|
let sql = $SQL.to_string();
|
||||||
|
for scenario in $DB_SETUP.make().await {
|
||||||
|
let DbScenario {
|
||||||
|
scenario_name, db, ..
|
||||||
|
} = scenario;
|
||||||
|
let db = Arc::new(db);
|
||||||
|
|
||||||
|
println!("Running scenario '{}'", scenario_name);
|
||||||
|
println!("SQL: '{:#?}'", sql);
|
||||||
|
let planner = SqlQueryPlanner::default();
|
||||||
|
let executor = db.executor();
|
||||||
|
|
||||||
|
let physical_plan = planner
|
||||||
|
.query(db, &sql, executor.as_ref())
|
||||||
|
.expect("built plan successfully");
|
||||||
|
|
||||||
|
let results: Vec<RecordBatch> =
|
||||||
|
executor.collect(physical_plan).await.expect("Running plan");
|
||||||
|
|
||||||
|
assert_batches_eq!($EXPECTED_LINES, &results);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn sql_select_from_cpu() {
|
async fn sql_select_from_cpu() {
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
|
@ -409,10 +438,8 @@ async fn sql_select_with_schema_merge_subset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn sql_predicate_pushdown() {
|
async fn sql_predicate_pushdown_correctness() {
|
||||||
// Test 1: Select everything
|
// Test 1: Select everything
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -432,17 +459,7 @@ async fn sql_predicate_pushdown() {
|
||||||
&expected
|
&expected
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Make push-down predicates shown in explain verbose. Ticket #1538 - actively working on this
|
|
||||||
// Check the plan
|
|
||||||
// run_sql_test_case!(
|
|
||||||
// TwoMeasurementsPredicatePushDown {},
|
|
||||||
// "EXPLAIN VERBOSE SELECT * from restaurant",
|
|
||||||
// &expected
|
|
||||||
// );
|
|
||||||
|
|
||||||
// Test 2: One push-down expression: count > 200
|
// Test 2: One push-down expression: count > 200
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -461,16 +478,7 @@ async fn sql_predicate_pushdown() {
|
||||||
&expected
|
&expected
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check the plan
|
|
||||||
// run_sql_test_case!(
|
|
||||||
// TwoMeasurementsPredicatePushDown {},
|
|
||||||
// "EXPLAIN VERBOSE SELECT * from restaurant where count > 200",
|
|
||||||
// &expected
|
|
||||||
// );
|
|
||||||
|
|
||||||
// Test 3: Two push-down expression: count > 200 and town != 'tewsbury'
|
// Test 3: Two push-down expression: count > 200 and town != 'tewsbury'
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -488,17 +496,8 @@ async fn sql_predicate_pushdown() {
|
||||||
&expected
|
&expected
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check the plan
|
|
||||||
// run_sql_test_case!(
|
|
||||||
// TwoMeasurementsPredicatePushDown {},
|
|
||||||
// "EXPLAIN VERBOSE SELECT * from restaurant where count > 200 and town != 'tewsbury'",
|
|
||||||
// &expected
|
|
||||||
// );
|
|
||||||
|
|
||||||
// Test 4: Still two push-down expression: count > 200 and town != 'tewsbury'
|
// Test 4: Still two push-down expression: count > 200 and town != 'tewsbury'
|
||||||
// even though the results are different
|
// even though the results are different
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -516,8 +515,6 @@ async fn sql_predicate_pushdown() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test 5: three push-down expression: count > 200 and town != 'tewsbury' and count < 40000
|
// Test 5: three push-down expression: count > 200 and town != 'tewsbury' and count < 40000
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -534,8 +531,6 @@ async fn sql_predicate_pushdown() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test 6: two push-down expression: count > 200 and count < 40000
|
// Test 6: two push-down expression: count > 200 and count < 40000
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -554,8 +549,6 @@ async fn sql_predicate_pushdown() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test 7: two push-down expression on float: system > 4.0 and system < 7.0
|
// Test 7: two push-down expression on float: system > 4.0 and system < 7.0
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+-----------+",
|
"+-------+--------+-------------------------------+-----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -575,8 +568,6 @@ async fn sql_predicate_pushdown() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test 8: two push-down expression on float: system > 5.0 and system < 7.0
|
// Test 8: two push-down expression on float: system > 5.0 and system < 7.0
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+----------+",
|
"+-------+--------+-------------------------------+----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -593,8 +584,6 @@ async fn sql_predicate_pushdown() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test 9: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
// Test 9: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+----------+",
|
"+-------+--------+-------------------------------+----------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -611,8 +600,6 @@ async fn sql_predicate_pushdown() {
|
||||||
|
|
||||||
// Test 10: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
// Test 10: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
||||||
// even though there are more expressions,(count = 632 or town = 'reading'), in the filter
|
// even though there are more expressions,(count = 632 or town = 'reading'), in the filter
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
"+-------+--------+-------------------------------+---------+",
|
"+-------+--------+-------------------------------+---------+",
|
||||||
"| count | system | time | town |",
|
"| count | system | time | town |",
|
||||||
|
@ -626,11 +613,8 @@ async fn sql_predicate_pushdown() {
|
||||||
&expected
|
&expected
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test 11: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
// Test 11: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0 and
|
||||||
// After DF ticket, https://github.com/apache/arrow-datafusion/issues/383 is done,
|
// time > to_timestamp('1970-01-01T00:00:00.000000120+00:00') rewritten to time GT INT(130)
|
||||||
// there will be more pushed-down predicate time > to_timestamp('1970-01-01T00:00:00.000000120+00:00')
|
|
||||||
//
|
|
||||||
// Check correctness
|
|
||||||
let expected = vec!["++", "++"];
|
let expected = vec!["++", "++"];
|
||||||
run_sql_test_case!(
|
run_sql_test_case!(
|
||||||
TwoMeasurementsPredicatePushDown {},
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
@ -671,3 +655,306 @@ async fn sql_predicate_pushdown() {
|
||||||
&expected
|
&expected
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn sql_predicate_pushdown_explain() {
|
||||||
|
// Test 1: Select everything
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+--------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+--------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+--------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 2: One push-down expression: count > 200
|
||||||
|
// TODO: Make push-down predicates shown in explain verbose. Ticket #1538
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: CAST(count AS Int64) > 200 |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where count > 200",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check the plan
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: CAST(count AS Int64) > 200 |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where count > 200",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 3: Two push-down expression: count > 200 and town != 'tewsbury'
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+-----------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+-----------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: CAST(count AS Int64) > 200 AND CAST(town AS Utf8) != tewsbury |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+-----------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where count > 200 and town != 'tewsbury'",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 4: Still two push-down expression: count > 200 and town != 'tewsbury'
|
||||||
|
// even though the results are different
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") And #system Eq Int64(5) Or #town Eq Utf8(\"lawrence\") |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") And #system Eq Int64(5) Or #town Eq Utf8(\"lawrence\") |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") And #system Eq Int64(5) Or #town Eq Utf8(\"lawrence\") |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: CAST(count AS Int64) > 200 AND CAST(town AS Utf8) != tewsbury AND system = CAST(5 AS Float64) OR CAST(town AS Utf8) = lawrence |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where count > 200 and town != 'tewsbury' and (system =5 or town = 'lawrence')",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 5: three push-down expression: count > 200 and town != 'tewsbury' and count < 40000
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") And #system Eq Int64(5) Or #town Eq Utf8(\"lawrence\") And #count Lt Int64(40000) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") And #system Eq Int64(5) Or #town Eq Utf8(\"lawrence\") And #count Lt Int64(40000) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #town NotEq Utf8(\"tewsbury\") And #system Eq Int64(5) Or #town Eq Utf8(\"lawrence\") And #count Lt Int64(40000) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: CAST(count AS Int64) > 200 AND CAST(town AS Utf8) != tewsbury AND system = CAST(5 AS Float64) OR CAST(town AS Utf8) = lawrence AND CAST(count AS Int64) < 40000 |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where count > 200 and town != 'tewsbury' and (system =5 or town = 'lawrence') and count < 40000",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 6: two push-down expression: count > 200 and count < 40000
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #count Lt Int64(40000) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #count Lt Int64(40000) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #count Gt Int64(200) And #count Lt Int64(40000) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: CAST(count AS Int64) > 200 AND CAST(count AS Int64) < 40000 |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where count > 200 and count < 40000",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 7: two push-down expression on float: system > 4.0 and system < 7.0
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(4) And #system Lt Float64(7) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(4) And #system Lt Float64(7) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(4) And #system Lt Float64(7) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: system > 4 AND system < 7 |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where system > 4.0 and system < 7.0",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 8: two push-down expression on float: system > 5.0 and system < 7.0
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And #system Lt Float64(7) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And #system Lt Float64(7) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And #system Lt Float64(7) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: system > 5 AND system < 7 |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+----------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where system > 5.0 and system < 7.0",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 9: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+--------------------------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+--------------------------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And #town NotEq Utf8(\"tewsbury\") And Float64(7) Gt #system |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And #town NotEq Utf8(\"tewsbury\") And Float64(7) Gt #system |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And #town NotEq Utf8(\"tewsbury\") And Float64(7) Gt #system |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: system > 5 AND CAST(town AS Utf8) != tewsbury AND 7 > system |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+--------------------------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where system > 5.0 and town != 'tewsbury' and 7.0 > system",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 10: three push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0
|
||||||
|
// even though there are more expressions,(count = 632 or town = 'reading'), in the filter
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And Utf8(\"tewsbury\") NotEq #town And #system Lt Float64(7) And #count Eq Int64(632) Or #town Eq Utf8(\"reading\") |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And Utf8(\"tewsbury\") NotEq #town And #system Lt Float64(7) And #count Eq Int64(632) Or #town Eq Utf8(\"reading\") |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: #system Gt Float64(5) And Utf8(\"tewsbury\") NotEq #town And #system Lt Float64(7) And #count Eq Int64(632) Or #town Eq Utf8(\"reading\") |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: system > 5 AND tewsbury != CAST(town AS Utf8) AND system < 7 AND CAST(count AS Int64) = 632 OR CAST(town AS Utf8) = reading |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where system > 5.0 and 'tewsbury' != town and system < 7.0 and (count = 632 or town = 'reading')",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 11: four push-down expression: system > 5.0 and town != 'tewsbury' and system < 7.0 and
|
||||||
|
// time > to_timestamp('1970-01-01T00:00:00.000000120+00:00') rewritten to time GT INT(130)
|
||||||
|
let expected = vec![
|
||||||
|
"+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| plan_type | plan |",
|
||||||
|
"+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
"| logical_plan | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: Float64(5) Lt #system And #town NotEq Utf8(\"tewsbury\") And #system Lt Float64(7) And #count Eq Int64(632) Or #town Eq Utf8(\"reading\") And #time Gt totimestamp(Utf8(\"1970-01-01T00:00:00.000000130+00:00\")) |",
|
||||||
|
"| | TableScan: restaurant projection=None |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: Float64(5) Lt #system And #town NotEq Utf8(\"tewsbury\") And #system Lt Float64(7) And #count Eq Int64(632) Or #town Eq Utf8(\"reading\") And #time Gt totimestamp(Utf8(\"1970-01-01T00:00:00.000000130+00:00\")) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| logical_plan after projection_push_down | Projection: #count, #system, #time, #town |",
|
||||||
|
"| | Filter: Float64(5) Lt #system And #town NotEq Utf8(\"tewsbury\") And #system Lt Float64(7) And #count Eq Int64(632) Or #town Eq Utf8(\"reading\") And #time Gt totimestamp(Utf8(\"1970-01-01T00:00:00.000000130+00:00\")) |",
|
||||||
|
"| | TableScan: restaurant projection=Some([0, 1, 2, 3]) |",
|
||||||
|
"| physical_plan | ProjectionExec: expr=[count, system, time, town] |",
|
||||||
|
"| | FilterExec: 5 < system AND CAST(town AS Utf8) != tewsbury AND system < 7 AND CAST(count AS Int64) = 632 OR CAST(town AS Utf8) = reading AND time > totimestamp(1970-01-01T00:00:00.000000130+00:00) |",
|
||||||
|
"| | IOxReadFilterNode: table_name=restaurant, chunks=1 predicate=Predicate |",
|
||||||
|
"+-----------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+",
|
||||||
|
];
|
||||||
|
run_sql_explain_test_case!(
|
||||||
|
TwoMeasurementsPredicatePushDown {},
|
||||||
|
"EXPLAIN VERBOSE SELECT * from restaurant where 5.0 < system and town != 'tewsbury' and system < 7.0 and (count = 632 or town = 'reading') and time > to_timestamp('1970-01-01T00:00:00.000000130+00:00')",
|
||||||
|
&expected
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue