Skip to content

Commit 0405bda

Browse files
paleolimbotalamb
authored andcommitted
Enable placeholders with extension types (apache#17986)
## Which issue does this PR close? - Closes apache#17862 ## Rationale for this change Most logical plan expressions now propagate metadata; however, parameters with extension types or other field metadata cannot participate in placeholder/parameter binding. ## What changes are included in this PR? The DataType in the Placeholder struct was replaced with a FieldRef along with anything that stored the "DataType" of a parameter. Strictly speaking one could bind parameters with an extension type by copy/pasting the placeholder replacer, which I figured out towards the end of this change. I still think this change makes sense and opens up the door for things like handling UUID in SQL with full parameter binding support. ## Are these changes tested? Yes ## Are there any user-facing changes? Yes, one new function was added to extract the placeholder fields from a plan. This is a breaking change for code that specifically interacts with the pub fields of the modified structs (ParamValues, Placeholder, and Prepare are the main ones). --------- Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent f431f15 commit 0405bda

File tree

33 files changed

+1288
-456
lines changed

33 files changed

+1288
-456
lines changed

datafusion/common/src/datatype.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//! [DataTypeExt] extension trait for converting DataTypes to Fields
19+
20+
use crate::arrow::datatypes::{DataType, Field, FieldRef};
21+
use std::sync::Arc;
22+
23+
/// DataFusion extension methods for Arrow [`DataType`]
24+
pub trait DataTypeExt {
25+
/// Convert the type to field with nullable type and "" name
26+
///
27+
/// This is used to track the places where we convert a [`DataType`]
28+
/// into a nameless field to interact with an API that is
29+
/// capable of representing an extension type and/or nullability.
30+
fn into_nullable_field(self) -> Field;
31+
32+
/// Convert the type to field ref with nullable type and "" name
33+
///
34+
/// Concise wrapper around [`DataTypeExt::into_nullable_field`] that
35+
/// constructs a [`FieldRef`].
36+
fn into_nullable_field_ref(self) -> FieldRef;
37+
}
38+
39+
impl DataTypeExt for DataType {
40+
fn into_nullable_field(self) -> Field {
41+
Field::new("", self, true)
42+
}
43+
44+
fn into_nullable_field_ref(self) -> FieldRef {
45+
Arc::new(Field::new("", self, true))
46+
}
47+
}
48+
49+
/// DataFusion extension methods for Arrow [`Field`]
50+
pub trait FieldExt {
51+
/// Returns a new Field representing a List of this Field's DataType.
52+
fn into_list(self) -> Self;
53+
54+
/// Return a new Field representing this Field as the item type of a FixedSizeList
55+
fn into_fixed_size_list(self, list_size: i32) -> Self;
56+
57+
/// Create a field with the default list field name ("item")
58+
///
59+
/// Note that lists are allowed to have an arbitrarily named field;
60+
/// however, a name other than 'item' will cause it to fail an
61+
/// == check against a more idiomatically created list in
62+
/// arrow-rs which causes issues.
63+
fn into_list_item(self) -> Self;
64+
}
65+
66+
impl FieldExt for Field {
67+
fn into_list(self) -> Self {
68+
DataType::List(Arc::new(self.into_list_item())).into_nullable_field()
69+
}
70+
71+
fn into_fixed_size_list(self, list_size: i32) -> Self {
72+
DataType::FixedSizeList(self.into_list_item().into(), list_size)
73+
.into_nullable_field()
74+
}
75+
76+
fn into_list_item(self) -> Self {
77+
if self.name() != Field::LIST_FIELD_DEFAULT_NAME {
78+
self.with_name(Field::LIST_FIELD_DEFAULT_NAME)
79+
} else {
80+
self
81+
}
82+
}
83+
}
84+
85+
impl FieldExt for Arc<Field> {
86+
fn into_list(self) -> Self {
87+
DataType::List(self.into_list_item())
88+
.into_nullable_field()
89+
.into()
90+
}
91+
92+
fn into_fixed_size_list(self, list_size: i32) -> Self {
93+
DataType::FixedSizeList(self.into_list_item(), list_size)
94+
.into_nullable_field()
95+
.into()
96+
}
97+
98+
fn into_list_item(self) -> Self {
99+
if self.name() != Field::LIST_FIELD_DEFAULT_NAME {
100+
Arc::unwrap_or_clone(self)
101+
.with_name(Field::LIST_FIELD_DEFAULT_NAME)
102+
.into()
103+
} else {
104+
self
105+
}
106+
}
107+
}

datafusion/common/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub mod alias;
3939
pub mod cast;
4040
pub mod config;
4141
pub mod cse;
42+
pub mod datatype;
4243
pub mod diagnostic;
4344
pub mod display;
4445
pub mod encryption;
@@ -47,6 +48,7 @@ pub mod file_options;
4748
pub mod format;
4849
pub mod hash_utils;
4950
pub mod instant;
51+
pub mod metadata;
5052
pub mod nested_struct;
5153
mod null_equality;
5254
pub mod parsers;

0 commit comments

Comments
 (0)