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

Fix empty filter bug #19

Merged
merged 1 commit into from
Jun 14, 2017

Conversation

gramanas
Copy link

@gramanas gramanas commented Jun 7, 2017

When user types "filter:" and nothing after it, the query should return the
whole library since in the search we have just an empty filter.

Basically I removes the IS NULL sqlNode that was created in SearchQueryParser::parseTokens

@daschuer
Copy link
Owner

daschuer commented Jun 7, 2017

@jmigual Please have a look in this.

This is NULL feature was explicit introduced here:
6aac36c#diff-74cc91f7c2236563aad44e59ee0654f7

Do you remember why?

Is there a use case for an empty search query?
Like finding all tracks without a genre?

@jmigual
Copy link

jmigual commented Jun 7, 2017

Yes it was introduced to search for tracks that do not have a certain field. I introduced it because in the sorting tree the elements that belong to the "Unknown" tag need to be able to be selected when the user clicks it.

For example if I have tracks that do not have artist they'll show all grouped under the "Unknown" tag and when I click it I will expect to see this tracks and, since the tree is a query helper, I introduced the NULL feature.

@gramanas
Copy link
Author

gramanas commented Jun 7, 2017

But it can't be generated when a user has typed nothing. Maybe a special keyword could be used to generate it, eg NULL.

@gramanas
Copy link
Author

gramanas commented Jun 7, 2017

I added a nullFilterMatcher in SearchQueryParser witch captures paterns like "artist:0"
so you can use this in the Unknown tag.

@jmigual
Copy link

jmigual commented Jun 7, 2017

But in the way it's now if the user types
"artist:" the NULL is added so I don't understand why the 0 must be added.

@gramanas
Copy link
Author

gramanas commented Jun 7, 2017

because if the user types "artist:" the full library should be returned, cause this is the way the filters worked so far. I also find it more logical, like you've typed what filter you want to use (eg artist:) and you see the whole library, then you start typing the artist's name and the results narrow to your search. If you want to get the NULL values you use the special filter ":0". Ofc if you find ":0" strange we could make it something else

@gramanas
Copy link
Author

gramanas commented Jun 7, 2017

@daschuer @jmigual Ok, the new null filter matcher matches stuff like "artist:=0" I modified the query generated by the unknown tag in the tree to be able to generate this one.

Also the old (artist IS NULL) didn't work for me, I got 282 songs in my library without artist. Only 4 of them were shown. So I changed it to ((artist IS NULL) OR (artist LIKE "")) and now it shows everything. From my tests everything works fine, please have a look and comment if you have any problems with what is happening.

@daschuer
Copy link
Owner

daschuer commented Jun 7, 2017

"artist:0" does not work well, because it also stands for as artist containing "0". The original solution was quite natural for me. On one hand you are right that you are narrowing the we search while typing, on the other hand it does not work anyway, because while you type you are actually searching for a track containing "artist" only after the colon the real search starts.
We may consider to use artist:"" but I like the original behaviour more.

@Be-ing what do you think about this?

@gramanas
Copy link
Author

gramanas commented Jun 7, 2017

I am open to suggestions to change the zero, I don't like it that much either. But I really feel that artist: alone should return the whole library.

Also we should change crate: to also have an exact match with crate:= and think about the following: Should crate:=0 or whatever we make it to be return all the songs that are NOT in a crate?

Following the same logic I feel that this whole IS NULL thing should maybe be a modifier like - so I am thinking on something in the line of !artist: since ! already means NOT in computer word.

For the exact match of the crate we just need to add a function in CrateStorage witch instead of creating the query using LIKE it does so using the equality operator.

@jmigual
Copy link

jmigual commented Jun 7, 2017

If I remember properly (I have to check it though) the meaning of := wasn't the same of : so we have both versions and they do different things. I think it was something like := is the exact match and : is a similar match using SQLite LIKE function.

@jmigual
Copy link

jmigual commented Jun 7, 2017

And for the empty search artist: i prefer the way that is it now because you are specifying all the tracks where artist is a null string, if you want to see all the library you can just remove the query and you'll see all the library.

