spring-projects / spring-data-commons

Spring Data Commons. Interfaces and code shared between the various datastore specific implementations.

Home Page:https://spring.io/projects/spring-data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Window.positionAt should always return exact position of element

christophstrobl opened this issue · comments

The current implementation of the positionAt method of Window conceptually differs for keyset and offset-based windows.
With keyset, the returned ScrollPosition contains the exact coordinates used to identify an element.
The offset-based variant behaves a little differently in the sense of being 1-based (adding +1 to the actual offset of the element, pointing not to the element itself but to the next one in the list):

               keyset                  |                offset  
---------------------------------------+---------------------------------------
[                                      | [
  0: { id: 1, name: luke }             |    0: { id: 1, name: luke }
  1: { id: 2, name: han }              |    1: { id: 2, name: han }
]                                      | ]
---------------------------------------+---------------------------------------
positionAt(0) - { id: 1, name: luke }  | positionAt(0) - { offset: 1 }
positionAt(1) - { id: 2, name: han }   | positionAt(1) - { offset: 2 }

The various store implementations currently follow the 1-based offsets. This results in a mixed approach when loading entries from the database by including the element at a given ScrollPosition if ScrollPosition.isInitial() and excluding the position otherwise. There's no way to differentiate between ScrollPosition.offset() and ScrollPosition.offset(0).

Going forward, we need to tell implementing stores if the result should contain the element at the ScrollPosition or not.
Current implementations are using greater than & less than filters for keyset scrolling which means if the element at a given position needs to be part of the result set, an additional entry identifying the element needs to be added to the or concatenated filter.

One small observation. I believe the way to find out if there are previous results is to check if isInitial() on the position at index 0 is true. Given that offsets start at 1 the following never works:

Window<String> window = Window.from(List.of("a", "b", "c"), OffsetScrollPosition.positionFunction(0));
ScrollPosition pos = window.positionAt(0);
boolean hasPrevious = !pos.isInitial();

assertThat(hasPrevious).isFalse();