This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new 18c0f1cd5e Use OwnedTableReference for subquery aliases (#6022)
18c0f1cd5e is described below
commit 18c0f1cd5e859bb1629ecc8f1bfefd4dc9d6517a
Author: Sean Smith <[email protected]>
AuthorDate: Mon Apr 17 05:22:38 2023 -0500
Use OwnedTableReference for subquery aliases (#6022)
* Use OwnedTableReference for subquery aliases
* proto changes
* add sqllogictest
* Add tests
---
.../core/tests/sqllogictests/test_files/ddl.slt | 37 ++++++++++++++++++++++
datafusion/expr/src/logical_plan/builder.rs | 4 +--
datafusion/expr/src/logical_plan/plan.rs | 18 +++++------
.../optimizer/src/analyzer/inline_table_scan.rs | 14 +++-----
datafusion/optimizer/src/decorrelate_where_in.rs | 2 +-
.../optimizer/src/scalar_subquery_to_join.rs | 2 +-
datafusion/proto/proto/datafusion.proto | 3 +-
datafusion/proto/src/generated/pbjson.rs | 10 +++---
datafusion/proto/src/generated/prost.rs | 4 +--
datafusion/proto/src/logical_plan/mod.rs | 13 +++++---
10 files changed, 71 insertions(+), 36 deletions(-)
diff --git a/datafusion/core/tests/sqllogictests/test_files/ddl.slt
b/datafusion/core/tests/sqllogictests/test_files/ddl.slt
index d21d85267a..addc20af99 100644
--- a/datafusion/core/tests/sqllogictests/test_files/ddl.slt
+++ b/datafusion/core/tests/sqllogictests/test_files/ddl.slt
@@ -150,6 +150,43 @@ select * from "foo.bar.baz";
statement ok
drop view "foo.bar.baz"
+##########
+# Query views in other schemas.
+##########
+
+statement ok
+CREATE SCHEMA foo_schema;
+
+# Should be able to create view in "foo_schema".
+statement ok
+CREATE VIEW foo_schema.bar AS (SELECT 1 as a, 2 as b);
+
+# And be able to query it.
+query II
+SELECT * FROM foo_schema.bar;
+----
+1 2
+
+# Make sure we can query individual columns with various qualifications.
+
+query I
+SELECT a FROM foo_schema.bar;
+----
+1
+
+query I
+SELECT bar.a FROM foo_schema.bar;
+----
+1
+
+query I
+SELECT foo_schema.bar.a FROM foo_schema.bar;
+----
+1
+
+# TODO: Drop schema for cleanup, see #6027
+# statement ok
+# DROP SCHEMA foo_schema;
##########
# Drop view error tests
diff --git a/datafusion/expr/src/logical_plan/builder.rs
b/datafusion/expr/src/logical_plan/builder.rs
index d16b7cd8c5..ec2a27542c 100644
--- a/datafusion/expr/src/logical_plan/builder.rs
+++ b/datafusion/expr/src/logical_plan/builder.rs
@@ -381,7 +381,7 @@ impl LogicalPlanBuilder {
}
/// Apply an alias
- pub fn alias(self, alias: impl Into<String>) -> Result<Self> {
+ pub fn alias(self, alias: impl Into<OwnedTableReference>) -> Result<Self> {
Ok(Self::from(subquery_alias(self.plan, alias)?))
}
@@ -1236,7 +1236,7 @@ pub fn project(
/// Create a SubqueryAlias to wrap a LogicalPlan.
pub fn subquery_alias(
plan: LogicalPlan,
- alias: impl Into<String>,
+ alias: impl Into<OwnedTableReference>,
) -> Result<LogicalPlan> {
Ok(LogicalPlan::SubqueryAlias(SubqueryAlias::try_new(
plan, alias,
diff --git a/datafusion/expr/src/logical_plan/plan.rs
b/datafusion/expr/src/logical_plan/plan.rs
index 50d5e7d607..825a7b56e4 100644
--- a/datafusion/expr/src/logical_plan/plan.rs
+++ b/datafusion/expr/src/logical_plan/plan.rs
@@ -36,7 +36,7 @@ use datafusion_common::tree_node::{
};
use datafusion_common::{
plan_err, Column, DFSchema, DFSchemaRef, DataFusionError,
OwnedTableReference,
- Result, ScalarValue, TableReference,
+ Result, ScalarValue,
};
use std::collections::{HashMap, HashSet};
use std::fmt::{self, Debug, Display, Formatter};
@@ -1304,20 +1304,20 @@ pub struct SubqueryAlias {
/// The incoming logical plan
pub input: Arc<LogicalPlan>,
/// The alias for the input relation
- pub alias: String,
+ pub alias: OwnedTableReference,
/// The schema with qualified field names
pub schema: DFSchemaRef,
}
impl SubqueryAlias {
- pub fn try_new(plan: LogicalPlan, alias: impl Into<String>) ->
Result<Self> {
+ pub fn try_new(
+ plan: LogicalPlan,
+ alias: impl Into<OwnedTableReference>,
+ ) -> Result<Self> {
let alias = alias.into();
- let table_ref = TableReference::bare(&alias);
let schema: Schema = plan.schema().as_ref().clone().into();
- let schema = DFSchemaRef::new(DFSchema::try_from_qualified_schema(
- table_ref.to_owned_reference(),
- &schema,
- )?);
+ let schema =
+ DFSchemaRef::new(DFSchema::try_from_qualified_schema(&alias,
&schema)?);
Ok(SubqueryAlias {
input: Arc::new(plan),
alias,
@@ -1913,7 +1913,7 @@ mod tests {
use crate::{col, exists, in_subquery, lit};
use arrow::datatypes::{DataType, Field, Schema};
use datafusion_common::tree_node::TreeNodeVisitor;
- use datafusion_common::DFSchema;
+ use datafusion_common::{DFSchema, TableReference};
use std::collections::HashMap;
fn employee_schema() -> Schema {
diff --git a/datafusion/optimizer/src/analyzer/inline_table_scan.rs
b/datafusion/optimizer/src/analyzer/inline_table_scan.rs
index 550d095f3e..0b8c72b822 100644
--- a/datafusion/optimizer/src/analyzer/inline_table_scan.rs
+++ b/datafusion/optimizer/src/analyzer/inline_table_scan.rs
@@ -64,16 +64,10 @@ fn analyze_internal(plan: LogicalPlan) ->
Result<Transformed<LogicalPlan>> {
let projection_exprs = generate_projection_expr(&projection,
sub_plan)?;
let plan = LogicalPlanBuilder::from(sub_plan.clone())
.project(projection_exprs)?
- // Since this This is creating a subquery like:
- //```sql
- // ...
- // FROM <view definition> as "table_name"
- // ```
- //
- // it doesn't make sense to have a qualified
- // reference (e.g. "foo"."bar") -- this convert to
- // string
- .alias(table_name.to_string())?
+ // Ensures that the reference to the inlined table remains the
+ // same, meaning we don't have to change any of the parent
nodes
+ // that reference this table.
+ .alias(table_name)?
.build()?;
Transformed::Yes(plan)
}
diff --git a/datafusion/optimizer/src/decorrelate_where_in.rs
b/datafusion/optimizer/src/decorrelate_where_in.rs
index d89fd935be..c4d46d93c0 100644
--- a/datafusion/optimizer/src/decorrelate_where_in.rs
+++ b/datafusion/optimizer/src/decorrelate_where_in.rs
@@ -183,7 +183,7 @@ fn optimize_where_in(
let right = LogicalPlanBuilder::from(subquery_input)
.project(projection_exprs)?
- .alias(&subquery_alias)?
+ .alias(subquery_alias.clone())?
.build()?;
// join our sub query into the main plan
diff --git a/datafusion/optimizer/src/scalar_subquery_to_join.rs
b/datafusion/optimizer/src/scalar_subquery_to_join.rs
index df0b9245fa..d88aca32cb 100644
--- a/datafusion/optimizer/src/scalar_subquery_to_join.rs
+++ b/datafusion/optimizer/src/scalar_subquery_to_join.rs
@@ -266,7 +266,7 @@ fn optimize_scalar(
let subqry_plan = subqry_plan
.aggregate(group_by, aggr.aggr_expr.clone())?
.project(proj)?
- .alias(&subqry_alias)?
+ .alias(subqry_alias.clone())?
.build()?;
// qualify the join columns for outside the subquery
diff --git a/datafusion/proto/proto/datafusion.proto
b/datafusion/proto/proto/datafusion.proto
index 1b8f999f28..6b8cc61034 100644
--- a/datafusion/proto/proto/datafusion.proto
+++ b/datafusion/proto/proto/datafusion.proto
@@ -294,8 +294,9 @@ message SelectionExecNode {
}
message SubqueryAliasNode {
+ reserved 2; // Was string alias
LogicalPlanNode input = 1;
- string alias = 2;
+ OwnedTableReference alias = 3;
}
// logical expressions
diff --git a/datafusion/proto/src/generated/pbjson.rs
b/datafusion/proto/src/generated/pbjson.rs
index c2bfe3d08a..2acac28c40 100644
--- a/datafusion/proto/src/generated/pbjson.rs
+++ b/datafusion/proto/src/generated/pbjson.rs
@@ -20231,15 +20231,15 @@ impl serde::Serialize for SubqueryAliasNode {
if self.input.is_some() {
len += 1;
}
- if !self.alias.is_empty() {
+ if self.alias.is_some() {
len += 1;
}
let mut struct_ser =
serializer.serialize_struct("datafusion.SubqueryAliasNode", len)?;
if let Some(v) = self.input.as_ref() {
struct_ser.serialize_field("input", v)?;
}
- if !self.alias.is_empty() {
- struct_ser.serialize_field("alias", &self.alias)?;
+ if let Some(v) = self.alias.as_ref() {
+ struct_ser.serialize_field("alias", v)?;
}
struct_ser.end()
}
@@ -20315,13 +20315,13 @@ impl<'de> serde::Deserialize<'de> for
SubqueryAliasNode {
if alias__.is_some() {
return
Err(serde::de::Error::duplicate_field("alias"));
}
- alias__ = Some(map.next_value()?);
+ alias__ = map.next_value()?;
}
}
}
Ok(SubqueryAliasNode {
input: input__,
- alias: alias__.unwrap_or_default(),
+ alias: alias__,
})
}
}
diff --git a/datafusion/proto/src/generated/prost.rs
b/datafusion/proto/src/generated/prost.rs
index 84689e56f5..a3d60ef436 100644
--- a/datafusion/proto/src/generated/prost.rs
+++ b/datafusion/proto/src/generated/prost.rs
@@ -448,8 +448,8 @@ pub struct SelectionExecNode {
pub struct SubqueryAliasNode {
#[prost(message, optional, boxed, tag = "1")]
pub input:
::core::option::Option<::prost::alloc::boxed::Box<LogicalPlanNode>>,
- #[prost(string, tag = "2")]
- pub alias: ::prost::alloc::string::String,
+ #[prost(message, optional, tag = "3")]
+ pub alias: ::core::option::Option<OwnedTableReference>,
}
/// logical expressions
#[allow(clippy::derive_partial_eq_without_eq)]
diff --git a/datafusion/proto/src/logical_plan/mod.rs
b/datafusion/proto/src/logical_plan/mod.rs
index 5aa956c97e..0c58fada0a 100644
--- a/datafusion/proto/src/logical_plan/mod.rs
+++ b/datafusion/proto/src/logical_plan/mod.rs
@@ -256,7 +256,8 @@ impl AsLogicalPlan for LogicalPlanNode {
Some(a) => match a {
protobuf::projection_node::OptionalAlias::Alias(alias)
=> {
Ok(LogicalPlan::SubqueryAlias(SubqueryAlias::try_new(
- new_proj, alias,
+ new_proj,
+ alias.clone(),
)?))
}
},
@@ -593,9 +594,11 @@ impl AsLogicalPlan for LogicalPlanNode {
LogicalPlanType::SubqueryAlias(aliased_relation) => {
let input: LogicalPlan =
into_logical_plan!(aliased_relation.input, ctx,
extension_codec)?;
- LogicalPlanBuilder::from(input)
- .alias(&aliased_relation.alias)?
- .build()
+ let alias = from_owned_table_reference(
+ aliased_relation.alias.as_ref(),
+ "SubqueryAlias",
+ )?;
+ LogicalPlanBuilder::from(input).alias(alias)?.build()
}
LogicalPlanType::Limit(limit) => {
let input: LogicalPlan =
@@ -1069,7 +1072,7 @@ impl AsLogicalPlan for LogicalPlanNode {
logical_plan_type:
Some(LogicalPlanType::SubqueryAlias(Box::new(
protobuf::SubqueryAliasNode {
input: Some(Box::new(input)),
- alias: alias.clone(),
+ alias: Some(alias.to_owned_reference().into()),
},
))),
})