Skip to content

Commit

Permalink
Merge pull request #9 from uklotzde/column-cache-fix
Browse files Browse the repository at this point in the history
ColumnCache: Verify consistency of all column maps
  • Loading branch information
ywwg authored Dec 16, 2020
2 parents 54fd729 + fe5d7ac commit 7a24153
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 78 deletions.
170 changes: 92 additions & 78 deletions src/library/columncache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,67 +22,71 @@ void ColumnCache::setColumns(const QStringList& columns) {
m_columnIndexByName.clear();
for (int i = 0; i < columns.size(); ++i) {
QString column = columns[i];
DEBUG_ASSERT(!m_columnIndexByName.contains(column));
m_columnIndexByName[column] = i;
}

m_columnNameByEnum.clear();
m_columnNameByEnum[COLUMN_LIBRARYTABLE_ID] = LIBRARYTABLE_ID;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_ARTIST] = LIBRARYTABLE_ARTIST;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_TITLE] = LIBRARYTABLE_TITLE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_ALBUM] = LIBRARYTABLE_ALBUM;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_ALBUMARTIST] = LIBRARYTABLE_ALBUMARTIST;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_YEAR] = LIBRARYTABLE_YEAR;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_GENRE] = LIBRARYTABLE_GENRE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COMPOSER] = LIBRARYTABLE_COMPOSER;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_GROUPING] = LIBRARYTABLE_GROUPING;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_TRACKNUMBER] = LIBRARYTABLE_TRACKNUMBER;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_FILETYPE] = LIBRARYTABLE_FILETYPE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_NATIVELOCATION] = LIBRARYTABLE_LOCATION;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COMMENT] = LIBRARYTABLE_COMMENT;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_DURATION] = LIBRARYTABLE_DURATION;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_BITRATE] = LIBRARYTABLE_BITRATE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_BPM] = LIBRARYTABLE_BPM;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_REPLAYGAIN] = LIBRARYTABLE_REPLAYGAIN;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_CUEPOINT] = LIBRARYTABLE_CUEPOINT;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_URL] = LIBRARYTABLE_URL;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_SAMPLERATE] = LIBRARYTABLE_SAMPLERATE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_WAVESUMMARYHEX] = LIBRARYTABLE_WAVESUMMARYHEX;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_CHANNELS] = LIBRARYTABLE_CHANNELS;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_MIXXXDELETED] = LIBRARYTABLE_MIXXXDELETED;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_DATETIMEADDED] = LIBRARYTABLE_DATETIMEADDED;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_HEADERPARSED] = LIBRARYTABLE_HEADERPARSED;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_TIMESPLAYED] = LIBRARYTABLE_TIMESPLAYED;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_PLAYED] = LIBRARYTABLE_PLAYED;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_RATING] = LIBRARYTABLE_RATING;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_KEY] = LIBRARYTABLE_KEY;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_KEY_ID] = LIBRARYTABLE_KEY_ID;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_BPM_LOCK] = LIBRARYTABLE_BPM_LOCK;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_PREVIEW] = LIBRARYTABLE_PREVIEW;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COLOR] = LIBRARYTABLE_COLOR;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COVERART] = LIBRARYTABLE_COVERART;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COVERART_SOURCE] = LIBRARYTABLE_COVERART_SOURCE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COVERART_TYPE] = LIBRARYTABLE_COVERART_TYPE;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COVERART_LOCATION] = LIBRARYTABLE_COVERART_LOCATION;
m_columnNameByEnum[COLUMN_LIBRARYTABLE_COVERART_HASH] = LIBRARYTABLE_COVERART_HASH;

m_columnNameByEnum[COLUMN_TRACKLOCATIONSTABLE_FSDELETED] = TRACKLOCATIONSTABLE_FSDELETED;

m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_TRACKID] = PLAYLISTTRACKSTABLE_TRACKID;
m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_POSITION] = PLAYLISTTRACKSTABLE_POSITION;
m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_PLAYLISTID] = PLAYLISTTRACKSTABLE_PLAYLISTID;
m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_LOCATION] = PLAYLISTTRACKSTABLE_LOCATION;
m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_ARTIST] = PLAYLISTTRACKSTABLE_ARTIST;
m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_TITLE] = PLAYLISTTRACKSTABLE_TITLE;
m_columnNameByEnum[COLUMN_PLAYLISTTRACKSTABLE_DATETIMEADDED] =
PLAYLISTTRACKSTABLE_DATETIMEADDED;

