Skip to content

Commit c84d33f

Browse files
miland-dbMaxGekk
authored andcommitted
[SPARK-51131][SQL] Throw exception when SQL Script is found inside EXECUTE IMMEDIATE command
### What changes were proposed in this pull request? An exception is thrown when user tries to use SQL Script as query string in EXECUTE IMMEDIATE. ### Why are the changes needed? This changes are needed to forbid scripts inside EXECUTE IMMEDIATE to not introduce additional complexity in script execution or leave system in undefined state. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? New test in `ExecuteImmediateEndToEndSuite`. ### Was this patch authored or co-authored using generative AI tooling? No Closes #49850 from miland-db/milan-dankovic_data/scripting-execute-immediate. Authored-by: Milan Dankovic <[email protected]> Signed-off-by: Max Gekk <[email protected]> (cherry picked from commit 4305bb1) Signed-off-by: Max Gekk <[email protected]>
1 parent eab674a commit c84d33f

File tree

4 files changed

+31
-2
lines changed

4 files changed

+31
-2
lines changed

common/utils/src/main/resources/error/error-conditions.json

+6
Original file line numberDiff line numberDiff line change
@@ -4622,6 +4622,12 @@
46224622
],
46234623
"sqlState" : "42K0I"
46244624
},
4625+
"SQL_SCRIPT_IN_EXECUTE_IMMEDIATE" : {
4626+
"message" : [
4627+
"SQL Scripts in EXECUTE IMMEDIATE commands are not allowed. Please ensure that the SQL query provided (<sqlString>) is not SQL Script. Make sure the sql_string is a well-formed SQL statement and does not contain BEGIN and END."
4628+
],
4629+
"sqlState" : "07501"
4630+
},
46254631
"STAR_GROUP_BY_POS" : {
46264632
"message" : [
46274633
"Star (*) is not allowed in a select list when GROUP BY an ordinal position is used."

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/executeImmediate.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import scala.util.{Either, Left, Right}
2121

2222
import org.apache.spark.sql.catalyst.expressions.{Alias, Expression, VariableReference}
2323
import org.apache.spark.sql.catalyst.parser.ParseException
24-
import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, SetVariable}
24+
import org.apache.spark.sql.catalyst.plans.logical.{CompoundBody, LogicalPlan, SetVariable}
2525
import org.apache.spark.sql.catalyst.rules.Rule
2626
import org.apache.spark.sql.catalyst.trees.TreePattern.{EXECUTE_IMMEDIATE, TreePattern}
2727
import org.apache.spark.sql.connector.catalog.CatalogManager
@@ -179,6 +179,10 @@ class SubstituteExecuteImmediate(val catalogManager: CatalogManager)
179179
catalogManager.v1SessionCatalog.parser.parsePlan(queryString)
180180
}
181181

182+
if (plan.isInstanceOf[CompoundBody]) {
183+
throw QueryCompilationErrors.sqlScriptInExecuteImmediate(queryString)
184+
}
185+
182186
// do not allow nested execute immediate
183187
if (plan.containsPattern(EXECUTE_IMMEDIATE)) {
184188
throw QueryCompilationErrors.nestedExecuteImmediate(queryString)

sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala

+6
Original file line numberDiff line numberDiff line change
@@ -4103,6 +4103,12 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase with Compilat
41034103
messageParameters = Map("sqlString" -> toSQLStmt(queryString)))
41044104
}
41054105

4106+
def sqlScriptInExecuteImmediate(sqlScriptString: String): Throwable = {
4107+
throw new AnalysisException(
4108+
errorClass = "SQL_SCRIPT_IN_EXECUTE_IMMEDIATE",
4109+
messageParameters = Map("sqlString" -> toSQLStmt(sqlScriptString)))
4110+
}
4111+
41064112
def dataSourceTableSchemaMismatchError(
41074113
dsSchema: StructType, expectedSchema: StructType): Throwable = {
41084114
new AnalysisException(

sql/core/src/test/scala/org/apache/spark/sql/execution/ExecuteImmediateEndToEndSuite.scala

+14-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
*/
1717
package org.apache.spark.sql.execution
1818

19-
import org.apache.spark.sql.{QueryTest}
19+
import org.apache.spark.sql.{AnalysisException, QueryTest}
20+
import org.apache.spark.sql.internal.SQLConf
2021
import org.apache.spark.sql.test.SharedSparkSession
2122

2223
class ExecuteImmediateEndToEndSuite extends QueryTest with SharedSparkSession {
@@ -36,4 +37,16 @@ class ExecuteImmediateEndToEndSuite extends QueryTest with SharedSparkSession {
3637
spark.sql("DROP TEMPORARY VARIABLE IF EXISTS parm;")
3738
}
3839
}
40+
41+
test("SQL Scripting not supported inside EXECUTE IMMEDIATE") {
42+
withSQLConf(SQLConf.SQL_SCRIPTING_ENABLED.key -> "true") {
43+
val executeImmediateText = "EXECUTE IMMEDIATE 'BEGIN SELECT 1; END'"
44+
checkError(
45+
exception = intercept[AnalysisException ] {
46+
spark.sql(executeImmediateText)
47+
},
48+
condition = "SQL_SCRIPT_IN_EXECUTE_IMMEDIATE",
49+
parameters = Map("sqlString" -> "BEGIN SELECT 1; END"))
50+
}
51+
}
3952
}

0 commit comments

Comments
 (0)