@@ -269,27 +269,44 @@ export class StorageKnexDB implements Database {
269
269
nextToken ?: string
270
270
maxKeys ?: number
271
271
startAfter ?: string
272
+ sortBy ?: {
273
+ column ?: string
274
+ order ?: string
275
+ }
272
276
}
273
277
) {
274
278
return this . runQuery ( 'ListObjectsV2' , async ( knex ) => {
275
279
if ( ! options ?. delimiter ) {
276
280
const query = knex
277
281
. table ( 'objects' )
278
282
. where ( 'bucket_id' , bucketId )
279
- . select ( [ 'id' , 'name' , 'metadata' , 'updated_at' ] )
283
+ . select ( [ 'id' , 'name' , 'metadata' , 'updated_at' , 'created_at' , 'last_accessed_at' ] )
280
284
. limit ( options ?. maxKeys || 100 )
281
285
286
+ // only allow these values for sort columns, "name" is excluded intentionally so it will use the default value (to include collate)
287
+ const allowedSortColumns = new Set ( [ 'updated_at' , 'created_at' , 'last_accessed_at' ] )
288
+ const allowedSortOrders = new Set ( [ 'asc' , 'desc' ] )
289
+ const sortColumn =
290
+ options ?. sortBy ?. column && allowedSortColumns . has ( options . sortBy . column )
291
+ ? options . sortBy . column
292
+ : 'name COLLATE "C"'
293
+ const sortOrder =
294
+ options ?. sortBy ?. order && allowedSortOrders . has ( options . sortBy . order )
295
+ ? options . sortBy . order
296
+ : 'asc'
297
+
282
298
// knex typing is wrong, it doesn't accept a knex.raw on orderBy, even though is totally legit
283
299
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
284
300
// @ts -ignore
285
- query . orderBy ( knex . raw ( 'name COLLATE "C"' ) )
301
+ query . orderBy ( knex . raw ( ` ${ sortColumn } ` ) , sortOrder )
286
302
287
303
if ( options ?. prefix ) {
288
304
query . where ( 'name' , 'like' , `${ options . prefix } %` )
289
305
}
290
306
291
307
if ( options ?. nextToken ) {
292
- query . andWhere ( knex . raw ( 'name COLLATE "C" > ?' , [ options ?. nextToken ] ) )
308
+ const pageOperator = sortOrder === 'asc' ? '>' : '<'
309
+ query . andWhere ( knex . raw ( `${ sortColumn } ${ pageOperator } ?` , [ options . nextToken ] ) )
293
310
}
294
311
295
312
return query
@@ -302,13 +319,21 @@ export class StorageKnexDB implements Database {
302
319
}
303
320
304
321
if ( useNewSearchVersion2 && options ?. delimiter === '/' ) {
322
+ let paramPlaceholders = '?,?,?,?,?'
323
+ const sortParams : string [ ] = [ ]
324
+ // this migration adds 2 more parameters to search v2 support sorting
325
+ if ( await tenantHasMigrations ( this . tenantId , 'add-search-v2-sort-support' ) ) {
326
+ paramPlaceholders += ',?,?'
327
+ sortParams . push ( options ?. sortBy ?. column || 'name' , options ?. sortBy ?. order || 'asc' )
328
+ }
305
329
const levels = ! options ?. prefix ? 1 : options . prefix . split ( '/' ) . length
306
- const query = await knex . raw ( ' select * from storage.search_v2(?,?,?,?,?)' , [
330
+ const query = await knex . raw ( ` select * from storage.search_v2(${ paramPlaceholders } )` , [
307
331
options ?. prefix || '' ,
308
332
bucketId ,
309
333
options ?. maxKeys || 1000 ,
310
334
levels ,
311
335
options ?. startAfter || '' ,
336
+ ...sortParams ,
312
337
] )
313
338
314
339
return query . rows
0 commit comments