m_columnNameByEnum[COLUMN_REKORDBOX_ANALYZE_PATH] = REKORDBOX_ANALYZE_PATH;
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_ID, LIBRARYTABLE_ID);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_ARTIST, LIBRARYTABLE_ARTIST);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_TITLE, LIBRARYTABLE_TITLE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_ALBUM, LIBRARYTABLE_ALBUM);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_ALBUMARTIST, LIBRARYTABLE_ALBUMARTIST);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_YEAR, LIBRARYTABLE_YEAR);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_GENRE, LIBRARYTABLE_GENRE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COMPOSER, LIBRARYTABLE_COMPOSER);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_GROUPING, LIBRARYTABLE_GROUPING);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_TRACKNUMBER, LIBRARYTABLE_TRACKNUMBER);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_FILETYPE, LIBRARYTABLE_FILETYPE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_NATIVELOCATION, LIBRARYTABLE_LOCATION);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COMMENT, LIBRARYTABLE_COMMENT);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_DURATION, LIBRARYTABLE_DURATION);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_BITRATE, LIBRARYTABLE_BITRATE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_BPM, LIBRARYTABLE_BPM);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_REPLAYGAIN, LIBRARYTABLE_REPLAYGAIN);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_CUEPOINT, LIBRARYTABLE_CUEPOINT);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_URL, LIBRARYTABLE_URL);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_SAMPLERATE, LIBRARYTABLE_SAMPLERATE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_WAVESUMMARYHEX, LIBRARYTABLE_WAVESUMMARYHEX);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_CHANNELS, LIBRARYTABLE_CHANNELS);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_MIXXXDELETED, LIBRARYTABLE_MIXXXDELETED);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_DATETIMEADDED, LIBRARYTABLE_DATETIMEADDED);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_HEADERPARSED, LIBRARYTABLE_HEADERPARSED);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_TIMESPLAYED, LIBRARYTABLE_TIMESPLAYED);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_PLAYED, LIBRARYTABLE_PLAYED);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_RATING, LIBRARYTABLE_RATING);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_KEY, LIBRARYTABLE_KEY);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_KEY_ID, LIBRARYTABLE_KEY_ID);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_BPM_LOCK, LIBRARYTABLE_BPM_LOCK);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_PREVIEW, LIBRARYTABLE_PREVIEW);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COLOR, LIBRARYTABLE_COLOR);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COVERART, LIBRARYTABLE_COVERART);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COVERART_SOURCE, LIBRARYTABLE_COVERART_SOURCE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COVERART_TYPE, LIBRARYTABLE_COVERART_TYPE);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COVERART_LOCATION, LIBRARYTABLE_COVERART_LOCATION);
insertColumnNameByEnum(COLUMN_LIBRARYTABLE_COVERART_HASH, LIBRARYTABLE_COVERART_HASH);

insertColumnNameByEnum(COLUMN_TRACKLOCATIONSTABLE_FSDELETED, TRACKLOCATIONSTABLE_FSDELETED);

insertColumnNameByEnum(COLUMN_PLAYLISTTRACKSTABLE_TRACKID, PLAYLISTTRACKSTABLE_TRACKID);
insertColumnNameByEnum(COLUMN_PLAYLISTTRACKSTABLE_POSITION, PLAYLISTTRACKSTABLE_POSITION);
insertColumnNameByEnum(COLUMN_PLAYLISTTRACKSTABLE_PLAYLISTID, PLAYLISTTRACKSTABLE_PLAYLISTID);
insertColumnNameByEnum(COLUMN_PLAYLISTTRACKSTABLE_LOCATION, PLAYLISTTRACKSTABLE_LOCATION);
insertColumnNameByEnum(COLUMN_PLAYLISTTRACKSTABLE_ARTIST, PLAYLISTTRACKSTABLE_ARTIST);
insertColumnNameByEnum(COLUMN_PLAYLISTTRACKSTABLE_TITLE, PLAYLISTTRACKSTABLE_TITLE);
insertColumnNameByEnum(
COLUMN_PLAYLISTTRACKSTABLE_DATETIMEADDED,
PLAYLISTTRACKSTABLE_DATETIMEADDED);

insertColumnNameByEnum(COLUMN_REKORDBOX_ANALYZE_PATH, REKORDBOX_ANALYZE_PATH);

for (int i = 0; i < NUM_COLUMNS; ++i) {
m_columnIndexByEnum[i] = -1;
}

for (auto it = m_columnNameByEnum.constBegin(); it != m_columnNameByEnum.constEnd(); ++it) {
DEBUG_ASSERT(it.key() >= 0);
DEBUG_ASSERT(it.key() < NUM_COLUMNS);
DEBUG_ASSERT(m_columnIndexByEnum[it.key()] == -1);
m_columnIndexByEnum[it.key()] = fieldIndex(it.value());
}

