@@ -337,6 +337,50 @@ pub async fn fetch_one(
337337 Ok ( result)
338338}
339339
340+ /// Execute a paginated SELECT query using keyset (cursor-based) pagination
341+ #[ allow( clippy:: too_many_arguments) ]
342+ #[ tauri:: command]
343+ pub async fn fetch_page (
344+ db_instances : State < ' _ , DbInstances > ,
345+ db : String ,
346+ query : String ,
347+ values : Vec < JsonValue > ,
348+ keyset : Vec < sqlx_sqlite_toolkit:: KeysetColumn > ,
349+ page_size : usize ,
350+ after : Option < Vec < JsonValue > > ,
351+ before : Option < Vec < JsonValue > > ,
352+ attached : Option < Vec < AttachedDatabaseSpec > > ,
353+ ) -> Result < sqlx_sqlite_toolkit:: KeysetPage > {
354+ if after. is_some ( ) && before. is_some ( ) {
355+ return Err ( Error :: Toolkit (
356+ sqlx_sqlite_toolkit:: Error :: ConflictingCursors ,
357+ ) ) ;
358+ }
359+
360+ let instances = db_instances. 0 . read ( ) . await ;
361+
362+ let wrapper = instances
363+ . get ( & db)
364+ . ok_or_else ( || Error :: DatabaseNotLoaded ( db. clone ( ) ) ) ?;
365+
366+ let mut builder = wrapper. fetch_page ( query, values, keyset, page_size) ;
367+
368+ if let Some ( cursor_values) = after {
369+ builder = builder. after ( cursor_values) ;
370+ } else if let Some ( cursor_values) = before {
371+ builder = builder. before ( cursor_values) ;
372+ }
373+
374+ if let Some ( specs) = attached {
375+ let resolved_specs = resolve_attached_specs ( specs, & instances) ?;
376+ builder = builder. attach ( resolved_specs) ;
377+ }
378+
379+ let result = builder. execute ( ) . await ?;
380+
381+ Ok ( result)
382+ }
383+
340384/// Close a specific database connection
341385///
342386/// Returns `true` if the database was loaded and successfully closed.
0 commit comments