diff --git a/proto/backend.proto b/proto/backend.proto index 67197e9bc..230158eb2 100644 --- a/proto/backend.proto +++ b/proto/backend.proto @@ -45,7 +45,6 @@ message BackendInput { CongratsLearnMsgIn congrats_learn_msg = 33; Empty empty_trash = 34; Empty restore_trash = 35; - DBQueryIn db_query = 36; } } @@ -74,7 +73,6 @@ message BackendOutput { Empty trash_media_files = 29; Empty empty_trash = 34; Empty restore_trash = 35; - DBQueryOut db_query = 36; BackendError error = 2047; } @@ -327,26 +325,3 @@ message CongratsLearnMsgIn { float next_due = 1; uint32 remaining = 2; } - -message DBQueryIn { - string sql = 1; - repeated SqlValue args = 2; -} - -message DBQueryOut { - repeated SqlRow rows = 1; -} - -message SqlValue { - oneof value { - Empty null = 1; - string string = 2; - int64 int = 3; - double double = 4; - bytes blob = 5; - } -} - -message SqlRow { - repeated SqlValue values = 1; -} diff --git a/pylib/anki/dbproxy.py b/pylib/anki/dbproxy.py index 84c3c45d7..ff89f2390 100644 --- a/pylib/anki/dbproxy.py +++ b/pylib/anki/dbproxy.py @@ -60,7 +60,7 @@ class DBProxy: self.mod = True # fetch rows # fixme: first_row_only - return self._backend.db_query_json(sql, args) + return self._backend.db_query(sql, args) # Query shortcuts ################### diff --git a/pylib/anki/rsbackend.py b/pylib/anki/rsbackend.py index 761a721c3..a44996ed9 100644 --- a/pylib/anki/rsbackend.py +++ b/pylib/anki/rsbackend.py @@ -385,44 +385,7 @@ class RustBackend: def restore_trash(self): self._run_command(pb.BackendInput(restore_trash=pb.Empty())) - def db_query(self, sql: str, args: Iterable[ValueForDB]) -> Iterable[DBRow]: - def arg_to_proto(arg: ValueForDB) -> pb.SqlValue: - if isinstance(arg, int): - return pb.SqlValue(int=arg) - elif isinstance(arg, float): - return pb.SqlValue(double=arg) - elif isinstance(arg, str): - return pb.SqlValue(string=arg) - elif arg is None: - return pb.SqlValue(null=pb.Empty()) - else: - raise Exception("unexpected DB type") - - output = self._run_command( - pb.BackendInput( - db_query=pb.DBQueryIn(sql=sql, args=map(arg_to_proto, args)) - ) - ).db_query - - def sqlvalue_to_native(arg: pb.SqlValue) -> Any: - v = arg.WhichOneof("value") - if v == "int": - return arg.int - elif v == "double": - return arg.double - elif v == "string": - return arg.string - elif v == "null": - return None - else: - assert_impossible_literal(v) - - def sqlrow_to_tuple(arg: pb.SqlRow) -> Tuple: - return tuple(map(sqlvalue_to_native, arg.values)) - - return map(sqlrow_to_tuple, output.rows) - - def db_query_json(self, sql: str, args: Iterable[ValueForDB]) -> List[DBRow]: + def db_query(self, sql: str, args: Iterable[ValueForDB]) -> List[DBRow]: input = orjson.dumps(dict(sql=sql, args=args)) output = self._backend.db_query(input) return orjson.loads(output) diff --git a/rslib/src/backend/dbproxy.rs b/rslib/src/backend/dbproxy.rs index 9e6bbe611..f86be1b0b 100644 --- a/rslib/src/backend/dbproxy.rs +++ b/rslib/src/backend/dbproxy.rs @@ -7,8 +7,6 @@ use crate::storage::SqliteStorage; use rusqlite::types::{FromSql, FromSqlError, ToSql, ToSqlOutput, ValueRef}; use serde_derive::{Deserialize, Serialize}; -// json implementation - #[derive(Deserialize)] pub(super) struct DBRequest { sql: String, @@ -84,59 +82,3 @@ pub(super) fn db_query_json(db: &SqliteStorage, input: DBRequest) -> Result std::result::Result, rusqlite::Error> { - use pb::sql_value::Value as SqlValue; - let val = match self - .value - .as_ref() - .unwrap_or_else(|| &SqlValue::Null(pb::Empty {})) - { - SqlValue::Null(_) => ValueRef::Null, - SqlValue::String(v) => ValueRef::Text(v.as_bytes()), - SqlValue::Int(v) => ValueRef::Integer(*v), - SqlValue::Double(v) => ValueRef::Real(*v), - SqlValue::Blob(v) => ValueRef::Blob(&v), - }; - Ok(ToSqlOutput::Borrowed(val)) - } -} - -impl FromSql for pb::SqlValue { - fn column_result(value: ValueRef<'_>) -> std::result::Result { - use pb::sql_value::Value as SqlValue; - let val = match value { - ValueRef::Null => SqlValue::Null(pb::Empty {}), - ValueRef::Integer(i) => SqlValue::Int(i), - ValueRef::Real(v) => SqlValue::Double(v), - ValueRef::Text(v) => SqlValue::String(String::from_utf8_lossy(v).to_string()), - ValueRef::Blob(v) => SqlValue::Blob(v.to_vec()), - }; - Ok(pb::SqlValue { value: Some(val) }) - } -} - -pub(super) fn db_query_proto(db: &SqliteStorage, input: pb::DbQueryIn) -> Result { - let mut stmt = db.db.prepare_cached(&input.sql)?; - - let columns = stmt.column_count(); - - let mut rows = stmt.query(&input.args)?; - - let mut output_rows = vec![]; - - while let Some(row) = rows.next()? { - let mut orow = Vec::with_capacity(columns); - for i in 0..columns { - let v: pb::SqlValue = row.get(i)?; - orow.push(v); - } - - output_rows.push(pb::SqlRow { values: orow }); - } - - Ok(pb::DbQueryOut { rows: output_rows }) -} diff --git a/rslib/src/backend/mod.rs b/rslib/src/backend/mod.rs index 1a2cc1eaa..bbf8b5266 100644 --- a/rslib/src/backend/mod.rs +++ b/rslib/src/backend/mod.rs @@ -2,7 +2,6 @@ // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html use crate::backend::dbproxy::db_query_json_str; -use crate::backend::dbproxy::db_query_proto; use crate::backend_proto::backend_input::Value; use crate::backend_proto::{Empty, RenderedTemplateReplacement, SyncMediaIn}; use crate::err::{AnkiError, NetworkErrorKind, Result, SyncErrorKind}; @@ -253,7 +252,6 @@ impl Backend { self.restore_trash()?; OValue::RestoreTrash(Empty {}) } - Value::DbQuery(input) => OValue::DbQuery(self.db_query(input)?), }) } @@ -495,13 +493,9 @@ impl Backend { checker.restore_trash() } - fn db_query(&self, input: pb::DbQueryIn) -> Result { + pub fn db_query(&self, input: pb::DbQueryIn) -> Result { db_query_proto(&self.col, input) } - - pub fn db_query_json(&self, input: &[u8]) -> Result { - db_query_json_str(&self.col, input) - } } fn translate_arg_to_fluent_val(arg: &pb::TranslateArgValue) -> FluentValue { diff --git a/rspy/src/lib.rs b/rspy/src/lib.rs index 80e8c762f..d921aa799 100644 --- a/rspy/src/lib.rs +++ b/rspy/src/lib.rs @@ -73,7 +73,7 @@ impl Backend { fn db_query(&mut self, py: Python, input: &PyBytes) -> PyObject { let in_bytes = input.as_bytes(); - let out_string = self.backend.db_query_json(in_bytes).unwrap(); + let out_string = self.backend.db_query(in_bytes).unwrap(); let out_obj = PyBytes::new(py, out_string.as_bytes()); out_obj.into() }