Extract a single field from a struct or map array
(base: ColumnarValue, name: ScalarValue)
| 192 | |
| 193 | /// Extract a single field from a struct or map array |
| 194 | fn extract_single_field(base: ColumnarValue, name: ScalarValue) -> Result<ColumnarValue> { |
| 195 | let arrays = ColumnarValue::values_to_arrays(&[base])?; |
| 196 | let array = Arc::clone(&arrays[0]); |
| 197 | |
| 198 | let string_value = name.try_as_str().flatten().map(|s| s.to_string()); |
| 199 | |
| 200 | match (array.data_type(), name, string_value) { |
| 201 | // Dictionary-encoded struct: extract the field from the dictionary's |
| 202 | // values (the deduplicated struct array) and rebuild a dictionary with |
| 203 | // the same keys. This preserves dictionary encoding without expanding. |
| 204 | (DataType::Dictionary(_, value_type), _, Some(field_name)) |
| 205 | if matches!(value_type.as_ref(), DataType::Struct(_)) => |
| 206 | { |
| 207 | let dict = array.as_any_dictionary(); |
| 208 | let values_struct = dict.values().as_struct(); |
| 209 | let field_col = |
| 210 | values_struct.column_by_name(&field_name).ok_or_else(|| { |
| 211 | exec_datafusion_err!( |
| 212 | "Field {field_name} not found in dictionary struct" |
| 213 | ) |
| 214 | })?; |
| 215 | Ok(ColumnarValue::Array( |
| 216 | dict.with_values(Arc::clone(field_col)), |
| 217 | )) |
| 218 | } |
| 219 | (DataType::Map(_, _), ScalarValue::List(arr), _) => { |
| 220 | let key_array: Arc<dyn Array> = arr; |
| 221 | process_map_array(&array, key_array) |
| 222 | } |
| 223 | (DataType::Map(_, _), ScalarValue::Struct(arr), _) => { |
| 224 | process_map_array(&array, arr as Arc<dyn Array>) |
| 225 | } |
| 226 | (DataType::Map(_, _), other, _) => { |
| 227 | let data_type = other.data_type(); |
| 228 | if data_type.is_nested() { |
| 229 | process_map_with_nested_key(&array, &other.to_array()?) |
| 230 | } else { |
| 231 | process_map_array(&array, other.to_array()?) |
| 232 | } |
| 233 | } |
| 234 | (DataType::Struct(_), _, Some(k)) => { |
| 235 | let as_struct_array = as_struct_array(&array)?; |
| 236 | match as_struct_array.column_by_name(&k) { |
| 237 | None => exec_err!("Field {k} not found in struct"), |
| 238 | Some(col) => Ok(ColumnarValue::Array(Arc::clone(col))), |
| 239 | } |
| 240 | } |
| 241 | (DataType::Struct(_), name, _) => exec_err!( |
| 242 | "get_field is only possible on struct with utf8 indexes. \ |
| 243 | Received with {name:?} index" |
| 244 | ), |
| 245 | (DataType::Null, _, _) => Ok(ColumnarValue::Scalar(ScalarValue::Null)), |
| 246 | (dt, name, _) => exec_err!( |
| 247 | "get_field is only possible on maps or structs. Received {dt} with {name:?} index" |
| 248 | ), |
| 249 | } |
| 250 | } |
| 251 |
searching dependent graphs…