@@ -1407,6 +1407,28 @@ def _cursor_pb(cursor_pair: Optional[Tuple[list, bool]]) -> Optional[Cursor]:
14071407 return None
14081408
14091409
1410+ def _get_cursor_exclusive_condition (
1411+ is_start_cursor : bool ,
1412+ ordering : pipeline_expressions .Ordering ,
1413+ value : pipeline_expressions .Constant ,
1414+ ) -> pipeline_expressions .BooleanExpression :
1415+ """
1416+ Helper to determine the correct comparison operator (greater_than or less_than)
1417+ based on the cursor type (start/end) and the sort direction (ascending/descending).
1418+ """
1419+ field = ordering .expr
1420+ if (
1421+ is_start_cursor
1422+ and ordering .order_dir == pipeline_expressions .Ordering .Direction .ASCENDING
1423+ ) or (
1424+ not is_start_cursor
1425+ and ordering .order_dir == pipeline_expressions .Ordering .Direction .DESCENDING
1426+ ):
1427+ return field .greater_than (value )
1428+ else :
1429+ return field .less_than (value )
1430+
1431+
14101432def _where_conditions_from_cursor (
14111433 cursor : Tuple [List , bool ],
14121434 orderings : List [pipeline_expressions .Ordering ],
@@ -1425,16 +1447,12 @@ def _where_conditions_from_cursor(
14251447 cursor_values , before = cursor
14261448 size = len (cursor_values )
14271449
1428- if is_start_cursor :
1429- filter_func = pipeline_expressions .Expression .greater_than
1430- else :
1431- filter_func = pipeline_expressions .Expression .less_than
1432-
1433- field = orderings [size - 1 ].expr
1450+ ordering = orderings [size - 1 ]
1451+ field = ordering .expr
14341452 value = pipeline_expressions .Constant (cursor_values [size - 1 ])
14351453
14361454 # Add condition for last bound
1437- condition = filter_func ( field , value )
1455+ condition = _get_cursor_exclusive_condition ( is_start_cursor , ordering , value )
14381456
14391457 if (is_start_cursor and before ) or (not is_start_cursor and not before ):
14401458 # When the cursor bound is inclusive, then the last bound
@@ -1443,14 +1461,18 @@ def _where_conditions_from_cursor(
14431461
14441462 # Iterate backwards over the remaining bounds, adding a condition for each one
14451463 for i in range (size - 2 , - 1 , - 1 ):
1446- field = orderings [i ].expr
1464+ ordering = orderings [i ]
1465+ field = ordering .expr
14471466 value = pipeline_expressions .Constant (cursor_values [i ])
14481467
14491468 # For each field in the orderings, the condition is either
14501469 # a) lessThan|greaterThan the cursor value,
14511470 # b) or equal the cursor value and lessThan|greaterThan the cursor values for other fields
1471+ exclusive_condition = _get_cursor_exclusive_condition (
1472+ is_start_cursor , ordering , value
1473+ )
14521474 condition = pipeline_expressions .Or (
1453- filter_func ( field , value ) ,
1475+ exclusive_condition ,
14541476 pipeline_expressions .And (field .equal (value ), condition ),
14551477 )
14561478
0 commit comments