@@ -341,6 +341,18 @@ fn comparison_expression(input: &str) -> IResult<&str, BooleanExpression> {
341341 } ,
342342 ) ) ;
343343 }
344+ // Match ILIKE pattern (case-insensitive LIKE)
345+ if let Ok ( ( input_after_ilike, ( _, _, pattern) ) ) =
346+ tuple ( ( tag_no_case ( "ILIKE" ) , multispace0, string_literal) ) ( input)
347+ {
348+ return Ok ( (
349+ input_after_ilike,
350+ BooleanExpression :: ILike {
351+ expression : left,
352+ pattern,
353+ } ,
354+ ) ) ;
355+ }
344356 // Match CONTAINS substring
345357 if let Ok ( ( input_after_contains, ( _, _, substring) ) ) =
346358 tuple ( ( tag_no_case ( "CONTAINS" ) , multispace0, string_literal) ) ( input)
@@ -1265,4 +1277,122 @@ mod tests {
12651277 _ => panic ! ( "Expected AND expression" ) ,
12661278 }
12671279 }
1280+
1281+ #[ test]
1282+ fn test_parse_ilike_pattern ( ) {
1283+ let query = "MATCH (n:Person) WHERE n.name ILIKE 'alice%' RETURN n.name" ;
1284+ let result = parse_cypher_query ( query) ;
1285+ assert ! ( result. is_ok( ) , "ILIKE pattern should parse successfully" ) ;
1286+
1287+ let ast = result. unwrap ( ) ;
1288+ let where_clause = ast. where_clause . expect ( "Expected WHERE clause" ) ;
1289+
1290+ match where_clause. expression {
1291+ BooleanExpression :: ILike {
1292+ expression,
1293+ pattern,
1294+ } => {
1295+ match expression {
1296+ ValueExpression :: Property ( prop) => {
1297+ assert_eq ! ( prop. variable, "n" ) ;
1298+ assert_eq ! ( prop. property, "name" ) ;
1299+ }
1300+ _ => panic ! ( "Expected property expression" ) ,
1301+ }
1302+ assert_eq ! ( pattern, "alice%" ) ;
1303+ }
1304+ _ => panic ! ( "Expected ILIKE expression" ) ,
1305+ }
1306+ }
1307+
1308+ #[ test]
1309+ fn test_parse_ilike_case_insensitive_keyword ( ) {
1310+ // Test that the ILIKE keyword itself is case-insensitive
1311+ let query = "MATCH (n:Person) WHERE n.name ilike 'ALICE%' RETURN n.name" ;
1312+ let result = parse_cypher_query ( query) ;
1313+ assert ! ( result. is_ok( ) , "ilike (lowercase) should parse" ) ;
1314+
1315+ match & result. unwrap ( ) . where_clause . unwrap ( ) . expression {
1316+ BooleanExpression :: ILike { pattern, .. } => {
1317+ assert_eq ! ( pattern, "ALICE%" ) ;
1318+ }
1319+ _ => panic ! ( "Expected ILIKE expression" ) ,
1320+ }
1321+ }
1322+
1323+ #[ test]
1324+ fn test_parse_ilike_with_double_quotes ( ) {
1325+ let query = r#"MATCH (n:Person) WHERE n.email ILIKE "%@EXAMPLE.COM" RETURN n.email"# ;
1326+ let result = parse_cypher_query ( query) ;
1327+ assert ! ( result. is_ok( ) , "ILIKE with double quotes should parse" ) ;
1328+
1329+ let ast = result. unwrap ( ) ;
1330+ let where_clause = ast. where_clause . expect ( "Expected WHERE clause" ) ;
1331+
1332+ match where_clause. expression {
1333+ BooleanExpression :: ILike { pattern, .. } => {
1334+ assert_eq ! ( pattern, "%@EXAMPLE.COM" ) ;
1335+ }
1336+ _ => panic ! ( "Expected ILIKE expression" ) ,
1337+ }
1338+ }
1339+
1340+ #[ test]
1341+ fn test_parse_ilike_in_complex_where ( ) {
1342+ let query = "MATCH (n:Person) WHERE n.age > 20 AND n.name ILIKE 'j%' RETURN n.name" ;
1343+ let result = parse_cypher_query ( query) ;
1344+ assert ! ( result. is_ok( ) , "ILIKE in complex WHERE should parse" ) ;
1345+
1346+ let ast = result. unwrap ( ) ;
1347+ let where_clause = ast. where_clause . expect ( "Expected WHERE clause" ) ;
1348+
1349+ match where_clause. expression {
1350+ BooleanExpression :: And ( left, right) => {
1351+ // Left should be age > 20
1352+ match * left {
1353+ BooleanExpression :: Comparison { .. } => { }
1354+ _ => panic ! ( "Expected comparison on left" ) ,
1355+ }
1356+ // Right should be ILIKE
1357+ match * right {
1358+ BooleanExpression :: ILike { pattern, .. } => {
1359+ assert_eq ! ( pattern, "j%" ) ;
1360+ }
1361+ _ => panic ! ( "Expected ILIKE expression on right" ) ,
1362+ }
1363+ }
1364+ _ => panic ! ( "Expected AND expression" ) ,
1365+ }
1366+ }
1367+
1368+ #[ test]
1369+ fn test_parse_like_and_ilike_together ( ) {
1370+ let query =
1371+ "MATCH (n:Person) WHERE n.name LIKE 'Alice%' OR n.name ILIKE 'bob%' RETURN n.name" ;
1372+ let result = parse_cypher_query ( query) ;
1373+ assert ! ( result. is_ok( ) , "LIKE and ILIKE together should parse" ) ;
1374+
1375+ let ast = result. unwrap ( ) ;
1376+ let where_clause = ast. where_clause . expect ( "Expected WHERE clause" ) ;
1377+
1378+ match where_clause. expression {
1379+ BooleanExpression :: Or ( left, right) => {
1380+ // Left should be LIKE (case-sensitive)
1381+ match * left {
1382+ BooleanExpression :: Like { pattern, .. } => {
1383+ assert_eq ! ( pattern, "Alice%" ) ;
1384+ }
1385+ _ => panic ! ( "Expected LIKE expression on left" ) ,
1386+ }
1387+ // Right should be ILIKE (case-insensitive)
1388+ match * right {
1389+ BooleanExpression :: ILike { pattern, .. } => {
1390+ assert_eq ! ( pattern, "bob%" ) ;
1391+ }
1392+ _ => panic ! ( "Expected ILIKE expression on right" ) ,
1393+ }
1394+ }
1395+ _ => panic ! ( "Expected OR expression" ) ,
1396+ }
1397+ }
12681398}
0 commit comments