| <!--- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| (spark-functions)= |
| |
| # Spark-Compatible Functions |
| |
| DataFusion ships Spark-compatible versions of a wide set of functions |
| (string, math, datetime, hash, array, aggregate) through the upstream |
| `datafusion-spark` crate. `datafusion-python` exposes these under |
| `datafusion.functions.spark` for use from the DataFrame API, and via |
| {py:meth}`~datafusion.SessionContext.enable_spark_functions` for use from |
| SQL. |
| |
| ## Why a Separate Namespace? |
| |
| Several Spark functions share names with DataFusion built-ins but differ in |
| semantics. The most common divergences: |
| |
| - `concat` propagates NULL. `concat('a', NULL, 'b')` returns NULL under |
| Spark semantics, whereas the DataFusion default returns `'ab'`. |
| - `substring` is 1-indexed and supports negative positions counting from |
| the end of the string. |
| - `round` uses HALF_UP rounding mode (`round(2.5, 0) == 3`). |
| - Numeric functions (`floor`, `ceil`, `mod`) follow Spark's edge-case |
| handling for negative values and decimals. |
| |
| Enabling Spark functions does not affect the DataFrame API: you choose which |
| implementation to call by which module you import from. |
| |
| ## DataFrame API |
| |
| Import `spark` and use it like any other functions module. The Spark |
| functions can go anywhere you'd put a DataFusion expression — inside |
| `select`, `filter`, `with_column`, `aggregate`, and so on. |
| |
| ```python |
| from datafusion import SessionContext, col, lit |
| from datafusion.functions import spark |
| |
| ctx = SessionContext() |
| df = ctx.from_pydict({"s": ["hello", "world"]}) |
| |
| # SHA-256 hash with Spark semantics |
| df.select(spark.sha2(col("s"), lit(256)).alias("h")).show() |
| |
| # 1-indexed substring |
| df.select(spark.substring(col("s"), lit(1), lit(3)).alias("p")).show() |
| ``` |
| |
| ## SQL |
| |
| To use Spark functions in SQL queries, call |
| {py:meth}`~datafusion.SessionContext.enable_spark_functions` on the context. |
| This registers every Spark UDF/UDAF/UDWF, overriding any DataFusion built-in |
| of the same name. |
| |
| ```python |
| from datafusion import SessionContext |
| |
| ctx = SessionContext() |
| ctx.enable_spark_functions() |
| |
| ctx.sql("SELECT sha2('hello', 256)").show() |
| ctx.sql("SELECT concat('a', NULL, 'b')").show() # -> NULL, not 'ab' |
| ``` |
| |
| The override applies for the lifetime of the session. To call DataFusion's |
| built-in versions afterwards, create a fresh `SessionContext`. |
| |
| ## Function Reference |
| |
| The full, up-to-date list of available Spark functions — with signatures |
| and per-function docstrings — lives in the |
| {py:mod}`datafusion.functions.spark` API reference. |