Expand All @@ -91,43 +95,53 @@ void ColumnCache::setColumns(const QStringList& columns) {

m_columnSortByIndex.clear();
// Add the columns that requires a special sort
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_ARTIST], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_TITLE], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_ALBUM], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_ALBUMARTIST], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_YEAR], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_GENRE], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_COMPOSER], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_GROUPING], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_TRACKNUMBER], sortInt);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_FILETYPE], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_NATIVELOCATION], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_COMMENT], sortNoCase);

m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_PLAYLISTTRACKSTABLE_LOCATION], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_PLAYLISTTRACKSTABLE_ARTIST], sortNoCase);
m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_PLAYLISTTRACKSTABLE_TITLE], sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_ARTIST, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_TITLE, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_ALBUM, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_ALBUMARTIST, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_YEAR, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_GENRE, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_COMPOSER, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_GROUPING, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_TRACKNUMBER, sortInt);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_FILETYPE, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_NATIVELOCATION, sortNoCase);
insertColumnSortByIndex(COLUMN_LIBRARYTABLE_COMMENT, sortNoCase);

insertColumnSortByIndex(COLUMN_PLAYLISTTRACKSTABLE_LOCATION, sortNoCase);
insertColumnSortByIndex(COLUMN_PLAYLISTTRACKSTABLE_ARTIST, sortNoCase);
insertColumnSortByIndex(COLUMN_PLAYLISTTRACKSTABLE_TITLE, sortNoCase);

slotSetKeySortOrder(m_pKeyNotationCP->get());
}

void ColumnCache::slotSetKeySortOrder(double notationValue) {
if (m_columnIndexByEnum[COLUMN_LIBRARYTABLE_KEY] < 0) return;
const int keyColumnIndex = m_columnIndexByEnum[COLUMN_LIBRARYTABLE_KEY];
if (keyColumnIndex < 0) {
return;
}

// A custom COLLATE function was tested, but using CASE ... WHEN was found to be faster
// see GitHub PR#649
// https://github.com/mixxxdj/mixxx/pull/649#discussion_r34863809
KeyUtils::KeyNotation notation =
const auto notation =
KeyUtils::keyNotationFromNumericValue(notationValue);
QString keySortSQL("CASE %1_id WHEN NULL THEN 0 ");
// The placeholder %1 will be replaced by the "key" column. The actual
// key code needed for sorting is stored in the column "key_id".
DEBUG_ASSERT(LIBRARYTABLE_KEY_ID == LIBRARYTABLE_KEY + QStringLiteral("_id"));
QString keySortSQL = QStringLiteral("CASE %1_id WHEN NULL THEN 0");
for (int i = 0; i <= 24; ++i) {
keySortSQL.append(QString("WHEN %1 THEN %2 ")
.arg(QString::number(i),
QString::number(KeyUtils::keyToCircleOfFifthsOrder(
static_cast<mixxx::track::io::key::ChromaticKey>(i),
notation))));
const auto sortOrder = KeyUtils::keyToCircleOfFifthsOrder(
static_cast<mixxx::track::io::key::ChromaticKey>(i),
notation);
keySortSQL +=
QStringLiteral(" WHEN ") +
QString::number(i) +
QStringLiteral(" THEN ") +
QString::number(sortOrder);
}
keySortSQL.append("END");
keySortSQL.append(" END");

m_columnSortByIndex.insert(m_columnIndexByEnum[COLUMN_LIBRARYTABLE_KEY], keySortSQL);
// Replace the existing sort order
m_columnSortByIndex[keyColumnIndex] = keySortSQL;
}
16 changes: 16 additions & 0 deletions src/library/columncache.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ class ColumnCache : public QObject {
return format.arg(columnNameForFieldIndex(index));
}

void insertColumnSortByIndex(
int index,
const QString& name) {
DEBUG_ASSERT(!m_columnSortByIndex.contains(index) ||
m_columnSortByIndex[index] == name);
m_columnSortByIndex.insert(index, name);
}

void insertColumnNameByEnum(
Column column,
const QString& name) {
DEBUG_ASSERT(!m_columnNameByEnum.contains(column) ||
m_columnNameByEnum[column] == name);
m_columnNameByEnum.insert(column, name);
}

QStringList m_columnsByIndex;
QMap<int, QString> m_columnSortByIndex;
QMap<QString, int> m_columnIndexByName;
Expand Down

0 comments on commit 7a24153

Please sign in to comment.