srielau commented on code in PR #52334:
URL: https://github.com/apache/spark/pull/52334#discussion_r2433344335


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala:
##########
@@ -50,9 +54,152 @@ class SparkSqlParser extends AbstractSqlParser {
 
   private val substitutor = new VariableSubstitution()
 
+  /**
+   * Parse SQL with explicit parameter context, avoiding thread-local usage.
+   * This is the preferred method for parsing SQL with parameters.
+   *
+   * @param command The SQL text to parse
+   * @param parameterContext The parameter context containing parameter values
+   * @param toResult Function to convert the parser result
+   * @return The parsed result
+   */
+  def parseWithParameters[T](
+      command: String,
+      parameterContext: ParameterContext)
+      (toResult: SqlBaseParser => T): T = {
+    parseInternal(command, Some(parameterContext), isTopLevel = true)(toResult)
+  }
+
+  /**
+   * Parse SQL plan with explicit parameter context, avoiding thread-local 
usage.
+   * This is the preferred method for parsing SQL plans with parameters.
+   *
+   * @param sqlText The SQL text to parse
+   * @param parameterContext The parameter context containing parameter values
+   * @return The parsed logical plan
+   */
+  override def parsePlanWithParameters(
+      sqlText: String,
+      parameterContext: ParameterContext): LogicalPlan = {
+    parseWithParameters(sqlText, parameterContext) { parser =>
+      val ctx = parser.compoundOrSingleStatement()
+      withErrorHandling(ctx, Some(sqlText)) {
+        astBuilder.visitCompoundOrSingleStatement(ctx) match {
+          case compoundBody: CompoundPlanStatement => compoundBody
+          case plan: LogicalPlan => plan
+          case _ =>
+            val position = Origin(None, None)
+            throw QueryParsingErrors.sqlStatementUnsupportedError(sqlText, 
position)
+        }
+      }
+    }
+  }
+
   protected override def parse[T](command: String)(toResult: SqlBaseParser => 
T): T = {
-    super.parse(substitutor.substitute(command))(toResult)
+    parseInternal(command, None, isTopLevel = true)(toResult)
   }
+
+  /**
+   * Internal parse method that handles both parameter substitution and 
regular parsing.
+   *
+   * @param command The SQL text to parse
+   * @param parameterContext Optional parameter context for parameter 
substitution
+   * @param isTopLevel Whether this is a top-level parse (vs identifier/data 
type parsing)
+   * @param toResult Function to convert the parser result
+   * @return The parsed result
+   */
+  private def parseInternal[T](
+      command: String,
+      parameterContext: Option[ParameterContext],
+      isTopLevel: Boolean)
+      (toResult: SqlBaseParser => T): T = {
+
+    // Step 1: Check if parameter substitution should occur.
+    val (paramSubstituted, substitutionOccurred, hasParameters) = 
parameterContext match {
+      case Some(context) if isTopLevel =>
+        if (SQLConf.get.legacyParameterSubstitutionConstantsOnly) {
+          // Legacy mode: skip parameter substitution but still detect 
parameters for context.
+          // Parameters detected but substitution skipped in legacy mode.
+          // Position mapping will be set up below.
+          (command, false, true)
+        } else {
+          // Modern mode: perform parameter substitution if parameters are 
present.
+          val substituted = substituteParametersOrSetupCallback(command, 
context)
+          (substituted, substituted != command, true) // Track if substitution 
occurred.
+        }
+      case _ =>
+        // No parameter context or not top-level - no parameter substitution.
+        (command, false, false)
+    }
+
+    // Step 2: Apply existing variable substitution.
+    val variableSubstituted = substitutor.substitute(paramSubstituted)

Review Comment:
   No problem.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to