Path: blob/main/crates/polars-plan/src/plans/functions/schema.rs
6940 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(crate) fn schema<'a>(26&self,27input_schema: &'a SchemaRef,28) -> PolarsResult<Cow<'a, SchemaRef>> {29use FunctionIR::*;30match self {31Opaque { schema, .. } => match schema {32None => Ok(Cow::Borrowed(input_schema)),33Some(schema_fn) => {34let output_schema = schema_fn.get_schema(input_schema)?;35Ok(Cow::Owned(output_schema))36},37},38#[cfg(feature = "python")]39OpaquePython(OpaquePythonUdf { schema, .. }) => Ok(schema40.as_ref()41.map(|schema| Cow::Owned(schema.clone()))42.unwrap_or_else(|| Cow::Borrowed(input_schema))),43FastCount { alias, .. } => {44let mut schema: Schema = Schema::with_capacity(1);45let name = alias.clone().unwrap_or_else(get_len_name);46schema.insert_at_index(0, name, IDX_DTYPE)?;47Ok(Cow::Owned(Arc::new(schema)))48},49Rechunk => Ok(Cow::Borrowed(input_schema)),50Unnest { columns: _columns } => {51#[cfg(feature = "dtype-struct")]52{53let mut new_schema = Schema::with_capacity(input_schema.len() * 2);54for (name, dtype) in input_schema.iter() {55if _columns.iter().any(|item| item == name) {56match dtype {57DataType::Struct(flds) => {58for fld in flds {59new_schema60.with_column(fld.name().clone(), fld.dtype().clone());61}62},63DataType::Unknown(_) => {64// pass through unknown65},66_ => {67polars_bail!(68SchemaMismatch: "expected struct dtype, got: `{}`", dtype69);70},71}72} else {73new_schema.with_column(name.clone(), dtype.clone());74}75}7677Ok(Cow::Owned(Arc::new(new_schema)))78}79#[cfg(not(feature = "dtype-struct"))]80{81panic!("activate feature 'dtype-struct'")82}83},84RowIndex { schema, name, .. } => Ok(Cow::Owned(row_index_schema(85schema,86input_schema,87name.clone(),88))),89Explode { schema, columns } => explode_schema(schema, input_schema, columns),90#[cfg(feature = "pivot")]91Unpivot { schema, args } => unpivot_schema(args, schema, input_schema),92}93}94}9596fn row_index_schema(97cached_schema: &CachedSchema,98input_schema: &SchemaRef,99name: PlSmallStr,100) -> SchemaRef {101let mut guard = cached_schema.lock().unwrap();102if let Some(schema) = &*guard {103return schema.clone();104}105let mut schema = (**input_schema).clone();106schema.insert_at_index(0, name, IDX_DTYPE).unwrap();107let schema_ref = Arc::new(schema);108*guard = Some(schema_ref.clone());109schema_ref110}111112fn explode_schema<'a>(113cached_schema: &CachedSchema,114schema: &'a Schema,115columns: &[PlSmallStr],116) -> PolarsResult<Cow<'a, SchemaRef>> {117let mut guard = cached_schema.lock().unwrap();118if let Some(schema) = &*guard {119return Ok(Cow::Owned(schema.clone()));120}121let mut schema = schema.clone();122123// columns to string124columns.iter().try_for_each(|name| {125match schema.try_get(name)? {126DataType::List(inner) => {127schema.with_column(name.clone(), inner.as_ref().clone());128},129#[cfg(feature = "dtype-array")]130DataType::Array(inner, _) => {131schema.with_column(name.clone(), inner.as_ref().clone());132},133_ => {},134}135136PolarsResult::Ok(())137})?;138let schema = Arc::new(schema);139*guard = Some(schema.clone());140Ok(Cow::Owned(schema))141}142143#[cfg(feature = "pivot")]144fn unpivot_schema<'a>(145args: &UnpivotArgsIR,146cached_schema: &CachedSchema,147input_schema: &'a Schema,148) -> PolarsResult<Cow<'a, SchemaRef>> {149let mut guard = cached_schema.lock().unwrap();150if let Some(schema) = &*guard {151return Ok(Cow::Owned(schema.clone()));152}153154let mut new_schema = args155.index156.iter()157.map(|id| Ok(Field::new(id.clone(), input_schema.try_get(id)?.clone())))158.collect::<PolarsResult<Schema>>()?;159let variable_name = args160.variable_name161.as_ref()162.cloned()163.unwrap_or_else(|| "variable".into());164let value_name = args165.value_name166.as_ref()167.cloned()168.unwrap_or_else(|| "value".into());169170new_schema.with_column(variable_name, DataType::String);171172// We need to determine the supertype of all value columns.173let mut supertype = DataType::Null;174175// take all columns that are not in `id_vars` as `value_var`176if args.on.is_empty() {177let id_vars = PlHashSet::from_iter(&args.index);178for (name, dtype) in input_schema.iter() {179if !id_vars.contains(name) {180supertype = try_get_supertype(&supertype, dtype)?;181}182}183} else {184for name in &args.on {185let dtype = input_schema.try_get(name)?;186supertype = try_get_supertype(&supertype, dtype)?;187}188}189new_schema.with_column(value_name, supertype);190let schema = Arc::new(new_schema);191*guard = Some(schema.clone());192Ok(Cow::Owned(schema))193}194195196