start work on field changes, and add search_cards to col
This commit is contained in:
parent
cc297f1dc6
commit
04f0ea8599
@ -24,7 +24,7 @@ use crate::{
|
||||
notetype::{all_stock_notetypes, NoteTypeID, NoteTypeSchema11},
|
||||
sched::cutoff::{local_minutes_west_for_stamp, sched_timing_today},
|
||||
sched::timespan::{answer_button_time, learning_congrats, studied_today, time_span},
|
||||
search::{search_cards, SortMode},
|
||||
search::SortMode,
|
||||
template::{
|
||||
render_card, without_legacy_template_directives, FieldMap, FieldRequirements,
|
||||
ParsedTemplate, RenderedNode,
|
||||
@ -696,7 +696,7 @@ impl Backend {
|
||||
} else {
|
||||
SortMode::FromConfig
|
||||
};
|
||||
let cids = search_cards(col, &input.search, order)?;
|
||||
let cids = col.search_cards(&input.search, order)?;
|
||||
Ok(pb::SearchCardsOut {
|
||||
card_ids: cids.into_iter().map(|v| v.0).collect(),
|
||||
})
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
mod fields;
|
||||
mod schema11;
|
||||
mod schemachange;
|
||||
mod stock;
|
||||
mod templates;
|
||||
|
||||
@ -16,7 +17,9 @@ pub use stock::all_stock_notetypes;
|
||||
pub use templates::CardTemplate;
|
||||
|
||||
use crate::{
|
||||
collection::Collection,
|
||||
define_newtype,
|
||||
err::{AnkiError, Result},
|
||||
template::{without_legacy_template_directives, FieldRequirements, ParsedTemplate},
|
||||
text::ensure_string_in_nfc,
|
||||
timestamp::TimestampSecs,
|
||||
@ -175,3 +178,16 @@ impl From<NoteType> for NoteTypeProto {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
pub fn update_notetype(&mut self, nt: &mut NoteType) -> Result<()> {
|
||||
self.transact(None, |col| {
|
||||
let existing_notetype = col
|
||||
.storage
|
||||
.get_full_notetype(nt.id)?
|
||||
.ok_or_else(|| AnkiError::invalid_input("no such notetype"))?;
|
||||
col.update_notes_for_changed_fields(nt, existing_notetype.fields.len())?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
73
rslib/src/notetype/schemachange.rs
Normal file
73
rslib/src/notetype/schemachange.rs
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use super::{NoteField, NoteType};
|
||||
use crate::{collection::Collection, err::Result};
|
||||
|
||||
/// If any fields added, removed or reordered, returns a list of the new
|
||||
/// field length, comprised of the original ordinals.
|
||||
fn field_change_map(fields: &[NoteField], previous_field_count: usize) -> Option<Vec<Option<u32>>> {
|
||||
let map: Vec<_> = fields.iter().map(|f| f.ord).collect();
|
||||
let changed = map.len() != previous_field_count
|
||||
|| map
|
||||
.iter()
|
||||
.enumerate()
|
||||
.any(|(idx, f)| f != &Some(idx as u32));
|
||||
if changed {
|
||||
Some(map)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
/// Caller must create transaction
|
||||
pub(crate) fn update_notes_for_changed_fields(
|
||||
&mut self,
|
||||
nt: &NoteType,
|
||||
previous_field_count: usize,
|
||||
) -> Result<()> {
|
||||
let change_map = match field_change_map(&nt.fields, previous_field_count) {
|
||||
None => {
|
||||
// nothing to do
|
||||
return Ok(());
|
||||
}
|
||||
Some(map) => map,
|
||||
};
|
||||
|
||||
let nids = self.search_notes(&format!("mid:{}", nt.id))?;
|
||||
let usn = self.usn()?;
|
||||
for nid in nids {
|
||||
let mut note = self.storage.get_note(nid)?.unwrap();
|
||||
note.fields = change_map
|
||||
.iter()
|
||||
.map(|f| {
|
||||
if let Some(idx) = f {
|
||||
note.fields
|
||||
.get(*idx as usize)
|
||||
.map(AsRef::as_ref)
|
||||
.unwrap_or("")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
})
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
note.prepare_for_update(nt.config.sort_field_idx as usize, usn);
|
||||
self.storage.update_note(¬e)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::collection::open_test_collection;
|
||||
|
||||
#[test]
|
||||
fn fields() {
|
||||
let mut _col = open_test_collection();
|
||||
|
||||
// fixme: need note adding before we can check this
|
||||
}
|
||||
}
|
@ -10,51 +10,49 @@ use crate::err::Result;
|
||||
use crate::search::parser::parse;
|
||||
use rusqlite::params;
|
||||
|
||||
pub(crate) enum SortMode {
|
||||
pub enum SortMode {
|
||||
NoOrder,
|
||||
FromConfig,
|
||||
Builtin { kind: SortKind, reverse: bool },
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
pub(crate) fn search_cards<'a, 'b>(
|
||||
req: &'b mut Collection,
|
||||
search: &'a str,
|
||||
order: SortMode,
|
||||
) -> Result<Vec<CardID>> {
|
||||
let top_node = Node::Group(parse(search)?);
|
||||
let (sql, args) = node_to_sql(req, &top_node)?;
|
||||
impl Collection {
|
||||
pub fn search_cards(&mut self, search: &str, order: SortMode) -> Result<Vec<CardID>> {
|
||||
let top_node = Node::Group(parse(search)?);
|
||||
let (sql, args) = node_to_sql(self, &top_node)?;
|
||||
|
||||
let mut sql = format!(
|
||||
"select c.id from cards c, notes n where c.nid=n.id and {}",
|
||||
sql
|
||||
);
|
||||
let mut sql = format!(
|
||||
"select c.id from cards c, notes n where c.nid=n.id and {}",
|
||||
sql
|
||||
);
|
||||
|
||||
match order {
|
||||
SortMode::NoOrder => (),
|
||||
SortMode::FromConfig => {
|
||||
let kind = req.get_browser_sort_kind();
|
||||
prepare_sort(req, &kind)?;
|
||||
sql.push_str(" order by ");
|
||||
write_order(&mut sql, &kind, req.get_browser_sort_reverse())?;
|
||||
}
|
||||
SortMode::Builtin { kind, reverse } => {
|
||||
prepare_sort(req, &kind)?;
|
||||
sql.push_str(" order by ");
|
||||
write_order(&mut sql, &kind, reverse)?;
|
||||
}
|
||||
SortMode::Custom(order_clause) => {
|
||||
sql.push_str(" order by ");
|
||||
sql.push_str(&order_clause);
|
||||
match order {
|
||||
SortMode::NoOrder => (),
|
||||
SortMode::FromConfig => {
|
||||
let kind = self.get_browser_sort_kind();
|
||||
prepare_sort(self, &kind)?;
|
||||
sql.push_str(" order by ");
|
||||
write_order(&mut sql, &kind, self.get_browser_sort_reverse())?;
|
||||
}
|
||||
SortMode::Builtin { kind, reverse } => {
|
||||
prepare_sort(self, &kind)?;
|
||||
sql.push_str(" order by ");
|
||||
write_order(&mut sql, &kind, reverse)?;
|
||||
}
|
||||
SortMode::Custom(order_clause) => {
|
||||
sql.push_str(" order by ");
|
||||
sql.push_str(&order_clause);
|
||||
}
|
||||
}
|
||||
|
||||
let mut stmt = self.storage.db.prepare(&sql)?;
|
||||
let ids: Vec<_> = stmt
|
||||
.query_map(&args, |row| row.get(0))?
|
||||
.collect::<std::result::Result<_, _>>()?;
|
||||
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
let mut stmt = req.storage.db.prepare(&sql)?;
|
||||
let ids: Vec<_> = stmt
|
||||
.query_map(&args, |row| row.get(0))?
|
||||
.collect::<std::result::Result<_, _>>()?;
|
||||
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
/// Add the order clause to the sql.
|
||||
@ -96,24 +94,24 @@ fn write_order(sql: &mut String, kind: &SortKind, reverse: bool) -> Result<()> {
|
||||
|
||||
// In the future these items should be moved from JSON into separate SQL tables,
|
||||
// - for now we use a temporary deck to sort them.
|
||||
fn prepare_sort(req: &mut Collection, kind: &SortKind) -> Result<()> {
|
||||
fn prepare_sort(col: &mut Collection, kind: &SortKind) -> Result<()> {
|
||||
use SortKind::*;
|
||||
match kind {
|
||||
CardDeck | NoteType => {
|
||||
prepare_sort_order_table(req)?;
|
||||
let mut stmt = req
|
||||
prepare_sort_order_table(col)?;
|
||||
let mut stmt = col
|
||||
.storage
|
||||
.db
|
||||
.prepare("insert into sort_order (k,v) values (?,?)")?;
|
||||
|
||||
match kind {
|
||||
CardDeck => {
|
||||
for (k, v) in req.storage.get_all_decks()? {
|
||||
for (k, v) in col.storage.get_all_decks()? {
|
||||
stmt.execute(params![k, v.name()])?;
|
||||
}
|
||||
}
|
||||
NoteType => {
|
||||
for (k, v) in req.storage.get_all_notetypes_as_schema11()? {
|
||||
for (k, v) in col.storage.get_all_notetypes_as_schema11()? {
|
||||
stmt.execute(params![k, v.name])?;
|
||||
}
|
||||
}
|
||||
@ -121,13 +119,13 @@ fn prepare_sort(req: &mut Collection, kind: &SortKind) -> Result<()> {
|
||||
}
|
||||
}
|
||||
CardTemplate => {
|
||||
prepare_sort_order_table2(req)?;
|
||||
let mut stmt = req
|
||||
prepare_sort_order_table2(col)?;
|
||||
let mut stmt = col
|
||||
.storage
|
||||
.db
|
||||
.prepare("insert into sort_order (k1,k2,v) values (?,?,?)")?;
|
||||
|
||||
for (ntid, nt) in req.storage.get_all_notetypes_as_schema11()? {
|
||||
for (ntid, nt) in col.storage.get_all_notetypes_as_schema11()? {
|
||||
for tmpl in nt.tmpls {
|
||||
stmt.execute(params![ntid, tmpl.ord, tmpl.name])?;
|
||||
}
|
||||
@ -139,15 +137,15 @@ fn prepare_sort(req: &mut Collection, kind: &SortKind) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_sort_order_table(req: &mut Collection) -> Result<()> {
|
||||
req.storage
|
||||
fn prepare_sort_order_table(col: &mut Collection) -> Result<()> {
|
||||
col.storage
|
||||
.db
|
||||
.execute_batch(include_str!("sort_order.sql"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_sort_order_table2(req: &mut Collection) -> Result<()> {
|
||||
req.storage
|
||||
fn prepare_sort_order_table2(col: &mut Collection) -> Result<()> {
|
||||
col.storage
|
||||
.db
|
||||
.execute_batch(include_str!("sort_order2.sql"))?;
|
||||
Ok(())
|
||||
|
@ -3,4 +3,4 @@ mod notes;
|
||||
mod parser;
|
||||
mod sqlwriter;
|
||||
|
||||
pub(crate) use cards::{search_cards, SortMode};
|
||||
pub use cards::SortMode;
|
||||
|
@ -73,7 +73,7 @@ impl SqliteStorage {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_full_notetype(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> {
|
||||
pub(crate) fn get_full_notetype(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> {
|
||||
match self.get_notetype_core(ntid)? {
|
||||
Some(mut nt) => {
|
||||
nt.fields = self.get_notetype_fields(ntid)?;
|
||||
|
Loading…
Reference in New Issue
Block a user