Bye the way @gramanas take in account that if you change the NULL definition you must update the query tree helper in the sidebar so it continues working.

@gramanas
Copy link
Author

gramanas commented Jun 7, 2017

I did update the query tree helper, it works correctly. About the IS NULL query as I said , I got 282 songs in my library without artist. Only 4 of them were shown with your code. So I changed it to ((artist IS NULL) OR (artist LIKE "")) and now it shows everything. Check in the searchqueryparser.cpp where it generates the IS NULL query.

Ok, if you prefer artist: to show the NULL stuff it's ok. It's just not the way it works right now.
When we decide something I will implement it happily!

@Be-ing
Copy link

Be-ing commented Jun 8, 2017

We may consider to use artist:"" but I like the original behaviour more.
@Be-ing what do you think about this?

What about using artist:="" to explicitly search for an empty field and make artist: by itself do nothing as @gramanas is proposing? I would prefer this to complicating the query syntax with another special operator.

Also we should change crate: to also have an exact match with crate:= and think about the following: Should crate:=0 or whatever we make it to be return all the songs that are NOT in a crate?

-crate:="" should return all tracks that are in any crate.

@daschuer
Copy link
Owner

daschuer commented Jun 8, 2017 via email

@Be-ing
Copy link

Be-ing commented Jun 8, 2017

I think you are right that artist:="" is not easily discoverable. An observant user may notice that query generated when clicking "Unknown" in the tree, but the subtle details of the = and the empty string together would be difficult to notice. So I think using plain artist: to find tracks without an artist is best, even if it is a bit strange if you're expecting the entire library. If you want the entire library, just delete the filter.

@uklotzde
Copy link

uklotzde commented Jun 8, 2017

From a theoretical point of view I prefer continuous functions with consistent behaviour. The more characters you add, the more you narrow your search: No characters -> Match all.

But I must agree with @Be-ing. You convinced me with your last argument 👍 We don't need a multitude of possible inputs for the same result when on the other hand we have to introduce ambiguous inputs for handling the missing use cases.

@gramanas
Copy link
Author

gramanas commented Jun 8, 2017

Ok, I'll fix and push as you said. But then crate: should return all tracks that are not in a crate. We should look at that later.

@uklotzde
Copy link

uklotzde commented Jun 8, 2017

Sounds reasonable: "crate:" => all tracks that are not contained in any crate

One use case I could think of is to identify all tracks that have not been sorted into crates, yet.

@gramanas
Copy link
Author

gramanas commented Jun 9, 2017

I did as you said and almost everything works.

I am having some trouble with the SearchQueryParserTest.TextFilterEmpty again. No matter what I try, while the sql works fine the match function does not... @uklotzde any ideas?

}
if (value != "0") {
value = "\"" + value + "\"";
}
Copy link
Owner

Choose a reason for hiding this comment

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

Is this a leftover form the artist:0 version?

@gramanas
Copy link
Author

gramanas commented Jun 9, 2017 via email

@daschuer
Copy link
Owner

SearchQueryParserTest.TextFilterEmpty fails.

There seams to be also an escaping issue. I have a crate "40's" and "crate:40's" does not return any result. Other crates are working fine.

@gramanas
Copy link
Author

gramanas commented Jun 11, 2017

There is no escaping happening anywhere in the crate filter, @uklotzde @Be-ing it appears I missed that part. I'll try adding it here.

About the TextFIlterEmpty test: I believe TextFilterNode::match() has some problems.
This line:
if (value.toString().contains(m_argument, Qt::CaseInsensitive)) { return true; }

when the query has an empty string as an argument artist:"" for example,
it will always return true.

Apparently the SqlNode that was created could not match() as it should
so I removed it and made TextFilter to be aware of the empty argument
and act accordingly

Add escape to crate filter argument
@gramanas
Copy link
Author

I added escape in crate filter and I think I also fixed the bug.

Now for the empty text filter:
As it was the parser generated a SqlNode with the IS NULL argument. Then the SqlNode::match() function always returns true cause it's not supposed to be used this way.

I modified the TextFilter and the ExactFilter to be aware that the argument is empty. Everything seems to work fine.

