From 77395ed1330d087671773418771591d0eecd00a8 Mon Sep 17 00:00:00 2001 From: Alexander Beedie Date: Fri, 14 Jul 2023 15:26:33 +0200 Subject: [PATCH] feat(python): add `INITCAP` string function for SQL --- crates/polars-sql/src/functions.rs | 7 +++++++ py-polars/tests/unit/test_sql.py | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/crates/polars-sql/src/functions.rs b/crates/polars-sql/src/functions.rs index 2158ce2874512..e6af2b11a9fbf 100644 --- a/crates/polars-sql/src/functions.rs +++ b/crates/polars-sql/src/functions.rs @@ -181,6 +181,11 @@ pub(crate) enum PolarsSqlFunctions { /// SELECT column_2 from df WHERE ENDS_WITH(column_1, 'a'); /// ``` EndsWith, + /// SQL 'initcap' function + /// ```sql + /// SELECT INITCAP(column_1) from df; + /// ``` + InitCap, /// SQL 'left' function /// ```sql /// SELECT LEFT(column_1, 3) from df; @@ -498,6 +503,7 @@ impl PolarsSqlFunctions { // String functions // ---- "ends_with" => Self::EndsWith, + "initcap" => Self::InitCap, "length" => Self::Length, "left" => Self::Left, "lower" => Self::Lower, @@ -615,6 +621,7 @@ impl SqlFunctionVisitor<'_> { // String functions // ---- EndsWith => self.visit_binary(|e, s| e.str().ends_with(s)), + InitCap => self.visit_unary(|e| e.str().to_titlecase()), Left => self.try_visit_binary(|e, length| { Ok(e.str().str_slice(0, match length { Expr::Literal(LiteralValue::Int64(n)) => Some(n as u64), diff --git a/py-polars/tests/unit/test_sql.py b/py-polars/tests/unit/test_sql.py index 3a18c2a3c14c5..968062eb07ff8 100644 --- a/py-polars/tests/unit/test_sql.py +++ b/py-polars/tests/unit/test_sql.py @@ -708,6 +708,29 @@ def test_sql_round_ndigits_errors() -> None: ctx.execute("SELECT ROUND(n,-1) AS n FROM df") +def test_sql_string_case() -> None: + df = pl.DataFrame({"words": ["Test SOME words"]}) + + with pl.SQLContext(frame=df) as ctx: + res = ctx.execute( + """ + SELECT + words, + INITCAP(words) as cap, + UPPER(words) as upper, + LOWER(words) as lower, + FROM frame + """ + ).collect() + + assert res.to_dict(False) == { + "words": ["Test SOME words"], + "cap": ["Test Some Words"], + "upper": ["TEST SOME WORDS"], + "lower": ["test some words"], + } + + def test_sql_string_lengths() -> None: df = pl.DataFrame({"words": ["Café", None, "東京"]})