diff --git a/pylib/anki/dbproxy.py b/pylib/anki/dbproxy.py index 71eff93f3..80cb3795d 100644 --- a/pylib/anki/dbproxy.py +++ b/pylib/anki/dbproxy.py @@ -100,12 +100,11 @@ class DBProxy: # Updates ################ - def executemany(self, sql: str, args: Iterable[Iterable[ValueForDB]]) -> None: + def executemany(self, sql: str, args: Iterable[Sequence[ValueForDB]]) -> None: self.mod = True - # fixme - for row in args: - self.execute(sql, *row) - - def executescript(self, sql: str) -> None: - self.mod = True - raise Exception("fixme") + assert ":" not in sql + if isinstance(args, list): + list_args = args + else: + list_args = list(args) + self._backend.db_execute_many(sql, list_args) diff --git a/pylib/anki/rsbackend.py b/pylib/anki/rsbackend.py index ab2534a54..db427b4a2 100644 --- a/pylib/anki/rsbackend.py +++ b/pylib/anki/rsbackend.py @@ -386,9 +386,12 @@ class RustBackend: def restore_trash(self): self._run_command(pb.BackendInput(restore_trash=pb.Empty())) - def db_query(self, sql: str, args: Iterable[ValueForDB]) -> List[DBRow]: + def db_query(self, sql: str, args: List[ValueForDB]) -> List[DBRow]: return self._db_command(dict(kind="query", sql=sql, args=args)) + def db_execute_many(self, sql: str, args: List[List[ValueForDB]]) -> List[DBRow]: + return self._db_command(dict(kind="executemany", sql=sql, args=args)) + def db_begin(self) -> None: return self._db_command(dict(kind="begin")) diff --git a/rslib/src/backend/dbproxy.rs b/rslib/src/backend/dbproxy.rs index f0c2512a2..f4ebaf8b6 100644 --- a/rslib/src/backend/dbproxy.rs +++ b/rslib/src/backend/dbproxy.rs @@ -9,10 +9,17 @@ use serde_derive::{Deserialize, Serialize}; #[derive(Deserialize)] #[serde(tag = "kind", rename_all = "lowercase")] pub(super) enum DBRequest { - Query { sql: String, args: Vec }, + Query { + sql: String, + args: Vec, + }, Begin, Commit, Rollback, + ExecuteMany { + sql: String, + args: Vec>, + }, } #[derive(Serialize)] @@ -74,13 +81,13 @@ pub(super) fn db_command_bytes(ctx: &StorageContext, input: &[u8]) -> Result db_execute_many(ctx, &sql, &args)?, }; Ok(serde_json::to_string(&resp)?) } pub(super) fn db_query(ctx: &StorageContext, sql: &str, args: &[SqlValue]) -> Result { let mut stmt = ctx.db.prepare_cached(sql)?; - let columns = stmt.column_count(); let res: std::result::Result>, rusqlite::Error> = stmt @@ -96,3 +103,17 @@ pub(super) fn db_query(ctx: &StorageContext, sql: &str, args: &[SqlValue]) -> Re Ok(DBResult::Rows(res?)) } + +pub(super) fn db_execute_many( + ctx: &StorageContext, + sql: &str, + args: &[Vec], +) -> Result { + let mut stmt = ctx.db.prepare_cached(sql)?; + + for params in args { + stmt.execute(params)?; + } + + Ok(DBResult::None) +}