@@ -1939,6 +1939,54 @@ def test_below_int_bounds_in() -> None:
19391939 assert expression_evaluator (schema , NotIn ("id" , [1 , below_min ]), True )(Record (IntegerType .min )) is True
19401940
19411941
1942+ @pytest .mark .parametrize (
1943+ "literals" ,
1944+ [
1945+ [IntegerType .max + 1 , IntegerType .max + 2 ],
1946+ [IntegerType .min - 1 , IntegerType .min - 2 ],
1947+ [IntegerType .min - 1 , IntegerType .max + 1 ],
1948+ ],
1949+ )
1950+ def test_int_bounds_in_all_literals_out_of_range (literals : list [int ]) -> None :
1951+ schema = Schema (NestedField (1 , "id" , IntegerType (), required = False ))
1952+ in_expr = In ("id" , literals )
1953+ not_in_expr = NotIn ("id" , literals )
1954+
1955+ assert in_expr .bind (schema ) == AlwaysFalse ()
1956+ assert not_in_expr .bind (schema ) == AlwaysTrue ()
1957+ for value in [None , IntegerType .min , 0 , IntegerType .max ]:
1958+ assert expression_evaluator (schema , in_expr , True )(Record (value )) is False
1959+ assert expression_evaluator (schema , not_in_expr , True )(Record (value )) is True
1960+
1961+
1962+ def test_int_bounds_in_keeps_multiple_literals () -> None :
1963+ schema = Schema (NestedField (1 , "id" , IntegerType (), required = False ))
1964+ literals = [1 , 2 , IntegerType .min - 1 , IntegerType .max + 1 ]
1965+ in_expr = In ("id" , literals )
1966+ not_in_expr = NotIn ("id" , literals )
1967+
1968+ assert in_expr .bind (schema ) == In ("id" , [1 , 2 ]).bind (schema )
1969+ assert not_in_expr .bind (schema ) == NotIn ("id" , [1 , 2 ]).bind (schema )
1970+ values = [None , 1 , 2 , 3 , IntegerType .min , IntegerType .max ]
1971+ eval_in = expression_evaluator (schema , in_expr , True )
1972+ eval_not_in = expression_evaluator (schema , not_in_expr , True )
1973+ assert [value for value in values if eval_in (Record (value ))] == [1 , 2 ]
1974+ assert [value for value in values if eval_not_in (Record (value ))] == [None , 3 , IntegerType .min , IntegerType .max ]
1975+
1976+
1977+ @pytest .mark .parametrize (
1978+ "boundary,out_of_range" ,
1979+ [(IntegerType .min , IntegerType .min - 1 ), (IntegerType .max , IntegerType .max + 1 )],
1980+ )
1981+ def test_int_bounds_in_metrics (schema_data_file : Schema , boundary : int , out_of_range : int ) -> None :
1982+ bounds = {1 : to_bytes (IntegerType (), boundary )}
1983+ data_file = _single_value_metrics_file (boundary , lower_bounds = bounds , upper_bounds = bounds )
1984+
1985+ assert _InclusiveMetricsEvaluator (schema_data_file , In ("id" , [1 , out_of_range ])).eval (data_file ) == ROWS_CANNOT_MATCH
1986+ assert _StrictMetricsEvaluator (schema_data_file , NotIn ("id" , [1 , out_of_range ])).eval (data_file ) == ROWS_MUST_MATCH
1987+ assert _StrictMetricsEvaluator (schema_data_file , In ("id" , [1 , boundary , out_of_range ])).eval (data_file ) == ROWS_MUST_MATCH
1988+
1989+
19421990def test_int_bounds_in_keeps_the_boundary_value () -> None :
19431991 """A sentinel is equal to the boundary literal it clamps to, so it must not absorb it."""
19441992 schema = Schema (NestedField (1 , "id" , IntegerType (), required = False ))
0 commit comments