有没有办法验证raw spark SQL查询的语法?
例如,我想知道是否有任何isValid
API调用spark提供?
val query = "select * from table"
if(isValid(query)) {
sparkSession.sql(query)
} else {
log.error("Invalid Syntax")
}
我尝试了以下
val query = "select * morf table" // Invalid query
val parser = spark.sessionState.sqlParser
try{
parser.parseExpression(query)
} catch (ParseException ex) {
throw new Exception(ex); //Exception not getting thrown
}
Dataset<>Row df = sparkSession.sql(query) // Exception gets thrown here
df.writeStream.format("console").start()
问题:parser.parseExpression
在点击sparkSession.sql
之前没有捕获无效语法。换句话说,它在上面的代码中没有帮助。任何原因?我的目标是在将语法错误传递给sparkSession.sql
答案 0 :(得分:4)
使用Spark SQL Parser:
val parser = spark.sessionState.sqlParser
parser.parseExpression("select * from table")
答案 1 :(得分:2)
经过无数次研究之后,我找到了一种方法,可以通过阅读一些Spark sql代码来实现。这些代码行可以完成这项工作:
.catch(error => 'send error response to user
请注意,在分析阶段,我们需要进行表解析,列名解析等操作。因此,这基本上是在进行语法和上下文分析
答案 2 :(得分:1)
虽然已经晚了,但可能对其他人有帮助。使用
spark.sessionState.sqlParser
似乎没有什么用,因为即使对于查询字符串为“ Hello World”也没有抱怨
最好使用,
sparkSession.sql(query)
实际验证查询语法。由于spark主要懒惰地工作,因此理想情况下,不应对实际数据集执行任何操作。
def validateSql(query: String, session: SparkSession): Boolean = {
try {
val result1 = session.sql(query)
println(s"No Syntax Error [$result1] Query [$query]")
return true;
} catch {
case e: Throwable => {
println(s"Query has syntax error. Error [${e.getMessage}] Query [$query]")
return false
}
}
}
如果您在Spark日志中查找上述代码,则该内容类似于
19/08/07 11:17:09 INFO SparkSqlParser: Parsing command: select * from XYZ limit 5
19/08/07 11:17:10 INFO CatalystSqlParser: Parsing command: bigint
19/08/07 11:17:10 INFO CatalystSqlParser: Parsing command: bigint
19/08/07 11:17:10 INFO CatalystSqlParser: Parsing command: bigint
19/08/07 11:17:10 INFO CatalystSqlParser: Parsing command: bigint
No Syntax Error [[A: bigint, BC: bigint ... 2 more fields]] Query [select * from XYZ limit 5]
相同的细节可以在SO的另一个问题中找到。 How to validate SQL expression (in user frontend) without executing it?
但是,由于sparkSession.sql(query)需要表元数据来验证表列,所以最好直接指向配置单元存储。以下是通过编程进行相同操作的参考。
How to connect to a Hive metastore programmatically in SparkSQL?