From 7bb7a093a54c79e2c7595e3a3f7d9bcb4631007b Mon Sep 17 00:00:00 2001 From: Jian Li Date: Mon, 16 Dec 2019 16:03:02 +0100 Subject: [PATCH 01/14] when filename starts with number, or ends with number , order by filename and number. --- src/Media.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index 56bf7398..cebe8f83 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -877,6 +877,7 @@ std::string Media::sortRequest( const QueryParameters* params ) auto sort = params != nullptr ? params->sort : SortingCriteria::Default; auto desc = params != nullptr ? params->desc : false; + auto added = false; switch ( sort ) { case SortingCriteria::Duration: @@ -893,7 +894,26 @@ std::string Media::sortRequest( const QueryParameters* params ) desc = !desc; // Make decreasing order default for play count sorting break; case SortingCriteria::Filename: - req += "m.filename"; + if ( desc == true ) { + req += "trim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789') COLLATE NOCASE DESC , cast(m.filename as INTEGER) DESC, "; + req += "cast(substr("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",length(rtrim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789'))+1) as INTEGER) DESC"; + } else { + req += "trim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789') COLLATE NOCASE ASC , cast(m.filename as INTEGER) ASC, "; + req += "cast(substr("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",length(rtrim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789'))+1) as INTEGER) ASC"; + } + added = true; break; case SortingCriteria::LastModificationDate: req += "f.last_modification_date"; @@ -902,30 +922,45 @@ std::string Media::sortRequest( const QueryParameters* params ) req += "f.size"; break; case SortingCriteria::Album: - if ( desc == true ) + if ( desc == true ) req += "alb.title DESC, att.track_number"; else req += "alb.title, att.track_number"; + added = true; break; case SortingCriteria::Artist: - req += "art.name"; + if ( desc == true ) { + req += "trim(art.name,'0123456789') COLLATE NOCASE DESC , cast(art.name as INTEGER) DESC, "; + req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) DESC"; + } else { + req += "trim(art.name,'0123456789')COLLATE NOCASE ASC , cast(art.name as INTEGER) ASC, "; + req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) ASC"; + } + added = true; break; case SortingCriteria::TrackId: - if ( desc == true ) + if ( desc == true ) req += "alb.title, att.track_number DESC, att.disc_number"; else req += "alb.title, att.track_number, att.disc_number"; + added = true; break; default: LOG_WARN( "Unsupported sorting criteria, falling back to SortingCriteria::Default (Alpha)" ); /* fall-through */ case SortingCriteria::Default: case SortingCriteria::Alpha: - req += "m.title"; + if ( desc == true ) { + req += "trim(m.title,'0123456789') COLLATE NOCASE DESC , cast(m.title as INTEGER) DESC, "; + req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) DESC"; + } else { + req += "trim(m.title,'0123456789') COLLATE NOCASE ASC , cast(m.title as INTEGER) ASC, "; + req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) ASC"; + } + added = true; break; } - if ( desc == true && sort != SortingCriteria::Album && - sort != SortingCriteria::TrackId ) + if ( desc == true && !added) req += " DESC"; return req; } -- GitLab From d8a2192304086c19ae00af4d81e8456db1fb3f72 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Tue, 17 Dec 2019 20:33:59 +0900 Subject: [PATCH 02/14] add unittest --- test/unittest/MediaTests.cpp | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 01bddb92..530e4456 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -867,7 +867,46 @@ TEST_F( Medias, Pagination ) media = paginator->items( 1, i ); } } +TEST_F( Medias, SortFilenameStartsWithNumber ) +{ + auto m1 = std::static_pointer_cast( ml->addMedia( "9 song.mp3", IMedia::Type::Audio ) ); + auto m2 = std::static_pointer_cast( ml->addMedia( "1 song.mp3", IMedia::Type::Audio ) ); + auto m3 = std::static_pointer_cast( ml->addMedia( "10 song.mp3", IMedia::Type::Audio ) ); + + QueryParameters params { SortingCriteria::Filename, false }; + auto media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[0]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[2]->id() ); + params.desc = true; + media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[2]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[0]->id() ); +} +TEST_F( Medias, SortFilenameEndsWithNumber ) +{ + auto m1 = std::static_pointer_cast( ml->addMedia( "song9.mp3", IMedia::Type::Audio ) ); + auto m2 = std::static_pointer_cast( ml->addMedia( "song1.mp3", IMedia::Type::Audio ) ); + auto m3 = std::static_pointer_cast( ml->addMedia( "song10.mp3", IMedia::Type::Audio ) ); + + QueryParameters params { SortingCriteria::Filename, false }; + auto media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[0]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[2]->id() ); + + params.desc = true; + media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[2]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[0]->id() ); +} TEST_F( Medias, SortFilename ) { auto m1 = std::static_pointer_cast( ml->addMedia( "AAAAB.mp3", IMedia::Type::Audio ) ); -- GitLab From cd0636194ccd134faf87c7f42138223cc1b0b97b Mon Sep 17 00:00:00 2001 From: Li Jian Date: Tue, 17 Dec 2019 23:36:38 +0900 Subject: [PATCH 03/14] move the sorting logic to one function --- src/Media.cpp | 49 ++++++++---------------------------- src/database/SqliteTools.h | 18 +++++++++++++ test/unittest/MediaTests.cpp | 2 +- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index cebe8f83..2820391f 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -894,26 +894,8 @@ std::string Media::sortRequest( const QueryParameters* params ) desc = !desc; // Make decreasing order default for play count sorting break; case SortingCriteria::Filename: - if ( desc == true ) { - req += "trim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789') COLLATE NOCASE DESC , cast(m.filename as INTEGER) DESC, "; - req += "cast(substr("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",length(rtrim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789'))+1) as INTEGER) DESC"; - } else { - req += "trim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789') COLLATE NOCASE ASC , cast(m.filename as INTEGER) ASC, "; - req += "cast(substr("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",length(rtrim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789'))+1) as INTEGER) ASC"; - } - added = true; + req += sqlite::Tools::sortedStringField("m.filename",desc,true); + added = true; break; case SortingCriteria::LastModificationDate: req += "f.last_modification_date"; @@ -922,27 +904,24 @@ std::string Media::sortRequest( const QueryParameters* params ) req += "f.size"; break; case SortingCriteria::Album: + + req += sqlite::Tools::sortedStringField("alb.title",desc); if ( desc == true ) - req += "alb.title DESC, att.track_number"; + req += ", att.track_number"; else - req += "alb.title, att.track_number"; + req += ", att.track_number"; added = true; break; case SortingCriteria::Artist: - if ( desc == true ) { - req += "trim(art.name,'0123456789') COLLATE NOCASE DESC , cast(art.name as INTEGER) DESC, "; - req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) DESC"; - } else { - req += "trim(art.name,'0123456789')COLLATE NOCASE ASC , cast(art.name as INTEGER) ASC, "; - req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) ASC"; - } + req += sqlite::Tools::sortedStringField("art.name",desc); added = true; break; case SortingCriteria::TrackId: + req += sqlite::Tools::sortedStringField("alb.title",false); if ( desc == true ) - req += "alb.title, att.track_number DESC, att.disc_number"; + req += ", att.track_number DESC, att.disc_number"; else - req += "alb.title, att.track_number, att.disc_number"; + req += ", att.track_number, att.disc_number"; added = true; break; default: @@ -950,13 +929,7 @@ std::string Media::sortRequest( const QueryParameters* params ) /* fall-through */ case SortingCriteria::Default: case SortingCriteria::Alpha: - if ( desc == true ) { - req += "trim(m.title,'0123456789') COLLATE NOCASE DESC , cast(m.title as INTEGER) DESC, "; - req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) DESC"; - } else { - req += "trim(m.title,'0123456789') COLLATE NOCASE ASC , cast(m.title as INTEGER) ASC, "; - req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) ASC"; - } + req += sqlite::Tools::sortedStringField("m.title",desc); added = true; break; } diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 0fb016ba..172536dd 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -433,7 +433,25 @@ class Tools * sqlite, and a '*' appended */ static std::string sanitizePattern( const std::string& pattern ); + static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt=false) + { + auto f = std::string(field); + auto d = desc?std::string("DESC"):std::string("ASC"); + return std::string( + hasExt ? + "trim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789') COLLATE NOCASE "+d+"," // like aaa123.mp3 => aaa + : + "rtrim("+f+",'0123456789') COLLATE NOCASE "+d+"," + ) // like aaa123 => aaa + + " cast("+f+" as INTEGER) "+d+", " + //prefix like 123aaa => 123 + std::string( + hasExt ? // aaa123.mp3=>123 + "cast(substr(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),length(rtrim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789'))+1) as INTEGER) "+d + : + "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)" // aaa123=>123 + ); //postfix + } private: template static void executeRequestLocked( sqlite::Connection* dbConnection, diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 530e4456..7986e86b 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -471,7 +471,7 @@ TEST_F( Medias, SortByAlpha ) QueryParameters params { SortingCriteria::Alpha, false }; auto media = ml->audioFiles( ¶ms )->all(); - ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( 3u, media.size() ); ASSERT_EQ( m1->id(), media[0]->id() ); ASSERT_EQ( m3->id(), media[1]->id() ); ASSERT_EQ( m2->id(), media[2]->id() ); -- GitLab From 24fad3270d9c71c5c2b3b5c11d22b93bd12dcb87 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 21:15:20 +0900 Subject: [PATCH 04/14] refactor sortedStringField --- src/Media.cpp | 8 ++++---- src/database/SqliteTools.h | 38 +++++++++++++++++++----------------- test/unittest/MediaTests.cpp | 2 +- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index 2820391f..c7556e14 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -905,7 +905,7 @@ std::string Media::sortRequest( const QueryParameters* params ) break; case SortingCriteria::Album: - req += sqlite::Tools::sortedStringField("alb.title",desc); + req += sqlite::Tools::sortedStringField("alb.title",desc,false); if ( desc == true ) req += ", att.track_number"; else @@ -913,11 +913,11 @@ std::string Media::sortRequest( const QueryParameters* params ) added = true; break; case SortingCriteria::Artist: - req += sqlite::Tools::sortedStringField("art.name",desc); + req += sqlite::Tools::sortedStringField("art.name",desc,false); added = true; break; case SortingCriteria::TrackId: - req += sqlite::Tools::sortedStringField("alb.title",false); + req += sqlite::Tools::sortedStringField("alb.title",false,false); if ( desc == true ) req += ", att.track_number DESC, att.disc_number"; else @@ -929,7 +929,7 @@ std::string Media::sortRequest( const QueryParameters* params ) /* fall-through */ case SortingCriteria::Default: case SortingCriteria::Alpha: - req += sqlite::Tools::sortedStringField("m.title",desc); + req += sqlite::Tools::sortedStringField("m.title",desc,false); added = true; break; } diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 172536dd..3a69ee36 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -433,25 +433,27 @@ class Tools * sqlite, and a '*' appended */ static std::string sanitizePattern( const std::string& pattern ); - static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt=false) - { - auto f = std::string(field); - auto d = desc?std::string("DESC"):std::string("ASC"); - return std::string( - hasExt ? - "trim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789') COLLATE NOCASE "+d+"," // like aaa123.mp3 => aaa - : - "rtrim("+f+",'0123456789') COLLATE NOCASE "+d+"," - ) // like aaa123 => aaa - + " cast("+f+" as INTEGER) "+d+", " + //prefix like 123aaa => 123 - std::string( - hasExt ? // aaa123.mp3=>123 - "cast(substr(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),length(rtrim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789'))+1) as INTEGER) "+d - : - "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)" // aaa123=>123 - ); //postfix + static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt) + { + auto f = std::string(field); + auto d = desc?" DESC":" ASC"; - } + //aaa.mp3 => aaa + auto removeExt = "rtrim(rtrim("+f+",replace("+f+",'.','')),'.')"; + auto lengthAfterRemoveExtNumber = "length(rtrim("+ removeExt +",'0123456789'))"; + + auto removeLastNumber = "rtrim("+f+",'0123456789')"; + auto removeNumberAndExt = "trim(" + removeExt + ",'0123456789')"; + auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE "+d; + + auto lastNumberNoExt = "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)"; + auto lastNumberAfterRemoveExt = "cast(substr("+removeExt+","+ lengthAfterRemoveExtNumber +"+1) as INTEGER) "; + auto lastNumber = (hasExt ? lastNumberAfterRemoveExt : lastNumberNoExt) + d; + + auto firstNumber = " cast("+f+" as INTEGER) "+d; + + return titleNoExtNumber + "," + firstNumber +" , " + lastNumber; + } private: template static void executeRequestLocked( sqlite::Connection* dbConnection, diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 7986e86b..530e4456 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -471,7 +471,7 @@ TEST_F( Medias, SortByAlpha ) QueryParameters params { SortingCriteria::Alpha, false }; auto media = ml->audioFiles( ¶ms )->all(); - ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( 3u, media.size() ); ASSERT_EQ( m1->id(), media[0]->id() ); ASSERT_EQ( m3->id(), media[1]->id() ); ASSERT_EQ( m2->id(), media[2]->id() ); -- GitLab From fa265f8c6f2c1c90e7c7c447e42adaccd228412d Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 21:23:57 +0900 Subject: [PATCH 05/14] refactor sortedStringField --- src/database/SqliteTools.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 3a69ee36..95e93509 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -435,22 +435,21 @@ class Tools static std::string sanitizePattern( const std::string& pattern ); static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt) { - auto f = std::string(field); auto d = desc?" DESC":" ASC"; //aaa.mp3 => aaa - auto removeExt = "rtrim(rtrim("+f+",replace("+f+",'.','')),'.')"; + auto removeExt = "rtrim(rtrim("+field+",replace("+field+",'.','')),'.')"; auto lengthAfterRemoveExtNumber = "length(rtrim("+ removeExt +",'0123456789'))"; - auto removeLastNumber = "rtrim("+f+",'0123456789')"; + auto removeLastNumber = "rtrim("+field+",'0123456789')"; auto removeNumberAndExt = "trim(" + removeExt + ",'0123456789')"; auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE "+d; - auto lastNumberNoExt = "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)"; + auto lastNumberNoExt = "cast(ltrim("+field+",rtrim("+field+",'0123456789')) as INTEGER)"; auto lastNumberAfterRemoveExt = "cast(substr("+removeExt+","+ lengthAfterRemoveExtNumber +"+1) as INTEGER) "; auto lastNumber = (hasExt ? lastNumberAfterRemoveExt : lastNumberNoExt) + d; - auto firstNumber = " cast("+f+" as INTEGER) "+d; + auto firstNumber = " cast("+field+" as INTEGER) "+d; return titleNoExtNumber + "," + firstNumber +" , " + lastNumber; } -- GitLab From dbc20fca92edce64d08d9eb5d0a69741511997e3 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 21:59:36 +0900 Subject: [PATCH 06/14] remove the const from the bool parameter --- src/database/SqliteTools.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 95e93509..58b5000f 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -433,25 +433,25 @@ class Tools * sqlite, and a '*' appended */ static std::string sanitizePattern( const std::string& pattern ); - static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt) + static std::string sortedStringField( const std::string& field, bool desc, bool hasExt) { - auto d = desc?" DESC":" ASC"; + auto d = desc ? " DESC":" ASC"; //aaa.mp3 => aaa - auto removeExt = "rtrim(rtrim("+field+",replace("+field+",'.','')),'.')"; - auto lengthAfterRemoveExtNumber = "length(rtrim("+ removeExt +",'0123456789'))"; + auto removeExt = "rtrim(rtrim(" + field + ",replace(" + field + ",'.','')),'.')"; + auto lengthAfterRemoveExtNumber = "length(rtrim(" + removeExt + ",'0123456789'))"; - auto removeLastNumber = "rtrim("+field+",'0123456789')"; + auto removeLastNumber = "rtrim(" + field + ",'0123456789')"; auto removeNumberAndExt = "trim(" + removeExt + ",'0123456789')"; - auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE "+d; + auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE " + d; - auto lastNumberNoExt = "cast(ltrim("+field+",rtrim("+field+",'0123456789')) as INTEGER)"; - auto lastNumberAfterRemoveExt = "cast(substr("+removeExt+","+ lengthAfterRemoveExtNumber +"+1) as INTEGER) "; + auto lastNumberNoExt = "cast(ltrim(" + field + ",rtrim(" + field + ",'0123456789')) as INTEGER)"; + auto lastNumberAfterRemoveExt = "cast(substr(" + removeExt + "," + lengthAfterRemoveExtNumber + " + 1) as INTEGER) "; auto lastNumber = (hasExt ? lastNumberAfterRemoveExt : lastNumberNoExt) + d; - auto firstNumber = " cast("+field+" as INTEGER) "+d; + auto firstNumber = " cast(" + field + " as INTEGER) " + d; - return titleNoExtNumber + "," + firstNumber +" , " + lastNumber; + return titleNoExtNumber + "," + firstNumber + " , " + lastNumber; } private: template -- GitLab From 76a0152d64b8ba87cd7feb1169209051a52f2483 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 22:29:10 +0900 Subject: [PATCH 07/14] remove added to descAdded --- src/Media.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index c7556e14..2dde4457 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -877,7 +877,7 @@ std::string Media::sortRequest( const QueryParameters* params ) auto sort = params != nullptr ? params->sort : SortingCriteria::Default; auto desc = params != nullptr ? params->desc : false; - auto added = false; + auto descAdded = false; switch ( sort ) { case SortingCriteria::Duration: @@ -895,7 +895,7 @@ std::string Media::sortRequest( const QueryParameters* params ) break; case SortingCriteria::Filename: req += sqlite::Tools::sortedStringField("m.filename",desc,true); - added = true; + descAdded = true; break; case SortingCriteria::LastModificationDate: req += "f.last_modification_date"; @@ -910,11 +910,11 @@ std::string Media::sortRequest( const QueryParameters* params ) req += ", att.track_number"; else req += ", att.track_number"; - added = true; + descAdded = true; break; case SortingCriteria::Artist: req += sqlite::Tools::sortedStringField("art.name",desc,false); - added = true; + descAdded = true; break; case SortingCriteria::TrackId: req += sqlite::Tools::sortedStringField("alb.title",false,false); @@ -922,7 +922,7 @@ std::string Media::sortRequest( const QueryParameters* params ) req += ", att.track_number DESC, att.disc_number"; else req += ", att.track_number, att.disc_number"; - added = true; + descAdded = true; break; default: LOG_WARN( "Unsupported sorting criteria, falling back to SortingCriteria::Default (Alpha)" ); @@ -930,10 +930,10 @@ std::string Media::sortRequest( const QueryParameters* params ) case SortingCriteria::Default: case SortingCriteria::Alpha: req += sqlite::Tools::sortedStringField("m.title",desc,false); - added = true; + descAdded = true; break; } - if ( desc == true && !added) + if ( desc == true && !descAdded) req += " DESC"; return req; } -- GitLab From 012586dbdf7767b20d2ea0aacadd553622c3902a Mon Sep 17 00:00:00 2001 From: Jian Li Date: Mon, 16 Dec 2019 16:03:02 +0100 Subject: [PATCH 08/14] when filename starts with number, or ends with number , order by filename and number. --- src/Media.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index 1e8011ac..22a3984f 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -886,6 +886,7 @@ std::string Media::sortRequest( const QueryParameters* params ) auto sort = params != nullptr ? params->sort : SortingCriteria::Default; auto desc = params != nullptr ? params->desc : false; + auto added = false; switch ( sort ) { case SortingCriteria::Duration: @@ -902,7 +903,26 @@ std::string Media::sortRequest( const QueryParameters* params ) desc = !desc; // Make decreasing order default for play count sorting break; case SortingCriteria::Filename: - req += "m.filename"; + if ( desc == true ) { + req += "trim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789') COLLATE NOCASE DESC , cast(m.filename as INTEGER) DESC, "; + req += "cast(substr("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",length(rtrim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789'))+1) as INTEGER) DESC"; + } else { + req += "trim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789') COLLATE NOCASE ASC , cast(m.filename as INTEGER) ASC, "; + req += "cast(substr("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",length(rtrim("; + req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; + req +=",'0123456789'))+1) as INTEGER) ASC"; + } + added = true; break; case SortingCriteria::LastModificationDate: req += "f.last_modification_date"; @@ -911,30 +931,45 @@ std::string Media::sortRequest( const QueryParameters* params ) req += "f.size"; break; case SortingCriteria::Album: - if ( desc == true ) + if ( desc == true ) req += "alb.title DESC, att.track_number"; else req += "alb.title, att.track_number"; + added = true; break; case SortingCriteria::Artist: - req += "art.name"; + if ( desc == true ) { + req += "trim(art.name,'0123456789') COLLATE NOCASE DESC , cast(art.name as INTEGER) DESC, "; + req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) DESC"; + } else { + req += "trim(art.name,'0123456789')COLLATE NOCASE ASC , cast(art.name as INTEGER) ASC, "; + req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) ASC"; + } + added = true; break; case SortingCriteria::TrackId: - if ( desc == true ) + if ( desc == true ) req += "alb.title, att.track_number DESC, att.disc_number"; else req += "alb.title, att.track_number, att.disc_number"; + added = true; break; default: LOG_WARN( "Unsupported sorting criteria, falling back to SortingCriteria::Default (Alpha)" ); /* fall-through */ case SortingCriteria::Default: case SortingCriteria::Alpha: - req += "m.title"; + if ( desc == true ) { + req += "trim(m.title,'0123456789') COLLATE NOCASE DESC , cast(m.title as INTEGER) DESC, "; + req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) DESC"; + } else { + req += "trim(m.title,'0123456789') COLLATE NOCASE ASC , cast(m.title as INTEGER) ASC, "; + req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) ASC"; + } + added = true; break; } - if ( desc == true && sort != SortingCriteria::Album && - sort != SortingCriteria::TrackId ) + if ( desc == true && !added) req += " DESC"; return req; } -- GitLab From aee63ce038a37145840b0b8a6b709bd2f7198841 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Tue, 17 Dec 2019 20:33:59 +0900 Subject: [PATCH 09/14] add unittest --- test/unittest/MediaTests.cpp | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 01bddb92..530e4456 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -867,7 +867,46 @@ TEST_F( Medias, Pagination ) media = paginator->items( 1, i ); } } +TEST_F( Medias, SortFilenameStartsWithNumber ) +{ + auto m1 = std::static_pointer_cast( ml->addMedia( "9 song.mp3", IMedia::Type::Audio ) ); + auto m2 = std::static_pointer_cast( ml->addMedia( "1 song.mp3", IMedia::Type::Audio ) ); + auto m3 = std::static_pointer_cast( ml->addMedia( "10 song.mp3", IMedia::Type::Audio ) ); + + QueryParameters params { SortingCriteria::Filename, false }; + auto media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[0]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[2]->id() ); + params.desc = true; + media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[2]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[0]->id() ); +} +TEST_F( Medias, SortFilenameEndsWithNumber ) +{ + auto m1 = std::static_pointer_cast( ml->addMedia( "song9.mp3", IMedia::Type::Audio ) ); + auto m2 = std::static_pointer_cast( ml->addMedia( "song1.mp3", IMedia::Type::Audio ) ); + auto m3 = std::static_pointer_cast( ml->addMedia( "song10.mp3", IMedia::Type::Audio ) ); + + QueryParameters params { SortingCriteria::Filename, false }; + auto media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[0]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[2]->id() ); + + params.desc = true; + media = ml->audioFiles( ¶ms )->all(); + ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( m2->id(), media[2]->id() ); + ASSERT_EQ( m1->id(), media[1]->id() ); + ASSERT_EQ( m3->id(), media[0]->id() ); +} TEST_F( Medias, SortFilename ) { auto m1 = std::static_pointer_cast( ml->addMedia( "AAAAB.mp3", IMedia::Type::Audio ) ); -- GitLab From 335a9daeb771974f59bccebe16122359251f9f2b Mon Sep 17 00:00:00 2001 From: Li Jian Date: Tue, 17 Dec 2019 23:36:38 +0900 Subject: [PATCH 10/14] move the sorting logic to one function --- src/Media.cpp | 49 ++++++++---------------------------- src/database/SqliteTools.h | 18 +++++++++++++ test/unittest/MediaTests.cpp | 2 +- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index 22a3984f..531cbc57 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -903,26 +903,8 @@ std::string Media::sortRequest( const QueryParameters* params ) desc = !desc; // Make decreasing order default for play count sorting break; case SortingCriteria::Filename: - if ( desc == true ) { - req += "trim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789') COLLATE NOCASE DESC , cast(m.filename as INTEGER) DESC, "; - req += "cast(substr("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",length(rtrim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789'))+1) as INTEGER) DESC"; - } else { - req += "trim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789') COLLATE NOCASE ASC , cast(m.filename as INTEGER) ASC, "; - req += "cast(substr("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",length(rtrim("; - req +="rtrim(rtrim(m.filename,replace(m.filename,'.','')),'.')"; - req +=",'0123456789'))+1) as INTEGER) ASC"; - } - added = true; + req += sqlite::Tools::sortedStringField("m.filename",desc,true); + added = true; break; case SortingCriteria::LastModificationDate: req += "f.last_modification_date"; @@ -931,27 +913,24 @@ std::string Media::sortRequest( const QueryParameters* params ) req += "f.size"; break; case SortingCriteria::Album: + + req += sqlite::Tools::sortedStringField("alb.title",desc); if ( desc == true ) - req += "alb.title DESC, att.track_number"; + req += ", att.track_number"; else - req += "alb.title, att.track_number"; + req += ", att.track_number"; added = true; break; case SortingCriteria::Artist: - if ( desc == true ) { - req += "trim(art.name,'0123456789') COLLATE NOCASE DESC , cast(art.name as INTEGER) DESC, "; - req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) DESC"; - } else { - req += "trim(art.name,'0123456789')COLLATE NOCASE ASC , cast(art.name as INTEGER) ASC, "; - req += "cast(substr(art.name,length(rtrim(art.name,'0123456789'))+1) as INTEGER) ASC"; - } + req += sqlite::Tools::sortedStringField("art.name",desc); added = true; break; case SortingCriteria::TrackId: + req += sqlite::Tools::sortedStringField("alb.title",false); if ( desc == true ) - req += "alb.title, att.track_number DESC, att.disc_number"; + req += ", att.track_number DESC, att.disc_number"; else - req += "alb.title, att.track_number, att.disc_number"; + req += ", att.track_number, att.disc_number"; added = true; break; default: @@ -959,13 +938,7 @@ std::string Media::sortRequest( const QueryParameters* params ) /* fall-through */ case SortingCriteria::Default: case SortingCriteria::Alpha: - if ( desc == true ) { - req += "trim(m.title,'0123456789') COLLATE NOCASE DESC , cast(m.title as INTEGER) DESC, "; - req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) DESC"; - } else { - req += "trim(m.title,'0123456789') COLLATE NOCASE ASC , cast(m.title as INTEGER) ASC, "; - req += "cast(substr(m.title,length(rtrim(m.title,'0123456789'))+1) as INTEGER) ASC"; - } + req += sqlite::Tools::sortedStringField("m.title",desc); added = true; break; } diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 95e539c9..83815596 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -459,7 +459,25 @@ class Tools * sqlite, and a '*' appended */ static std::string sanitizePattern( const std::string& pattern ); + static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt=false) + { + auto f = std::string(field); + auto d = desc?std::string("DESC"):std::string("ASC"); + return std::string( + hasExt ? + "trim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789') COLLATE NOCASE "+d+"," // like aaa123.mp3 => aaa + : + "rtrim("+f+",'0123456789') COLLATE NOCASE "+d+"," + ) // like aaa123 => aaa + + " cast("+f+" as INTEGER) "+d+", " + //prefix like 123aaa => 123 + std::string( + hasExt ? // aaa123.mp3=>123 + "cast(substr(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),length(rtrim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789'))+1) as INTEGER) "+d + : + "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)" // aaa123=>123 + ); //postfix + } private: template static void executeRequestLocked( sqlite::Connection* dbConnection, diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 530e4456..7986e86b 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -471,7 +471,7 @@ TEST_F( Medias, SortByAlpha ) QueryParameters params { SortingCriteria::Alpha, false }; auto media = ml->audioFiles( ¶ms )->all(); - ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( 3u, media.size() ); ASSERT_EQ( m1->id(), media[0]->id() ); ASSERT_EQ( m3->id(), media[1]->id() ); ASSERT_EQ( m2->id(), media[2]->id() ); -- GitLab From eb27657706069234c6f5fdf4a359feb3c35eea11 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 21:15:20 +0900 Subject: [PATCH 11/14] refactor sortedStringField --- src/Media.cpp | 8 ++++---- src/database/SqliteTools.h | 38 +++++++++++++++++++----------------- test/unittest/MediaTests.cpp | 2 +- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index 531cbc57..6f021cd3 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -914,7 +914,7 @@ std::string Media::sortRequest( const QueryParameters* params ) break; case SortingCriteria::Album: - req += sqlite::Tools::sortedStringField("alb.title",desc); + req += sqlite::Tools::sortedStringField("alb.title",desc,false); if ( desc == true ) req += ", att.track_number"; else @@ -922,11 +922,11 @@ std::string Media::sortRequest( const QueryParameters* params ) added = true; break; case SortingCriteria::Artist: - req += sqlite::Tools::sortedStringField("art.name",desc); + req += sqlite::Tools::sortedStringField("art.name",desc,false); added = true; break; case SortingCriteria::TrackId: - req += sqlite::Tools::sortedStringField("alb.title",false); + req += sqlite::Tools::sortedStringField("alb.title",false,false); if ( desc == true ) req += ", att.track_number DESC, att.disc_number"; else @@ -938,7 +938,7 @@ std::string Media::sortRequest( const QueryParameters* params ) /* fall-through */ case SortingCriteria::Default: case SortingCriteria::Alpha: - req += sqlite::Tools::sortedStringField("m.title",desc); + req += sqlite::Tools::sortedStringField("m.title",desc,false); added = true; break; } diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 83815596..4af9b80e 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -459,25 +459,27 @@ class Tools * sqlite, and a '*' appended */ static std::string sanitizePattern( const std::string& pattern ); - static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt=false) - { - auto f = std::string(field); - auto d = desc?std::string("DESC"):std::string("ASC"); - return std::string( - hasExt ? - "trim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789') COLLATE NOCASE "+d+"," // like aaa123.mp3 => aaa - : - "rtrim("+f+",'0123456789') COLLATE NOCASE "+d+"," - ) // like aaa123 => aaa - + " cast("+f+" as INTEGER) "+d+", " + //prefix like 123aaa => 123 - std::string( - hasExt ? // aaa123.mp3=>123 - "cast(substr(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),length(rtrim(rtrim(rtrim("+f+",replace("+f+",'.','')),'.'),'0123456789'))+1) as INTEGER) "+d - : - "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)" // aaa123=>123 - ); //postfix + static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt) + { + auto f = std::string(field); + auto d = desc?" DESC":" ASC"; - } + //aaa.mp3 => aaa + auto removeExt = "rtrim(rtrim("+f+",replace("+f+",'.','')),'.')"; + auto lengthAfterRemoveExtNumber = "length(rtrim("+ removeExt +",'0123456789'))"; + + auto removeLastNumber = "rtrim("+f+",'0123456789')"; + auto removeNumberAndExt = "trim(" + removeExt + ",'0123456789')"; + auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE "+d; + + auto lastNumberNoExt = "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)"; + auto lastNumberAfterRemoveExt = "cast(substr("+removeExt+","+ lengthAfterRemoveExtNumber +"+1) as INTEGER) "; + auto lastNumber = (hasExt ? lastNumberAfterRemoveExt : lastNumberNoExt) + d; + + auto firstNumber = " cast("+f+" as INTEGER) "+d; + + return titleNoExtNumber + "," + firstNumber +" , " + lastNumber; + } private: template static void executeRequestLocked( sqlite::Connection* dbConnection, diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 7986e86b..530e4456 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -471,7 +471,7 @@ TEST_F( Medias, SortByAlpha ) QueryParameters params { SortingCriteria::Alpha, false }; auto media = ml->audioFiles( ¶ms )->all(); - ASSERT_EQ( 3u, media.size() ); + ASSERT_EQ( 3u, media.size() ); ASSERT_EQ( m1->id(), media[0]->id() ); ASSERT_EQ( m3->id(), media[1]->id() ); ASSERT_EQ( m2->id(), media[2]->id() ); -- GitLab From 4cdf74b8e2a9e9d8db1b3102b0c0f0abdc71a3ac Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 21:23:57 +0900 Subject: [PATCH 12/14] refactor sortedStringField --- src/database/SqliteTools.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index 4af9b80e..fe02f206 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -461,22 +461,21 @@ class Tools static std::string sanitizePattern( const std::string& pattern ); static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt) { - auto f = std::string(field); auto d = desc?" DESC":" ASC"; //aaa.mp3 => aaa - auto removeExt = "rtrim(rtrim("+f+",replace("+f+",'.','')),'.')"; + auto removeExt = "rtrim(rtrim("+field+",replace("+field+",'.','')),'.')"; auto lengthAfterRemoveExtNumber = "length(rtrim("+ removeExt +",'0123456789'))"; - auto removeLastNumber = "rtrim("+f+",'0123456789')"; + auto removeLastNumber = "rtrim("+field+",'0123456789')"; auto removeNumberAndExt = "trim(" + removeExt + ",'0123456789')"; auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE "+d; - auto lastNumberNoExt = "cast(ltrim("+f+",rtrim("+f+",'0123456789')) as INTEGER)"; + auto lastNumberNoExt = "cast(ltrim("+field+",rtrim("+field+",'0123456789')) as INTEGER)"; auto lastNumberAfterRemoveExt = "cast(substr("+removeExt+","+ lengthAfterRemoveExtNumber +"+1) as INTEGER) "; auto lastNumber = (hasExt ? lastNumberAfterRemoveExt : lastNumberNoExt) + d; - auto firstNumber = " cast("+f+" as INTEGER) "+d; + auto firstNumber = " cast("+field+" as INTEGER) "+d; return titleNoExtNumber + "," + firstNumber +" , " + lastNumber; } -- GitLab From a795fb74008e3acc21c15f9dd20a95f770d91d00 Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 21:59:36 +0900 Subject: [PATCH 13/14] remove the const from the bool parameter --- src/database/SqliteTools.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/database/SqliteTools.h b/src/database/SqliteTools.h index fe02f206..67ce6d71 100644 --- a/src/database/SqliteTools.h +++ b/src/database/SqliteTools.h @@ -459,25 +459,25 @@ class Tools * sqlite, and a '*' appended */ static std::string sanitizePattern( const std::string& pattern ); - static std::string sortedStringField( const std::string& field, const bool desc,const bool hasExt) + static std::string sortedStringField( const std::string& field, bool desc, bool hasExt) { - auto d = desc?" DESC":" ASC"; + auto d = desc ? " DESC":" ASC"; //aaa.mp3 => aaa - auto removeExt = "rtrim(rtrim("+field+",replace("+field+",'.','')),'.')"; - auto lengthAfterRemoveExtNumber = "length(rtrim("+ removeExt +",'0123456789'))"; + auto removeExt = "rtrim(rtrim(" + field + ",replace(" + field + ",'.','')),'.')"; + auto lengthAfterRemoveExtNumber = "length(rtrim(" + removeExt + ",'0123456789'))"; - auto removeLastNumber = "rtrim("+field+",'0123456789')"; + auto removeLastNumber = "rtrim(" + field + ",'0123456789')"; auto removeNumberAndExt = "trim(" + removeExt + ",'0123456789')"; - auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE "+d; + auto titleNoExtNumber = (hasExt ? removeNumberAndExt : removeLastNumber) + " COLLATE NOCASE " + d; - auto lastNumberNoExt = "cast(ltrim("+field+",rtrim("+field+",'0123456789')) as INTEGER)"; - auto lastNumberAfterRemoveExt = "cast(substr("+removeExt+","+ lengthAfterRemoveExtNumber +"+1) as INTEGER) "; + auto lastNumberNoExt = "cast(ltrim(" + field + ",rtrim(" + field + ",'0123456789')) as INTEGER)"; + auto lastNumberAfterRemoveExt = "cast(substr(" + removeExt + "," + lengthAfterRemoveExtNumber + " + 1) as INTEGER) "; auto lastNumber = (hasExt ? lastNumberAfterRemoveExt : lastNumberNoExt) + d; - auto firstNumber = " cast("+field+" as INTEGER) "+d; + auto firstNumber = " cast(" + field + " as INTEGER) " + d; - return titleNoExtNumber + "," + firstNumber +" , " + lastNumber; + return titleNoExtNumber + "," + firstNumber + " , " + lastNumber; } private: template -- GitLab From 318ac80101f203f87c26827e6e873f7b73ac07aa Mon Sep 17 00:00:00 2001 From: Li Jian Date: Thu, 19 Dec 2019 22:29:10 +0900 Subject: [PATCH 14/14] remove added to descAdded --- src/Media.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Media.cpp b/src/Media.cpp index 6f021cd3..5ca08cc2 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -886,7 +886,7 @@ std::string Media::sortRequest( const QueryParameters* params ) auto sort = params != nullptr ? params->sort : SortingCriteria::Default; auto desc = params != nullptr ? params->desc : false; - auto added = false; + auto descAdded = false; switch ( sort ) { case SortingCriteria::Duration: @@ -904,7 +904,7 @@ std::string Media::sortRequest( const QueryParameters* params ) break; case SortingCriteria::Filename: req += sqlite::Tools::sortedStringField("m.filename",desc,true); - added = true; + descAdded = true; break; case SortingCriteria::LastModificationDate: req += "f.last_modification_date"; @@ -919,11 +919,11 @@ std::string Media::sortRequest( const QueryParameters* params ) req += ", att.track_number"; else req += ", att.track_number"; - added = true; + descAdded = true; break; case SortingCriteria::Artist: req += sqlite::Tools::sortedStringField("art.name",desc,false); - added = true; + descAdded = true; break; case SortingCriteria::TrackId: req += sqlite::Tools::sortedStringField("alb.title",false,false); @@ -931,7 +931,7 @@ std::string Media::sortRequest( const QueryParameters* params ) req += ", att.track_number DESC, att.disc_number"; else req += ", att.track_number, att.disc_number"; - added = true; + descAdded = true; break; default: LOG_WARN( "Unsupported sorting criteria, falling back to SortingCriteria::Default (Alpha)" ); @@ -939,10 +939,10 @@ std::string Media::sortRequest( const QueryParameters* params ) case SortingCriteria::Default: case SortingCriteria::Alpha: req += sqlite::Tools::sortedStringField("m.title",desc,false); - added = true; + descAdded = true; break; } - if ( desc == true && !added) + if ( desc == true && !descAdded) req += " DESC"; return req; } -- GitLab