Decouple browse views from FTS
This commit is contained in:
parent
9fa2dbbadc
commit
d8ecf5f607
3 changed files with 40 additions and 106 deletions
138
script.js
138
script.js
|
@ -1471,38 +1471,6 @@
|
|||
ORDER BY name COLLATE NOCASE
|
||||
LIMIT ${pageSize} OFFSET ${offset}
|
||||
`;
|
||||
const ftsCountSql = `
|
||||
SELECT COUNT(*) AS count FROM (
|
||||
SELECT a.id
|
||||
FROM fts_tracks
|
||||
JOIN tracks t ON t.id = fts_tracks.rowid
|
||||
JOIN artists a ON a.id = t.artist_id
|
||||
WHERE fts_tracks MATCH ?
|
||||
GROUP BY a.id
|
||||
) AS matches
|
||||
`;
|
||||
const buildFtsRowsSql = (pageSize, offset) => `
|
||||
SELECT a.id, a.name
|
||||
FROM fts_tracks
|
||||
JOIN tracks t ON t.id = fts_tracks.rowid
|
||||
JOIN artists a ON a.id = t.artist_id
|
||||
WHERE fts_tracks MATCH ?
|
||||
GROUP BY a.id
|
||||
ORDER BY a.name COLLATE NOCASE
|
||||
LIMIT ${pageSize} OFFSET ${offset}
|
||||
`;
|
||||
|
||||
function buildArtistFtsMatch(input) {
|
||||
const tokens = String(input)
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.split(/\s+/)
|
||||
.map((token) => token.replace(/[^0-9a-z]/gi, '').slice(0, 32))
|
||||
.filter((token) => token.length >= 2);
|
||||
if (!tokens.length) return null;
|
||||
return tokens.map((token) => `artist:${token}*`).join(' AND ');
|
||||
}
|
||||
|
||||
function updateJumpButtons() {
|
||||
jumpButtons.forEach((btn) => {
|
||||
const letter = btn.dataset.letter || 'all';
|
||||
|
@ -1514,7 +1482,6 @@
|
|||
|
||||
function loadArtistsImmediate() {
|
||||
const typedFilter = state.filter.trim();
|
||||
const ftsMatch = buildArtistFtsMatch(typedFilter);
|
||||
const likeTerm = buildLikeTerm();
|
||||
const useUnfilteredQuery = !typedFilter && !state.prefix;
|
||||
listState.showLoading('Loading…');
|
||||
|
@ -1541,83 +1508,46 @@
|
|||
({ pageSize, offset } = initialSanitized);
|
||||
let total = 0;
|
||||
const rows = [];
|
||||
let usedFts = false;
|
||||
|
||||
try {
|
||||
if (ftsMatch) {
|
||||
const ftsCountStmt = prepareForView(
|
||||
db,
|
||||
VIEW_NAMES.browseArtists,
|
||||
applyFtsMatch(ftsCountSql, ftsMatch),
|
||||
'fts-count',
|
||||
);
|
||||
if (ftsCountStmt.step()) total = Number(ftsCountStmt.getAsObject().count) || 0;
|
||||
ftsCountStmt.free();
|
||||
const countStmt = prepareForView(
|
||||
db,
|
||||
VIEW_NAMES.browseArtists,
|
||||
useUnfilteredQuery ? baseCountSql : countSql,
|
||||
useUnfilteredQuery ? 'count' : 'count-filtered',
|
||||
);
|
||||
if (!useUnfilteredQuery) countStmt.bind([likeTerm]);
|
||||
if (countStmt.step()) total = Number(countStmt.getAsObject().count) || 0;
|
||||
countStmt.free();
|
||||
|
||||
if (total > 0) {
|
||||
if (clampPaginationToTotal({
|
||||
state,
|
||||
total,
|
||||
pageSize,
|
||||
view: VIEW_NAMES.browseArtists,
|
||||
})) {
|
||||
({ page, pageSize, offset } = getNormalizedPagination());
|
||||
const sanitized = sanitizeLimitAndOffset(pageSize, offset);
|
||||
if (!sanitized) return;
|
||||
({ pageSize, offset } = sanitized);
|
||||
}
|
||||
const ftsRowsStmt = prepareForView(
|
||||
db,
|
||||
VIEW_NAMES.browseArtists,
|
||||
applyFtsMatch(buildFtsRowsSql(pageSize, offset), ftsMatch),
|
||||
'fts-rows',
|
||||
);
|
||||
while (ftsRowsStmt.step()) rows.push(ftsRowsStmt.getAsObject());
|
||||
ftsRowsStmt.free();
|
||||
usedFts = true;
|
||||
}
|
||||
if (total === 0) {
|
||||
table.clear();
|
||||
listState.showEmpty('No artists found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!usedFts) {
|
||||
const countStmt = prepareForView(
|
||||
db,
|
||||
VIEW_NAMES.browseArtists,
|
||||
useUnfilteredQuery ? baseCountSql : countSql,
|
||||
useUnfilteredQuery ? 'count' : 'count-filtered',
|
||||
);
|
||||
if (!useUnfilteredQuery) countStmt.bind([likeTerm]);
|
||||
if (countStmt.step()) total = Number(countStmt.getAsObject().count) || 0;
|
||||
countStmt.free();
|
||||
|
||||
if (total === 0) {
|
||||
table.clear();
|
||||
listState.showEmpty('No artists found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (clampPaginationToTotal({
|
||||
state,
|
||||
total,
|
||||
pageSize,
|
||||
view: VIEW_NAMES.browseArtists,
|
||||
})) {
|
||||
({ page, pageSize, offset } = getNormalizedPagination());
|
||||
const sanitized = sanitizeLimitAndOffset(pageSize, offset);
|
||||
if (!sanitized) return;
|
||||
({ pageSize, offset } = sanitized);
|
||||
}
|
||||
|
||||
const rowsStmt = prepareForView(
|
||||
db,
|
||||
VIEW_NAMES.browseArtists,
|
||||
useUnfilteredQuery
|
||||
? buildBaseRowsSql(pageSize, offset)
|
||||
: buildRowsSql(likeTerm, pageSize, offset),
|
||||
useUnfilteredQuery ? 'rows' : 'rows-filtered',
|
||||
);
|
||||
while (rowsStmt.step()) rows.push(rowsStmt.getAsObject());
|
||||
rowsStmt.free();
|
||||
if (clampPaginationToTotal({
|
||||
state,
|
||||
total,
|
||||
pageSize,
|
||||
view: VIEW_NAMES.browseArtists,
|
||||
})) {
|
||||
({ page, pageSize, offset } = getNormalizedPagination());
|
||||
const sanitized = sanitizeLimitAndOffset(pageSize, offset);
|
||||
if (!sanitized) return;
|
||||
({ pageSize, offset } = sanitized);
|
||||
}
|
||||
|
||||
const rowsStmt = prepareForView(
|
||||
db,
|
||||
VIEW_NAMES.browseArtists,
|
||||
useUnfilteredQuery
|
||||
? buildBaseRowsSql(pageSize, offset)
|
||||
: buildRowsSql(likeTerm, pageSize, offset),
|
||||
useUnfilteredQuery ? 'rows' : 'rows-filtered',
|
||||
);
|
||||
while (rowsStmt.step()) rows.push(rowsStmt.getAsObject());
|
||||
rowsStmt.free();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
listState.showError('Failed to load artists.');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue