From 76336f451e71bb32dbe8ce2a410112ca4d13b814 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 09:02:43 -0600 Subject: [PATCH 01/19] Added support for conditional expression functions --- CHANGELOG.md | 11 + docs/source/snowpark/functions.rst | 10 + .../snowpark/_functions/scalar_functions.py | 282 ++++++++++++++++++ 3 files changed, 303 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6757f356b..75c4c95f58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,17 @@ - Added support for `FileOperation.list` to list files in a stage with metadata. - Added support for `FileOperation.remove` to remove files in a stage. - Added support for parameter `use_vectorized_scanner` in function `Session.write_pandas()`. +- Added support for the following scalar functions in `functions.py`: + - `booland` + - `boolnot` + - `boolor` + - `boolxor` + - `decode` + - `greatest_ignore_nulls` + - `least_ignore_nulls` + - `nullif` + - `nvl2` + - `regr_valx` #### Bug Fixes diff --git a/docs/source/snowpark/functions.rst b/docs/source/snowpark/functions.rst index ce396ef74f..8cefc4788e 100644 --- a/docs/source/snowpark/functions.rst +++ b/docs/source/snowpark/functions.rst @@ -109,6 +109,10 @@ Functions bitshiftright bitxor bitxor_agg + booland + boolnot + boolor + boolxor build_stage_file_url builtin bround @@ -180,6 +184,7 @@ Functions dayofmonth dayofweek dayofyear + decode degrees dense_rank desc @@ -221,6 +226,7 @@ Functions get_ignore_case get_path greatest + greatest_ignore_nulls grouping grouping_id hash @@ -259,6 +265,7 @@ Functions last_value lead least + least_ignore_nulls left length listagg @@ -298,8 +305,10 @@ Functions not_ nth_value ntile + nullif nullifzero nvl + nvl2 object_agg object_construct object_construct_keep_null @@ -336,6 +345,7 @@ Functions regr_sxx regr_sxy regr_syy + regr_valx repeat replace right diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index a6ce9de8eb..67abf33660 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -314,3 +314,285 @@ def getbit( else None ) return builtin("getbit", _emit_ast=_emit_ast)(c, pos) + + +@publicapi +def booland(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Computes the Boolean AND of two numeric expressions. In accordance with Boolean semantics: + - Non-zero values (including negative numbers) are regarded as True. + - Zero values are regarded as False. + + As a result, the function returns: + - True if both expressions are non-zero. + - False if both expressions are zero or one expression is zero and the other expression is non-zero or NULL. + - NULL if both expressions are NULL or one expression is NULL and the other expression is non-zero. + + Example:: + + >>> df = session.create_dataframe([[1, -2], [0, 2], [0, 0], [5, 3]], schema=["a", "b"]) + >>> df.select(booland(col("a"), col("b")).alias("result")).collect() + [Row(RESULT=True), Row(RESULT=False), Row(RESULT=False), Row(RESULT=True)] + """ + c1 = _to_col_if_str(expr1, "booland") + c2 = _to_col_if_str(expr2, "booland") + return builtin("booland", _emit_ast=_emit_ast)(c1, c2) + + +@publicapi +def boolnot(e: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Computes the Boolean NOT of a single numeric expression. In accordance with Boolean semantics: + - Non-zero values (including negative numbers) are regarded as True. + - Zero values are regarded as False. + + As a result, the function returns: + - True if the expression is zero. + - False if the expression is non-zero. + - NULL if the expression is NULL. + + Args: + e: A numeric expression (Column or column name) to be evaluated. + _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + + Returns: + A `~nowflake.snowpark.column` representing the Boolean NOT of the input expression. + + Example:: + + >>> df = session.create_dataframe([0, 10, -5], schema=["a"]) + >>> df.select(boolnot("a")).collect() + [Row(BOOLNOT("A")=True), Row(BOOLNOT("A")=False), Row(BOOLNOT("A")=False)] + """ + c = _to_col_if_str(e, "boolnot") + return builtin("boolnot", _emit_ast=_emit_ast)(c) + + +@publicapi +def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Computes the Boolean OR of two numeric expressions. In accordance with Boolean semantics: + - Non-zero values (including negative numbers) are regarded as True. + - Zero values are regarded as False. + + As a result, the function returns: + - True if both expressions are non-zero or one expression is non-zero and the other expression is zero or NULL. + - False if both expressions are zero. + - NULL if both expressions are NULL or one expression is NULL and the other expression is zero. + + Args: + expr1: A :class:`Column` or column name representing the first boolean expression. + expr2: A :class:`Column` or column name representing the second boolean expression. + + Returns: + A :class:`Column` object representing the logical OR result. Returns True if either + expression is True, False if both are False, and None if either expression is None + and the other is not True. + + Example:: + + >>> df = session.create_dataframe([ + ... [1, 2], + ... [-1, 0], + ... [3, None], + ... [0, 0], + ... [None, 0], + ... [None, None] + ... ], schema=["expr1", "expr2"]) + >>> df.select(boolor(col("expr1"), col("expr2")).alias("result")).collect() + [Row(RESULT=True), Row(RESULT=True), Row(RESULT=True), Row(RESULT=False), Row(RESULT=None), Row(RESULT=None)] + """ + c1 = _to_col_if_str(expr1, "boolor") + c2 = _to_col_if_str(expr2, "boolor") + return builtin("boolor", _emit_ast=_emit_ast)(c1, c2) + + +@publicapi +def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Computes the Boolean XOR of two numeric expressions (i.e. one of the expressions, but not both expressions, is TRUE). + In accordance with Boolean semantics: + - Non-zero values (including negative numbers) are regarded as True. + - Zero values are regarded as False. + + As a result, the function returns: + - True if one expression is non-zero and the other expression is zero. + - False if both expressions are non-zero or both expressions are zero. + - NULL if one or both expressions are NULL. + + Args: + expr1: First numeric expression or a string name of the column. + expr2: Second numeric expression or a string name of the column. + _emit_ast: Whether to emit the AST for this function. This is for internal use only. + + Example:: + + >>> df = session.create_dataframe([[2, 0], [1, -1], [0, 0], [None, 3]], schema=["a", "b"]) + >>> df.select(boolxor(col("a"), col("b")).alias("result")).collect() + [Row(RESULT=True), Row(RESULT=False), Row(RESULT=False), Row(RESULT=None)] + """ + c1 = _to_col_if_str(expr1, "boolxor") + c2 = _to_col_if_str(expr2, "boolxor") + return builtin("boolxor", _emit_ast=_emit_ast)(c1, c2) + + +@publicapi +def decode(expr: ColumnOrName, *args: ColumnOrName, _emit_ast: bool = True) -> Column: + """Decodes an expression by comparing it with search values and returning corresponding result values. + + Similar to a Case statement, this function compares an expression to one or more search values + and returns the corresponding result when a match is found. + + Args: + expr (ColumnOrName): The expression to decode. Can be a Column or column name string. + *args (ColumnOrName): Variable length argument list containing pairs of search values and + result values, with an optional default value at the end. + _emit_ast (bool, optional): Internal parameter for AST generation. Defaults to True. + + Returns: + Column: A Column object representing the decoded result. + + Example: + + >>> df = session.create_dataframe([[1, 1], [2, 4], [16, 24]], schema=["a", "b"]) + >>> df.select(decode(col("a"), lit(1), lit("one"), lit(2), lit("two"), lit("default")).alias("RESULT")).collect() + [Row(RESULT='one'), Row(RESULT='two'), Row(RESULT='default')] + """ + expr_col = _to_col_if_str(expr, "decode") + arg_cols = [_to_col_if_str(arg, "decode") for arg in args] + return builtin("decode", _emit_ast=_emit_ast)(expr_col, *arg_cols) + + +@publicapi +def greatest_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Returns the largest value from a list of expressions, ignoring NULL values. + If all argument values are NULL, the result is NULL. + + Args: + columns (ColumnOrName): A variable number of Column or column name strings to compare. + _emit_ast (bool, optional): Internal parameter for AST generation. Defaults to True. + + Returns: + Column: A `~snowflake.snowpark.Column` object representing the greatest value, ignoring NULLs. + + Examples:: + + >>> df = session.create_dataframe([[1, 2, 3, 4.25], [2, 4, -1, None], [3, 6, None, -2.75]], schema=["a", "b", "c", "d"]) + >>> df.select(greatest_ignore_nulls(df["a"], df["b"], df["c"], df["d"]).alias("greatest_ignore_nulls")).collect() + [Row(GREATEST_IGNORE_NULLS=4.25), Row(GREATEST_IGNORE_NULLS=4.0), Row(GREATEST_IGNORE_NULLS=6.0)] + """ + c = [_to_col_if_str(ex, "greatest_ignore_nulls") for ex in columns] + return builtin("greatest_ignore_nulls", _emit_ast=_emit_ast)(*c) + + +@publicapi +def least_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Returns the smallest value from a list of expressions, ignoring NULL values. + If all argument values are NULL, the result is NULL. + + Args: + columns: list of :class:`Column` or column names to compare. + _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + + Returns: + :class:`Column`: A column containing the smallest value from the list of expressions, ignoring NULL values. + + Example:: + + >>> df = session.create_dataframe([[1, 2, 3], [2, 4, -1], [3, 6, None]], schema=["a", "b", "c"]) + >>> df.select(least_ignore_nulls(df["a"], df["b"], df["c"]).alias("least_ignore_nulls")).collect() + [Row(LEAST_IGNORE_NULLS=1), Row(LEAST_IGNORE_NULLS=-1), Row(LEAST_IGNORE_NULLS=3)] + """ + c = [_to_col_if_str(ex, "least_ignore_nulls") for ex in columns] + return builtin("least_ignore_nulls", _emit_ast=_emit_ast)(*c) + + +@publicapi +def nullif(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Returns NULL if expr1 is equal to expr2, otherwise returns expr1. + + Args: + expr1: The first expression to compare. Can be a :class:`Column` or a column name. + expr2: The second expression to compare. Can be a :class:`Column` or a column name. + _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + + Returns: + :class:`Column`: A column containing NULL if expr1 is equal to expr2, otherwise expr1. + + Example:: + + >>> df = session.create_dataframe([[0, 0], [0, 1], [1, 0], [1, 1], [None, 0]], schema=["a", "b"]) + >>> df.select(nullif(df["a"], df["b"]).alias("result")).collect() + [Row(RESULT=None), Row(RESULT=0), Row(RESULT=1), Row(RESULT=None), Row(RESULT=None)] + """ + c1 = _to_col_if_str(expr1, "nullif") + c2 = _to_col_if_str(expr2, "nullif") + return builtin("nullif", _emit_ast=_emit_ast)(c1, c2) + + +@publicapi +def nvl2( + expr1: ColumnOrName, + expr2: ColumnOrName, + expr3: ColumnOrName, + _emit_ast: bool = True, +) -> Column: + """ + Returns expr2 if expr1 is not NULL, otherwise returns expr3. + + Args: + expr1: The expression to test for NULL. + expr2: The value to return if expr1 is not NULL. + expr3: The value to return if expr1 is NULL. + _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + + Returns: + A :class:`Column` representing the result of the nvl2 function. + + Example:: + + >>> from snowflake.snowpark.functions import col + >>> df = session.create_dataframe([ + ... [0, 5, 3], + ... [0, 5, None], + ... [0, None, 3], + ... [None, 5, 3], + ... [None, None, 3] + ... ], schema=["a", "b", "c"]) + >>> df.select(nvl2(col("a"), col("b"), col("c")).alias("nvl2_result")).collect() + [Row(NVL2_RESULT=5), Row(NVL2_RESULT=5), Row(NVL2_RESULT=None), Row(NVL2_RESULT=3), Row(NVL2_RESULT=3)] + """ + c1 = _to_col_if_str(expr1, "nvl2") + c2 = _to_col_if_str(expr2, "nvl2") + c3 = _to_col_if_str(expr3, "nvl2") + return builtin("nvl2", _emit_ast=_emit_ast)(c1, c2, c3) + + +@publicapi +def regr_valx(y: ColumnOrName, x: ColumnOrName, _emit_ast: bool = True) -> Column: + """ + Returns NULL if the first argument is NULL; otherwise, returns the second argument. + Note that REGR_VALX is a NULL-preserving function, while the more commonly-used NVL is a NULL-replacing function. + + Args: + y: The dependent variable column. + x: The independent variable column. + _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + + Returns: + A :class:`Column` representing the result of the regr_valx function. + + Example:: + + >>> df = session.create_dataframe([[2.0, 1.0], [None, 3.0], [6.0, None]], schema=["col_y", "col_x"]) + >>> result = df.select(regr_valx(df["col_y"], df["col_x"]).alias("result")).collect() + >>> assert result == [Row(RESULT=1.0), Row(RESULT=None), Row(RESULT=None)] + + Important: Note the order of the arguments; y precedes x + """ + y_col = _to_col_if_str(y, "regr_valx") + x_col = _to_col_if_str(x, "regr_valx") + return builtin("regr_valx", _emit_ast=_emit_ast)(y_col, x_col) From 793608921dc3edcc07c54671d546fc6de806a11e Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 10:03:23 -0600 Subject: [PATCH 02/19] Fix tests --- src/snowflake/snowpark/_functions/scalar_functions.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 67abf33660..4f579a606c 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -330,6 +330,7 @@ def booland(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Example:: + >>> from snowflake.snowpark.functions import col >>> df = session.create_dataframe([[1, -2], [0, 2], [0, 0], [5, 3]], schema=["a", "b"]) >>> df.select(booland(col("a"), col("b")).alias("result")).collect() [Row(RESULT=True), Row(RESULT=False), Row(RESULT=False), Row(RESULT=True)] @@ -391,6 +392,7 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Example:: + >>> from snowflake.snowpark.functions import col >>> df = session.create_dataframe([ ... [1, 2], ... [-1, 0], @@ -427,6 +429,7 @@ def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Example:: + >>> from snowflake.snowpark.functions import col >>> df = session.create_dataframe([[2, 0], [1, -1], [0, 0], [None, 3]], schema=["a", "b"]) >>> df.select(boolxor(col("a"), col("b")).alias("result")).collect() [Row(RESULT=True), Row(RESULT=False), Row(RESULT=False), Row(RESULT=None)] @@ -454,6 +457,7 @@ def decode(expr: ColumnOrName, *args: ColumnOrName, _emit_ast: bool = True) -> C Example: + >>> from snowflake.snowpark.functions import col, lit >>> df = session.create_dataframe([[1, 1], [2, 4], [16, 24]], schema=["a", "b"]) >>> df.select(decode(col("a"), lit(1), lit("one"), lit(2), lit("two"), lit("default")).alias("RESULT")).collect() [Row(RESULT='one'), Row(RESULT='two'), Row(RESULT='default')] @@ -587,6 +591,7 @@ def regr_valx(y: ColumnOrName, x: ColumnOrName, _emit_ast: bool = True) -> Colum Example:: + >>> from snowflake.snowpark import Row >>> df = session.create_dataframe([[2.0, 1.0], [None, 3.0], [6.0, None]], schema=["col_y", "col_x"]) >>> result = df.select(regr_valx(df["col_y"], df["col_x"]).alias("result")).collect() >>> assert result == [Row(RESULT=1.0), Row(RESULT=None), Row(RESULT=None)] From 749ba798c8b7ae521823496f884ef337d1fe214c Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 10:04:19 -0600 Subject: [PATCH 03/19] Update src/snowflake/snowpark/_functions/scalar_functions.py Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> --- src/snowflake/snowpark/_functions/scalar_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 4f579a606c..45c84e0f78 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -357,7 +357,7 @@ def boolnot(e: ColumnOrName, _emit_ast: bool = True) -> Column: _emit_ast: Whether to emit the AST node for this function. This is for internal use only. Returns: - A `~nowflake.snowpark.column` representing the Boolean NOT of the input expression. + A `~snowflake.snowpark.column` representing the Boolean NOT of the input expression. Example:: From 25808703f8558eef060414879adb8fd601051aa1 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 10:24:05 -0600 Subject: [PATCH 04/19] Update src/snowflake/snowpark/_functions/scalar_functions.py Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> --- src/snowflake/snowpark/_functions/scalar_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 45c84e0f78..f61f10544d 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -578,7 +578,7 @@ def nvl2( @publicapi def regr_valx(y: ColumnOrName, x: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Returns NULL if the first argument is NULL; otherwise, returns the second argument. + Returns NULL if either argument is NULL; otherwise, returns the second argument. Note that REGR_VALX is a NULL-preserving function, while the more commonly-used NVL is a NULL-replacing function. Args: From dbdd8ad606ee553b436021735bf423f8bf374d58 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 11:48:55 -0600 Subject: [PATCH 05/19] Update src/snowflake/snowpark/_functions/scalar_functions.py Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> --- src/snowflake/snowpark/_functions/scalar_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index f61f10544d..6c767690ea 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -377,7 +377,7 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> - Zero values are regarded as False. As a result, the function returns: - - True if both expressions are non-zero or one expression is non-zero and the other expression is zero or NULL. + - True if both expressions are non-zero or one expression is non-zero and the other expression is zero. - False if both expressions are zero. - NULL if both expressions are NULL or one expression is NULL and the other expression is zero. From 528b7e5a7136f175922ad53988e5158d4b921ffb Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 14:15:35 -0600 Subject: [PATCH 06/19] Fix boolor documentation. --- src/snowflake/snowpark/_functions/scalar_functions.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 6c767690ea..b64e7bd11f 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -377,18 +377,16 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> - Zero values are regarded as False. As a result, the function returns: - - True if both expressions are non-zero or one expression is non-zero and the other expression is zero. + - True if both expressions are non-zero or one expression is non-zero and the other expression is zero or None. - False if both expressions are zero. - - NULL if both expressions are NULL or one expression is NULL and the other expression is zero. + - None if both expressions are None or one expression is None and the other expression is zero. Args: expr1: A :class:`Column` or column name representing the first boolean expression. expr2: A :class:`Column` or column name representing the second boolean expression. Returns: - A :class:`Column` object representing the logical OR result. Returns True if either - expression is True, False if both are False, and None if either expression is None - and the other is not True. + A :class:`Column` object representing the logical OR result. Example:: From 96a02883353f5da87e372fb85e6f21405968c634 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 15:56:29 -0600 Subject: [PATCH 07/19] Update boolxor indentation. --- src/snowflake/snowpark/_functions/scalar_functions.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index b64e7bd11f..2864233e1d 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -414,19 +414,15 @@ def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> In accordance with Boolean semantics: - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. - As a result, the function returns: - True if one expression is non-zero and the other expression is zero. - False if both expressions are non-zero or both expressions are zero. - NULL if one or both expressions are NULL. - Args: expr1: First numeric expression or a string name of the column. expr2: Second numeric expression or a string name of the column. _emit_ast: Whether to emit the AST for this function. This is for internal use only. - Example:: - >>> from snowflake.snowpark.functions import col >>> df = session.create_dataframe([[2, 0], [1, -1], [0, 0], [None, 3]], schema=["a", "b"]) >>> df.select(boolxor(col("a"), col("b")).alias("result")).collect() From aab65217f69e33a90a686fd7375ee478c57a6e31 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 16:08:08 -0600 Subject: [PATCH 08/19] Update comment --- src/snowflake/snowpark/_functions/scalar_functions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 1402bb365d..669afb15ec 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -627,14 +627,16 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> @publicapi def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Computes the Boolean XOR of two numeric expressions (i.e. one of the expressions, but not both expressions, is TRUE). + Computes the Boolean XOR of two numeric expressions (i.e. one of the expressions, but not both expressions, is True). In accordance with Boolean semantics: - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. + As a result, the function returns: - True if one expression is non-zero and the other expression is zero. - False if both expressions are non-zero or both expressions are zero. - NULL if one or both expressions are NULL. + Args: expr1: First numeric expression or a string name of the column. expr2: Second numeric expression or a string name of the column. From 8475da4c75d76ff043bb05585a76b2b1894581b7 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 22:06:59 -0600 Subject: [PATCH 09/19] Fix indentation docstring --- src/snowflake/snowpark/_functions/scalar_functions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 669afb15ec..a0d8133594 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -627,8 +627,7 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> @publicapi def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Computes the Boolean XOR of two numeric expressions (i.e. one of the expressions, but not both expressions, is True). - In accordance with Boolean semantics: + Computes the Boolean XOR of two numeric expressions (i.e. one of the expressions, but not both expressions, is True). In accordance with Boolean semantics: - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. From ba654bf2d45895189ac96cd875f0ee93f822ea44 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 11 Sep 2025 22:18:05 -0600 Subject: [PATCH 10/19] Update boolor docstring --- src/snowflake/snowpark/_functions/scalar_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index a0d8133594..88a2812551 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -594,9 +594,9 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> - Zero values are regarded as False. As a result, the function returns: - - True if both expressions are non-zero or one expression is non-zero and the other expression is zero or None. + - True if both expressions are non-zero or the first expression is non-zero and the second expression is zero or None. - False if both expressions are zero. - - None if both expressions are None or one expression is None and the other expression is zero. + - None if both expressions are None or the first expression is None and the second expression is zero. Args: expr1: A :class:`Column` or column name representing the first boolean expression. From be97a7eece6e066eba86adae43ce40f48447dc5b Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Tue, 16 Sep 2025 12:19:57 -0600 Subject: [PATCH 11/19] Update docstrings --- .../snowpark/_functions/scalar_functions.py | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 88a2812551..0a87edc859 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -540,13 +540,17 @@ def booland(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. - As a result, the function returns: + Args: + expr1 (ColumnOrName): The first boolean expression. + expr2 (ColumnOrName): The second boolean expression. + _emit_ast (bool, optional): Whether to emit the AST for this function. This is for internal use only. + + Returns: - True if both expressions are non-zero. - False if both expressions are zero or one expression is zero and the other expression is non-zero or NULL. - NULL if both expressions are NULL or one expression is NULL and the other expression is non-zero. Example:: - >>> from snowflake.snowpark.functions import col >>> df = session.create_dataframe([[1, -2], [0, 2], [0, 0], [5, 3]], schema=["a", "b"]) >>> df.select(booland(col("a"), col("b")).alias("result")).collect() @@ -564,17 +568,14 @@ def boolnot(e: ColumnOrName, _emit_ast: bool = True) -> Column: - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. - As a result, the function returns: - - True if the expression is zero. - - False if the expression is non-zero. - - NULL if the expression is NULL. - Args: - e: A numeric expression (Column or column name) to be evaluated. - _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + e (ColumnOrName): A numeric expression to be evaluated. + _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Defaults to True. Returns: - A `~snowflake.snowpark.column` representing the Boolean NOT of the input expression. + - True if the expression is zero. + - False if the expression is non-zero. + - NULL if the expression is NULL. Example:: @@ -593,17 +594,15 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. - As a result, the function returns: - - True if both expressions are non-zero or the first expression is non-zero and the second expression is zero or None. - - False if both expressions are zero. - - None if both expressions are None or the first expression is None and the second expression is zero. - Args: - expr1: A :class:`Column` or column name representing the first boolean expression. - expr2: A :class:`Column` or column name representing the second boolean expression. + expr1 (ColumnOrName): The first boolean expression. + expr2 (ColumnOrName): The second boolean expression. + _emit_ast (bool, optional): Whether to emit the AST for this function. This is for internal use only. Returns: - A :class:`Column` object representing the logical OR result. + - True if both expressions are non-zero or the first expression is non-zero and the second expression is zero or None. + - False if both expressions are zero. + - None if both expressions are None or the first expression is None and the second expression is zero. Example:: @@ -631,15 +630,16 @@ def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> - Non-zero values (including negative numbers) are regarded as True. - Zero values are regarded as False. - As a result, the function returns: - - True if one expression is non-zero and the other expression is zero. - - False if both expressions are non-zero or both expressions are zero. - - NULL if one or both expressions are NULL. - Args: - expr1: First numeric expression or a string name of the column. - expr2: Second numeric expression or a string name of the column. - _emit_ast: Whether to emit the AST for this function. This is for internal use only. + expr1 (ColumnOrName): First numeric expression or a string name of the column. + expr2 (ColumnOrName): Second numeric expression or a string name of the column. + _emit_ast (bool, optional): Whether to emit the AST for this function. This is for internal use only. + + Returns: + - True if exactly one of the expressions is non-zero. + - False if both expressions are zero or both expressions are non-zero. + - NULL if both expressions are NULL, or one expression is NULL and the other expression is zero. + Example:: >>> from snowflake.snowpark.functions import col >>> df = session.create_dataframe([[2, 0], [1, -1], [0, 0], [None, 3]], schema=["a", "b"]) @@ -690,7 +690,7 @@ def greatest_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Col _emit_ast (bool, optional): Internal parameter for AST generation. Defaults to True. Returns: - Column: A `~snowflake.snowpark.Column` object representing the greatest value, ignoring NULLs. + Column: A column object representing the greatest value, ignoring NULLs. Examples:: @@ -709,11 +709,11 @@ def least_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column If all argument values are NULL, the result is NULL. Args: - columns: list of :class:`Column` or column names to compare. - _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + columns (ColumnOrName): list of column or column names to compare. + _emit_ast (ColumnOrName): Whether to emit the AST node for this function. This is for internal use only. Returns: - :class:`Column`: A column containing the smallest value from the list of expressions, ignoring NULL values. + A column containing the smallest value from the list of expressions, ignoring NULL values. Example:: @@ -731,12 +731,12 @@ def nullif(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Returns NULL if expr1 is equal to expr2, otherwise returns expr1. Args: - expr1: The first expression to compare. Can be a :class:`Column` or a column name. - expr2: The second expression to compare. Can be a :class:`Column` or a column name. - _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + expr1 (ColumnOrName): The first expression to compare. Can be a :class:`Column` or a column name. + expr2 (ColumnOrName): The second expression to compare. Can be a :class:`Column` or a column name. + _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Returns: - :class:`Column`: A column containing NULL if expr1 is equal to expr2, otherwise expr1. + A column containing NULL if expr1 is equal to expr2, otherwise expr1. Example:: @@ -760,13 +760,13 @@ def nvl2( Returns expr2 if expr1 is not NULL, otherwise returns expr3. Args: - expr1: The expression to test for NULL. - expr2: The value to return if expr1 is not NULL. - expr3: The value to return if expr1 is NULL. - _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + expr1 (ColumnOrName): The expression to test for NULL. + expr2 (ColumnOrName): The value to return if expr1 is not NULL. + expr3 (ColumnOrName): The value to return if expr1 is NULL. + _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Returns: - A :class:`Column` representing the result of the nvl2 function. + A column representing the result of the nvl2 function. Example:: @@ -794,12 +794,12 @@ def regr_valx(y: ColumnOrName, x: ColumnOrName, _emit_ast: bool = True) -> Colum Note that REGR_VALX is a NULL-preserving function, while the more commonly-used NVL is a NULL-replacing function. Args: - y: The dependent variable column. - x: The independent variable column. - _emit_ast: Whether to emit the AST node for this function. This is for internal use only. + y (ColumnOrName): The dependent variable column. + x (ColumnOrName): The independent variable column. + _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Returns: - A :class:`Column` representing the result of the regr_valx function. + A column representing the result of the regr_valx function. Example:: From 2912f301b52d1a2761f887e6e8025c3ae38210d7 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Tue, 16 Sep 2025 12:23:22 -0600 Subject: [PATCH 12/19] Update changelog --- CHANGELOG.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57d6075161..566701f377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,26 +18,26 @@ - Added a new function `snowflake.snowpark.functions.vectorized` that allows users to mark a function as vectorized UDF. - Added support for parameter `use_vectorized_scanner` in function `Session.write_pandas()`. - Added support for the following scalar functions in `functions.py`: - - `getdate` - - `getvariable` - - `invoker_role` - - `invoker_share` - - `is_application_role_in_session` - - `is_database_role_in_session` - - `is_granted_to_invoker_role` - - `is_role_in_session` - - `localtime` - - `systimestamp` - - `booland` - - `boolnot` - - `boolor` - - `boolxor` - - `decode` - - `greatest_ignore_nulls` - - `least_ignore_nulls` - - `nullif` - - `nvl2` - - `regr_valx` +- `booland` +- `boolnot` +- `boolor` +- `boolxor` +- `decode` +- `getdate` +- `getvariable` +- `greatest_ignore_nulls` +- `invoker_role` +- `invoker_share` +- `is_application_role_in_session` +- `is_database_role_in_session` +- `is_granted_to_invoker_role` +- `is_role_in_session` +- `least_ignore_nulls` +- `localtime` +- `nullif` +- `nvl2` +- `regr_valx` +- `systimestamp` #### Bug Fixes From 9ba61d173797bc7edd2741066332d4f6e5a98147 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Tue, 16 Sep 2025 16:11:14 -0600 Subject: [PATCH 13/19] Update docstrings --- .../snowpark/_functions/scalar_functions.py | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 0a87edc859..8601c58bb5 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -543,7 +543,6 @@ def booland(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Args: expr1 (ColumnOrName): The first boolean expression. expr2 (ColumnOrName): The second boolean expression. - _emit_ast (bool, optional): Whether to emit the AST for this function. This is for internal use only. Returns: - True if both expressions are non-zero. @@ -570,7 +569,6 @@ def boolnot(e: ColumnOrName, _emit_ast: bool = True) -> Column: Args: e (ColumnOrName): A numeric expression to be evaluated. - _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Defaults to True. Returns: - True if the expression is zero. @@ -597,7 +595,6 @@ def boolor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Args: expr1 (ColumnOrName): The first boolean expression. expr2 (ColumnOrName): The second boolean expression. - _emit_ast (bool, optional): Whether to emit the AST for this function. This is for internal use only. Returns: - True if both expressions are non-zero or the first expression is non-zero and the second expression is zero or None. @@ -633,7 +630,6 @@ def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Args: expr1 (ColumnOrName): First numeric expression or a string name of the column. expr2 (ColumnOrName): Second numeric expression or a string name of the column. - _emit_ast (bool, optional): Whether to emit the AST for this function. This is for internal use only. Returns: - True if exactly one of the expressions is non-zero. @@ -659,13 +655,13 @@ def decode(expr: ColumnOrName, *args: ColumnOrName, _emit_ast: bool = True) -> C and returns the corresponding result when a match is found. Args: - expr (ColumnOrName): The expression to decode. Can be a Column or column name string. + expr (ColumnOrName): The expression to decode. *args (ColumnOrName): Variable length argument list containing pairs of search values and result values, with an optional default value at the end. - _emit_ast (bool, optional): Internal parameter for AST generation. Defaults to True. + Returns: - Column: A Column object representing the decoded result. + Column: The decoded result. Example: @@ -686,11 +682,10 @@ def greatest_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Col If all argument values are NULL, the result is NULL. Args: - columns (ColumnOrName): A variable number of Column or column name strings to compare. - _emit_ast (bool, optional): Internal parameter for AST generation. Defaults to True. + columns (ColumnOrName): The name strings to compare. Returns: - Column: A column object representing the greatest value, ignoring NULLs. + Column: The greatest value, ignoring NULLs. Examples:: @@ -710,10 +705,9 @@ def least_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column Args: columns (ColumnOrName): list of column or column names to compare. - _emit_ast (ColumnOrName): Whether to emit the AST node for this function. This is for internal use only. Returns: - A column containing the smallest value from the list of expressions, ignoring NULL values. + Column: The smallest value from the list of expressions, ignoring NULL values. Example:: @@ -731,12 +725,11 @@ def nullif(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Returns NULL if expr1 is equal to expr2, otherwise returns expr1. Args: - expr1 (ColumnOrName): The first expression to compare. Can be a :class:`Column` or a column name. - expr2 (ColumnOrName): The second expression to compare. Can be a :class:`Column` or a column name. - _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. + expr1 (ColumnOrName): The first expression to compare. + expr2 (ColumnOrName): The second expression to compare. Returns: - A column containing NULL if expr1 is equal to expr2, otherwise expr1. + Column: NULL if expr1 is equal to expr2, otherwise expr1. Example:: @@ -763,10 +756,9 @@ def nvl2( expr1 (ColumnOrName): The expression to test for NULL. expr2 (ColumnOrName): The value to return if expr1 is not NULL. expr3 (ColumnOrName): The value to return if expr1 is NULL. - _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Returns: - A column representing the result of the nvl2 function. + Column: The result of the nvl2 function. Example:: @@ -796,10 +788,9 @@ def regr_valx(y: ColumnOrName, x: ColumnOrName, _emit_ast: bool = True) -> Colum Args: y (ColumnOrName): The dependent variable column. x (ColumnOrName): The independent variable column. - _emit_ast (bool, optional): Whether to emit the AST node for this function. This is for internal use only. Returns: - A column representing the result of the regr_valx function. + Column: The result of the regr_valx function. Example:: From efe000ec7a37fe2c16749b535b7a5c36450107a1 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 18 Sep 2025 09:47:46 -0600 Subject: [PATCH 14/19] Fix local test --- tests/mock/test_functions.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/mock/test_functions.py b/tests/mock/test_functions.py index c09f9fbcce..df70994af6 100644 --- a/tests/mock/test_functions.py +++ b/tests/mock/test_functions.py @@ -340,11 +340,11 @@ def test_patch_unsupported_function(session): df = session.create_dataframe([[3, 1], [3, 2], [4, 3]], schema=["a", "b"]) with pytest.raises(NotImplementedError): df.select( - call_function("greatest_ignore_nulls", df["a"], df["b"]).alias("greatest") + call_function("my_function", df["a"], df["b"]).alias("greatest") ).collect() - @patch("greatest_ignore_nulls") - def mock_greatest_ignore_nulls( + @patch("my_mocked_function") + def mock_my_mocked_function( *columns: Iterable[ColumnEmulator], ) -> ColumnEmulator: return ColumnEmulator( @@ -352,10 +352,10 @@ def mock_greatest_ignore_nulls( ) assert df.select( - call_function("greatest_ignore_nulls", df["a"], df["b"]).alias("greatest") + call_function("my_mocked_function", df["a"], df["b"]).alias("greatest") ).collect() == [Row(1), Row(1), Row(1)] - @patch("greatest_ignore_nulls") + @patch("my_mocked_function_2") def mock_wrong_patch(columns: Iterable[ColumnEmulator]) -> ColumnEmulator: return ColumnEmulator( [1] * len(columns[0]), sf_type=ColumnType(IntegerType(), False) @@ -363,7 +363,7 @@ def mock_wrong_patch(columns: Iterable[ColumnEmulator]) -> ColumnEmulator: with pytest.raises(SnowparkLocalTestingException) as exc: df.select( - call_function("greatest_ignore_nulls", df["a"], df["b"]).alias("greatest") + call_function("my_mocked_function_2", df["a"], df["b"]).alias("greatest") ).collect() assert "Please ensure the implementation follows specifications" in str(exc.value) From bd5c5e11572b1fda4d690ab9118d8b30253da4b2 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 18 Sep 2025 09:54:04 -0600 Subject: [PATCH 15/19] update changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0af760efed..cbe2e93f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,17 @@ #### Improvements - Hybrid execution mode is now enabled by default. Certain operations on smaller data will now automatically execute in native pandas in-memory. Use `from modin.config import AutoSwitchBackend; AutoSwitchBackend.disable()` to turn this off and force all execution to occur in Snowflake. - Removed an unnecessary `SHOW OBJECTS` query issued from `read_snowflake` under certain conditions. +- Added support for the following scalar functions in `functions.py`: + - `booland` + - `boolnot` + - `boolor` + - `boolxor` + - `decode` + - `greatest_ignore_nulls` + - `least_ignore_nulls` + - `nullif` + - `nvl2` + - `regr_valx` ## 1.39.0 (2025-09-17) From 6c9a693fe7ed98830189e36ca9e596e04fdeefab Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 18 Sep 2025 09:56:32 -0600 Subject: [PATCH 16/19] update changelog --- CHANGELOG.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbe2e93f67..2869251ef4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,25 +61,15 @@ - Added a new function `snowflake.snowpark.functions.vectorized` that allows users to mark a function as vectorized UDF. - Added support for parameter `use_vectorized_scanner` in function `Session.write_pandas()`. - Added support for the following scalar functions in `functions.py`: -- `booland` -- `boolnot` -- `boolor` -- `boolxor` -- `decode` - `getdate` - `getvariable` -- `greatest_ignore_nulls` - `invoker_role` - `invoker_share` - `is_application_role_in_session` - `is_database_role_in_session` - `is_granted_to_invoker_role` - `is_role_in_session` -- `least_ignore_nulls` - `localtime` -- `nullif` -- `nvl2` -- `regr_valx` - `systimestamp` #### Bug Fixes From ff33709bb43f947cb7d82c8e2b1ec3c5d2d1f6f5 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 18 Sep 2025 09:57:49 -0600 Subject: [PATCH 17/19] update changelog --- CHANGELOG.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2869251ef4..340f36a711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,16 +61,16 @@ - Added a new function `snowflake.snowpark.functions.vectorized` that allows users to mark a function as vectorized UDF. - Added support for parameter `use_vectorized_scanner` in function `Session.write_pandas()`. - Added support for the following scalar functions in `functions.py`: -- `getdate` -- `getvariable` -- `invoker_role` -- `invoker_share` -- `is_application_role_in_session` -- `is_database_role_in_session` -- `is_granted_to_invoker_role` -- `is_role_in_session` -- `localtime` -- `systimestamp` + - `getdate` + - `getvariable` + - `invoker_role` + - `invoker_share` + - `is_application_role_in_session` + - `is_database_role_in_session` + - `is_granted_to_invoker_role` + - `is_role_in_session` + - `localtime` + - `systimestamp` #### Bug Fixes From 5e8212d66f7025c23f7b6291228efc40795dd72e Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 18 Sep 2025 10:07:21 -0600 Subject: [PATCH 18/19] update docstring --- .../snowpark/_functions/scalar_functions.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/snowflake/snowpark/_functions/scalar_functions.py b/src/snowflake/snowpark/_functions/scalar_functions.py index 8601c58bb5..e0bd5ab8dd 100644 --- a/src/snowflake/snowpark/_functions/scalar_functions.py +++ b/src/snowflake/snowpark/_functions/scalar_functions.py @@ -634,7 +634,7 @@ def boolxor(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Returns: - True if exactly one of the expressions is non-zero. - False if both expressions are zero or both expressions are non-zero. - - NULL if both expressions are NULL, or one expression is NULL and the other expression is zero. + - None if both expressions are None, or one expression is None and the other expression is zero. Example:: >>> from snowflake.snowpark.functions import col @@ -678,14 +678,14 @@ def decode(expr: ColumnOrName, *args: ColumnOrName, _emit_ast: bool = True) -> C @publicapi def greatest_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Returns the largest value from a list of expressions, ignoring NULL values. - If all argument values are NULL, the result is NULL. + Returns the largest value from a list of expressions, ignoring None values. + If all argument values are None, the result is None. Args: columns (ColumnOrName): The name strings to compare. Returns: - Column: The greatest value, ignoring NULLs. + Column: The greatest value, ignoring None values. Examples:: @@ -700,14 +700,14 @@ def greatest_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Col @publicapi def least_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Returns the smallest value from a list of expressions, ignoring NULL values. - If all argument values are NULL, the result is NULL. + Returns the smallest value from a list of expressions, ignoring None values. + If all argument values are None, the result is None. Args: columns (ColumnOrName): list of column or column names to compare. Returns: - Column: The smallest value from the list of expressions, ignoring NULL values. + Column: The smallest value from the list of expressions, ignoring None values. Example:: @@ -722,14 +722,14 @@ def least_ignore_nulls(*columns: ColumnOrName, _emit_ast: bool = True) -> Column @publicapi def nullif(expr1: ColumnOrName, expr2: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Returns NULL if expr1 is equal to expr2, otherwise returns expr1. + Returns None if expr1 is equal to expr2, otherwise returns expr1. Args: expr1 (ColumnOrName): The first expression to compare. expr2 (ColumnOrName): The second expression to compare. Returns: - Column: NULL if expr1 is equal to expr2, otherwise expr1. + Column: None if expr1 is equal to expr2, otherwise expr1. Example:: @@ -750,12 +750,12 @@ def nvl2( _emit_ast: bool = True, ) -> Column: """ - Returns expr2 if expr1 is not NULL, otherwise returns expr3. + Returns expr2 if expr1 is not None, otherwise returns expr3. Args: - expr1 (ColumnOrName): The expression to test for NULL. - expr2 (ColumnOrName): The value to return if expr1 is not NULL. - expr3 (ColumnOrName): The value to return if expr1 is NULL. + expr1 (ColumnOrName): The expression to test for None. + expr2 (ColumnOrName): The value to return if expr1 is not None. + expr3 (ColumnOrName): The value to return if expr1 is None. Returns: Column: The result of the nvl2 function. @@ -782,8 +782,8 @@ def nvl2( @publicapi def regr_valx(y: ColumnOrName, x: ColumnOrName, _emit_ast: bool = True) -> Column: """ - Returns NULL if either argument is NULL; otherwise, returns the second argument. - Note that REGR_VALX is a NULL-preserving function, while the more commonly-used NVL is a NULL-replacing function. + Returns None if either argument is None; otherwise, returns the second argument. + Note that REGR_VALX is a None-preserving function, while the more commonly-used NVL is a None-replacing function. Args: y (ColumnOrName): The dependent variable column. From bc1b3cec9a563ea510bdf6ea074c42005edc8461 Mon Sep 17 00:00:00 2001 From: Arturo Herrera Aguilar Date: Thu, 18 Sep 2025 20:56:00 -0600 Subject: [PATCH 19/19] Update changelog --- CHANGELOG.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7276f01c5..14cbe060d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,11 +20,17 @@ - Added support for the following scalar functions in `functions.py`: - `array_remove_at` - `as_boolean` + - `booland` + - `boolnot` + - `boolor` - `boolor_agg` + - `boolxor` - `chr` + - `decode` - `div0null` - `dp_interval_high` - `dp_interval_low` + - `greatest_ignore_nulls` - `h3_cell_to_boundary` - `h3_cell_to_parent` - `h3_cell_to_point` @@ -38,6 +44,11 @@ - `hex_decode_binary` - `last_query_id` - `last_transaction` + - `least_ignore_nulls` + - `nullif` + - `nvl2` + - `regr_valx` + ### Snowpark pandas API Updates @@ -48,17 +59,6 @@ - Hybrid execution mode is now enabled by default. Certain operations on smaller data will now automatically execute in native pandas in-memory. Use `from modin.config import AutoSwitchBackend; AutoSwitchBackend.disable()` to turn this off and force all execution to occur in Snowflake. - Added a session parameter `pandas_hybrid_execution_enabled` to enable/disable hybrid execution as an alternative to using `AutoSwitchBackend`. - Removed an unnecessary `SHOW OBJECTS` query issued from `read_snowflake` under certain conditions. -- Added support for the following scalar functions in `functions.py`: - - `booland` - - `boolnot` - - `boolor` - - `boolxor` - - `decode` - - `greatest_ignore_nulls` - - `least_ignore_nulls` - - `nullif` - - `nvl2` - - `regr_valx` ## 1.39.0 (2025-09-17)