@@ -129,6 +129,7 @@ class ExpressionEvaluationSuite extends FunSuite {
129129
130130 test(" LIKE literal Regular Expression" ) {
131131 checkEvaluation(Literal (null , StringType ).like(" a" ), null )
132+ checkEvaluation(Literal (" a" , StringType ).like(Literal (null , StringType )), null )
132133 checkEvaluation(Literal (null , StringType ).like(Literal (null , StringType )), null )
133134 checkEvaluation(" abdef" like " abdef" , true )
134135 checkEvaluation(" a_%b" like " a\\ __b" , true )
@@ -157,9 +158,14 @@ class ExpressionEvaluationSuite extends FunSuite {
157158 checkEvaluation(" abc" like regEx, true , new GenericRow (Array [Any ](" a%" )))
158159 checkEvaluation(" abc" like regEx, false , new GenericRow (Array [Any ](" b%" )))
159160 checkEvaluation(" abc" like regEx, false , new GenericRow (Array [Any ](" bc%" )))
161+
162+ checkEvaluation(Literal (null , StringType ) like regEx, null , new GenericRow (Array [Any ](" bc%" )))
160163 }
161164
162165 test(" RLIKE literal Regular Expression" ) {
166+ checkEvaluation(Literal (null , StringType ) rlike " abdef" , null )
167+ checkEvaluation(" abdef" rlike Literal (null , StringType ), null )
168+ checkEvaluation(Literal (null , StringType ) rlike Literal (null , StringType ), null )
163169 checkEvaluation(" abdef" rlike " abdef" , true )
164170 checkEvaluation(" abbbbc" rlike " a.*c" , true )
165171
@@ -244,17 +250,19 @@ class ExpressionEvaluationSuite extends FunSuite {
244250
245251 intercept[Exception ] {evaluate(Literal (1 ) cast BinaryType , null )}
246252
247- assert((" abcdef" cast StringType ).nullable === false )
248- assert((" abcdef" cast BinaryType ).nullable === false )
249- assert((" abcdef" cast BooleanType ).nullable === false )
250- assert((" abcdef" cast TimestampType ).nullable === true )
251- assert((" abcdef" cast LongType ).nullable === true )
252- assert((" abcdef" cast IntegerType ).nullable === true )
253- assert((" abcdef" cast ShortType ).nullable === true )
254- assert((" abcdef" cast ByteType ).nullable === true )
255- assert((" abcdef" cast DecimalType ).nullable === true )
256- assert((" abcdef" cast DoubleType ).nullable === true )
257- assert((" abcdef" cast FloatType ).nullable === true )
253+ checkEvaluation((" abcdef" cast StringType ).nullable, false )
254+ checkEvaluation((" abcdef" cast BinaryType ).nullable,false )
255+ checkEvaluation((" abcdef" cast BooleanType ).nullable, false )
256+ checkEvaluation((" abcdef" cast TimestampType ).nullable, true )
257+ checkEvaluation((" abcdef" cast LongType ).nullable, true )
258+ checkEvaluation((" abcdef" cast IntegerType ).nullable, true )
259+ checkEvaluation((" abcdef" cast ShortType ).nullable, true )
260+ checkEvaluation((" abcdef" cast ByteType ).nullable, true )
261+ checkEvaluation((" abcdef" cast DecimalType ).nullable, true )
262+ checkEvaluation((" abcdef" cast DoubleType ).nullable, true )
263+ checkEvaluation((" abcdef" cast FloatType ).nullable, true )
264+
265+ checkEvaluation(Cast (Literal (null , IntegerType ), ShortType ), null )
258266 }
259267
260268 test(" timestamp" ) {
@@ -285,5 +293,108 @@ class ExpressionEvaluationSuite extends FunSuite {
285293 // A test for higher precision than millis
286294 checkEvaluation(Cast (Cast (0.00000001 , TimestampType ), DoubleType ), 0.00000001 )
287295 }
296+
297+ test(" null checking" ) {
298+ val row = new GenericRow (Array [Any ](" ^Ba*n" , null , true , null ))
299+ val c1 = ' a .string.at(0 )
300+ val c2 = ' a .string.at(1 )
301+ val c3 = ' a .boolean.at(2 )
302+ val c4 = ' a .boolean.at(3 )
303+
304+ checkEvaluation(IsNull (c1), false , row)
305+ checkEvaluation(IsNotNull (c1), true , row)
306+
307+ checkEvaluation(IsNull (c2), true , row)
308+ checkEvaluation(IsNotNull (c2), false , row)
309+
310+ checkEvaluation(IsNull (Literal (1 , ShortType )), false )
311+ checkEvaluation(IsNotNull (Literal (1 , ShortType )), true )
312+
313+ checkEvaluation(IsNull (Literal (null , ShortType )), true )
314+ checkEvaluation(IsNotNull (Literal (null , ShortType )), false )
315+
316+ checkEvaluation(Coalesce (c1 :: c2 :: Nil ), " ^Ba*n" , row)
317+ checkEvaluation(Coalesce (Literal (null , StringType ) :: Nil ), null , row)
318+ checkEvaluation(Coalesce (Literal (null , StringType ) :: c1 :: c2 :: Nil ), " ^Ba*n" , row)
319+
320+ checkEvaluation(If (c3, Literal (" a" , StringType ), Literal (" b" , StringType )), " a" , row)
321+ checkEvaluation(If (c3, c1, c2), " ^Ba*n" , row)
322+ checkEvaluation(If (c4, c2, c1), " ^Ba*n" , row)
323+ checkEvaluation(If (Literal (null , BooleanType ), c2, c1), " ^Ba*n" , row)
324+ checkEvaluation(If (Literal (true , BooleanType ), c1, c2), " ^Ba*n" , row)
325+ checkEvaluation(If (Literal (false , BooleanType ), c2, c1), " ^Ba*n" , row)
326+ checkEvaluation(If (Literal (false , BooleanType ),
327+ Literal (" a" , StringType ), Literal (" b" , StringType )), " b" , row)
328+
329+ checkEvaluation(In (c1, c1 :: c2 :: Nil ), true , row)
330+ checkEvaluation(In (Literal (" ^Ba*n" , StringType ),
331+ Literal (" ^Ba*n" , StringType ) :: Nil ), true , row)
332+ checkEvaluation(In (Literal (" ^Ba*n" , StringType ),
333+ Literal (" ^Ba*n" , StringType ) :: c2 :: Nil ), true , row)
334+ }
335+
336+ test(" complex type" ) {
337+ val row = new GenericRow (Array [Any ](
338+ " ^Ba*n" , // 0
339+ null .asInstanceOf [String ], // 1
340+ new GenericRow (Array [Any ](" aa" , " bb" )), // 2
341+ Map (" aa" -> " bb" ), // 3
342+ Seq (" aa" , " bb" ) // 4
343+ ))
344+
345+ val typeS = StructType (
346+ StructField (" a" , StringType , true ) :: StructField (" b" , StringType , true ) :: Nil
347+ )
348+ val typeMap = MapType (StringType , StringType )
349+ val typeArray = ArrayType (StringType )
350+
351+ checkEvaluation(GetItem (BoundReference (3 , AttributeReference (" c" , typeMap)()),
352+ Literal (" aa" )), " bb" , row)
353+ checkEvaluation(GetItem (Literal (null , typeMap), Literal (" aa" )), null , row)
354+ checkEvaluation(GetItem (Literal (null , typeMap), Literal (null , StringType )), null , row)
355+ checkEvaluation(GetItem (BoundReference (3 , AttributeReference (" c" , typeMap)()),
356+ Literal (null , StringType )), null , row)
357+
358+ checkEvaluation(GetItem (BoundReference (4 , AttributeReference (" c" , typeArray)()),
359+ Literal (1 )), " bb" , row)
360+ checkEvaluation(GetItem (Literal (null , typeArray), Literal (1 )), null , row)
361+ checkEvaluation(GetItem (Literal (null , typeArray), Literal (null , IntegerType )), null , row)
362+ checkEvaluation(GetItem (BoundReference (4 , AttributeReference (" c" , typeArray)()),
363+ Literal (null , IntegerType )), null , row)
364+
365+ checkEvaluation(GetField (BoundReference (2 , AttributeReference (" c" , typeS)()), " a" ), " aa" , row)
366+ checkEvaluation(GetField (Literal (null , typeS), " a" ), null , row)
367+ }
368+
369+ test(" arithmetic" ) {
370+ val row = new GenericRow (Array [Any ](1 , 2 , 3 , null ))
371+ val c1 = ' a .int.at(0 )
372+ val c2 = ' a .int.at(1 )
373+ val c3 = ' a .int.at(2 )
374+ val c4 = ' a .int.at(3 )
375+
376+ checkEvaluation(UnaryMinus (c1), - 1 , row)
377+ checkEvaluation(UnaryMinus (Literal (100 , IntegerType )), - 100 )
378+
379+ checkEvaluation(Add (c1, c4), null , row)
380+ checkEvaluation(Add (c1, c2), 3 , row)
381+ checkEvaluation(Add (c1, Literal (null , IntegerType )), null , row)
382+ checkEvaluation(Add (Literal (null , IntegerType ), c2), null , row)
383+ checkEvaluation(Add (Literal (null , IntegerType ), Literal (null , IntegerType )), null , row)
384+ }
385+
386+ test(" BinaryComparison" ) {
387+ val row = new GenericRow (Array [Any ](1 , 2 , 3 , null ))
388+ val c1 = ' a .int.at(0 )
389+ val c2 = ' a .int.at(1 )
390+ val c3 = ' a .int.at(2 )
391+ val c4 = ' a .int.at(3 )
392+
393+ checkEvaluation(LessThan (c1, c4), null , row)
394+ checkEvaluation(LessThan (c1, c2), true , row)
395+ checkEvaluation(LessThan (c1, Literal (null , IntegerType )), null , row)
396+ checkEvaluation(LessThan (Literal (null , IntegerType ), c2), null , row)
397+ checkEvaluation(LessThan (Literal (null , IntegerType ), Literal (null , IntegerType )), null , row)
398+ }
288399}
289400
0 commit comments