cache notetypes

This commit is contained in:
Damien Elmes 2020-04-18 10:23:14 +10:00
parent 1ca7fb4a80
commit a226f70733
5 changed files with 49 additions and 34 deletions

View file

@ -7,11 +7,12 @@ use crate::log::Logger;
use crate::timestamp::TimestampSecs; use crate::timestamp::TimestampSecs;
use crate::types::Usn; use crate::types::Usn;
use crate::{ use crate::{
notetype::{NoteType, NoteTypeID},
sched::cutoff::{sched_timing_today, SchedTimingToday}, sched::cutoff::{sched_timing_today, SchedTimingToday},
storage::SqliteStorage, storage::SqliteStorage,
undo::UndoManager, undo::UndoManager,
}; };
use std::path::PathBuf; use std::{collections::HashMap, path::PathBuf, sync::Arc};
pub fn open_collection<P: Into<PathBuf>>( pub fn open_collection<P: Into<PathBuf>>(
path: P, path: P,
@ -50,6 +51,7 @@ pub struct CollectionState {
task_state: CollectionTaskState, task_state: CollectionTaskState,
pub(crate) undo: UndoManager, pub(crate) undo: UndoManager,
timing_today: Option<SchedTimingToday>, timing_today: Option<SchedTimingToday>,
pub(crate) notetype_cache: HashMap<NoteTypeID, Arc<NoteType>>,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]

View file

@ -380,7 +380,7 @@ where
renamed: &HashMap<String, String>, renamed: &HashMap<String, String>,
) -> Result<HashSet<String>> { ) -> Result<HashSet<String>> {
let mut referenced_files = HashSet::new(); let mut referenced_files = HashSet::new();
let note_types = self.ctx.storage.get_all_notetype_core()?; let note_types = self.ctx.get_all_notetypes()?;
let mut collection_modified = false; let mut collection_modified = false;
let nids = self.ctx.search_notes("")?; let nids = self.ctx.search_notes("")?;

View file

@ -30,7 +30,10 @@ use crate::{
timestamp::TimestampSecs, timestamp::TimestampSecs,
types::Usn, types::Usn,
}; };
use std::collections::{HashMap, HashSet}; use std::{
collections::{HashMap, HashSet},
sync::Arc,
};
use unicase::UniCase; use unicase::UniCase;
define_newtype!(NoteTypeID, i64); define_newtype!(NoteTypeID, i64);
@ -200,11 +203,45 @@ impl Collection {
.get_notetype(nt.id)? .get_notetype(nt.id)?
.ok_or_else(|| AnkiError::invalid_input("no such notetype"))?; .ok_or_else(|| AnkiError::invalid_input("no such notetype"))?;
col.update_notes_for_changed_fields(nt, existing_notetype.fields.len())?; col.update_notes_for_changed_fields(nt, existing_notetype.fields.len())?;
// fixme: card templates
// fixme: update cache instead of clearing
col.state.notetype_cache.remove(&nt.id);
Ok(()) Ok(())
}) })
} }
pub fn get_notetype_by_name(&mut self, name: &str) -> Result<Option<NoteType>> { pub fn get_notetype_by_name(&mut self, name: &str) -> Result<Option<Arc<NoteType>>> {
self.storage.get_notetype_by_name(name) if let Some(ntid) = self.storage.get_notetype_id(name)? {
self.get_notetype(ntid)
} else {
Ok(None)
}
}
pub fn get_notetype(&mut self, ntid: NoteTypeID) -> Result<Option<Arc<NoteType>>> {
if let Some(nt) = self.state.notetype_cache.get(&ntid) {
return Ok(Some(nt.clone()));
}
if let Some(nt) = self.storage.get_notetype(ntid)? {
let nt = Arc::new(nt);
self.state.notetype_cache.insert(ntid, nt.clone());
Ok(Some(nt))
} else {
Ok(None)
}
}
pub fn get_all_notetypes(&mut self) -> Result<HashMap<NoteTypeID, Arc<NoteType>>> {
self.storage
.get_all_notetype_names()?
.into_iter()
.map(|(ntid, _)| {
self.get_notetype(ntid)
.transpose()
.unwrap()
.map(|nt| (ntid, nt))
})
.collect()
} }
} }

View file

@ -297,12 +297,11 @@ impl SqlWriter<'_> {
} }
fn write_single_field(&mut self, field_name: &str, val: &str, is_re: bool) -> Result<()> { fn write_single_field(&mut self, field_name: &str, val: &str, is_re: bool) -> Result<()> {
let note_types = self.col.storage.get_all_notetype_core()?; let note_types = self.col.get_all_notetypes()?;
let mut field_map = vec![]; let mut field_map = vec![];
for nt in note_types.values() { for nt in note_types.values() {
let fields = self.col.storage.get_notetype_fields(nt.id)?; for field in &nt.fields {
for field in &fields {
if matches_wildcard(&field.name, field_name) { if matches_wildcard(&field.name, field_name) {
field_map.push((nt.id, field.ord)); field_map.push((nt.id, field.ord));
} }

View file

@ -46,21 +46,7 @@ impl SqliteStorage {
.transpose() .transpose()
} }
pub(crate) fn get_all_notetype_core(&self) -> Result<HashMap<NoteTypeID, NoteType>> { fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteField>> {
let mut nts: 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::<Result<_>>()?;
for nt in nts.values_mut() {
nt.fields = self.get_notetype_fields(nt.id)?;
}
Ok(nts)
}
// pub as currently used by searching code
pub(crate) fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteField>> {
self.db self.db
.prepare_cached(include_str!("get_fields.sql"))? .prepare_cached(include_str!("get_fields.sql"))?
.query_and_then(&[ntid], |row| { .query_and_then(&[ntid], |row| {
@ -90,7 +76,7 @@ impl SqliteStorage {
.collect() .collect()
} }
fn get_notetype_id(&self, name: &str) -> Result<Option<NoteTypeID>> { pub(crate) fn get_notetype_id(&self, name: &str) -> Result<Option<NoteTypeID>> {
self.db self.db
.prepare_cached("select id from notetypes where name = ?")? .prepare_cached("select id from notetypes where name = ?")?
.query_row(params![name], |row| row.get(0)) .query_row(params![name], |row| row.get(0))
@ -98,16 +84,7 @@ impl SqliteStorage {
.map_err(Into::into) .map_err(Into::into)
} }
pub fn get_notetype_by_name(&mut self, name: &str) -> Result<Option<NoteType>> { pub fn get_all_notetype_names(&self) -> Result<Vec<(NoteTypeID, String)>> {
if let Some(id) = self.get_notetype_id(name)? {
self.get_notetype(id)
} else {
Ok(None)
}
}
#[allow(dead_code)]
fn get_all_notetype_names(&self) -> Result<Vec<(NoteTypeID, String)>> {
self.db self.db
.prepare_cached(include_str!("get_notetype_names.sql"))? .prepare_cached(include_str!("get_notetype_names.sql"))?
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))? .query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))?