Find excluded columns in the schema, if any SELECT * EXCLUDE(col1, col2), would return `vec![col1, col2]`
(
opt_exclude: Option<&ExcludeSelectItem>,
opt_except: Option<&ExceptSelectItem>,
schema: &DFSchema,
qualifier: Option<&TableReference>,
)
| 329 | /// Find excluded columns in the schema, if any |
| 330 | /// SELECT * EXCLUDE(col1, col2), would return `vec![col1, col2]` |
| 331 | fn get_excluded_columns( |
| 332 | opt_exclude: Option<&ExcludeSelectItem>, |
| 333 | opt_except: Option<&ExceptSelectItem>, |
| 334 | schema: &DFSchema, |
| 335 | qualifier: Option<&TableReference>, |
| 336 | ) -> Result<Vec<Column>> { |
| 337 | let mut idents = vec![]; |
| 338 | if let Some(excepts) = opt_except { |
| 339 | idents.push(&excepts.first_element); |
| 340 | idents.extend(&excepts.additional_elements); |
| 341 | } |
| 342 | // Declared outside the `if let` so `idents.extend(exclude_owned.iter())` |
| 343 | // below can borrow references that outlive the inner scope. |
| 344 | let exclude_owned: Vec<Ident>; |
| 345 | if let Some(exclude) = opt_exclude { |
| 346 | let object_name_to_ident = |name: &ObjectName| -> Result<Ident> { |
| 347 | if name.0.len() != 1 { |
| 348 | return plan_err!( |
| 349 | "EXCLUDE with multi-part identifiers is not supported: {name}" |
| 350 | ); |
| 351 | } |
| 352 | let part = &name.0[0]; |
| 353 | let Some(ident) = part.as_ident() else { |
| 354 | return plan_err!( |
| 355 | "EXCLUDE with non-identifier name part is not supported: {part}" |
| 356 | ); |
| 357 | }; |
| 358 | Ok(ident.clone()) |
| 359 | }; |
| 360 | exclude_owned = match exclude { |
| 361 | ExcludeSelectItem::Single(name) => vec![object_name_to_ident(name)?], |
| 362 | ExcludeSelectItem::Multiple(names) => names |
| 363 | .iter() |
| 364 | .map(object_name_to_ident) |
| 365 | .collect::<Result<Vec<_>>>()?, |
| 366 | }; |
| 367 | idents.extend(exclude_owned.iter()); |
| 368 | } |
| 369 | // Excluded columns should be unique |
| 370 | let n_elem = idents.len(); |
| 371 | let unique_idents = idents.into_iter().collect::<HashSet<_>>(); |
| 372 | // If HashSet size, and vector length are different, this means that some of the excluded columns |
| 373 | // are not unique. In this case return error. |
| 374 | if n_elem != unique_idents.len() { |
| 375 | return plan_err!("EXCLUDE or EXCEPT contains duplicate column names"); |
| 376 | } |
| 377 | |
| 378 | let mut result = vec![]; |
| 379 | for ident in unique_idents.into_iter() { |
| 380 | let col_name = ident.value.as_str(); |
| 381 | let (qualifier, field) = schema.qualified_field_with_name(qualifier, col_name)?; |
| 382 | result.push(Column::from((qualifier, field))); |
| 383 | } |
| 384 | Ok(result) |
| 385 | } |
| 386 | |
| 387 | /// Returns all `Expr`s in the schema, except the `Column`s in the `columns_to_skip` |
| 388 | fn get_exprs_except_skipped( |
no test coverage detected
searching dependent graphs…