Repository navigation
[SPARK-60495][CONNECT][SDP] Block EXECUTE IMMEDIATE, CALL, and IDENTIFIER clause commands in the SDP SQL guard - #59736
dongjoon-hyun wants to merge 1 commit into
Conversation
…mmands in the SDP SQL guard
spark-test
left a comment
There was a problem hiding this comment.
Review summary
This review found no defects in the updated SDP SQL guard. The new PlanWithUnresolvedIdentifier branch builds the deferred statement with a placeholder name and sends it through the same allowlist and blocklist check. As a result, USE SCHEMA IDENTIFIER(...) and CREATE TEMPORARY VIEW IDENTIFIER(...) AS ... are rejected, while SHOW COLUMNS FROM IDENTIFIER(...) and TABLE IDENTIFIER(...) are still allowed. The new UnresolvedExecuteImmediate and ExecutableDuringAnalysis blocklist entries reject every root-level EXECUTE IMMEDIATE and CALL. The added grid-test entries cover each newly rejected statement both outside and inside a query function, and they cover the read-only IDENTIFIER forms that stay allowed.
Findings
0 total: 0 P0, 0 P1, 0 P2, 0 P3.
No findings.
PR description suggestions
- In the user-facing change section, say that every
CALLis now rejected in pipelinespark.sql, including procedures that only read data. This is the same trade-off the description already accepts forEXECUTE IMMEDIATE 'SELECT 1'.
Generated by Omnigent on Databricks
What changes were proposed in this pull request?
This PR makes
PipelinesHandler.blockUnsupportedSqlCommand, the guard forspark.sql(...)in Spark Declarative Pipelines (SDP), reject three kinds of statements. The parser does not produce aCommandfor them, but they run a command or a procedure once they are analyzed.EXECUTE IMMEDIATE '<sql>'UnresolvedExecuteImmediateResolveExecuteImmediateparses and analyzes<sql>, and a command payload then runs asExecuteImmediateCommand.CALL cat.ns.proc(...)Call(anExecutableDuringAnalysis)InvokeProceduresruns the procedure.IDENTIFIERclause that the parser does not build yet, e.g.USE SCHEMA IDENTIFIER('a' || 'b'),CREATE TABLE IDENTIFIER('a' || 'b') (id INT), orCREATE TEMPORARY VIEW IDENTIFIER('v') AS SELECT 1PlanWithUnresolvedIdentifierResolveIdentifierClauseevaluates the clause and builds the actual command.The guard now does the following.
UnresolvedExecuteImmediateandExecutableDuringAnalysis, the trait thatCallimplements.PlanWithUnresolvedIdentifier, it builds the statement through the node'splanBuilderwith a placeholder name and checks that statement with the same allowlist and blocklist. As a result,USE SCHEMA IDENTIFIER('a' || 'b')is rejected asSetNamespaceCommand, likeUSE SCHEMA IDENTIFIER('ab'), while read-only forms such asSHOW COLUMNS FROM IDENTIFIER(...)andTABLE IDENTIFIER(...)are still allowed.Because the change is in
blockUnsupportedSqlCommand, it covers both a plain SQL relation and the root SQL of a SQL-with-referencesWITH_RELATIONS(SPARK-57189).Like the existing checks, the new checks are applied to the top node of the parsed plan. Nested cases such as
WITH ... INSERT ...are out of scope here. They are the top-node limitation discussed in #59425.Why are the changes needed?
The guard checks only the class of the top node of the parsed plan. The statements above pass that check, and
session.sqlthen analyzes them, which runs the command or the procedure. For example, the following line in a pipeline definition file creates a table while the pipeline is being registered, althoughspark.sql("CREATE TABLE ...")is rejected.Similarly,
spark.sql("USE SCHEMA IDENTIFIER('some_' || 'schema')")runsSetNamespaceCommandalthoughUSE SCHEMA some_schemais rejected, andCALLruns a procedure of a configuredProcedureCatalog. Inside a flow function, the guard lets these statements pass as well.Does this PR introduce any user-facing change?
Yes. In an SDP pipeline definition,
spark.sql(...)withEXECUTE IMMEDIATE,CALL, or a command named by such anIDENTIFIERclause now fails with errors like the following instead of running.This includes
EXECUTE IMMEDIATEof a query such asEXECUTE IMMEDIATE 'SELECT 1', because its SQL string is parsed only during analysis. This is a bug fix for the SDP SQL guard, which has existed since Apache Spark 4.1.0 (2025-12-11).How was this patch tested?
Pass the CIs with the newly added test cases in
PythonPipelineSuite.unsupportedSqlCommandList:EXECUTE IMMEDIATE,CALL,USE SCHEMAwith a non-literalIDENTIFIERclause, andCREATE TEMPORARY VIEWwith a literalIDENTIFIERclause. Each is checked outside and inside a query function. Without the fix, these 8 test cases fail because the guard does not reject the statements. For example, outside a query function,EXECUTE IMMEDIATEcreates the table, andUSE SCHEMA IDENTIFIER(...)runsSetNamespaceCommandand fails withSCHEMA_NOT_FOUND.supportedSqlCommandList:SHOW COLUMNS FROM IDENTIFIER(...)andTABLE IDENTIFIER(...)with a non-literalIDENTIFIERclause, to make sure that the new check does not block them.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Opus 5.5