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()),
                         },
                     ))),
                 })

Reply via email to