@@ -179,7 +179,7 @@ private[sql] object JDBCRDD extends Logging {
179
179
case stringValue : String => s " ' ${escapeSql(stringValue)}' "
180
180
case timestampValue : Timestamp => " '" + timestampValue + " '"
181
181
case dateValue : Date => " '" + dateValue + " '"
182
- case arrayValue : Array [Object ] => arrayValue.map(compileValue).mkString(" , " )
182
+ case arrayValue : Array [Any ] => arrayValue.map(compileValue).mkString(" , " )
183
183
case _ => value
184
184
}
185
185
@@ -188,24 +188,41 @@ private[sql] object JDBCRDD extends Logging {
188
188
189
189
/**
190
190
* Turns a single Filter into a String representing a SQL expression.
191
- * Returns null for an unhandled filter.
191
+ * Returns None for an unhandled filter.
192
192
*/
193
- private def compileFilter (f : Filter ): String = f match {
194
- case EqualTo (attr, value) => s " $attr = ${compileValue(value)}"
195
- case Not (f) => s " (NOT ( ${compileFilter(f)})) "
196
- case LessThan (attr, value) => s " $attr < ${compileValue(value)}"
197
- case GreaterThan (attr, value) => s " $attr > ${compileValue(value)}"
198
- case LessThanOrEqual (attr, value) => s " $attr <= ${compileValue(value)}"
199
- case GreaterThanOrEqual (attr, value) => s " $attr >= ${compileValue(value)}"
200
- case StringStartsWith (attr, value) => s " ${attr} LIKE ' ${value}%' "
201
- case StringEndsWith (attr, value) => s " ${attr} LIKE '% ${value}' "
202
- case StringContains (attr, value) => s " ${attr} LIKE '% ${value}%' "
203
- case IsNull (attr) => s " $attr IS NULL "
204
- case IsNotNull (attr) => s " $attr IS NOT NULL "
205
- case In (attr, value) => s " $attr IN ( ${compileValue(value)}) "
206
- case Or (f1, f2) => s " ( ${compileFilter(f1)}) OR ( ${compileFilter(f2)}) "
207
- case And (f1, f2) => s " ( ${compileFilter(f1)}) AND ( ${compileFilter(f2)}) "
208
- case _ => null
193
+ private def compileFilter (f : Filter ): Option [String ] = {
194
+ Option (f match {
195
+ case EqualTo (attr, value) => s " $attr = ${compileValue(value)}"
196
+ case LessThan (attr, value) => s " $attr < ${compileValue(value)}"
197
+ case GreaterThan (attr, value) => s " $attr > ${compileValue(value)}"
198
+ case LessThanOrEqual (attr, value) => s " $attr <= ${compileValue(value)}"
199
+ case GreaterThanOrEqual (attr, value) => s " $attr >= ${compileValue(value)}"
200
+ case IsNull (attr) => s " $attr IS NULL "
201
+ case IsNotNull (attr) => s " $attr IS NOT NULL "
202
+ case StringStartsWith (attr, value) => s " ${attr} LIKE ' ${value}%' "
203
+ case StringEndsWith (attr, value) => s " ${attr} LIKE '% ${value}' "
204
+ case StringContains (attr, value) => s " ${attr} LIKE '% ${value}%' "
205
+ case In (attr, value) => s " $attr IN ( ${compileValue(value)}) "
206
+ case Not (f) => compileFilter(f).map(p => s " (NOT ( $p)) " ).getOrElse(null )
207
+ case Or (f1, f2) =>
208
+ // We can't compile Or filter unless both sub-filters are compiled successfully.
209
+ // It applies too for the following And filter.
210
+ // If we can make sure compileFilter supports all filters, we can remove this check.
211
+ val or = Seq (f1, f2).map(compileFilter(_)).flatten
212
+ if (or.size == 2 ) {
213
+ or.map(p => s " ( $p) " ).mkString(" OR " )
214
+ } else {
215
+ null
216
+ }
217
+ case And (f1, f2) =>
218
+ val and = Seq (f1, f2).map(compileFilter(_)).flatten
219
+ if (and.size == 2 ) {
220
+ and.map(p => s " ( $p) " ).mkString(" AND " )
221
+ } else {
222
+ null
223
+ }
224
+ case _ => null
225
+ })
209
226
}
210
227
211
228
/**
@@ -307,25 +324,21 @@ private[sql] class JDBCRDD(
307
324
/**
308
325
* `filters`, but as a WHERE clause suitable for injection into a SQL query.
309
326
*/
310
- private val filterWhereClause : String = {
311
- val filterStrings = filters.map(JDBCRDD .compileFilter).filter(_ != null )
312
- if (filterStrings.size > 0 ) {
313
- val sb = new StringBuilder (" WHERE " )
314
- filterStrings.foreach(x => sb.append(x).append(" AND " ))
315
- sb.substring(0 , sb.length - 5 )
316
- } else " "
317
- }
327
+ private val filterWhereClause : String =
328
+ filters.map(JDBCRDD .compileFilter).flatten.mkString(" AND " )
318
329
319
330
/**
320
331
* A WHERE clause representing both `filters`, if any, and the current partition.
321
332
*/
322
333
private def getWhereClause (part : JDBCPartition ): String = {
323
334
if (part.whereClause != null && filterWhereClause.length > 0 ) {
324
- filterWhereClause + " AND " + part.whereClause
335
+ " WHERE " + filterWhereClause + " AND " + part.whereClause
325
336
} else if (part.whereClause != null ) {
326
337
" WHERE " + part.whereClause
338
+ } else if (filterWhereClause.length > 0 ) {
339
+ " WHERE " + filterWhereClause
327
340
} else {
328
- filterWhereClause
341
+ " "
329
342
}
330
343
}
331
344
0 commit comments