mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-06 03:39:50 +00:00
Added regex support to CategoryListQuery and SearchTrackListQuery, but
they're not wired up yet.
This commit is contained in:
parent
ba9b98794f
commit
d4a1fba4b6
@ -305,6 +305,7 @@ ITrackList* LocalMetadataProxy::QueryTracks(const char* query, int limit, int of
|
||||
std::shared_ptr<SearchTrackListQuery> search(
|
||||
new SearchTrackListQuery(
|
||||
this->library,
|
||||
SearchTrackListQuery::MatchType::Substring,
|
||||
std::string(query ? query : ""),
|
||||
TrackSortType::Album));
|
||||
|
||||
@ -456,6 +457,7 @@ IValueList* LocalMetadataProxy::QueryCategoryWithPredicate(
|
||||
|
||||
std::shared_ptr<CategoryListQuery> search(
|
||||
new CategoryListQuery(
|
||||
CategoryListQuery::MatchType::Substring,
|
||||
type,
|
||||
{ field, predicateId },
|
||||
std::string(filter ? filter : "")));
|
||||
@ -480,7 +482,10 @@ IValueList* LocalMetadataProxy::QueryCategoryWithPredicates(
|
||||
auto predicateList = toPredicateList(predicates, predicateCount);
|
||||
|
||||
auto query = std::make_shared<CategoryListQuery>(
|
||||
type, predicateList, std::string(filter ? filter : ""));
|
||||
CategoryListQuery::MatchType::Substring,
|
||||
type,
|
||||
predicateList,
|
||||
std::string(filter ? filter : ""));
|
||||
|
||||
this->library->EnqueueAndWait(query);
|
||||
|
||||
|
@ -50,6 +50,11 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
public sigslot::has_slots<>
|
||||
{
|
||||
public:
|
||||
enum class MatchType : int {
|
||||
Substring = 1,
|
||||
Regex = 2
|
||||
};
|
||||
|
||||
QueryBase()
|
||||
: status(IQuery::Idle)
|
||||
, options(0)
|
||||
|
@ -56,35 +56,44 @@ static const std::string kUnfilteredPlaylistsQuery =
|
||||
static const std::string kFilteredPlaylistsQuery =
|
||||
"SELECT DISTINCT id, name "
|
||||
"FROM playlists"
|
||||
"WHERE LOWER(name) LIKE LOWER(?) "
|
||||
"WHERE LOWER(name) {{match_type}} ? "
|
||||
"ORDER BY name;";
|
||||
|
||||
const std::string CategoryListQuery::kQueryName = "CategoryListQuery";
|
||||
|
||||
static std::string getMatchType(CategoryListQuery::MatchType matchType) {
|
||||
return matchType == CategoryListQuery::MatchType::Regex ? "REGEXP" : "LIKE";
|
||||
}
|
||||
|
||||
CategoryListQuery::CategoryListQuery() {
|
||||
}
|
||||
|
||||
CategoryListQuery::CategoryListQuery(
|
||||
const std::string& trackField, const std::string& filter)
|
||||
: CategoryListQuery(trackField, category::PredicateList(), filter) {
|
||||
MatchType matchType,
|
||||
const std::string& trackField,
|
||||
const std::string& filter)
|
||||
: CategoryListQuery(matchType, trackField, category::PredicateList(), filter) {
|
||||
}
|
||||
|
||||
CategoryListQuery::CategoryListQuery(
|
||||
MatchType matchType,
|
||||
const std::string& trackField,
|
||||
const category::Predicate predicate,
|
||||
const std::string& filter)
|
||||
: CategoryListQuery(trackField, category::PredicateList{ predicate }, filter) {
|
||||
: CategoryListQuery(matchType, trackField, category::PredicateList{ predicate }, filter) {
|
||||
}
|
||||
|
||||
CategoryListQuery::CategoryListQuery(
|
||||
MatchType matchType,
|
||||
const std::string& trackField,
|
||||
const category::PredicateList predicates,
|
||||
const std::string& filter)
|
||||
: trackField(trackField)
|
||||
: matchType(MatchType::Regex)
|
||||
, trackField(trackField)
|
||||
, filter(filter) {
|
||||
result.reset(new SdkValueList());
|
||||
|
||||
if (this->filter.size()) {
|
||||
if (this->filter.size() && this->matchType == MatchType::Substring) {
|
||||
/* transform "FilteR" => "%filter%" */
|
||||
std::string wild = this->filter;
|
||||
std::transform(wild.begin(), wild.end(), wild.begin(), tolower);
|
||||
@ -134,6 +143,8 @@ void CategoryListQuery::QueryPlaylist(musik::core::db::Connection& db) {
|
||||
? kFilteredPlaylistsQuery
|
||||
: kUnfilteredPlaylistsQuery;
|
||||
|
||||
category::ReplaceAll(query, "{{match_type}}", getMatchType(matchType));
|
||||
|
||||
Statement stmt(query.c_str() , db);
|
||||
|
||||
if (filtered) {
|
||||
@ -157,6 +168,7 @@ void CategoryListQuery::QueryRegular(musik::core::db::Connection &db) {
|
||||
if (this->filter.size()) {
|
||||
regularFilter = category::REGULAR_FILTER;
|
||||
category::ReplaceAll(regularFilter, "{{table}}", prop.first);
|
||||
category::ReplaceAll(regularFilter, "{{match_type}}", getMatchType(matchType));
|
||||
args.push_back(category::StringArgument(this->filter));
|
||||
}
|
||||
|
||||
@ -184,6 +196,7 @@ void CategoryListQuery::QueryExtended(musik::core::db::Connection &db) {
|
||||
if (this->filter.size()) {
|
||||
extendedFilter = category::EXTENDED_FILTER;
|
||||
args.push_back(category::StringArgument(this->filter));
|
||||
category::ReplaceAll(extendedFilter, "{{match_type}}", getMatchType(matchType));
|
||||
}
|
||||
|
||||
category::ReplaceAll(query, "{{regular_predicates}}", regular);
|
||||
@ -242,6 +255,7 @@ std::string CategoryListQuery::SerializeQuery() {
|
||||
query["options"] = {
|
||||
{ "trackField", this->trackField },
|
||||
{ "filter", this->filter },
|
||||
{ "matchType", this->matchType },
|
||||
{ "outputType", this->outputType },
|
||||
{ "regularPredicateList", PredicateListToJson(this->regular) },
|
||||
{ "extendedPredicateList", PredicateListToJson(this->extended) }
|
||||
@ -269,6 +283,7 @@ std::shared_ptr<CategoryListQuery> CategoryListQuery::DeserializeQuery(const std
|
||||
std::shared_ptr<CategoryListQuery> result(new CategoryListQuery());
|
||||
result->trackField = options.value("trackField", "");
|
||||
result->filter = options.value("filter", "");
|
||||
result->matchType = options.value("matchType", MatchType::Substring);
|
||||
result->outputType = (OutputType)options.value("outputType", OutputType::Regular);
|
||||
PredicateListFromJson(options["regularPredicateList"], result->regular);
|
||||
PredicateListFromJson(options["extendedPredicateList"], result->extended);
|
||||
|
@ -52,15 +52,18 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
using Result = SdkValueList::Shared;
|
||||
|
||||
CategoryListQuery(
|
||||
MatchType matchType,
|
||||
const std::string& trackField,
|
||||
const std::string& filter = "");
|
||||
|
||||
CategoryListQuery(
|
||||
MatchType matchType,
|
||||
const std::string& trackField,
|
||||
const category::Predicate predicate,
|
||||
const std::string& filter = "");
|
||||
|
||||
CategoryListQuery(
|
||||
MatchType matchType,
|
||||
const std::string& trackField,
|
||||
const category::PredicateList predicate,
|
||||
const std::string& filter = "");
|
||||
@ -100,6 +103,7 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
|
||||
std::string trackField;
|
||||
std::string filter;
|
||||
MatchType matchType;
|
||||
OutputType outputType;
|
||||
category::PredicateList regular, extended;
|
||||
Result result;
|
||||
|
@ -61,9 +61,13 @@ using namespace boost::algorithm;
|
||||
const std::string SearchTrackListQuery::kQueryName = "SearchTrackListQuery";
|
||||
|
||||
SearchTrackListQuery::SearchTrackListQuery(
|
||||
ILibraryPtr library, const std::string& filter, TrackSortType sort)
|
||||
ILibraryPtr library,
|
||||
MatchType matchType,
|
||||
const std::string& filter,
|
||||
TrackSortType sort)
|
||||
{
|
||||
this->library = library;
|
||||
this->matchType = matchType;
|
||||
this->sortType = sort;
|
||||
this->filter = filter;
|
||||
|
||||
@ -105,11 +109,10 @@ bool SearchTrackListQuery::OnRun(Connection& db) {
|
||||
headers.reset(new std::set<size_t>());
|
||||
}
|
||||
|
||||
bool useRegex = (matchType == MatchType::Regex);
|
||||
bool hasFilter = (this->filter.size() > 0);
|
||||
|
||||
std::string lastAlbum;
|
||||
size_t index = 0;
|
||||
|
||||
std::string query;
|
||||
|
||||
if (hasFilter) {
|
||||
@ -119,9 +122,11 @@ bool SearchTrackListQuery::OnRun(Connection& db) {
|
||||
"WHERE "
|
||||
" tracks.visible=1 AND "
|
||||
+ this->orderByPredicate +
|
||||
"(tracks.title LIKE ? OR al.name LIKE ? OR ar.name LIKE ? OR gn.name LIKE ?) "
|
||||
"(tracks.title {{match_type}} ? OR al.name {{match_type}} ? OR ar.name {{match_type}} ? OR gn.name {{match_type}} ?) "
|
||||
" AND tracks.album_id=al.id AND tracks.visual_genre_id=gn.id AND tracks.visual_artist_id=ar.id "
|
||||
"ORDER BY " + this->orderBy + " ";
|
||||
|
||||
ReplaceAll(query, "{{match_type}}", useRegex ? "REGEXP" : "LIKE");
|
||||
}
|
||||
else {
|
||||
query =
|
||||
@ -139,11 +144,13 @@ bool SearchTrackListQuery::OnRun(Connection& db) {
|
||||
Statement trackQuery(query.c_str(), db);
|
||||
|
||||
if (hasFilter) {
|
||||
std::string filterWithWildcard = "%" + trim_copy(to_lower_copy(filter)) + "%";
|
||||
trackQuery.BindText(0, filterWithWildcard);
|
||||
trackQuery.BindText(1, filterWithWildcard);
|
||||
trackQuery.BindText(2, filterWithWildcard);
|
||||
trackQuery.BindText(3, filterWithWildcard);
|
||||
std::string patternToMatch = useRegex
|
||||
? filter : "%" + trim_copy(to_lower_copy(filter)) + "%";
|
||||
|
||||
trackQuery.BindText(0, patternToMatch);
|
||||
trackQuery.BindText(1, patternToMatch);
|
||||
trackQuery.BindText(2, patternToMatch);
|
||||
trackQuery.BindText(3, patternToMatch);
|
||||
}
|
||||
|
||||
while (trackQuery.Step() == Row) {
|
||||
@ -173,7 +180,8 @@ std::string SearchTrackListQuery::SerializeQuery() {
|
||||
{ "name", kQueryName },
|
||||
{ "options", {
|
||||
{ "filter", filter },
|
||||
{ "sortType", sortType}
|
||||
{ "matchType", matchType },
|
||||
{ "sortType", sortType }
|
||||
}}
|
||||
};
|
||||
return FinalizeSerializedQueryWithLimitAndOffset(output);
|
||||
@ -194,6 +202,7 @@ std::shared_ptr<SearchTrackListQuery> SearchTrackListQuery::DeserializeQuery(mus
|
||||
auto options = nlohmann::json::parse(data)["options"];
|
||||
auto result = std::make_shared<SearchTrackListQuery>(
|
||||
library,
|
||||
options.value("matchType", MatchType::Substring),
|
||||
options["filter"].get<std::string>(),
|
||||
options["sortType"].get<TrackSortType>());
|
||||
result->ExtractLimitAndOffsetFromDeserializedQuery(options);
|
||||
|
@ -45,6 +45,7 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
|
||||
SearchTrackListQuery(
|
||||
musik::core::ILibraryPtr library,
|
||||
MatchType matchType,
|
||||
const std::string& filter,
|
||||
TrackSortType sort);
|
||||
|
||||
@ -70,6 +71,7 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
|
||||
private:
|
||||
musik::core::ILibraryPtr library;
|
||||
MatchType matchType;
|
||||
bool parseHeaders;
|
||||
std::string orderBy;
|
||||
std::string orderByPredicate;
|
||||
|
@ -71,10 +71,10 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
};
|
||||
|
||||
static const std::string REGULAR_PREDICATE = " tracks.{{fk_id}}=? ";
|
||||
static const std::string REGULAR_FILTER = " AND LOWER({{table}}.name) LIKE ? ";
|
||||
static const std::string REGULAR_FILTER = " AND LOWER({{table}}.name) {{match_type}} ? ";
|
||||
|
||||
static const std::string EXTENDED_PREDICATE = " (key=? AND meta_value_id=?) ";
|
||||
static const std::string EXTENDED_FILTER = " AND LOWER(extended_metadata.value) LIKE ?";
|
||||
static const std::string EXTENDED_FILTER = " AND LOWER(extended_metadata.value) {{match_type}} ?";
|
||||
|
||||
static const std::string EXTENDED_INNER_JOIN =
|
||||
"INNER JOIN ( "
|
||||
@ -193,7 +193,7 @@ namespace musik { namespace core { namespace library { namespace query {
|
||||
and other supplementary information. */
|
||||
|
||||
static const std::string ALBUM_LIST_FILTER =
|
||||
" AND (LOWER(album) like ? OR LOWER(album_artist) like ?) ";
|
||||
" AND (LOWER(album) LIKE ? OR LOWER(album_artist) LIKE ?) ";
|
||||
|
||||
static const std::string ALBUM_LIST_QUERY =
|
||||
"SELECT DISTINCT "
|
||||
|
@ -149,7 +149,11 @@ void TrackSearchLayout::Requery() {
|
||||
const std::string& filter = this->input->GetText();
|
||||
const TrackSortType sortOrder = getDefaultTrackSort(this->prefs);
|
||||
this->trackList->Requery(std::shared_ptr<TrackListQueryBase>(
|
||||
new SearchTrackListQuery(this->library, filter, sortOrder)));
|
||||
new SearchTrackListQuery(
|
||||
this->library,
|
||||
SearchTrackListQuery::MatchType::Substring,
|
||||
filter,
|
||||
sortOrder)));
|
||||
}
|
||||
|
||||
void TrackSearchLayout::PlayFromTop() {
|
||||
|
@ -151,8 +151,8 @@ static void queryPlaylists(
|
||||
ILibraryPtr library,
|
||||
std::function<void(std::shared_ptr<CategoryListQuery>)> callback)
|
||||
{
|
||||
std::shared_ptr<CategoryListQuery> query(
|
||||
new CategoryListQuery(Playlists::TABLE_NAME, ""));
|
||||
std::shared_ptr<CategoryListQuery> query(new CategoryListQuery(
|
||||
CategoryListQuery::MatchType::Substring, Playlists::TABLE_NAME, ""));
|
||||
|
||||
library->Enqueue(query, [callback, query](auto q) {
|
||||
callback(query->GetStatus() == IQuery::Finished
|
||||
|
@ -109,7 +109,8 @@ void CategoryListView::RequeryWithField(
|
||||
this->fieldIdColumn = getFieldIdColumn(fieldName);
|
||||
this->selectAfterQuery = selectAfterQuery;
|
||||
this->filter = filter;
|
||||
this->activeQuery.reset(new CategoryListQuery(fieldName, filter));
|
||||
this->activeQuery.reset(new CategoryListQuery(
|
||||
CategoryListQuery::MatchType::Substring, fieldName, filter));
|
||||
this->library->Enqueue(activeQuery);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user