From 360e1e28ce2d5f858b4d225cf8cd495615413d9a Mon Sep 17 00:00:00 2001
From: Cameron Riddell <cameron@dutc.io>
Date: Fri, 10 Jan 2025 08:46:39 -0800
Subject: [PATCH] add duckdb replace_all with regex

---
 narwhals/_duckdb/expr.py                  | 13 +++++++++++--
 tests/expr_and_series/str/replace_test.py |  3 ---
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/narwhals/_duckdb/expr.py b/narwhals/_duckdb/expr.py
index e5e6120857..dcc7d1b2cb 100644
--- a/narwhals/_duckdb/expr.py
+++ b/narwhals/_duckdb/expr.py
@@ -662,8 +662,17 @@ def replace_all(
         from duckdb import FunctionExpression
 
         if literal is False:
-            msg = "`replace_all` for DuckDB currently only supports `literal=True`."
-            raise NotImplementedError(msg)
+            return self._compliant_expr._from_call(
+                lambda _input: FunctionExpression(
+                    "regexp_replace",
+                    _input,
+                    ConstantExpression(pattern),
+                    ConstantExpression(value),
+                    ConstantExpression("g"),
+                ),
+                "replace_all",
+                returns_scalar=self._compliant_expr._returns_scalar,
+            )
         return self._compliant_expr._from_call(
             lambda _input: FunctionExpression(
                 "replace", _input, ConstantExpression(pattern), ConstantExpression(value)
diff --git a/tests/expr_and_series/str/replace_test.py b/tests/expr_and_series/str/replace_test.py
index 4d6da63dee..68adf26e7a 100644
--- a/tests/expr_and_series/str/replace_test.py
+++ b/tests/expr_and_series/str/replace_test.py
@@ -116,15 +116,12 @@ def test_str_replace_expr(
 )
 def test_str_replace_all_expr(
     constructor: Constructor,
-    request: pytest.FixtureRequest,
     data: dict[str, list[str]],
     pattern: str,
     value: str,
     literal: bool,  # noqa: FBT001
     expected: dict[str, list[str]],
 ) -> None:
-    if "duckdb" in str(constructor) and literal is False:
-        request.applymarker(pytest.mark.xfail)
     df = nw.from_native(constructor(data))
     result = df.select(
         nw.col("a").str.replace_all(pattern=pattern, value=value, literal=literal)