@@ -13,7 +13,7 @@ use nom::{
1313 bytes:: complete:: { tag, tag_no_case, take_while1} ,
1414 character:: complete:: { char, multispace0, multispace1} ,
1515 combinator:: { map, opt, recognize} ,
16- multi:: { many0, separated_list0} ,
16+ multi:: { many0, separated_list0, separated_list1 } ,
1717 sequence:: { delimited, pair, preceded, tuple} ,
1818 IResult ,
1919} ;
@@ -316,14 +316,28 @@ fn comparison_expression(input: &str) -> IResult<&str, BooleanExpression> {
316316 let ( input, _) = multispace0 ( input) ?;
317317 let ( input, left) = value_expression ( input) ?;
318318 let ( input, _) = multispace0 ( input) ?;
319+ let left_clone = left. clone ( ) ;
320+
321+ if let Ok ( ( input_after_in, ( _, _, list) ) ) =
322+ tuple ( ( tag_no_case ( "IN" ) , multispace0, value_expression_list) ) ( input)
323+ {
324+ return Ok ( (
325+ input_after_in,
326+ BooleanExpression :: In {
327+ expression : left,
328+ list,
329+ } ,
330+ ) ) ;
331+ }
332+
319333 let ( input, operator) = comparison_operator ( input) ?;
320334 let ( input, _) = multispace0 ( input) ?;
321335 let ( input, right) = value_expression ( input) ?;
322336
323337 Ok ( (
324338 input,
325339 BooleanExpression :: Comparison {
326- left,
340+ left : left_clone ,
327341 operator,
328342 right,
329343 } ,
@@ -352,6 +366,17 @@ fn value_expression(input: &str) -> IResult<&str, ValueExpression> {
352366 ) ) ( input)
353367}
354368
369+ fn value_expression_list ( input : & str ) -> IResult < & str , Vec < ValueExpression > > {
370+ delimited (
371+ tuple ( ( char ( '[' ) , multispace0) ) ,
372+ separated_list1 (
373+ tuple ( ( multispace0, char ( ',' ) , multispace0) ) ,
374+ value_expression,
375+ ) ,
376+ tuple ( ( multispace0, char ( ']' ) ) ) ,
377+ ) ( input)
378+ }
379+
355380// Parse a property reference: variable.property
356381fn property_reference ( input : & str ) -> IResult < & str , PropertyRef > {
357382 let ( input, variable) = identifier ( input) ?;
@@ -726,6 +751,39 @@ mod tests {
726751 }
727752 }
728753
754+ #[ test]
755+ fn test_parse_query_with_in_clause ( ) {
756+ let query = "MATCH (src:Entity)-[rel:RELATIONSHIP]->(dst:Entity) WHERE rel.relationship_type IN ['WORKS_FOR', 'PART_OF'] RETURN src.name" ;
757+ let result = parse_cypher_query ( query) . unwrap ( ) ;
758+
759+ let where_clause = result. where_clause . expect ( "Expected WHERE clause" ) ;
760+ match where_clause. expression {
761+ BooleanExpression :: In { expression, list } => {
762+ match expression {
763+ ValueExpression :: Property ( prop_ref) => {
764+ assert_eq ! ( prop_ref. variable, "rel" ) ;
765+ assert_eq ! ( prop_ref. property, "relationship_type" ) ;
766+ }
767+ _ => panic ! ( "Expected property reference in IN expression" ) ,
768+ }
769+ assert_eq ! ( list. len( ) , 2 ) ;
770+ match & list[ 0 ] {
771+ ValueExpression :: Literal ( PropertyValue :: String ( val) ) => {
772+ assert_eq ! ( val, "WORKS_FOR" ) ;
773+ }
774+ _ => panic ! ( "Expected first list item to be a string literal" ) ,
775+ }
776+ match & list[ 1 ] {
777+ ValueExpression :: Literal ( PropertyValue :: String ( val) ) => {
778+ assert_eq ! ( val, "PART_OF" ) ;
779+ }
780+ _ => panic ! ( "Expected second list item to be a string literal" ) ,
781+ }
782+ }
783+ other => panic ! ( "Expected IN expression, got {:?}" , other) ,
784+ }
785+ }
786+
729787 #[ test]
730788 fn test_parse_query_with_limit ( ) {
731789 let query = "MATCH (n:Person) RETURN n.name LIMIT 10" ;
0 commit comments