如果在下推的过滤器表达式中使用日期文字,例如
val postingDate = java.sql.Date.valueOf("2016-06-03")
val count = jdbcDF.filter($"POSTINGDATE" === postingDate).count
其中POSTINGDATE
列是JDBC类型Date,生成的下推SQL查询如下所示:
SELECT .. <columns> ... FROM <table> WHERE POSTINGDATE = '2016-06-03'
具体来说,使用java.sql.Date.toString
发出的硬编码yyyy-MM-dd格式将日期编译成字符串文字。请注意JDBCRDD.compileValue
/**
* Converts value to SQL expression.
*/
private def compileValue(value: Any): Any = value match {
case stringValue: String => s"'${escapeSql(stringValue)}'"
case timestampValue: Timestamp => "'" + timestampValue + "'"
case dateValue: Date => "'" + dateValue + "'"
case arrayValue: Array[Any] => arrayValue.map(compileValue).mkString(", ")
case _ => value
}
如果数据库期望日期字符串文字的格式不同,则生成的查询将失败。例如,Oracle的默认格式是“dd-MMM-yy&#39;”,因此在执行关系查询时,它会因语法错误而失败。
ORA-01861: literal does not match format string
01861. 00000 - "literal does not match format string"
在某些情况下,可能会更改数据库的预期日期格式以匹配Java格式,但在我们的情况下,我们无法控制它。
似乎这种转换应该通过某种特定于供应商的转换(例如通过JDBCDialect
)。我已经提交了一个JIRA问题,但同时,我建议如何解决这个问题?我已经尝试了各种不同的方法,无论是在火花方面还是在JDBC方面,但还没有想出任何东西。这对我们来说是一个关键问题,因为我们正在处理按日期组织的非常大的表 - 没有下推,我们最终会将整个表格拉到Spark侧过滤器。