From 4ab0d400441adc91b94306b186ed3968e8c214a9 Mon Sep 17 00:00:00 2001 From: rdettai Date: Wed, 23 Jun 2021 18:44:15 +0200 Subject: [PATCH 1/2] [fix] select * on empty table --- datafusion/src/execution/context.rs | 15 ++++++++++++++- datafusion/src/optimizer/projection_push_down.rs | 5 +++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/datafusion/src/execution/context.rs b/datafusion/src/execution/context.rs index 926e2db9450a..165263084cc7 100644 --- a/datafusion/src/execution/context.rs +++ b/datafusion/src/execution/context.rs @@ -893,7 +893,7 @@ mod tests { logical_plan::{col, create_udf, sum, Expr}, }; use crate::{ - datasource::{MemTable, TableType}, + datasource::{empty::EmptyTable, MemTable, TableType}, logical_plan::create_udaf, physical_plan::expressions::AvgAccumulator, }; @@ -3333,6 +3333,19 @@ mod tests { assert_batches_sorted_eq!(expected, &result); } + #[tokio::test] + async fn query_empty_table() { + let mut ctx = ExecutionContext::new(); + let empty_table = Arc::new(EmptyTable::new(Arc::new(Schema::empty()))); + ctx.register_table("test_tbl", empty_table).unwrap(); + let sql = "SELECT * FROM test_tbl"; + let result = plan_and_collect(&mut ctx, sql) + .await + .expect("Query empty table"); + let expected = vec!["++", "++"]; + assert_batches_sorted_eq!(expected, &result); + } + struct MyPhysicalPlanner {} impl PhysicalPlanner for MyPhysicalPlanner { diff --git a/datafusion/src/optimizer/projection_push_down.rs b/datafusion/src/optimizer/projection_push_down.rs index 2544d89d0492..629d311bf5f2 100644 --- a/datafusion/src/optimizer/projection_push_down.rs +++ b/datafusion/src/optimizer/projection_push_down.rs @@ -83,9 +83,10 @@ fn get_projected_schema( .collect(); if projection.is_empty() { - if has_projection { + if has_projection && schema.fields().len() > 0 { // Ensure that we are reading at least one column from the table in case the query - // does not reference any columns directly such as "SELECT COUNT(1) FROM table" + // does not reference any columns directly such as "SELECT COUNT(1) FROM table", + // except when the table is empty (no column) projection.push(0); } else { // for table scan without projection, we default to return all columns From 0023c05139171e4e8a7e48b1ab4f93e7b177ead8 Mon Sep 17 00:00:00 2001 From: rdettai Date: Wed, 23 Jun 2021 19:11:44 +0200 Subject: [PATCH 2/2] clippy --- datafusion/src/optimizer/projection_push_down.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/src/optimizer/projection_push_down.rs b/datafusion/src/optimizer/projection_push_down.rs index 629d311bf5f2..a9e571f3d00b 100644 --- a/datafusion/src/optimizer/projection_push_down.rs +++ b/datafusion/src/optimizer/projection_push_down.rs @@ -83,7 +83,7 @@ fn get_projected_schema( .collect(); if projection.is_empty() { - if has_projection && schema.fields().len() > 0 { + if has_projection && !schema.fields().is_empty() { // Ensure that we are reading at least one column from the table in case the query // does not reference any columns directly such as "SELECT COUNT(1) FROM table", // except when the table is empty (no column)