You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@spark.apache.org by "Anitesh Minj (Jira)" <ji...@apache.org> on 2024/09/04 12:31:00 UTC
[jira] [Created] (SPARK-49510) The withWatermark method in Dataset.scala is throwing a ParseException when a number is passed to the eventTime parameter
Anitesh Minj created SPARK-49510:
------------------------------------
Summary: The withWatermark method in Dataset.scala is throwing a ParseException when a number is passed to the eventTime parameter
Key: SPARK-49510
URL: https://issues.apache.org/jira/browse/SPARK-49510
Project: Spark
Issue Type: Bug
Components: SQL, Structured Streaming
Affects Versions: 3.3.2, 3.3.0
Reporter: Anitesh Minj
def withWatermark(eventTime: String, delayThreshold: String): Dataset[T] = withTypedPlan {
val parsedDelay = IntervalUtils.fromIntervalString(delayThreshold)
require(!IntervalUtils.isNegative(parsedDelay),
s"delay threshold ($delayThreshold) should not be negative.")
EliminateEventTimeWatermark(
EventTimeWatermark(UnresolvedAttribute(eventTime), parsedDelay, logicalPlan))
}
In the above withWatermark function of Dataset.scala, if we pass number as eventTime parameter. It fails with below ParseException
{color:#de350b}Caused by: org.apache.spark.sql.catalyst.parser.ParseException: {color}
{color:#de350b}Syntax error at or near '1'(line 1, pos 0){color}
{color:#de350b}== SQL =={color}
{color:#de350b}1{color}
{color:#de350b}^^^{color}
{color:#de350b} at org.apache.spark.sql.catalyst.parser.ParseException.withCommand(ParseDriver.scala:315){color}
{color:#de350b} at org.apache.spark.sql.catalyst.parser.AbstractSqlParser.parse(ParseDriver.scala:152){color}
{color:#de350b} at org.apache.spark.sql.catalyst.parser.AbstractSqlParser.parseMultipartIdentifier(ParseDriver.scala:68){color}
{color:#de350b} at org.apache.spark.sql.catalyst.analysis.UnresolvedAttribute$.apply(unresolved.scala:161){color}
{color:#de350b} at org.apache.spark.sql.Dataset.withWatermark(Dataset.scala:748){color}
In spark 3.1.1 it was able to parse number properly. It was not throwing any error.
The current issue is seen because of the checkin done for the issue https://issues.apache.org/jira/browse/SPARK-34636.
The changes made to the {{apply}} method in the {{Unresolved.scala}} file are causing the issue. I have attached the relevant code sections below for Spark 3.1 and Spark 3.2, highlighting the differences.:-
*Spark 3.1*
def apply(name: String): UnresolvedAttribute = {color:#00875a}{color:#172b4d}new UnresolvedAttribute({color:#00875a}name.split("\\."){color}){color}
{color:#172b4d}*Spark 3.2*{color}
{color}def apply(name: String): UnresolvedAttribute =
new UnresolvedAttribute({color:#de350b}CatalystSqlParser.parseMultipartIdentifier(name){color})
Please visit this link to see the code changes:- [https://github.com/apache/spark/commit/94fd6cb0ce56684de47eb5cca925055859c968ef]
In above code for spark 3.1, we can see that in object instantiation of the apply Method only name.split is being done.
But with the above mentioned changed in spark 3.2 code and in later versions of spark CatalystSqlParser.parseMultipartIdentifier(name) is being called.
In turn this parseMultipartIdentifier method will call singleMultipartIdentifier method of SQLParser. we can see in the below code snippet.
override def parseMultipartIdentifier(sqlText: String): Seq[String] = {
parse(sqlText) { parser =>
astBuilder.visitSingleMultipartIdentifier({color:#4c9aff}parser.singleMultipartIdentifier(){color})
}
}
Now, once {color:#4c9aff}parser.singleMultipartIdentifier(){color} method is called. It will try to validate sqlText using the singleMultipartIdentifier rule. This sqlText parameter will contain the same value which we passed to eventTime parameter of withWaterMark function.
Now when this sqlText is a number(For Example "1"), than it will throw {color:#de350b}ParseException{color} which i mentioned in the beginning, as singleMultipartIdentifier rule can't parse Integer Value (numbers).
Possible Solution that i can suggest:
Introduce a new method in object of UnresolvedAttribute as shown below
object UnresolvedAttribute {
{color:#4c9aff}def numberString(name:String){color}
{color:#4c9aff}: UnresolvedAttribute = new UnresolvedAttribute(name.split("\\.")){color}
{color:#172b4d}}{color}
and in withWatermark function of Dataset.scala do a function call to UnresolvedAttribute.numberString(eventTime) inplace of calling a constructor UnresolvedAttribute(eventTime) as shown below
def withWatermark(eventTime: String, delayThreshold: String): Dataset[T] = withTypedPlan {
val parsedDelay = IntervalUtils.fromIntervalString(delayThreshold)
require(!IntervalUtils.isNegative(parsedDelay),
s"delay threshold ($delayThreshold) should not be negative.")
EliminateEventTimeWatermark(
EventTimeWatermark({color:#4c9aff}UnresolvedAttribute.numberString(eventTime){color}, parsedDelay, logicalPlan))
}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@spark.apache.org
For additional commands, e-mail: issues-help@spark.apache.org