@jmigual The GLOB clause in the exact filter can't match stuff like this [ MISC ]. I got some tracks with this as a genre and the exact filter can't find them. It seems that GLOB gets lists of characters to match enclosed in brackets. So this genre:="[ MISC ]" Matches one character from the enclosed list of characters. I haven't given this any thought since it's not a major issue. Maybe instead of GLOB we could use = and use GLOB only when wildstars * are necessary.

if (value.toString().contains(m_argument, Qt::CaseInsensitive)) {
return true;
if (m_argument.isEmpty()) {
if (value.toString().isEmpty()) {

Choose a reason for hiding this comment

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

Both if statements on the 2nd level can be simplified: return

Handling the special case m_argument.isEmpty() separately seems reasonable to me.

@gramanas
Copy link
Author

@daschuer @jmigual what do you think, should we merge it?

@jmigual
Copy link

jmigual commented Jun 14, 2017

@jmigual The GLOB clause in the exact filter can't match stuff like this [ MISC ]. I got some tracks with this as a genre and the exact filter can't find them. It seems that GLOB gets lists of characters to match enclosed in brackets. So this genre:="[ MISC ]" Matches one character from the enclosed list of characters. I haven't given this any thought since it's not a major issue. Maybe instead of GLOB we could use = and use GLOB only when wildstars * are necessary.

In this case I added the GLOB to allow the user to search for things like artist:=A* which should return all the artists with a name starting with A (if I remember properly this is used by the tree query helper). If we replace GLOB by = we remove this possibility. Also, with this type of query, there's no way to know if the user is creating a glob like a[abc] (which should return aa, ab, ac) or it's really a genre name.

A solution may be to remove the possibility to search with a glob like a[abc] and always escape the [ and ] characters.

@daschuer
Copy link
Owner

daschuer commented Jun 14, 2017

I am in favour to keep the syntax simple in the first place. artist:bla schould return all artists containing bla, no special character replacement like * or [.
Later we can also consider to replace this by a phonetic search. artist:dune schould match the artist Dúné, artist:pink schould match P!nk, and artist:*NSYNC schould match 'N Sync and even spelling errors schould be considered.

With the syntax artist:="" we can do all more technical things we discussed​ above. We can also invent a new syntax for fully GLOB cause compliant.

@Be-ing
Copy link

Be-ing commented Jun 14, 2017

Regarding the issue with GLOB and brackets, I agree with @daschuer that the syntax should remain very simple, so the filters should escape any [ and ] characters the user enters. The use case for using those as they behave unescaped should be fulfilled with a way to combine QueryNodes with an OR relationship instead of AND. IMO that is not something we need to deal with right now. I have opened a Launchpad ticket so we do not forget about it.

@gramanas
Copy link
Author

Ok but don't think this is a place to fix such an issue so let's merge this branch and work on it in another.

Copy link

@Be-ing Be-ing left a comment

Choose a reason for hiding this comment

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

Some minor style nitpicks, but nothing that needs to hold back merging this.

&m_pTrackCollection->crates(), argument);
} else {
//TODO(gramanas) It should generate a query to
//match all the tracks that are not in a crate.
Copy link

Choose a reason for hiding this comment

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

An explicit continue line here would make it a little easier to read.

//match all the tracks that are not in a crate.
}
}
else {
Copy link

Choose a reason for hiding this comment

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

Please put on one line:
} else {

auto pQuery(
m_parser.parseQuery("comment:", searchColumns, ""));
m_parser.parseQuery("album: ", searchColumns, ""));
Copy link

Choose a reason for hiding this comment

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

It would be good to add a test to check that "album: " and "album:" are treated the same.

@daschuer
Copy link
Owner

Works now good. Sorry for the delay.

@daschuer daschuer merged commit 94ad1d5 into daschuer:jmigual-library-redesign Jun 14, 2017
@gramanas gramanas deleted the EmptyFilterBug branch June 14, 2017 22:39
@gramanas
Copy link
Author

No problem, thanks!

daschuer pushed a commit that referenced this pull request Sep 30, 2021
CI: Update Docker image for GitHub pre-commit workflow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants