Skip to content

Commit

Permalink
feat(api): add a uuid function for returning a new uuid
Browse files Browse the repository at this point in the history
  • Loading branch information
jcrist committed Feb 23, 2024
1 parent 753a268 commit 733fffc
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 0 deletions.
1 change: 1 addition & 0 deletions ibis/backends/bigquery/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class BigQueryCompiler(SQLGlotCompiler):
ops.Levenshtein: "edit_distance",
ops.Modulus: "mod",
ops.RandomScalar: "rand",
ops.RandomUUID: "generate_uuid",
ops.RegexReplace: "regexp_replace",
ops.RegexSearch: "regexp_contains",
ops.Time: "time",
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/clickhouse/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ClickHouseCompiler(SQLGlotCompiler):
ops.NullIf: "nullIf",
ops.RStrip: "trimRight",
ops.RandomScalar: "randCanonical",
ops.RandomUUID: "generateUUIDv4",
ops.RegexReplace: "replaceRegexpAll",
ops.RowNumber: "row_number",
ops.StartsWith: "startsWith",
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/duckdb/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class DuckDBCompiler(SQLGlotCompiler):
ops.MapMerge: "map_concat",
ops.MapValues: "map_values",
ops.Mode: "mode",
ops.RandomUUID: "uuid",
ops.TimeFromHMS: "make_time",
ops.TypeOf: "typeof",
ops.GeoPoint: "st_point",
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/impala/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ImpalaCompiler(SQLGlotCompiler):
ops.Ln: "ln",
ops.Log10: "log10",
ops.Log2: "log2",
ops.RandomUUID: "uuid",
ops.RStrip: "rtrim",
ops.Strip: "trim",
ops.TypeOf: "typeof",
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/postgres/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class PostgresCompiler(SQLGlotCompiler):
ops.MapContains: "exist",
ops.MapKeys: "akeys",
ops.MapValues: "avals",
ops.RandomUUID: "gen_random_uuid",
ops.RegexSearch: "regexp_like",
ops.TimeFromHMS: "make_time",
}
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/risingwave/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class RisingwaveCompiler(PostgresCompiler):
(
ops.DateFromYMD,
ops.Mode,
ops.RandomUUID,
*(
op
for op in ALL_OPERATIONS
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/snowflake/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class SnowflakeCompiler(SQLGlotCompiler):
ops.Hash: "hash",
ops.Median: "median",
ops.Mode: "mode",
ops.RandomUUID: "uuid_string",
ops.StringToTimestamp: "to_timestamp_tz",
ops.TimeFromHMS: "time_from_parts",
ops.TimestampFromYMDHMS: "timestamp_from_parts",
Expand Down
1 change: 1 addition & 0 deletions ibis/backends/sqlite/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class SQLiteCompiler(SQLGlotCompiler):
ops.Mode: "_ibis_mode",
ops.Time: "time",
ops.Date: "date",
ops.RandomUUID: "uuid",
}

def _aggregate(self, funcname: str, *args, where):
Expand Down
6 changes: 6 additions & 0 deletions ibis/backends/sqlite/udf.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from collections import defaultdict
from typing import Any, Callable, NamedTuple
from urllib.parse import parse_qs, urlsplit
from uuid import uuid4

try:
import regex as re
Expand Down Expand Up @@ -222,6 +223,11 @@ def pi():
return math.pi


@udf(skip_if_exists=True)
def uuid():
return str(uuid4())


# Additional UDFS


Expand Down
22 changes: 22 additions & 0 deletions ibis/backends/tests/test_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,25 @@ def test_uuid_literal(con, backend):

with contextlib.suppress(com.OperationNotDefinedError):
assert con.execute(expr.typeof()) == UUID_BACKEND_TYPE[backend_name]


@pytest.mark.notimpl(
[
"datafusion",
"druid",
"exasol",
"flink",
"mssql",
"mysql",
"oracle",
"polars",
"pyspark",
"risingwave",
],
raises=com.OperationNotDefinedError,
)
@pytest.mark.notimpl(["pandas", "dask"], raises=ValueError)
def test_uuid_function(con):
obj = con.execute(ibis.uuid())
assert isinstance(obj, uuid.UUID)
assert obj.version == 4
1 change: 1 addition & 0 deletions ibis/backends/trino/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class TrinoCompiler(SQLGlotCompiler):
ops.ExtractPath: "url_extract_path",
ops.ExtractFragment: "url_extract_fragment",
ops.ArrayPosition: "array_position",
ops.RandomUUID: "uuid",
}

def _aggregate(self, funcname: str, *args, where):
Expand Down
20 changes: 20 additions & 0 deletions ibis/expr/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
"trailing_range_window",
"trailing_window",
"union",
"uuid",
"watermark",
"where",
"window",
Expand Down Expand Up @@ -690,6 +691,25 @@ def random() -> ir.FloatingScalar:
return ops.RandomScalar().to_expr()


def uuid() -> ir.UUIDScalar:
"""Return a random UUID version 4 value.
Similar to [('uuid.uuid4`) in the Python standard library.
Examples
--------
>>> from ibis.interactive import *
>>> ibis.uuid() # doctest: +SKIP
UUID('e57e927b-aed2-483b-9140-dc32a26cad95')
Returns
-------
UUIDScalar
Random UUID value expression
"""
return ops.RandomUUID().to_expr()


@overload
def timestamp(
value_or_year: int | ir.IntegerValue | Deferred,
Expand Down
5 changes: 5 additions & 0 deletions ibis/expr/operations/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ class RandomScalar(Constant):
dtype = dt.float64


@public
class RandomUUID(Constant):
dtype = dt.uuid


@public
class E(Constant):
dtype = dt.float64
Expand Down
9 changes: 9 additions & 0 deletions ibis/tests/expr/test_uuid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from __future__ import annotations

import ibis


def test_uuid():
u = ibis.uuid()
assert u.type().is_uuid()
assert isinstance(u.op().shape, ibis.expr.datashape.Scalar)

0 comments on commit 733fffc

Please sign in to comment.