Skip to content

Commit a386d2e

Browse files
authored
Merge pull request #40 from pmorris-dev/pagination-command-layer
feat: add fetch_page Tauri command for keyset pagination
2 parents c8443e2 + 7e24e40 commit a386d2e

8 files changed

Lines changed: 102 additions & 3 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ members = [
55
"crates/sqlx-sqlite-observer",
66
"crates/sqlx-sqlite-toolkit",
77
]
8-
exclude = ["examples/observer-demo/src-tauri"]
8+
exclude = ["examples/observer-demo/src-tauri", "examples/pagination-demo/src-tauri"]
99

1010
[package]
1111
name = "tauri-plugin-sqlite"

build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ fn main() {
88
"transaction_read",
99
"fetch_all",
1010
"fetch_one",
11+
"fetch_page",
1112
"close",
1213
"close_all",
1314
"remove",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Automatically generated - DO NOT EDIT!
2+
3+
"$schema" = "../../schemas/schema.json"
4+
5+
[[permission]]
6+
identifier = "allow-fetch-page"
7+
description = "Enables the fetch_page command without any pre-configured scope."
8+
commands.allow = ["fetch_page"]
9+
10+
[[permission]]
11+
identifier = "deny-fetch-page"
12+
description = "Denies the fetch_page command without any pre-configured scope."
13+
commands.deny = ["fetch_page"]

permissions/autogenerated/reference.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Default permissions for the sqlite plugin - allows all database operations
1212
- `allow-transaction-read`
1313
- `allow-fetch-all`
1414
- `allow-fetch-one`
15+
- `allow-fetch-page`
1516
- `allow-close`
1617
- `allow-close-all`
1718
- `allow-remove`
@@ -215,6 +216,32 @@ Denies the fetch_one command without any pre-configured scope.
215216
<tr>
216217
<td>
217218

219+
`sqlite:allow-fetch-page`
220+
221+
</td>
222+
<td>
223+
224+
Enables the fetch_page command without any pre-configured scope.
225+
226+
</td>
227+
</tr>
228+
229+
<tr>
230+
<td>
231+
232+
`sqlite:deny-fetch-page`
233+
234+
</td>
235+
<td>
236+
237+
Denies the fetch_page command without any pre-configured scope.
238+
239+
</td>
240+
</tr>
241+
242+
<tr>
243+
<td>
244+
218245
`sqlite:allow-get-migration-events`
219246

220247
</td>

permissions/default.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ permissions = [
1515
"allow-transaction-read",
1616
"allow-fetch-all",
1717
"allow-fetch-one",
18+
"allow-fetch-page",
1819
"allow-close",
1920
"allow-close-all",
2021
"allow-remove",

permissions/schemas/schema.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,18 @@
378378
"const": "deny-fetch-one",
379379
"markdownDescription": "Denies the fetch_one command without any pre-configured scope."
380380
},
381+
{
382+
"description": "Enables the fetch_page command without any pre-configured scope.",
383+
"type": "string",
384+
"const": "allow-fetch-page",
385+
"markdownDescription": "Enables the fetch_page command without any pre-configured scope."
386+
},
387+
{
388+
"description": "Denies the fetch_page command without any pre-configured scope.",
389+
"type": "string",
390+
"const": "deny-fetch-page",
391+
"markdownDescription": "Denies the fetch_page command without any pre-configured scope."
392+
},
381393
{
382394
"description": "Enables the get_migration_events command without any pre-configured scope.",
383395
"type": "string",
@@ -499,10 +511,10 @@
499511
"markdownDescription": "Denies the unsubscribe command without any pre-configured scope."
500512
},
501513
{
502-
"description": "Default permissions for the sqlite plugin - allows all database operations\n#### This default permission set includes:\n\n- `allow-load`\n- `allow-execute`\n- `allow-execute-transaction`\n- `allow-begin-interruptible-transaction`\n- `allow-transaction-continue`\n- `allow-transaction-read`\n- `allow-fetch-all`\n- `allow-fetch-one`\n- `allow-close`\n- `allow-close-all`\n- `allow-remove`\n- `allow-get-migration-events`\n- `allow-observe`\n- `allow-subscribe`\n- `allow-unsubscribe`\n- `allow-unobserve`",
514+
"description": "Default permissions for the sqlite plugin - allows all database operations\n#### This default permission set includes:\n\n- `allow-load`\n- `allow-execute`\n- `allow-execute-transaction`\n- `allow-begin-interruptible-transaction`\n- `allow-transaction-continue`\n- `allow-transaction-read`\n- `allow-fetch-all`\n- `allow-fetch-one`\n- `allow-fetch-page`\n- `allow-close`\n- `allow-close-all`\n- `allow-remove`\n- `allow-get-migration-events`\n- `allow-observe`\n- `allow-subscribe`\n- `allow-unsubscribe`\n- `allow-unobserve`",
503515
"type": "string",
504516
"const": "default",
505-
"markdownDescription": "Default permissions for the sqlite plugin - allows all database operations\n#### This default permission set includes:\n\n- `allow-load`\n- `allow-execute`\n- `allow-execute-transaction`\n- `allow-begin-interruptible-transaction`\n- `allow-transaction-continue`\n- `allow-transaction-read`\n- `allow-fetch-all`\n- `allow-fetch-one`\n- `allow-close`\n- `allow-close-all`\n- `allow-remove`\n- `allow-get-migration-events`\n- `allow-observe`\n- `allow-subscribe`\n- `allow-unsubscribe`\n- `allow-unobserve`"
517+
"markdownDescription": "Default permissions for the sqlite plugin - allows all database operations\n#### This default permission set includes:\n\n- `allow-load`\n- `allow-execute`\n- `allow-execute-transaction`\n- `allow-begin-interruptible-transaction`\n- `allow-transaction-continue`\n- `allow-transaction-read`\n- `allow-fetch-all`\n- `allow-fetch-one`\n- `allow-fetch-page`\n- `allow-close`\n- `allow-close-all`\n- `allow-remove`\n- `allow-get-migration-events`\n- `allow-observe`\n- `allow-subscribe`\n- `allow-unsubscribe`\n- `allow-unobserve`"
506518
}
507519
]
508520
}

src/commands.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ impl Builder {
184184
commands::transaction_read,
185185
commands::fetch_all,
186186
commands::fetch_one,
187+
commands::fetch_page,
187188
commands::close,
188189
commands::close_all,
189190
commands::remove,

0 commit comments

Comments
 (0)