Path: blob/main/crates/polars-plan/src/plans/functions/schema.rs
8433 views
#[cfg(feature = "pivot")]1use polars_core::utils::try_get_supertype;23use super::*;4use crate::constants::get_len_name;56impl FunctionIR {7pub(crate) fn clear_cached_schema(&self) {8use FunctionIR::*;9// We will likely add more branches later10#[allow(clippy::single_match)]11match self {12#[cfg(feature = "pivot")]13Unpivot { schema, .. } => {14let mut guard = schema.lock().unwrap();15*guard = None;16},17RowIndex { schema, .. } | Explode { schema, .. } => {18let mut guard = schema.lock().unwrap();19*guard = None;20},21_ => {},22}23}2425pub fn schema<'a>(&self, input_schema: &'a SchemaRef) -> PolarsResult<Cow<'a, SchemaRef>> {26use FunctionIR::*;27match self {28Opaque { schema, .. } => match schema {29None => Ok(Cow::Borrowed(input_schema)),30Some(schema_fn) => {31let output_schema = schema_fn.get_schema(input_schema)?;32Ok(Cow::Owned(output_schema))33},34},35#[cfg(feature = "python")]36OpaquePython(OpaquePythonUdf { schema, .. }) => Ok(schema37.as_ref()38.map(|schema| Cow::Owned(schema.clone()))39.unwrap_or_else(|| Cow::Borrowed(input_schema))),40FastCount { alias, .. } => {41let mut schema: Schema = Schema::with_capacity(1);42let name = alias.clone().unwrap_or_else(get_len_name);43schema.insert_at_index(0, name, IDX_DTYPE)?;44Ok(Cow::Owned(Arc::new(schema)))45},46Rechunk => Ok(Cow::Borrowed(input_schema)),47Unnest { columns, separator } => {48#[cfg(feature = "dtype-struct")]49{50let mut new_schema = Schema::with_capacity(input_schema.len() * 2);51for (name, dtype) in input_schema.iter() {52if columns.iter().any(|item| item == name) {53match dtype {54DataType::Struct(flds) => {55for fld in flds {56let fld_name = match separator {57None => fld.name().clone(),58Some(sep) => {59polars_utils::format_pl_smallstr!(60"{name}{sep}{}",61fld.name()62)63},64};65new_schema.with_column(fld_name, fld.dtype().clone());66}67},68DataType::Unknown(_) => {69// pass through unknown70},71_ => {72polars_bail!(73SchemaMismatch: "expected struct dtype, got: `{}`", dtype74);75},76}77} else {78new_schema.with_column(name.clone(), dtype.clone());79}80}8182Ok(Cow::Owned(Arc::new(new_schema)))83}84#[cfg(not(feature = "dtype-struct"))]85{86panic!("activate feature 'dtype-struct'")87}88},89RowIndex { schema, name, .. } => Ok(Cow::Owned(row_index_schema(90schema,91input_schema,92name.clone(),93))),94Explode {95schema,96options: _,97columns,98} => explode_schema(schema, input_schema, columns),99#[cfg(feature = "pivot")]100Unpivot { schema, args } => unpivot_schema(args, schema, input_schema),101Hint(_) => Ok(Cow::Borrowed(input_schema)),102}103}104}105106fn row_index_schema(107cached_schema: &CachedSchema,108input_schema: &SchemaRef,109name: PlSmallStr,110) -> SchemaRef {111let mut guard = cached_schema.lock().unwrap();112if let Some(schema) = &*guard {113return schema.clone();114}115let mut schema = (**input_schema).clone();116schema.insert_at_index(0, name, IDX_DTYPE).unwrap();117let schema_ref = Arc::new(schema);118*guard = Some(schema_ref.clone());119schema_ref120}121122fn explode_schema<'a>(123cached_schema: &CachedSchema,124schema: &'a Schema,125columns: &[PlSmallStr],126) -> PolarsResult<Cow<'a, SchemaRef>> {127let mut guard = cached_schema.lock().unwrap();128if let Some(schema) = &*guard {129return Ok(Cow::Owned(schema.clone()));130}131let mut schema = schema.clone();132133// columns to string134columns.iter().try_for_each(|name| {135match schema.try_get(name)? {136DataType::List(inner) => {137schema.with_column(name.clone(), inner.as_ref().clone());138},139#[cfg(feature = "dtype-array")]140DataType::Array(inner, _) => {141schema.with_column(name.clone(), inner.as_ref().clone());142},143_ => {},144}145146PolarsResult::Ok(())147})?;148let schema = Arc::new(schema);149*guard = Some(schema.clone());150Ok(Cow::Owned(schema))151}152153#[cfg(feature = "pivot")]154fn unpivot_schema<'a>(155args: &UnpivotArgsIR,156cached_schema: &CachedSchema,157input_schema: &'a Schema,158) -> PolarsResult<Cow<'a, SchemaRef>> {159let mut guard = cached_schema.lock().unwrap();160if let Some(schema) = &*guard {161return Ok(Cow::Owned(schema.clone()));162}163164let mut new_schema = args165.index166.iter()167.map(|id| Ok(Field::new(id.clone(), input_schema.try_get(id)?.clone())))168.collect::<PolarsResult<Schema>>()?;169170new_schema.with_column(args.variable_name.clone(), DataType::String);171172// We need to determine the supertype of all value columns.173let mut supertype = DataType::Null;174175for name in &args.on {176let dtype = input_schema.try_get(name)?;177supertype = try_get_supertype(&supertype, dtype)?;178}179180new_schema.with_column(args.value_name.clone(), supertype);181let schema = Arc::new(new_schema);182*guard = Some(schema.clone());183Ok(Cow::Owned(schema))184}185186187