Skip to content

Commit b4dd97e

Browse files
chenkovskyalamb
authored andcommitted
feat: support nested key for get_field (apache#18394)
## Which issue does this PR close? ## Rationale for this change get_field doesn't support nested key ## What changes are included in this PR? support nested key ## Are these changes tested? UT ## Are there any user-facing changes? No --------- Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent ba5279f commit b4dd97e

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

datafusion/functions/src/core/getfield.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,46 @@ impl ScalarUDFImpl for GetFieldFunc {
245245
Ok(ColumnarValue::Array(data))
246246
}
247247

248+
fn process_map_with_nested_key(
249+
array: Arc<dyn Array>,
250+
key_array: Arc<dyn Array>,
251+
) -> Result<ColumnarValue> {
252+
let map_array = as_map_array(array.as_ref())?;
253+
254+
let comparator = make_comparator(
255+
map_array.keys().as_ref(),
256+
key_array.as_ref(),
257+
SortOptions::default(),
258+
)?;
259+
260+
let original_data = map_array.entries().column(1).to_data();
261+
let capacity = Capacities::Array(original_data.len());
262+
let mut mutable =
263+
MutableArrayData::with_capacities(vec![&original_data], true, capacity);
264+
265+
for entry in 0..map_array.len() {
266+
let start = map_array.value_offsets()[entry] as usize;
267+
let end = map_array.value_offsets()[entry + 1] as usize;
268+
269+
let mut found_match = false;
270+
for i in start..end {
271+
if comparator(i, 0).is_eq() {
272+
mutable.extend(0, i, i + 1);
273+
found_match = true;
274+
break;
275+
}
276+
}
277+
278+
if !found_match {
279+
mutable.extend_nulls(1);
280+
}
281+
}
282+
283+
let data = mutable.freeze();
284+
let data = make_array(data);
285+
Ok(ColumnarValue::Array(data))
286+
}
287+
248288
match (array.data_type(), name) {
249289
(DataType::Map(_, _), ScalarValue::List(arr)) => {
250290
let key_array: Arc<dyn Array> = arr;
@@ -256,7 +296,7 @@ impl ScalarUDFImpl for GetFieldFunc {
256296
(DataType::Map(_, _), other) => {
257297
let data_type = other.data_type();
258298
if data_type.is_nested() {
259-
exec_err!("unsupported type {} for map access", data_type)
299+
process_map_with_nested_key(array, other.to_array()?)
260300
} else {
261301
process_map_array(array, other.to_array()?)
262302
}

datafusion/sqllogictest/test_files/map.slt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -544,11 +544,19 @@ SELECT (CASE WHEN 1 > 0 THEN MAP {'x': 100} ELSE MAP {'y': 200} END)['x'];
544544
----
545545
100
546546

547-
# TODO(https://github.com/apache/datafusion/issues/11785): fix accessing map with non-string key
548-
# query ?
549-
# SELECT MAP { MAP {1:'a', 2:'b'}:1, MAP {1:'c', 2:'d'}:2 }[MAP {1:'a', 2:'b'}];
550-
# ----
551-
# 1
547+
# fix accessing map with nested key
548+
query I
549+
SELECT MAP { MAP {1:'a', 2:'b'}:1, MAP {1:'c', 2:'d'}:2 }[MAP {1:'a', 2:'b'}];
550+
----
551+
1
552+
553+
query I
554+
SELECT MAP { MAP {1:'a', 2:'b'}:1, MAP {1:'c', 2:'d'}:2 }[MAP {2:'b', 1:'a'}];
555+
----
556+
NULL
557+
558+
# TODO(https://github.com/apache/datafusion/pull/18394): Test accessing map with empty map as key
559+
# TODO(https://github.com/apache/datafusion/pull/18394): Test accessing map with null map as key
552560

553561
# accessing map with non-string key
554562
query I

0 commit comments

Comments
 (0)