From f1d35cc57bd5bf92995ce09995593deffc9fc1b9 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Thu, 19 Sep 2024 14:02:01 -0500 Subject: [PATCH] fix(mssql): ensure `ibis.random()` generates a new value per call --- ibis/backends/sql/compilers/mssql.py | 6 ++++++ ibis/backends/tests/test_numeric.py | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/ibis/backends/sql/compilers/mssql.py b/ibis/backends/sql/compilers/mssql.py index 70215fed821ac..dbb0e3f9fe2c3 100644 --- a/ibis/backends/sql/compilers/mssql.py +++ b/ibis/backends/sql/compilers/mssql.py @@ -171,6 +171,12 @@ def to_sqlglot( def visit_RandomUUID(self, op, **_): return self.f.newid() + def visit_RandomScalar(self, op, **_): + # By default RAND() will generate the same value for all calls within a + # query. The standard way to work around this is to pass in a unique + # value per call, which `CHECKSUM(NEWID())` provides. + return self.f.rand(self.f.checksum(self.f.newid())) + def visit_StringLength(self, op, *, arg): """The MSSQL LEN function doesn't count trailing spaces. diff --git a/ibis/backends/tests/test_numeric.py b/ibis/backends/tests/test_numeric.py index d5c16e9d08ac1..4d23680c7cf40 100644 --- a/ibis/backends/tests/test_numeric.py +++ b/ibis/backends/tests/test_numeric.py @@ -1309,6 +1309,18 @@ def test_random(con): assert 0 <= result <= 1 +@pytest.mark.notimpl(["polars"], raises=com.OperationNotDefinedError) +@pytest.mark.notimpl(["druid"], raises=PyDruidProgrammingError) +@pytest.mark.notimpl( + ["risingwave"], + raises=PsycoPg2InternalError, + reason="function random() does not exist", +) +def test_random_different_per_row(alltypes): + result = alltypes.select("int_col", rand_col=ibis.random()).execute() + assert result.rand_col.nunique() > 1 + + @pytest.mark.parametrize( ("ibis_func", "pandas_func"), [