Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make OffsetQueryPagingSource only work with Int #3386

Merged
merged 1 commit into from Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/android_sqlite/android_paging.md
Expand Up @@ -54,7 +54,7 @@ ORDER BY id ASC;

Queries used in keyset paging must have a unique ordering like shown above.

Both `beginInclusive` and `endExclusive` are _pre-calculated_ keys that act as page boundaries. Page sizes are established when pre-calculating page boundaries. The `pageBoundariesProvider` callback takes an `anchor: Key?` parameter as well as a `limit: Long?` parameter. An example query that pre-calculates page boundaries is shown below.
Both `beginInclusive` and `endExclusive` are _pre-calculated_ keys that act as page boundaries. Page sizes are established when pre-calculating page boundaries. The `pageBoundariesProvider` callback takes an `anchor: Key?` parameter as well as a `limit: Int?` parameter. An example query that pre-calculates page boundaries is shown below.

```sql
pageBoundaries:
Expand Down
Expand Up @@ -22,26 +22,26 @@ import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext

internal class OffsetQueryPagingSource<RowType : Any>(
private val queryProvider: (limit: Long, offset: Long) -> Query<RowType>,
private val countQuery: Query<Long>,
private val queryProvider: (limit: Int, offset: Int) -> Query<RowType>,
private val countQuery: Query<Int>,
private val transacter: Transacter,
private val context: CoroutineContext,
) : QueryPagingSource<Long, RowType>() {
) : QueryPagingSource<Int, RowType>() {

override val jumpingSupported get() = true

override suspend fun load(
params: LoadParams<Long>,
): LoadResult<Long, RowType> = withContext(context) {
params: LoadParams<Int>,
): LoadResult<Int, RowType> = withContext(context) {
try {
val key = params.key ?: 0L
val key = params.key ?: 0
transacter.transactionWithResult {
val count = countQuery.executeAsOne()
if (count != 0L && key >= count) throw IndexOutOfBoundsException()
if (count != 0 && key >= count) throw IndexOutOfBoundsException()

val loadSize = if (key < 0) params.loadSize + key else params.loadSize

val data = queryProvider(loadSize.toLong(), maxOf(0, key))
val data = queryProvider(loadSize, maxOf(0, key))
.also { currentQuery = it }
.executeAsList()

Expand All @@ -51,8 +51,8 @@ internal class OffsetQueryPagingSource<RowType : Any>(
// misaligned prepend queries to avoid duplicates.
prevKey = if (key <= 0L) null else key - params.loadSize,
nextKey = if (key + params.loadSize >= count) null else key + params.loadSize,
itemsBefore = maxOf(0L, key).toInt(),
itemsAfter = maxOf(0, (count - (key + params.loadSize))).toInt(),
itemsBefore = maxOf(0, key),
itemsAfter = maxOf(0, (count - (key + params.loadSize))),
)
}
} catch (e: Exception) {
Expand All @@ -61,5 +61,5 @@ internal class OffsetQueryPagingSource<RowType : Any>(
}
}

override fun getRefreshKey(state: PagingState<Long, RowType>) = state.anchorPosition?.toLong()
override fun getRefreshKey(state: PagingState<Int, RowType>) = state.anchorPosition
}
Expand Up @@ -59,11 +59,11 @@ internal abstract class QueryPagingSource<Key : Any, RowType : Any> :
*/
@Suppress("FunctionName")
fun <RowType : Any> QueryPagingSource(
countQuery: Query<Long>,
countQuery: Query<Int>,
transacter: Transacter,
context: CoroutineContext = Dispatchers.IO,
queryProvider: (limit: Long, offset: Long) -> Query<RowType>,
): PagingSource<Long, RowType> = OffsetQueryPagingSource(
queryProvider: (limit: Int, offset: Int) -> Query<RowType>,
): PagingSource<Int, RowType> = OffsetQueryPagingSource(
queryProvider,
countQuery,
transacter,
Expand Down
Expand Up @@ -72,7 +72,7 @@ class OffsetQueryPagingSourceTest {
val results = runBlocking { source.load(Refresh(null, 2, false)) }

assertNull((results as LoadResult.Page).prevKey)
assertEquals(2L, results.nextKey)
assertEquals(2, results.nextKey)
}

@Test fun `aligned last page gives correct prevKey and nextKey`() {
Expand All @@ -85,7 +85,7 @@ class OffsetQueryPagingSourceTest {

val results = runBlocking { source.load(Refresh(8, 2, false)) }

assertEquals(6L, (results as LoadResult.Page).prevKey)
assertEquals(6, (results as LoadResult.Page).prevKey)
assertNull(results.nextKey)
}

Expand All @@ -98,12 +98,13 @@ class OffsetQueryPagingSourceTest {
)

runBlocking {
val expected = (0L until 10L).chunked(2).iterator()
var nextKey: Long? = null
val expected = (0 until 10).chunked(2).iterator()
var nextKey: Int? = null
do {
val results = source.load(Refresh(nextKey, 2, false))
assertEquals(expected.next(), (results as LoadResult.Page).data)
nextKey = results.nextKey
1L.toInt()
} while (nextKey != null)
}
}
Expand All @@ -118,7 +119,7 @@ class OffsetQueryPagingSourceTest {

val results = runBlocking { source.load(Refresh(9, 2, false)) }

assertEquals(7L, (results as LoadResult.Page).prevKey)
assertEquals(7, (results as LoadResult.Page).prevKey)
assertNull(results.nextKey)
}

Expand All @@ -130,10 +131,10 @@ class OffsetQueryPagingSourceTest {
EmptyCoroutineContext,
)

val results = runBlocking { source.load(Refresh(1L, 2, false)) }
val results = runBlocking { source.load(Refresh(1, 2, false)) }

assertEquals(-1L, (results as LoadResult.Page).prevKey)
assertEquals(3L, results.nextKey)
assertEquals(-1, (results as LoadResult.Page).prevKey)
assertEquals(3, results.nextKey)
}

@Test fun `initial page has correct itemsBefore and itemsAfter`() {
Expand Down Expand Up @@ -215,8 +216,8 @@ class OffsetQueryPagingSourceTest {
)

runBlocking {
val expected = listOf(listOf(1L, 2L), listOf(0L)).iterator()
var prevKey: Long? = 1L
val expected = listOf(listOf(1, 2), listOf(0)).iterator()
var prevKey: Int? = 1
do {
val results = source.load(Refresh(prevKey, 2, false))
assertEquals(expected.next(), (results as LoadResult.Page).data)
Expand Down Expand Up @@ -256,12 +257,12 @@ class OffsetQueryPagingSourceTest {
assertTrue(source.invalid)
}

private fun query(limit: Long, offset: Long) = object : Query<Long>(
{ cursor -> cursor.getLong(0)!! },
private fun query(limit: Int, offset: Int) = object : Query<Int>(
{ cursor -> cursor.getLong(0)!!.toInt() },
) {
override fun <R> execute(mapper: (SqlCursor) -> R) = driver.executeQuery(1, "SELECT value FROM testTable LIMIT ? OFFSET ?", mapper, 2) {
bindLong(0, limit)
bindLong(1, offset)
bindLong(0, limit.toLong())
bindLong(1, offset.toLong())
}

override fun addListener(listener: Listener) = driver.addListener(listener, arrayOf("testTable"))
Expand All @@ -275,7 +276,7 @@ class OffsetQueryPagingSourceTest {
"Test.sq",
"count",
"SELECT count(*) FROM testTable",
{ it.getLong(0)!! },
{ it.getLong(0)!!.toInt() },
)

private fun insert(value: Long, db: SqlDriver = driver) {
Expand Down