John Zhuge created SPARK-60483:
----------------------------------

             Summary: Add spark.sql.extensions.defaultList for platform default 
session extensions
                 Key: SPARK-60483
                 URL: https://issues.apache.org/jira/browse/SPARK-60483
             Project: Spark
          Issue Type: Improvement
          Components: SQL
    Affects Versions: 4.2.0
            Reporter: John Zhuge


h3. Problem

Platform or cluster operators often need a set of SparkSessionExtensions active 
for every application (for example a catalog integration, a parser extension, 
or an optimizer rule), while application owners add their own extensions.

{{spark.sql.extensions}} is a single list. If the operator sets it in
spark-defaults.conf and a user passes
{{{}--conf spark.sql.extensions=com.example.MyExtensions{}}}, the user value 
replaces
the operator value and the operator's extensions are silently dropped. Today
the user must know about the operator list and copy it by hand.
h3. Prior art in Spark

Spark already solves this for other list-valued configs with an operator-facing
default list that is prepended to the user value, via 
ConfigBuilder.withPrepended:
 * {{spark.plugins.defaultList}} prepended to {{spark.plugins}} (SPARK-29397, 
3.0.0)
 * {{spark.driver.defaultJavaOptions}} / {{spark.executor.defaultJavaOptions}}
prepended to the matching extraJavaOptions

SPARK-35380 (3.2.0) added SparkSessionExtensionsProvider via ServiceLoader. It
works well for libraries that self-register, but fits the operator case less
well: activation depends on classpath contents rather than configuration, the
active set is not visible in the application's conf, it cannot be disabled
without changing the classpath, and a failing provider is logged and skipped.
h3. Proposal

Add a static SQL conf {{spark.sql.extensions.defaultList}} (default: empty).
The effective value of {{spark.sql.extensions}} becomes the default list
followed by the user value, by applying withPrepended to
SPARK_SESSION_EXTENSIONS, as spark.plugins does.
{code:java}
# spark-defaults.conf (operator)
spark.sql.extensions.defaultList  
org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions

# application
--conf spark.sql.extensions=com.example.MyExtensions

# effective spark.sql.extensions
org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,com.example.MyExtensions
{code}
Semantics:
 * Unset: behavior is unchanged.
 * Order: default-list entries are applied before user entries. Order matters
because parser extensions chain and injected rules run in registration order.
 * ServiceLoader providers (SPARK-35380) and SparkSession.Builder.withExtensions
keep their current behavior and position.
 * A user can still opt out of a default by overriding defaultList itself, which
keeps the operator/user split explicit.

h3. Open questions
 # Should the effective list be de-duplicated, preserving order, as
PluginContainer does for plugins? Applying the same extension twice injects
its rules and parser wrapper twice. Proposed: yes.
 # Naming: {{spark.sql.extensions.defaultList}} mirrors
{{{}spark.plugins.defaultList{}}}. Open to alternatives.

h3. Testing

Unit tests (e.g. in SparkSessionExtensionSuite) for: default list plus user
list in order; default only; user only; unset leaves behavior unchanged;
duplicates handled per the decision above.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to