mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
migrate the schema11 usages to new structs/sql queries
This commit is contained in:
parent
e2b978e7cb
commit
32bc1e88eb
8 changed files with 88 additions and 83 deletions
|
@ -380,7 +380,7 @@ where
|
|||
renamed: &HashMap<String, String>,
|
||||
) -> Result<HashSet<String>> {
|
||||
let mut referenced_files = HashSet::new();
|
||||
let note_types = self.ctx.storage.get_all_notetypes_as_schema11()?;
|
||||
let note_types = self.ctx.storage.get_all_notetype_core()?;
|
||||
let mut collection_modified = false;
|
||||
|
||||
for_every_note(&self.ctx.storage.db, |note| {
|
||||
|
@ -401,7 +401,7 @@ where
|
|||
&self.mgr.media_folder,
|
||||
)? {
|
||||
// note was modified, needs saving
|
||||
set_note(&self.ctx.storage.db, note, nt)?;
|
||||
set_note(&self.ctx.storage.db, note, nt.sort_field_idx())?;
|
||||
collection_modified = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::err::{AnkiError, DBErrorKind, Result};
|
|||
use crate::notetype::NoteTypeID;
|
||||
use crate::text::strip_html_preserving_image_filenames;
|
||||
use crate::timestamp::TimestampSecs;
|
||||
use crate::{define_newtype, notetype::NoteTypeSchema11, types::Usn};
|
||||
use crate::{define_newtype, types::Usn};
|
||||
use rusqlite::{params, Connection, Row, NO_PARAMS};
|
||||
use std::convert::TryInto;
|
||||
|
||||
|
@ -84,27 +84,21 @@ fn row_to_note(row: &Row) -> Result<Note> {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn set_note(
|
||||
db: &Connection,
|
||||
note: &mut Note,
|
||||
note_type: &NoteTypeSchema11,
|
||||
) -> Result<()> {
|
||||
pub(super) fn set_note(db: &Connection, note: &mut Note, sort_field_idx: usize) -> Result<()> {
|
||||
note.mtime = TimestampSecs::now();
|
||||
// hard-coded for now
|
||||
note.usn = Usn(-1);
|
||||
let field1_nohtml = strip_html_preserving_image_filenames(¬e.fields()[0]);
|
||||
let csum = field_checksum(field1_nohtml.as_ref());
|
||||
let sort_field = if note_type.sortf == 0 {
|
||||
let sort_field = if sort_field_idx == 0 {
|
||||
field1_nohtml
|
||||
} else {
|
||||
strip_html_preserving_image_filenames(
|
||||
note.fields()
|
||||
.get(note_type.sortf as usize)
|
||||
.ok_or_else(|| AnkiError::DBError {
|
||||
info: "sort field out of range".to_string(),
|
||||
kind: DBErrorKind::MissingEntity,
|
||||
})?,
|
||||
)
|
||||
strip_html_preserving_image_filenames(note.fields().get(sort_field_idx).ok_or_else(
|
||||
|| AnkiError::DBError {
|
||||
info: "sort field out of range".to_string(),
|
||||
kind: DBErrorKind::MissingEntity,
|
||||
},
|
||||
)?)
|
||||
};
|
||||
|
||||
let mut stmt =
|
||||
|
|
|
@ -37,6 +37,7 @@ pub(crate) const DEFAULT_LATEX_HEADER: &str = r#"\documentclass[12pt]{article}
|
|||
pub(crate) const DEFAULT_LATEX_FOOTER: &str = r#"\end{document}"#;
|
||||
|
||||
// other: vec![], // fixme: ensure empty map converted to empty bytes
|
||||
// fixme: rollback savepoint when tags not changed
|
||||
|
||||
impl NoteType {
|
||||
pub fn new() -> Self {
|
||||
|
@ -53,6 +54,14 @@ impl NoteType {
|
|||
NoteTypeID(self.id)
|
||||
}
|
||||
|
||||
pub fn sort_field_idx(&self) -> usize {
|
||||
self.config.as_ref().unwrap().sort_field_idx as usize
|
||||
}
|
||||
|
||||
pub fn latex_uses_svg(&self) -> bool {
|
||||
self.config.as_ref().unwrap().latex_svg
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_names_unique(&mut self) {
|
||||
let mut names = HashSet::new();
|
||||
for t in &mut self.templates {
|
||||
|
|
|
@ -267,27 +267,16 @@ impl SqlWriter<'_> {
|
|||
write!(self.sql, "c.ord = {}", n).unwrap();
|
||||
}
|
||||
TemplateKind::Name(name) => {
|
||||
let note_types = self.col.storage.get_all_notetypes_as_schema11()?;
|
||||
let mut id_ords = vec![];
|
||||
for nt in note_types.values() {
|
||||
for tmpl in &nt.tmpls {
|
||||
if matches_wildcard(&tmpl.name, name) {
|
||||
id_ords.push((nt.id, tmpl.ord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort for the benefit of unit tests
|
||||
id_ords.sort();
|
||||
|
||||
if id_ords.is_empty() {
|
||||
self.sql.push_str("false");
|
||||
if let Some(glob) = glob_to_re(name) {
|
||||
self.sql.push_str(
|
||||
"(n.mid,c.ord) in (select ntid,ord from templates where name regexp ?)",
|
||||
);
|
||||
self.args.push(glob);
|
||||
} else {
|
||||
let v: Vec<_> = id_ords
|
||||
.iter()
|
||||
.map(|(ntid, ord)| format!("(n.mid = {} and c.ord = {})", ntid, ord))
|
||||
.collect();
|
||||
write!(self.sql, "({})", v.join(" or ")).unwrap();
|
||||
self.sql.push_str(
|
||||
"(n.mid,c.ord) in (select ntid,ord from templates where name = ?)",
|
||||
);
|
||||
self.args.push(name.to_string());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -295,29 +284,27 @@ impl SqlWriter<'_> {
|
|||
}
|
||||
|
||||
fn write_note_type(&mut self, nt_name: &str) -> Result<()> {
|
||||
let mut ntids: Vec<_> = self
|
||||
.col
|
||||
.storage
|
||||
.get_all_notetypes_as_schema11()?
|
||||
.values()
|
||||
.filter(|nt| matches_wildcard(&nt.name, nt_name))
|
||||
.map(|nt| nt.id)
|
||||
.collect();
|
||||
self.sql.push_str("n.mid in ");
|
||||
// sort for the benefit of unit tests
|
||||
ntids.sort();
|
||||
ids_to_string(&mut self.sql, &ntids);
|
||||
if let Some(glob) = glob_to_re(nt_name) {
|
||||
self.sql
|
||||
.push_str("n.mid in (select id from notetypes where name regexp ?)");
|
||||
self.args.push(glob);
|
||||
} else {
|
||||
self.sql
|
||||
.push_str("n.mid in (select id from notetypes where name = ?)");
|
||||
self.args.push(nt_name.to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_single_field(&mut self, field_name: &str, val: &str, is_re: bool) -> Result<()> {
|
||||
let note_types = self.col.storage.get_all_notetypes_as_schema11()?;
|
||||
let note_types = self.col.storage.get_all_notetype_core()?;
|
||||
|
||||
let mut field_map = vec![];
|
||||
for nt in note_types.values() {
|
||||
for field in &nt.flds {
|
||||
let fields = self.col.storage.get_notetype_fields(nt.id())?;
|
||||
for field in &fields {
|
||||
if matches_wildcard(&field.name, field_name) {
|
||||
field_map.push((nt.id, field.ord));
|
||||
field_map.push((nt.id(), field.ord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -539,18 +526,11 @@ mod test {
|
|||
assert_eq!(s(ctx, "deck:filtered"), ("(c.odid > 0)".into(), vec![],));
|
||||
|
||||
// card
|
||||
assert_eq!(s(ctx, "card:front"), ("(false)".into(), vec![],));
|
||||
assert_eq!(
|
||||
s(ctx, r#""card:card 1""#),
|
||||
(
|
||||
concat!(
|
||||
"(((n.mid = 1581236385344 and c.ord = 0) or ",
|
||||
"(n.mid = 1581236385345 and c.ord = 0) or ",
|
||||
"(n.mid = 1581236385346 and c.ord = 0) or ",
|
||||
"(n.mid = 1581236385347 and c.ord = 0)))"
|
||||
)
|
||||
.into(),
|
||||
vec![],
|
||||
"((n.mid,c.ord) in (select ntid,ord from templates where name = ?))".into(),
|
||||
vec!["card 1".into()]
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -633,10 +613,19 @@ mod test {
|
|||
);
|
||||
|
||||
// note types by name
|
||||
assert_eq!(&s(ctx, "note:basic").0, "(n.mid in (1581236385347))");
|
||||
assert_eq!(
|
||||
&s(ctx, "note:basic*").0,
|
||||
"(n.mid in (1581236385345,1581236385346,1581236385347,1581236385344))"
|
||||
s(ctx, "note:basic"),
|
||||
(
|
||||
"(n.mid in (select id from notetypes where name = ?))".into(),
|
||||
vec!["basic".into()]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
s(ctx, "note:basic*"),
|
||||
(
|
||||
"(n.mid in (select id from notetypes where name regexp ?))".into(),
|
||||
vec!["basic.*".into()]
|
||||
)
|
||||
);
|
||||
|
||||
// regex
|
||||
|
|
|
@ -4,4 +4,6 @@ select
|
|||
config
|
||||
from fields
|
||||
where
|
||||
ntid = ?
|
||||
ntid = ?
|
||||
order by
|
||||
ord
|
|
@ -1,8 +1,7 @@
|
|||
select
|
||||
id,
|
||||
name,
|
||||
mtime_secs,
|
||||
usn,
|
||||
config
|
||||
from notetypes
|
||||
where
|
||||
id = ?
|
|
@ -6,4 +6,6 @@ select
|
|||
config
|
||||
from templates
|
||||
where
|
||||
ntid = ?
|
||||
ntid = ?
|
||||
order by
|
||||
ord
|
|
@ -10,31 +10,41 @@ use crate::{
|
|||
notetype::{NoteTypeID, NoteTypeSchema11},
|
||||
};
|
||||
use prost::Message;
|
||||
use rusqlite::{params, NO_PARAMS};
|
||||
use rusqlite::{params, Row, NO_PARAMS};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use unicase::UniCase;
|
||||
|
||||
fn row_to_notetype_core(row: &Row) -> Result<NoteType> {
|
||||
let config = NoteTypeConfig::decode(row.get_raw(4).as_blob()?)?;
|
||||
Ok(NoteType {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
mtime_secs: row.get(2)?,
|
||||
usn: row.get(3)?,
|
||||
config: Some(config),
|
||||
fields: vec![],
|
||||
templates: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
impl SqliteStorage {
|
||||
fn get_notetype_core(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> {
|
||||
self.db
|
||||
.prepare_cached(include_str!("get_notetype.sql"))?
|
||||
.query_and_then(&[ntid], |row| {
|
||||
let config = NoteTypeConfig::decode(row.get_raw(3).as_blob()?)?;
|
||||
Ok(NoteType {
|
||||
id: ntid.0,
|
||||
name: row.get(0)?,
|
||||
mtime_secs: row.get(1)?,
|
||||
usn: row.get(2)?,
|
||||
config: Some(config),
|
||||
fields: vec![],
|
||||
templates: vec![],
|
||||
})
|
||||
})?
|
||||
.prepare_cached(concat!(include_str!("get_notetype.sql"), " where id = ?"))?
|
||||
.query_and_then(&[ntid], row_to_notetype_core)?
|
||||
.next()
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteField>> {
|
||||
pub(crate) fn get_all_notetype_core(&self) -> Result<HashMap<NoteTypeID, NoteType>> {
|
||||
self.db
|
||||
.prepare_cached(include_str!("get_notetype.sql"))?
|
||||
.query_and_then(NO_PARAMS, row_to_notetype_core)?
|
||||
.map(|ntres| ntres.map(|nt| (nt.id(), nt)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteField>> {
|
||||
self.db
|
||||
.prepare_cached(include_str!("get_fields.sql"))?
|
||||
.query_and_then(&[ntid], |row| {
|
||||
|
|
Loading…
Reference in a new issue