Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e9a2cbe
[SPARK-52407][SQL] Add support for Theta Sketch
Jun 27, 2025
5185c7f
Merge branch 'apache:master' into SPARK-52407_add_datasketches_thetas…
cboumalh Jun 27, 2025
a44a6be
added ExpressionDescription to ThetaIntersectionAgg, fixed some broke…
Jun 27, 2025
7c8e4f5
wrap array unit tests with array data to avoid casting errors test run
Jun 27, 2025
07a0c87
Update merge function parameter name in thesketchesAggregates
cboumalh Jun 27, 2025
1b3bfc8
Added Dataframes Suite, Theta Sketch Utils, sql expressions, error co…
Jul 12, 2025
edae21a
generate golden files
Jul 14, 2025
db75ca3
python functionality added
Jul 15, 2025
a892e0c
Merge branch 'master' into SPARK-52407_add_datasketches_thetasketch
cboumalh Jul 15, 2025
9e9886e
added missing builtin.py code for pyspark
Jul 15, 2025
b0d57a9
fix typos and formatting errors
Jul 15, 2025
5cca851
fix broken tests in ExpressionsSchemaSuite, PlanGenerationTestSuite, …
Jul 15, 2025
a00fdd6
add .explain files from ProtoToParsedPlanTestSuite
Jul 15, 2025
b3cb40a
typos, formatting, and naming fixes
Jul 16, 2025
2334aa1
changed theta sketch spark since version, added default sketch size t…
Jul 23, 2025
134dd29
remove unnecessary query from sql query tests
Jul 24, 2025
4928059
update to use toByteArrayCompressed, heapify in deserialization for s…
Jul 26, 2025
32a4d66
format
Jul 27, 2025
30fd361
optimize aggregating performance
Jul 27, 2025
3335453
test fix
Jul 27, 2025
5830fbc
test fix
Jul 27, 2025
41e3311
buffer empty check added
Jul 27, 2025
544079f
refactor
Jul 28, 2025
e79cf4e
Re-run checks
Jul 28, 2025
6ca7440
feature version back to 4.1.0
Jul 29, 2025
a996539
Merge branch 'master' into SPARK-52407_add_datasketches_thetasketch
cboumalh Jul 30, 2025
6548180
Merge branch 'master' into SPARK-52407_add_datasketches_thetasketch
cboumalh Jul 31, 2025
28a64a5
small refactor
Aug 8, 2025
3d00d23
small refactor
Aug 8, 2025
07da71c
fix
Aug 8, 2025
34ad644
fix
Aug 10, 2025
a80b7d4
comments fix
Aug 10, 2025
e91d702
comment fix
Aug 26, 2025
e792ac2
resolving comments
Aug 26, 2025
8905ea9
resolving comments
Aug 29, 2025
1075f6b
comment fix
Aug 29, 2025
ffd2b30
fix
Aug 29, 2025
49c88fc
fix
Aug 29, 2025
ae1f1bd
comments fix
Aug 29, 2025
8ef59e8
resolve comments
Aug 30, 2025
0ae8315
fix
Aug 30, 2025
526d791
fix
Aug 30, 2025
cc452e8
fix
Aug 30, 2025
c86c4bf
fix
Aug 30, 2025
f1669ec
fix
Sep 8, 2025
93f4a0a
fix
Sep 9, 2025
44fd9d4
fix
Sep 9, 2025
613ee05
fix
Sep 10, 2025
6c3b9bc
fix
Sep 11, 2025
b1cea44
Merge branch 'apache:master' into SPARK-52407_add_datasketches_thetas…
cboumalh Sep 14, 2025
78c6df8
fix
Sep 14, 2025
189dae6
fix
Sep 14, 2025
b1409d4
fix
Sep 14, 2025
a135d6a
fix
Sep 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 9 additions & 23 deletions python/pyspark/sql/connect/functions/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4259,60 +4259,46 @@ def theta_union_agg(

def theta_intersection_agg(
col: "ColumnOrName",
lgNomEntries: Optional[Union[int, Column]] = None,
) -> Column:
fn = "theta_intersection_agg"
if lgNomEntries is None:
return _invoke_function_over_columns(fn, col)
else:
return _invoke_function_over_columns(fn, col, lit(lgNomEntries))
return _invoke_function_over_columns(fn, col)


theta_intersection_agg.__doc__ = pysparkfuncs.theta_intersection_agg.__doc__


def theta_sketch_estimate(col: "ColumnOrName") -> Column:
fn = "theta_sketch_estimate"
return _invoke_function(fn, _to_col(col))
return _invoke_function_over_columns(fn, col)


theta_sketch_estimate.__doc__ = pysparkfuncs.theta_sketch_estimate.__doc__


def theta_union(
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[int] = None
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[Union[int, Column]] = None
) -> Column:
fn = "theta_union"
if lgNomEntries is None:
return _invoke_function(fn, _to_col(col1), _to_col(col2))
return _invoke_function_over_columns(fn, col1, col2)
else:
return _invoke_function(fn, _to_col(col1), _to_col(col2), lit(lgNomEntries))
return _invoke_function_over_columns(fn, col1, col2, lit(lgNomEntries))


theta_union.__doc__ = pysparkfuncs.theta_union.__doc__


def theta_intersection(
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[int] = None
) -> Column:
def theta_intersection(col1: "ColumnOrName", col2: "ColumnOrName") -> Column:
fn = "theta_intersection"
if lgNomEntries is None:
return _invoke_function(fn, _to_col(col1), _to_col(col2))
else:
return _invoke_function(fn, _to_col(col1), _to_col(col2), lit(lgNomEntries))
return _invoke_function_over_columns(fn, col1, col2)


theta_intersection.__doc__ = pysparkfuncs.theta_intersection.__doc__


def theta_difference(
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[int] = None
) -> Column:
def theta_difference(col1: "ColumnOrName", col2: "ColumnOrName") -> Column:
fn = "theta_difference"
if lgNomEntries is None:
return _invoke_function(fn, _to_col(col1), _to_col(col2))
else:
return _invoke_function(fn, _to_col(col1), _to_col(col2), lit(lgNomEntries))
return _invoke_function_over_columns(fn, col1, col2)


theta_difference.__doc__ = pysparkfuncs.theta_difference.__doc__
Expand Down
108 changes: 33 additions & 75 deletions python/pyspark/sql/functions/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15799,8 +15799,7 @@ def regexp_count(str: "ColumnOrName", regexp: "ColumnOrName") -> Column:

@_try_remote_functions
def regexp_extract(str: "ColumnOrName", pattern: str, idx: int) -> Column:
r"""Extract a specific group matched by the Java regex `regexp`, from the specified
string column.
r"""Extract a specific group matched by the Java regex `regexp`, from the specified string column.
Comment thread
cboumalh marked this conversation as resolved.
If the regex did not match, or the specified group did not match, an empty string is returned.

.. versionadded:: 1.5.0
Expand Down Expand Up @@ -25712,7 +25711,7 @@ def theta_sketch_agg(
) -> Column:
"""
Aggregate function: returns the compact binary representation of the Datasketches
ThetaSketch configured with lgNomEntries arg.
ThetaSketch with the values in the input column configured with lgNomEntries nominal entries.

.. versionadded:: 4.1.0

Expand Down Expand Up @@ -25769,8 +25768,7 @@ def theta_union_agg(
) -> Column:
"""
Aggregate function: returns the compact binary representation of the Datasketches
ThetaSketch, generated by merging previously created Datasketches ThetaSketch instances
via a Datasketches Union instance.
ThetaSketch that is the union of the Theta sketches in the input column.

.. versionadded:: 4.1.0

Expand Down Expand Up @@ -25815,23 +25813,16 @@ def theta_union_agg(


@_try_remote_functions
def theta_intersection_agg(
col: "ColumnOrName",
lgNomEntries: Optional[Union[int, Column]] = None,
) -> Column:
def theta_intersection_agg(col: "ColumnOrName") -> Column:
"""
Aggregate function: returns the compact binary representation of the Datasketches
ThetaSketch, generated by intersecting previously created Datasketches ThetaSketch
instances via a Datasketches Intersection instance.
ThetaSketch that is the intersection of the Theta sketches in the input column

.. versionadded:: 4.1.0

Parameters
----------
col : :class:`~pyspark.sql.Column` or column name
lgNomEntries : :class:`~pyspark.sql.Column` or int, optional
The log-base-2 of nominal entries for the intersection operation
(must be between 4 and 26, defaults to 12)

Returns
-------
Expand All @@ -25853,17 +25844,14 @@ def theta_intersection_agg(
>>> df2 = df2.agg(sf.theta_sketch_agg("value").alias("sketch"))
>>> df3 = df1.union(df2)
>>> df3.agg(sf.theta_sketch_estimate(sf.theta_intersection_agg("sketch"))).show()
+---------------------------------------------------------+
|theta_sketch_estimate(theta_intersection_agg(sketch, 12))|
+---------------------------------------------------------+
| 2|
+---------------------------------------------------------+
+-----------------------------------------------------+
|theta_sketch_estimate(theta_intersection_agg(sketch))|
+-----------------------------------------------------+
| 2|
+-----------------------------------------------------+
"""
fn = "theta_intersection_agg"
if lgNomEntries is None:
return _invoke_function_over_columns(fn, col)
else:
return _invoke_function_over_columns(fn, col, lit(lgNomEntries))
return _invoke_function_over_columns(fn, col)


@_try_remote_functions
Expand Down Expand Up @@ -25903,15 +25891,14 @@ def theta_sketch_estimate(col: "ColumnOrName") -> Column:
| 3|
+--------------------------------------------------+
"""
from pyspark.sql.classic.column import _to_java_column

fn = "theta_sketch_estimate"
return _invoke_function(fn, _to_java_column(col))
return _invoke_function_over_columns(fn, col)


@_try_remote_functions
def theta_union(
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[int] = None
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[Union[int, Column]] = None
) -> Column:
"""
Merges two binary representations of Datasketches ThetaSketch objects, using a
Expand All @@ -25923,7 +25910,7 @@ def theta_union(
----------
col1 : :class:`~pyspark.sql.Column` or column name
col2 : :class:`~pyspark.sql.Column` or column name
lgNomEntries : int, optional
lgNomEntries : :class:`~pyspark.sql.Column` or int, optional
The log-base-2 of nominal entries for the union operation
(must be between 4 and 26, defaults to 12)

Expand Down Expand Up @@ -25953,24 +25940,21 @@ def theta_union(
| 6|
+--------------------------------------------------------+
"""
from pyspark.sql.classic.column import _to_java_column

fn = "theta_union"
if lgNomEntries is not None:
return _invoke_function(
return _invoke_function_over_columns(
fn,
_to_java_column(col1),
_to_java_column(col2),
_enum_to_value(lgNomEntries),
col1,
col2,
lit(lgNomEntries),
)
else:
return _invoke_function(fn, _to_java_column(col1), _to_java_column(col2))
return _invoke_function_over_columns(fn, col1, col2)


@_try_remote_functions
def theta_intersection(
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[int] = None
) -> Column:
def theta_intersection(col1: "ColumnOrName", col2: "ColumnOrName") -> Column:
"""
Returns the intersection of two binary representations of Datasketches ThetaSketch
objects, using a Datasketches Intersection object.
Expand All @@ -25981,9 +25965,6 @@ def theta_intersection(
----------
col1 : :class:`~pyspark.sql.Column` or column name
col2 : :class:`~pyspark.sql.Column` or column name
lgNomEntries : int, optional
The log-base-2 of nominal entries for the intersection operation
(must be between 4 and 26, defaults to 12)

Returns
-------
Expand All @@ -26005,30 +25986,19 @@ def theta_intersection(
... sf.theta_sketch_agg("v2").alias("sketch2")
... )
>>> df.select(sf.theta_sketch_estimate(sf.theta_intersection(df.sketch1, "sketch2"))).show()
+---------------------------------------------------------------+
|theta_sketch_estimate(theta_intersection(sketch1, sketch2, 12))|
+---------------------------------------------------------------+
| 3|
+---------------------------------------------------------------+
+-----------------------------------------------------------+
|theta_sketch_estimate(theta_intersection(sketch1, sketch2))|
+-----------------------------------------------------------+
| 3|
+-----------------------------------------------------------+
"""
from pyspark.sql.classic.column import _to_java_column

fn = "theta_intersection"
if lgNomEntries is not None:
return _invoke_function(
fn,
_to_java_column(col1),
_to_java_column(col2),
_enum_to_value(lgNomEntries),
)
else:
return _invoke_function(fn, _to_java_column(col1), _to_java_column(col2))
return _invoke_function_over_columns(fn, col1, col2)


@_try_remote_functions
def theta_difference(
col1: "ColumnOrName", col2: "ColumnOrName", lgNomEntries: Optional[int] = None
) -> Column:
def theta_difference(col1: "ColumnOrName", col2: "ColumnOrName") -> Column:
"""
Returns the set difference of two binary representations of Datasketches ThetaSketch
objects (elements in first sketch but not in second), using a Datasketches ANotB object.
Expand All @@ -26039,9 +26009,6 @@ def theta_difference(
----------
col1 : :class:`~pyspark.sql.Column` or column name
col2 : :class:`~pyspark.sql.Column` or column name
lgNomEntries : int, optional
The log-base-2 of nominal entries for the difference operation
(must be between 4 and 26, defaults to 12)

Returns
-------
Expand All @@ -26064,24 +26031,15 @@ def theta_difference(
... sf.theta_sketch_agg("v2").alias("sketch2")
... )
>>> df.select(sf.theta_sketch_estimate(sf.theta_difference(df.sketch1, "sketch2"))).show()
+-------------------------------------------------------------+
|theta_sketch_estimate(theta_difference(sketch1, sketch2, 12))|
+-------------------------------------------------------------+
| 3|
+-------------------------------------------------------------+
+---------------------------------------------------------+
|theta_sketch_estimate(theta_difference(sketch1, sketch2))|
+---------------------------------------------------------+
| 3|
+---------------------------------------------------------+
"""
from pyspark.sql.classic.column import _to_java_column

fn = "theta_difference"
if lgNomEntries is not None:
return _invoke_function(
fn,
_to_java_column(col1),
_to_java_column(col2),
_enum_to_value(lgNomEntries),
)
else:
return _invoke_function(fn, _to_java_column(col1), _to_java_column(col2))
return _invoke_function_over_columns(fn, col1, col2)


# ---------------------- Predicates functions ------------------------------
Expand Down
Loading