Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track search: use := and quotes to find exact matches #12063

Merged
merged 3 commits into from Oct 11, 2023

Conversation

ronso0
Copy link
Member

@ronso0 ronso0 commented Oct 5, 2023

A quick check that has proven to work:
[text property]:="string" finds only tracks where the property is exactly string.
title:="Blob" finds all track titles that exactly "Blob", not "What a Blob" etc.

May be extended to include spaces and special chars before and after to find Blob and ..Blob!

Bug fix or feature? Doesn't change the ui, hence I targeted 2.4
But it reuires a manual update.

Closes #10699

: m_database(database),
m_sqlColumns(sqlColumns),
m_argument(argument) {
m_argument(argument),
m_exactMatch(exactMatch) {
Copy link
Contributor

@uklotzde uklotzde Oct 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool is a poor type choice. An enum class StringMatch with Equals and Contains variants would be much more concise, maintainable, and extensible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hint.
Though this is on hold for now, someone else may adopt it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.
And I implemented it in the existing text filter matcher, so the changes are much smaller, no code duplication anymore.

Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couldn't resist "meinen senf abzugeben" ;)

Thank you.

Comment on lines +191 to +193
EXPECT_STREQ(
qPrintable(QString("comment LIKE 'asdf'")),
qPrintable(pQuery->toSql()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this tests implementation details IMO and does not belong in a test IMO. wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are crucial implementation details, sure they need to be tested.
Please elaborate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well it conflates two different levels of abstraction. The first part of the test checks for the behavior. That should be very stable and even if we changed some details about our database these won't change. On the other hand, all the tests that involve toSql don't only rely on the fact that we use SQL (something that would not be true if we were to transition to aoide) but even how exactly we do the fuzzy matching (using LIKE) even though there are other implementations as well. Do you see how this introduces coupling? The test should be ensuring the behavior, not the way it works internally.
A little (admittedly childish and simplified) analogy: If I need to put a nail into a wall, I can just use a hammer, I don't care if the hammerhead is made of iron or steel, both do the job (I think, I'm not a carpenter 😅).
Sure if you need to test specific properties of a hammer, that is legitimate to test, but it doesn't belong in the same test as "it puts a nail into a wall".

I'm aware that this is quite theoretical and likely a little controversial the code in question just follows the same pattern as the rest of the file. I'm just saying that the current design is not great and we should question it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. of course, ideally, we'd just test the parser to return certain track ids of a sample library.

src/library/searchquery.cpp Outdated Show resolved Hide resolved
Comment on lines 92 to 94
QString SearchQueryParser::getTextArgument(QString argument,
QStringList* tokens) const {
QStringList* tokens,
StringMatch* matchMode) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dislike the implicitness of the out parameter. Eg its not fully transparent if the pointer is valid but shouldMatchExactly is false. then it'll just not set anything. A caller might expect it to always set it. The result is that if used incorrectly (which is not hard in this case), the caller could be left with an initialized variable.

Imo the better design would be not use an out-parameter in this case and instead just return a struct with both the matchmode and the argument.

Suggested change
QString SearchQueryParser::getTextArgument(QString argument,
QStringList* tokens) const {
QStringList* tokens,
StringMatch* matchMode) const {
struct TextArgumentResult {
QString argumentValue;
StringMatch matchmode;
};
TextArgumentResult SearchQueryParser::getTextArgument(QString argument,
QStringList* tokens) const {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eg its not fully transparent if the pointer is valid but shouldMatchExactly is false. then it'll just not set anything.

For now, I fixed that by setting matchMode at the beginning.

A struct would for me, too, but it requires more refactoring.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not so much imo. PR underway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/library/searchquery.cpp Outdated Show resolved Hide resolved
@ronso0 ronso0 changed the title Track search: use = and quotes to find exact matches Track search: use := and quotes to find exact matches Oct 9, 2023
Co-authored-by: Swiftb0y <12380386+Swiftb0y@users.noreply.github.com>
@ronso0 ronso0 force-pushed the search-exact branch 2 times, most recently from 31f95ef to 62da287 Compare October 10, 2023 01:26
@ronso0
Copy link
Member Author

ronso0 commented Oct 10, 2023

Looking good now.
@Swiftb0y Please let me know if you're happy with the fixup.

if (argument.startsWith("=")) {
// strip the '=' from the argument
argument = argument.mid(1);
// TODO(ronso0) should 'tag:"string"' really be equal to 'tag:="string"?
Copy link
Member Author

@ronso0 ronso0 Oct 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edit
tag:=string and tag:="string"

@Swiftb0y
Copy link
Member

lgtm otherwise. thank you.

@ronso0 ronso0 force-pushed the search-exact branch 2 times, most recently from ffcd6c0 to 51c2a38 Compare October 10, 2023 13:35
@Swiftb0y
Copy link
Member

fyi the parser could like be simplified even more if the tokenizer recognized the quotes and just consumed the entire thing as one token. That would make consumeQuotedArgument largely unnecessary...

@ronso0
Copy link
Member Author

ronso0 commented Oct 11, 2023

fyi the parser could like be simplified even more if the tokenizer recognized the quotes and just consumed the entire thing as one token. That would make consumeQuotedArgument largely unnecessary...

Tbh I'm not motivated to do more optimization, this has already grown way beyond my initial commit (though I very much appreciate your input!).

@Swiftb0y
Copy link
Member

Tbh I'm not motivated to do more optimization, this has already grown way beyond my initial commit (though I very much appreciate your input!).

Yes, I'm sorry for blowing up the scope. The previous comment was just a remark and not a request for more changes.

Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Thank you very much.

@Swiftb0y
Copy link
Member

remove draft and merge?

@ronso0
Copy link
Member Author

ronso0 commented Oct 11, 2023

Ready!

TODO
update the manual

@ronso0 ronso0 marked this pull request as ready for review October 11, 2023 10:24
@Swiftb0y Swiftb0y merged commit 1087d9b into mixxxdj:2.4 Oct 11, 2023
13 checks passed
@Swiftb0y
Copy link
Member

Thank you

@ronso0
Copy link
Member Author

ronso0 commented Oct 11, 2023

I'd say this deserves a changelog entry to make the change a bit more discoverable for upgraders (if they already read the search documentation they probably won't notice the change..).
Wdyt?

@ronso0 ronso0 mentioned this pull request Oct 12, 2023
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants