Skip to content

Commit 7f2a74c

Browse files
authored
Chore: refactor RANDSTR duckdb transpilation logic (#6631)
1 parent a4e1dec commit 7f2a74c

File tree

2 files changed

+24
-24
lines changed

2 files changed

+24
-24
lines changed

sqlglot/dialects/duckdb.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,24 @@ class Generator(generator.Generator):
15891589
"""
15901590
)
15911591

1592+
# Template for RANDSTR transpilation - placeholders get replaced with actual parameters
1593+
RANDSTR_TEMPLATE: exp.Expression = exp.maybe_parse(
1594+
f"""
1595+
SELECT LISTAGG(
1596+
SUBSTRING(
1597+
'{RANDSTR_CHAR_POOL}',
1598+
1 + CAST(FLOOR(random_value * 62) AS INT),
1599+
1
1600+
),
1601+
''
1602+
)
1603+
FROM (
1604+
SELECT (ABS(HASH(i + :seed)) % 1000) / 1000.0 AS random_value
1605+
FROM RANGE(:length) AS t(i)
1606+
)
1607+
""",
1608+
)
1609+
15921610
def bitmapbitposition_sql(self: DuckDB.Generator, expression: exp.BitmapBitPosition) -> str:
15931611
"""
15941612
Transpile Snowflake's BITMAP_BIT_POSITION to DuckDB CASE expression.
@@ -1615,6 +1633,7 @@ def bitmapbitposition_sql(self: DuckDB.Generator, expression: exp.BitmapBitPosit
16151633
def randstr_sql(self: DuckDB.Generator, expression: exp.Randstr) -> str:
16161634
"""
16171635
Transpile Snowflake's RANDSTR to DuckDB equivalent using deterministic hash-based random.
1636+
Uses a pre-parsed template with placeholders replaced by expression nodes.
16181637
16191638
RANDSTR(length, generator) generates a random string of specified length.
16201639
- With numeric seed: Use HASH(i + seed) for deterministic output (same seed = same result)
@@ -1635,27 +1654,8 @@ def randstr_sql(self: DuckDB.Generator, expression: exp.Randstr) -> str:
16351654
# No generator specified, use default seed (arbitrary but deterministic)
16361655
seed_value = exp.Literal.number(RANDSTR_SEED)
16371656

1638-
length_sql = self.sql(length)
1639-
seed_sql = self.sql(seed_value)
1640-
1641-
query: exp.Select = exp.maybe_parse(
1642-
f"""
1643-
SELECT LISTAGG(
1644-
SUBSTRING(
1645-
'{RANDSTR_CHAR_POOL}',
1646-
1 + CAST(FLOOR(random_value * 62) AS INT),
1647-
1
1648-
),
1649-
''
1650-
)
1651-
FROM (
1652-
SELECT (ABS(HASH(i + {seed_sql})) % 1000) / 1000.0 AS random_value
1653-
FROM RANGE({length_sql}) AS t(i)
1654-
)
1655-
""",
1656-
dialect="duckdb",
1657-
)
1658-
return f"({self.sql(query)})"
1657+
replacements = {"seed": seed_value, "length": length}
1658+
return f"({self.sql(exp.replace_placeholders(self.RANDSTR_TEMPLATE, **replacements))})"
16591659

16601660
def zipf_sql(self: DuckDB.Generator, expression: exp.Zipf) -> str:
16611661
"""

tests/dialects/test_snowflake.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,21 +253,21 @@ def test_snowflake(self):
253253
"SELECT RANDSTR(10, 123)",
254254
write={
255255
"snowflake": "SELECT RANDSTR(10, 123)",
256-
"duckdb": "SELECT (SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT (ABS(HASH(i + 123)) % 1000) / 1000.0 AS random_value FROM RANGE(0, 10) AS t(i)))",
256+
"duckdb": "SELECT (SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT (ABS(HASH(i + 123)) % 1000) / 1000.0 AS random_value FROM RANGE(10) AS t(i)))",
257257
},
258258
)
259259
self.validate_all(
260260
"SELECT RANDSTR(10, RANDOM(123))",
261261
write={
262262
"snowflake": "SELECT RANDSTR(10, RANDOM(123))",
263-
"duckdb": "SELECT (SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT (ABS(HASH(i + 123)) % 1000) / 1000.0 AS random_value FROM RANGE(0, 10) AS t(i)))",
263+
"duckdb": "SELECT (SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT (ABS(HASH(i + 123)) % 1000) / 1000.0 AS random_value FROM RANGE(10) AS t(i)))",
264264
},
265265
)
266266
self.validate_all(
267267
"SELECT RANDSTR(10, RANDOM())",
268268
write={
269269
"snowflake": "SELECT RANDSTR(10, RANDOM())",
270-
"duckdb": "SELECT (SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT (ABS(HASH(i + RANDOM())) % 1000) / 1000.0 AS random_value FROM RANGE(0, 10) AS t(i)))",
270+
"duckdb": "SELECT (SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT (ABS(HASH(i + RANDOM())) % 1000) / 1000.0 AS random_value FROM RANGE(10) AS t(i)))",
271271
},
272272
)
273273

0 commit comments

Comments
 (0)