mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 08:22:24 -04:00
rework aux table sorting
Instead of inserting text into the aux table and sorting on the fly (which does a binary sort), we insert the ids in unicase-sorted order, and then sort based on the automatically assigned rowids - giving us faster sorts, and proper unicase folding.
This commit is contained in:
parent
8246ba148e
commit
8d17edc1e6
7 changed files with 65 additions and 62 deletions
|
@ -158,7 +158,7 @@ impl Collection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, PartialEq, Debug)]
|
#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum SortKind {
|
pub enum SortKind {
|
||||||
#[serde(rename = "noteCrt")]
|
#[serde(rename = "noteCrt")]
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::collection::Collection;
|
||||||
use crate::config::SortKind;
|
use crate::config::SortKind;
|
||||||
use crate::err::Result;
|
use crate::err::Result;
|
||||||
use crate::search::parser::parse;
|
use crate::search::parser::parse;
|
||||||
use rusqlite::params;
|
|
||||||
|
|
||||||
pub enum SortMode {
|
pub enum SortMode {
|
||||||
NoOrder,
|
NoOrder,
|
||||||
|
@ -31,14 +30,14 @@ impl Collection {
|
||||||
SortMode::NoOrder => (),
|
SortMode::NoOrder => (),
|
||||||
SortMode::FromConfig => {
|
SortMode::FromConfig => {
|
||||||
let kind = self.get_browser_sort_kind();
|
let kind = self.get_browser_sort_kind();
|
||||||
prepare_sort(self, &kind)?;
|
prepare_sort(self, kind)?;
|
||||||
sql.push_str(" order by ");
|
sql.push_str(" order by ");
|
||||||
write_order(&mut sql, &kind, self.get_browser_sort_reverse())?;
|
write_order(&mut sql, kind, self.get_browser_sort_reverse())?;
|
||||||
}
|
}
|
||||||
SortMode::Builtin { kind, reverse } => {
|
SortMode::Builtin { kind, reverse } => {
|
||||||
prepare_sort(self, &kind)?;
|
prepare_sort(self, kind)?;
|
||||||
sql.push_str(" order by ");
|
sql.push_str(" order by ");
|
||||||
write_order(&mut sql, &kind, reverse)?;
|
write_order(&mut sql, kind, reverse)?;
|
||||||
}
|
}
|
||||||
SortMode::Custom(order_clause) => {
|
SortMode::Custom(order_clause) => {
|
||||||
sql.push_str(" order by ");
|
sql.push_str(" order by ");
|
||||||
|
@ -56,7 +55,7 @@ impl Collection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add the order clause to the sql.
|
/// Add the order clause to the sql.
|
||||||
fn write_order(sql: &mut String, kind: &SortKind, reverse: bool) -> Result<()> {
|
fn write_order(sql: &mut String, kind: SortKind, reverse: bool) -> Result<()> {
|
||||||
let tmp_str;
|
let tmp_str;
|
||||||
let order = match kind {
|
let order = match kind {
|
||||||
SortKind::NoteCreation => "n.id asc, c.ord asc",
|
SortKind::NoteCreation => "n.id asc, c.ord asc",
|
||||||
|
@ -72,9 +71,13 @@ fn write_order(sql: &mut String, kind: &SortKind, reverse: bool) -> Result<()> {
|
||||||
SortKind::CardLapses => "c.lapses asc",
|
SortKind::CardLapses => "c.lapses asc",
|
||||||
SortKind::CardInterval => "c.ivl asc",
|
SortKind::CardInterval => "c.ivl asc",
|
||||||
SortKind::NoteTags => "n.tags asc",
|
SortKind::NoteTags => "n.tags asc",
|
||||||
SortKind::CardDeck => "(select v from sort_order where k = c.did) asc",
|
SortKind::CardDeck => "(select pos from sort_order where did = c.did) asc",
|
||||||
SortKind::NoteType => "(select v from sort_order where k = n.mid) asc",
|
SortKind::NoteType => "(select pos from sort_order where ntid = n.mid) asc",
|
||||||
SortKind::CardTemplate => "(select v from sort_order where k1 = n.mid and k2 = c.ord) asc",
|
SortKind::CardTemplate => concat!(
|
||||||
|
"coalesce((select pos from sort_order where ntid = n.mid and ord = c.ord),",
|
||||||
|
// need to fall back on ord 0 for cloze cards
|
||||||
|
"(select pos from sort_order where ntid = n.mid and ord = 0)) asc"
|
||||||
|
),
|
||||||
};
|
};
|
||||||
if order.is_empty() {
|
if order.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -92,60 +95,28 @@ fn write_order(sql: &mut String, kind: &SortKind, reverse: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixme: use the new tables
|
fn needs_aux_sort_table(kind: SortKind) -> bool {
|
||||||
fn prepare_sort(col: &mut Collection, kind: &SortKind) -> Result<()> {
|
|
||||||
use SortKind::*;
|
use SortKind::*;
|
||||||
match kind {
|
match kind {
|
||||||
CardDeck | NoteType => {
|
CardDeck | NoteType | CardTemplate => true,
|
||||||
prepare_sort_order_table(col)?;
|
_ => false,
|
||||||
let mut stmt = col
|
}
|
||||||
.storage
|
}
|
||||||
.db
|
|
||||||
.prepare("insert into sort_order (k,v) values (?,?)")?;
|
|
||||||
|
|
||||||
match kind {
|
fn prepare_sort(col: &mut Collection, kind: SortKind) -> Result<()> {
|
||||||
CardDeck => {
|
if !needs_aux_sort_table(kind) {
|
||||||
for (k, v) in col.storage.get_all_decks_as_schema11()? {
|
return Ok(());
|
||||||
stmt.execute(params![k, v.name()])?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NoteType => {
|
|
||||||
for (k, v) in col.storage.get_all_notetypes_as_schema11()? {
|
|
||||||
stmt.execute(params![k, v.name])?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CardTemplate => {
|
|
||||||
prepare_sort_order_table2(col)?;
|
|
||||||
let mut stmt = col
|
|
||||||
.storage
|
|
||||||
.db
|
|
||||||
.prepare("insert into sort_order (k1,k2,v) values (?,?,?)")?;
|
|
||||||
|
|
||||||
for (ntid, nt) in col.storage.get_all_notetypes_as_schema11()? {
|
|
||||||
for tmpl in nt.tmpls {
|
|
||||||
stmt.execute(params![ntid, tmpl.ord, tmpl.name])?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
use SortKind::*;
|
||||||
}
|
let sql = match kind {
|
||||||
|
CardDeck => include_str!("deck_order.sql"),
|
||||||
|
NoteType => include_str!("notetype_order.sql"),
|
||||||
|
CardTemplate => include_str!("template_order.sql"),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
fn prepare_sort_order_table(col: &mut Collection) -> Result<()> {
|
col.storage.db.execute_batch(sql)?;
|
||||||
col.storage
|
|
||||||
.db
|
|
||||||
.execute_batch(include_str!("sort_order.sql"))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_sort_order_table2(col: &mut Collection) -> Result<()> {
|
|
||||||
col.storage
|
|
||||||
.db
|
|
||||||
.execute_batch(include_str!("sort_order2.sql"))?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
11
rslib/src/search/deck_order.sql
Normal file
11
rslib/src/search/deck_order.sql
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
drop table if exists sort_order;
|
||||||
|
create temporary table sort_order (
|
||||||
|
pos integer primary key,
|
||||||
|
did integer not null unique
|
||||||
|
);
|
||||||
|
insert into sort_order (did)
|
||||||
|
select
|
||||||
|
id
|
||||||
|
from decks
|
||||||
|
order by
|
||||||
|
name;
|
11
rslib/src/search/notetype_order.sql
Normal file
11
rslib/src/search/notetype_order.sql
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
drop table if exists sort_order;
|
||||||
|
create temporary table sort_order (
|
||||||
|
pos integer primary key,
|
||||||
|
ntid integer not null unique
|
||||||
|
);
|
||||||
|
insert into sort_order (ntid)
|
||||||
|
select
|
||||||
|
id
|
||||||
|
from notetypes
|
||||||
|
order by
|
||||||
|
name;
|
|
@ -1,2 +0,0 @@
|
||||||
drop table if exists sort_order;
|
|
||||||
create temporary table sort_order (k int primary key, v text);
|
|
|
@ -1,2 +0,0 @@
|
||||||
drop table if exists sort_order;
|
|
||||||
create temporary table sort_order (k1 int, k2 int, v text, primary key (k1, k2)) without rowid;
|
|
14
rslib/src/search/template_order.sql
Normal file
14
rslib/src/search/template_order.sql
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
drop table if exists sort_order;
|
||||||
|
create temporary table sort_order (
|
||||||
|
pos integer primary key,
|
||||||
|
ntid integer not null,
|
||||||
|
ord integer not null,
|
||||||
|
unique(ntid, ord)
|
||||||
|
);
|
||||||
|
insert into sort_order (ntid, ord)
|
||||||
|
select
|
||||||
|
ntid,
|
||||||
|
ord
|
||||||
|
from templates
|
||||||
|
order by
|
||||||
|
name
|
Loading…
Reference in a new issue