Repository: pola-rs/polars
File: crates/polars-plan/src/plans/conversion/dsl_to_ir/mod.rs (Rust)

Code before:
                    subset,
                    maintain_order: options.maintain_order,
                    keep_strategy: options.keep_strategy,
                    slice: None,
                },
            });

            // if no temporary cols (eg: no "subset" exprs), we're done...
            if temp_cols.is_empty() {
                return Ok(distinct_node);
            }

            // ...otherwise, drop the temporary cols by selecting the original schema
            let exprs = to_expr_irs(
                input_schema
                    .iter_names()
                    .map(|name| Expr::Column(name.clone()))
                    .collect(),
                &mut ExprToIRContext::new_with_opt_eager(
                    ctxt.expr_arena,
                    &input_schema,
                    ctxt.opt_flags,
                ),
            )?;

            return Ok(ctxt.lp_arena.add(IR::Select {
                input: distinct_node,
                expr: exprs,
                schema: input_schema,
                options: Default::default(),
            }));
        },
        DslPlan::MapFunction { input, function } => {
            let input = to_alp_impl(owned(input), ctxt)
                .map_err(|e| e.context(failed_here!(format!("{}", function).to_lowercase())))?;
            let input_schema = ctxt.lp_arena.get(input).schema(ctxt.lp_arena);

            match function {
                DslFunction::Explode {
                    columns,
                    allow_empty,
                } => {
                    let columns = columns.into_columns(&input_schema, &Default::default())?;
                    polars_ensure!(!columns.is_empty() || allow_empty, InvalidOperation: "no columns provided in explode");
                    if columns.is_empty() {
                        return Ok(input);
                    }
                    let function = FunctionIR::Explode {
                        columns: columns.into_iter().collect(),
                        schema: Default::default(),
                    };

Review comment (suggestion):
It's better to build `IR::SimpleProjection` here (that node is used for `select()`s that only contain column exprs).


Code after:
                    keep_strategy: options.keep_strategy,
                    slice: None,
                },
            });

            // if no temporary cols (eg: we had no "subset" exprs), we're done...
            if temp_cols.is_empty() {
                return Ok(distinct_node);
            }

            // ...otherwise, drop them by projecting the original schema
            return Ok(ctxt.lp_arena.add(IR::SimpleProjection {
                input: distinct_node,
                columns: input_schema,
            }));
        },
        DslPlan::MapFunction { input, function } => {
            let input = to_alp_impl(owned(input), ctxt)
                .map_err(|e| e.context(failed_here!(format!("{}", function).to_lowercase())))?;
            let input_schema = ctxt.lp_arena.get(input).schema(ctxt.lp_arena);

            match function {
                DslFunction::Explode {
                    columns,
                    allow_empty,
                } => {
                    let columns = columns.into_columns(&input_schema, &Default::default())?;
                    polars_ensure!(!columns.is_empty() || allow_empty, InvalidOperation: "no columns provided in explode");
                    if columns.is_empty() {
                        return Ok(input);
                    }
                    let function = FunctionIR::Explode {
                        columns: columns.into_iter().collect(),
                        schema: Default::default(),
                    };
                    let ir = IR::MapFunction { input, function };
                    return Ok(ctxt.lp_arena.add(ir));
                },
                DslFunction::FillNan(fill_value) => {
                    let exprs = input_schema
                        .iter()
                        .filter_map(|(name, dtype)| match dtype {
                            DataType::Float32 | DataType::Float64 => Some(
                                col(name.clone())
                                    .fill_nan(fill_value.clone())
                                    .alias(name.clone()),
                            ),
                            _ => None,
                        })
                        .collect::<Vec<_>>();