flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/services/search/src/store.rs

50 lines1,636 bytesCodeBlame
1//! Running [`Sql`] against D1.
2
3use serde::Deserialize;
4use serde::de::DeserializeOwned;
5use worker::wasm_bindgen::JsValue;
6use worker::{D1Database, D1PreparedStatement, Result};
7
8use crate::sql::{Param, Sql};
9
10fn value(param: &Param) -> JsValue {
11 match param {
12 Param::Text(text) => JsValue::from(text.as_str()),
13 // Every number bound is a page size, an offset or a count.
14 Param::Int(number) => JsValue::from(*number as f64),
15 Param::Null => JsValue::NULL,
16 }
17}
18
19pub fn statement(db: &D1Database, sql: &Sql) -> Result<D1PreparedStatement> {
20 let values: Vec<JsValue> = sql.params.iter().map(value).collect();
21 db.prepare(&sql.text).bind(&values)
22}
23
24/// A statement from SQL text and values.
25pub fn prepare(db: &D1Database, text: &str, params: Vec<Param>) -> Result<D1PreparedStatement> {
26 statement(db, &Sql { text: text.to_owned(), params })
27}
28
29pub async fn all<T: DeserializeOwned>(db: &D1Database, sql: &Sql) -> Result<Vec<T>> {
30 statement(db, sql)?.all().await?.results::<T>()
31}
32
33pub async fn count(db: &D1Database, sql: &Sql) -> Result<u32> {
34 #[derive(Deserialize)]
35 struct Count {
36 n: u32,
37 }
38 Ok(statement(db, sql)?.first::<Count>(None).await?.map_or(0, |row| row.n))
39}
40
41/// Runs statements in batches of at most 50, each batch all or nothing.
42pub async fn run_all(db: &D1Database, statements: Vec<D1PreparedStatement>) -> Result<()> {
43 let mut statements = statements;
44 while !statements.is_empty() {
45 let rest = statements.split_off(statements.len().min(50));
46 db.batch(statements).await?;
47 statements = rest;
48 }
49 Ok(())
50}