Replaced UUID storage from str to array of bytes
This commit is contained in:
@@ -35,7 +35,7 @@ namespace lms::db
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static constexpr Version LMS_DATABASE_VERSION{ 106 };
|
||||
static constexpr Version LMS_DATABASE_VERSION{ 107 };
|
||||
}
|
||||
|
||||
VersionInfo::VersionInfo()
|
||||
@@ -1736,6 +1736,44 @@ FROM track)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE "user" ADD COLUMN "lastfm_session_key" TEXT NOT NULL DEFAULT '')");
|
||||
}
|
||||
|
||||
void migrateFromV106(Session& session)
|
||||
{
|
||||
dropIndexes(session);
|
||||
|
||||
// Convert the 5 MBID TEXT columns to BLOB (16 raw bytes)
|
||||
// unhex() returns NULL for non-hex input, so malformed values become NULL
|
||||
|
||||
// artist.mbid
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE artist ADD COLUMN mbid_new BLOB)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(UPDATE artist SET mbid_new = CASE WHEN mbid != '' THEN unhex(replace(mbid, '-', '')) ELSE NULL END)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE artist DROP COLUMN mbid)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE artist RENAME COLUMN mbid_new TO mbid)");
|
||||
|
||||
// release.mbid
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE release ADD COLUMN mbid_new BLOB)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(UPDATE release SET mbid_new = CASE WHEN mbid != '' THEN unhex(replace(mbid, '-', '')) ELSE NULL END)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE release DROP COLUMN mbid)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE release RENAME COLUMN mbid_new TO mbid)");
|
||||
|
||||
// release.group_mbid
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE release ADD COLUMN group_mbid_new BLOB)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(UPDATE release SET group_mbid_new = CASE WHEN group_mbid != '' THEN unhex(replace(group_mbid, '-', '')) ELSE NULL END)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE release DROP COLUMN group_mbid)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE release RENAME COLUMN group_mbid_new TO group_mbid)");
|
||||
|
||||
// track.mbid
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE track ADD COLUMN mbid_new BLOB)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(UPDATE track SET mbid_new = CASE WHEN mbid != '' THEN unhex(replace(mbid, '-', '')) ELSE NULL END)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE track DROP COLUMN mbid)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE track RENAME COLUMN mbid_new TO mbid)");
|
||||
|
||||
// track.recording_mbid
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE track ADD COLUMN recording_mbid_new BLOB)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(UPDATE track SET recording_mbid_new = CASE WHEN recording_mbid != '' THEN unhex(replace(recording_mbid, '-', '')) ELSE NULL END)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE track DROP COLUMN recording_mbid)");
|
||||
utils::executeCommand(*session.getDboSession(), R"(ALTER TABLE track RENAME COLUMN recording_mbid_new TO recording_mbid)");
|
||||
}
|
||||
|
||||
bool doDbMigration(Session& session)
|
||||
{
|
||||
constexpr std::string_view outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
|
||||
@@ -1818,6 +1856,7 @@ FROM track)");
|
||||
{ 103, migrateFromV103 },
|
||||
{ 104, migrateFromV104 },
|
||||
{ 105, migrateFromV105 },
|
||||
{ 106, migrateFromV106 },
|
||||
};
|
||||
|
||||
bool migrationPerformed{};
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "traits/ImageHashTypeTraits.hpp"
|
||||
#include "traits/PartialDateTimeTraits.hpp"
|
||||
#include "traits/PathTraits.hpp"
|
||||
#include "traits/UUIDTraits.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "objects/detail/Types.hpp"
|
||||
#include "traits/IdTypeTraits.hpp"
|
||||
#include "traits/StringViewTraits.hpp"
|
||||
#include "traits/UUIDTraits.hpp"
|
||||
|
||||
DBO_INSTANTIATE_TEMPLATES(lms::db::Artist)
|
||||
|
||||
@@ -214,7 +215,7 @@ namespace lms::db
|
||||
} // namespace
|
||||
|
||||
Artist::Artist(const std::string& name, const std::optional<core::UUID>& mbid)
|
||||
: _mbid{ mbid ? mbid->getAsString() : "" }
|
||||
: _mbid{ mbid }
|
||||
{
|
||||
setName(name);
|
||||
}
|
||||
@@ -277,7 +278,7 @@ namespace lms::db
|
||||
Artist::pointer Artist::find(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Artist>>("SELECT a FROM artist a").where("a.mbid = ?").bind(std::string{ mbid.getAsString() }));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Artist>>("SELECT a FROM artist a").where("a.mbid = ?").bind(mbid));
|
||||
}
|
||||
|
||||
Artist::pointer Artist::find(Session& session, ArtistId id)
|
||||
@@ -386,17 +387,6 @@ AND NOT EXISTS (
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE artist SET preferred_artwork_id = NULL WHERE id = ?", artistId);
|
||||
}
|
||||
|
||||
std::optional<core::UUID> Artist::getMBID() const
|
||||
{
|
||||
return core::UUID::fromString(_mbid);
|
||||
}
|
||||
|
||||
bool Artist::hasMBID() const
|
||||
{
|
||||
// TODO optim this
|
||||
return getMBID().has_value();
|
||||
}
|
||||
|
||||
ObjectPtr<Artwork> Artist::getPreferredArtwork() const
|
||||
{
|
||||
return ObjectPtr<Artwork>{ _preferredArtwork };
|
||||
|
||||
@@ -112,13 +112,13 @@ namespace lms::db
|
||||
query.where("a_i.mbid_matched = FALSE");
|
||||
if (!allowArtistMBIDFallback)
|
||||
{
|
||||
query.where("a.mbid <> ''");
|
||||
query.where("a.mbid IS NOT NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
query.where(R"(
|
||||
(a.mbid <> '' AND EXISTS (SELECT 1 FROM artist a2 WHERE a2.name = a.name AND a2.mbid <> '' AND a2.mbid <> a.mbid))
|
||||
OR (a.mbid = '' AND (SELECT COUNT(*) FROM artist a2 WHERE a2.name = a.name AND a2.mbid <> '') = 1))");
|
||||
(a.mbid IS NOT NULL AND EXISTS (SELECT 1 FROM artist a2 WHERE a2.name = a.name AND a2.mbid IS NOT NULL AND a2.mbid <> a.mbid))
|
||||
OR (a.mbid IS NULL AND (SELECT COUNT(*) FROM artist a2 WHERE a2.name = a.name AND a2.mbid IS NOT NULL) = 1))");
|
||||
}
|
||||
|
||||
utils::applyRange(query, range);
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "traits/IdTypeTraits.hpp"
|
||||
#include "traits/PartialDateTimeTraits.hpp"
|
||||
#include "traits/StringViewTraits.hpp"
|
||||
#include "traits/UUIDTraits.hpp"
|
||||
|
||||
DBO_INSTANTIATE_TEMPLATES(lms::db::Country)
|
||||
DBO_INSTANTIATE_TEMPLATES(lms::db::Label)
|
||||
@@ -218,7 +219,7 @@ namespace lms::db
|
||||
query.where("t.codec = ?").bind(detail::getDbCodec(params.filters.codec.value()));
|
||||
|
||||
if (params.releaseGroupMBID)
|
||||
query.where("group_mbid = ?").bind(params.releaseGroupMBID->getAsString());
|
||||
query.where("group_mbid = ?").bind(*params.releaseGroupMBID);
|
||||
|
||||
switch (params.sortMethod)
|
||||
{
|
||||
@@ -454,7 +455,7 @@ namespace lms::db
|
||||
|
||||
Release::Release(const std::string& name, const std::optional<core::UUID>& MBID)
|
||||
: _name{ std::string(name, 0, _maxNameLength) }
|
||||
, _MBID{ MBID ? MBID->getAsString() : "" }
|
||||
, _MBID{ MBID }
|
||||
{
|
||||
}
|
||||
|
||||
@@ -467,7 +468,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Release>>("SELECT r from release r").where("r.mbid = ?").bind(mbid.getAsString()));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Release>>("SELECT r from release r").where("r.mbid = ?").bind(mbid));
|
||||
}
|
||||
|
||||
Release::pointer Release::find(Session& session, ReleaseId id)
|
||||
|
||||
@@ -123,13 +123,13 @@ namespace lms::db
|
||||
query.where("r_a_l.artist_mbid_matched = FALSE");
|
||||
if (!allowArtistMBIDFallback)
|
||||
{
|
||||
query.where("a.mbid <> ''");
|
||||
query.where("a.mbid IS NOT NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
query.where(R"(
|
||||
(a.mbid <> '' AND EXISTS (SELECT 1 FROM artist a2 WHERE a2.name = a.name AND a2.mbid <> '' AND a2.mbid <> a.mbid))
|
||||
OR (a.mbid = '' AND (SELECT COUNT(*) FROM artist a2 WHERE a2.name = a.name AND a2.mbid <> '') = 1))");
|
||||
(a.mbid IS NOT NULL AND EXISTS (SELECT 1 FROM artist a2 WHERE a2.name = a.name AND a2.mbid IS NOT NULL AND a2.mbid <> a.mbid))
|
||||
OR (a.mbid IS NULL AND (SELECT COUNT(*) FROM artist a2 WHERE a2.name = a.name AND a2.mbid IS NOT NULL) = 1))");
|
||||
}
|
||||
|
||||
utils::applyRange(query, range);
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "traits/PartialDateTimeTraits.hpp"
|
||||
#include "traits/PathTraits.hpp"
|
||||
#include "traits/StringViewTraits.hpp"
|
||||
#include "traits/UUIDTraits.hpp"
|
||||
|
||||
DBO_INSTANTIATE_TEMPLATES(lms::db::Track)
|
||||
|
||||
@@ -392,21 +393,21 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->query<Wt::Dbo::ptr<Track>>("SELECT t from track t").where("t.mbid = ?").bind(mbid.getAsString()));
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->query<Wt::Dbo::ptr<Track>>("SELECT t from track t").where("t.mbid = ?").bind(mbid));
|
||||
}
|
||||
|
||||
std::vector<Track::pointer> Track::findByRecordingMBID(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->query<Wt::Dbo::ptr<Track>>("SELECT t from track t").where("t.recording_mbid = ?").bind(mbid.getAsString()));
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->query<Wt::Dbo::ptr<Track>>("SELECT t from track t").where("t.recording_mbid = ?").bind(mbid));
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findIdsTrackMBIDDuplicates(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession()->query<TrackId>("SELECT track.id FROM track WHERE mbid in (SELECT mbid FROM track WHERE mbid <> '' GROUP BY mbid HAVING COUNT (*) > 1)").orderBy("track.release_id,track.mbid") };
|
||||
auto query{ session.getDboSession()->query<TrackId>("SELECT track.id FROM track WHERE mbid in (SELECT mbid FROM track WHERE mbid IS NOT NULL GROUP BY mbid HAVING COUNT (*) > 1)").orderBy("track.release_id,track.mbid") };
|
||||
|
||||
return utils::execRangeQuery<TrackId>(query, range);
|
||||
}
|
||||
|
||||
@@ -165,13 +165,13 @@ namespace lms::db
|
||||
query.where("t_a_l.artist_mbid_matched = FALSE");
|
||||
if (!allowArtistMBIDFallback)
|
||||
{
|
||||
query.where("a.mbid <> ''");
|
||||
query.where("a.mbid IS NOT NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
query.where(R"(
|
||||
(a.mbid <> '' AND EXISTS (SELECT 1 FROM artist a2 WHERE a2.name = a.name AND a2.mbid <> '' AND a2.mbid <> a.mbid))
|
||||
OR (a.mbid = '' AND (SELECT COUNT(*) FROM artist a2 WHERE a2.name = a.name AND a2.mbid <> '') = 1))");
|
||||
(a.mbid IS NOT NULL AND EXISTS (SELECT 1 FROM artist a2 WHERE a2.name = a.name AND a2.mbid IS NOT NULL AND a2.mbid <> a.mbid))
|
||||
OR (a.mbid IS NULL AND (SELECT COUNT(*) FROM artist a2 WHERE a2.name = a.name AND a2.mbid IS NOT NULL) = 1))");
|
||||
}
|
||||
|
||||
utils::applyRange(query, range);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/Dbo/StdSqlTraits.h>
|
||||
|
||||
#include "core/UUID.hpp"
|
||||
|
||||
namespace Wt::Dbo
|
||||
{
|
||||
template<>
|
||||
struct sql_value_traits<lms::core::UUID>
|
||||
{
|
||||
static constexpr bool specialized{ true };
|
||||
using UnderlyingType = std::vector<unsigned char>;
|
||||
|
||||
static std::string type(SqlConnection* conn, int size)
|
||||
{
|
||||
return sql_value_traits<UnderlyingType, void>::type(conn, size);
|
||||
}
|
||||
|
||||
static void bind(const lms::core::UUID& v, SqlStatement* statement, int column, int size)
|
||||
{
|
||||
constexpr auto binarySize{ lms::core::UUID::binarySize };
|
||||
const auto bytes{ v.bytes() };
|
||||
UnderlyingType blob(binarySize);
|
||||
std::memcpy(blob.data(), bytes.data(), binarySize);
|
||||
sql_value_traits<UnderlyingType>::bind(blob, statement, column, size);
|
||||
}
|
||||
|
||||
static bool read(lms::core::UUID& v, SqlStatement* statement, int column, int size)
|
||||
{
|
||||
constexpr auto binarySize{ lms::core::UUID::binarySize };
|
||||
UnderlyingType buf;
|
||||
if (!sql_value_traits<UnderlyingType>::read(buf, statement, column, size) || buf.size() != binarySize)
|
||||
return false;
|
||||
|
||||
v = lms::core::UUID::fromBytes(std::span<const std::byte, binarySize>{ reinterpret_cast<const std::byte*>(buf.data()), binarySize });
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Wt::Dbo
|
||||
@@ -141,8 +141,8 @@ namespace lms::db
|
||||
// Accessors
|
||||
const std::string& getName() const { return _name; }
|
||||
const std::string& getSortName() const { return _sortName; }
|
||||
std::optional<core::UUID> getMBID() const;
|
||||
bool hasMBID() const;
|
||||
std::optional<core::UUID> getMBID() const { return _mbid; }
|
||||
bool hasMBID() const { return _mbid.has_value(); }
|
||||
ObjectPtr<Artwork> getPreferredArtwork() const;
|
||||
ArtworkId getPreferredArtworkId() const;
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace lms::db
|
||||
std::vector<std::vector<ObjectPtr<Cluster>>> getClusterGroups(std::span<const ClusterTypeId> clusterTypeIds, std::size_t size) const;
|
||||
|
||||
void setName(std::string_view name);
|
||||
void setMBID(const std::optional<core::UUID>& mbid) { _mbid = mbid ? mbid->getAsString() : ""; }
|
||||
void setMBID(const std::optional<core::UUID>& mbid) { _mbid = mbid; }
|
||||
void setSortName(std::string_view sortName);
|
||||
void setPreferredArtwork(ObjectPtr<Artwork> artwork);
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace lms::db
|
||||
|
||||
std::string _name;
|
||||
std::string _sortName;
|
||||
std::string _mbid; // Musicbrainz Identifier
|
||||
std::optional<core::UUID> _mbid;
|
||||
|
||||
Wt::Dbo::ptr<Artwork> _preferredArtwork;
|
||||
};
|
||||
|
||||
@@ -298,8 +298,8 @@ namespace lms::db
|
||||
// Accessors
|
||||
std::string_view getName() const { return _name; }
|
||||
std::string_view getSortName() const { return _sortName; }
|
||||
std::optional<core::UUID> getMBID() const { return core::UUID::fromString(_MBID); }
|
||||
std::optional<core::UUID> getGroupMBID() const { return core::UUID::fromString(_groupMBID); }
|
||||
std::optional<core::UUID> getMBID() const { return _MBID; }
|
||||
std::optional<core::UUID> getGroupMBID() const { return _groupMBID; }
|
||||
std::optional<std::size_t> getTotalDisc() const { return _totalDisc; } // the number of discs this release should have if complete
|
||||
std::chrono::milliseconds getDuration() const;
|
||||
Wt::WDateTime getAddedTime() const;
|
||||
@@ -325,8 +325,8 @@ namespace lms::db
|
||||
// Setters
|
||||
void setName(std::string_view name) { _name = name; }
|
||||
void setSortName(std::string_view sortName) { _sortName = sortName; }
|
||||
void setMBID(const std::optional<core::UUID>& mbid) { _MBID = mbid ? mbid->getAsString() : ""; }
|
||||
void setGroupMBID(const std::optional<core::UUID>& mbid) { _groupMBID = mbid ? mbid->getAsString() : ""; }
|
||||
void setMBID(const std::optional<core::UUID>& mbid) { _MBID = mbid; }
|
||||
void setGroupMBID(const std::optional<core::UUID>& mbid) { _groupMBID = mbid; }
|
||||
void setTotalDisc(std::optional<int> totalDisc) { _totalDisc = totalDisc; }
|
||||
void setArtistDisplayName(std::string_view name) { _artistDisplayName = name; }
|
||||
void clearArtistLinks();
|
||||
@@ -382,8 +382,8 @@ namespace lms::db
|
||||
|
||||
std::string _name;
|
||||
std::string _sortName;
|
||||
std::string _MBID;
|
||||
std::string _groupMBID;
|
||||
std::optional<core::UUID> _MBID;
|
||||
std::optional<core::UUID> _groupMBID;
|
||||
std::optional<int> _totalDisc{};
|
||||
std::string _artistDisplayName;
|
||||
bool _isCompilation{}; // See https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#compilation-itunes-5
|
||||
|
||||
@@ -258,8 +258,8 @@ namespace lms::db
|
||||
void setName(std::string_view name);
|
||||
void setDate(const core::PartialDateTime& date) { _date = date; }
|
||||
void setOriginalDate(const core::PartialDateTime& date) { _originalDate = date; }
|
||||
void setTrackMBID(const std::optional<core::UUID>& MBID) { _trackMBID = MBID ? MBID->getAsString() : ""; }
|
||||
void setRecordingMBID(const std::optional<core::UUID>& MBID) { _recordingMBID = MBID ? MBID->getAsString() : ""; }
|
||||
void setTrackMBID(const std::optional<core::UUID>& MBID) { _trackMBID = MBID; }
|
||||
void setRecordingMBID(const std::optional<core::UUID>& MBID) { _recordingMBID = MBID; }
|
||||
void setCopyright(std::string_view copyright);
|
||||
void setCopyrightURL(std::string_view copyrightURL);
|
||||
void setAdvisory(Advisory advisory) { _advisory = advisory; }
|
||||
@@ -308,8 +308,8 @@ namespace lms::db
|
||||
std::optional<int> getOriginalYear() const;
|
||||
const Wt::WDateTime& getLastWriteTime() const { return _fileLastWrite; }
|
||||
bool hasLyrics() const;
|
||||
std::optional<core::UUID> getTrackMBID() const { return core::UUID::fromString(_trackMBID); }
|
||||
std::optional<core::UUID> getRecordingMBID() const { return core::UUID::fromString(_recordingMBID); }
|
||||
std::optional<core::UUID> getTrackMBID() const { return _trackMBID; }
|
||||
std::optional<core::UUID> getRecordingMBID() const { return _recordingMBID; }
|
||||
std::string_view getCopyright() const;
|
||||
std::string_view getCopyrightURL() const;
|
||||
std::string_view getArtistDisplayName() const { return _artistDisplayName; }
|
||||
@@ -413,8 +413,8 @@ namespace lms::db
|
||||
std::string _name;
|
||||
core::PartialDateTime _date;
|
||||
core::PartialDateTime _originalDate;
|
||||
std::string _trackMBID;
|
||||
std::string _recordingMBID;
|
||||
std::optional<core::UUID> _trackMBID;
|
||||
std::optional<core::UUID> _recordingMBID;
|
||||
std::string _copyright;
|
||||
std::string _copyrightURL;
|
||||
std::string _artistDisplayName;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Common.hpp"
|
||||
|
||||
#include "core/String.hpp"
|
||||
#include "core/UUID.hpp"
|
||||
|
||||
#include "database/objects/Artist.hpp"
|
||||
#include "database/objects/ArtistInfo.hpp"
|
||||
@@ -289,14 +290,14 @@ CREATE INDEX starred_release_user_scrobbler_idx ON starred_release(user_id,scrob
|
||||
CREATE INDEX starred_track_user_scrobbler_idx ON starred_track(user_id,scrobbler);)" };
|
||||
|
||||
const std::string_view createDummyData{ R"(
|
||||
-- Inserting artists
|
||||
-- Inserting artists (Artist A has a valid UUID MBID to verify round-trip through migration)
|
||||
INSERT INTO artist (version, name, sort_name, mbid) VALUES
|
||||
(1, 'Artist A', 'Artist A', 'mbid_artist_a'),
|
||||
(1, 'Artist A', 'Artist A', '550e8400-e29b-41d4-a716-446655440000'),
|
||||
(2, 'Artist B', 'Artist B', 'mbid_artist_b');
|
||||
|
||||
-- Inserting releases
|
||||
-- Inserting releases (Release X has a valid UUID MBID to verify round-trip through migration)
|
||||
INSERT INTO release (version, name, mbid) VALUES
|
||||
(1, 'Release X', 'mbid_release_x'),
|
||||
(1, 'Release X', '6ba7b810-9dad-11d1-80b4-00c04fd430c8'),
|
||||
(2, 'Release Y', 'mbid_release_y');
|
||||
|
||||
-- Inserting tracks without any associated artists or releases (Orphan Tracks)
|
||||
@@ -381,6 +382,19 @@ VALUES
|
||||
EXPECT_FALSE(TrackLyrics::find(session, TrackLyricsId{}));
|
||||
EXPECT_FALSE(UIState::find(session, UIStateId{}));
|
||||
EXPECT_FALSE(User::find(session, UserId{}));
|
||||
|
||||
// Verify UUID MBID round-trip through V107 migration (TEXT → BLOB)
|
||||
const auto artistMBID{ core::UUID::fromString("550e8400-e29b-41d4-a716-446655440000") };
|
||||
ASSERT_TRUE(artistMBID);
|
||||
const auto artist{ Artist::find(session, *artistMBID) };
|
||||
ASSERT_TRUE(artist);
|
||||
EXPECT_EQ(artist->getMBID(), artistMBID);
|
||||
|
||||
const auto releaseMBID{ core::UUID::fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") };
|
||||
ASSERT_TRUE(releaseMBID);
|
||||
const auto release{ Release::find(session, *releaseMBID) };
|
||||
ASSERT_TRUE(release);
|
||||
EXPECT_EQ(release->getMBID(), releaseMBID);
|
||||
}
|
||||
}
|
||||
} // namespace lms::db::tests
|
||||
Reference in New Issue
Block a user