From 755f9e63db7b416d93ff5c00bdcef7dba074a29e Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Sun, 10 May 2020 17:35:45 +0100 Subject: [PATCH] feat(queries): fixed keyset non-sequential scan pagination --- modules/core/objects/services.js | 15 +++++++++------ modules/core/tests/objects.spec.js | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/core/objects/services.js b/modules/core/objects/services.js index a9697ff5e..4cf1caf37 100644 --- a/modules/core/objects/services.js +++ b/modules/core/objects/services.js @@ -252,7 +252,7 @@ module.exports = { if ( orderBy.field === 'id' ) { cteInnerQuery.orderBy( 'id', direction ) } else { - cteInnerQuery.orderByRaw( knex.raw( `jsonb_path_query_first( data, ? ) ${direction}`, [ '$.' + orderBy.field ] ) ) + cteInnerQuery.orderByRaw( knex.raw( `jsonb_path_query_first( data, ? ) ${direction}, id asc`, [ '$.' + orderBy.field ] ) ) } } ) @@ -266,6 +266,9 @@ module.exports = { if ( typeof cursor.value === 'boolean' ) castType = 'boolean' if ( typeof cursor.value === 'number' ) castType = 'numeric' + if( castType === 'text') + cursor.value = `"${cursor.value}"` + if ( operatorsWhitelist.indexOf( cursor.operator ) == -1 ) throw new Error( 'Invalid operator for cursor' ) @@ -273,21 +276,21 @@ module.exports = { if ( cursor.field === 'id' ) { mainQuery.where( knex.raw( `id ${cursor.operator} ? `, [ cursor.value ] ) ) } else { - mainQuery.where( knex.raw( `jsonb_path_query_first( data, ? )::${castType} ${cursor.operator} ? `, [ '$.' + cursor.field, castType === 'text' ? `"${cursor.value}"` : cursor.value ] ) ) + mainQuery.where( knex.raw( `jsonb_path_query_first( data, ? )::${castType} ${cursor.operator}= ? `, [ '$.' + cursor.field, cursor.value ] ) ) } } else { - mainQuery.where( knex.raw( `??::${castType} ${cursor.operator}= ? `, [ select.indexOf( cursor.field ).toString( ), castType === 'text' ? `"${cursor.value}"` : cursor.value ] ) ) + mainQuery.where( knex.raw( `??::${castType} ${cursor.operator}= ? `, [ select.indexOf( cursor.field ).toString( ), cursor.value ] ) ) } if ( cursor.lastSeenId ) { console.log(cursor) mainQuery.andWhere( qb => { - qb.where( 'id', '>=', cursor.lastSeenId ) + qb.where( 'id', '>', cursor.lastSeenId ) // qb.andWhere( 'id', '!=', cursor.lastSeenId ) if ( unwrapData ) - qb.orWhere( knex.raw( `jsonb_path_query_first( data, ? )::${castType} ${cursor.operator} ? `, [ '$.' + cursor.field, castType === 'text' ? `"${cursor.value}"` : cursor.value ] ) ) + qb.orWhere( knex.raw( `jsonb_path_query_first( data, ? )::${castType} ${cursor.operator} ? `, [ '$.' + cursor.field, cursor.value ] ) ) else - qb.orWhere( knex.raw( `??::${castType} ${cursor.operator} ? `, [ select.indexOf( cursor.field ).toString( ), castType === 'text' ? `"${cursor.value}"` : cursor.value ] ) ) + qb.orWhere( knex.raw( `??::${castType} ${cursor.operator} ? `, [ select.indexOf( cursor.field ).toString( ), cursor.value ] ) ) } ) } } diff --git a/modules/core/tests/objects.spec.js b/modules/core/tests/objects.spec.js index 773f8842b..62c30e418 100644 --- a/modules/core/tests/objects.spec.js +++ b/modules/core/tests/objects.spec.js @@ -246,7 +246,7 @@ describe( 'Objects', ( ) => { select: [ 'similar', 'id' ], query: [ { field: 'similar', operator: '>=', value: 0 }, { field: 'similar', operator: '<', value: 100 } ], orderBy: { field: 'similar', direction: 'asc' }, - limit: 9 + limit: 2 } ) let test4 = await getObjectChildrenQuery( { @@ -255,7 +255,7 @@ describe( 'Objects', ( ) => { query: [ { field: 'similar', operator: '>=', value: 0 }, { field: 'similar', operator: '<', value: 100 } ], orderBy: { field: 'similar', direction: 'asc' }, cursor: test3.cursor, - limit: 9 + limit: 2 } ) console.log( test3.objects )