SQL encoding of PropertyIsEqualTo adds an unecessary "AND attribute IS NOT NULL"

Description

Hi

we access the WMS service by sending a request having a ogc:Filter. The Geoserver interprets the filter and creates SQL likes:

SELECT "gid",encode(ST_AsBinary(ST_Simplify(ST_Force2D("the_geom"), 488.15834624618293, true)),'base64') as "the_geom" FROM "public"."points_view" WHERE ("the_geom" && ST_GeomFromText('POLYGON ((309613.80322206434 5989409.96286553, 309613.80322206434 6289017.14787394, 1313683.0713944233 6289017.14787394, 1313683.0713944233 5989409.96286553, 309613.80322206434 5989409.96286553))', 3857) AND (("gid" = 39513 AND "gid" IS NOT NULL ) OR ("gid" = 39516 AND "gid" IS NOT NULL ) OR ("gid" = 39509 AND "gid" IS NOT NULL ) OR ("gid" = 39570 AND "gid" IS NOT NULL ) OR ("gid" = 39572 AND "gid" IS NOT NULL ) OR ("gid" = 39573 AND "gid" IS NOT NULL ) OR ("gid" = 39750 AND "gid" IS NOT NULL ) OR ("gid" = 40171 AND "gid" IS NOT NULL ) OR ("gid" = 40305 AND "gid" IS NOT NULL ) OR ("gid" = 40456 AND "gid" IS NOT NULL ) OR ….

There are case where we have to wait 20 sec. for postgres to respond. With the "gid" IS NOT NULL part out the Query is 2 sec long.

Below is the SLD we send.

<ogc:Filter><ogc:Or><ogc:PropertyIsEqualTo><ogc:PropertyName>gid</ogc:PropertyName><ogc:Literal>39513</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>gid</ogc:PropertyName><ogc:Literal>39516</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>gid</ogc:PropertyName><ogc:Literal>39509</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>gid</ogc:PropertyName><ogc:Literal>89082</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>gid</ogc:PropertyName><ogc:Literal>89150</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Or></ogc:Filter>

Thank You,
Sorin

Environment

None

Attachments

2

Activity

Sorin Dudui
June 19, 2017 at 4:45 PM

You are right, the above method is not a perfect workaround. I will try instead to create a new Filter Class where I will have 2 Filter Objects. The original One and the Not Null One. And return an AND Filter Object of both, in the guardAgainstNulls method.

Andrea Aime
June 19, 2017 at 4:17 PM

Eh, I wish I remember the details, but I don't (I will have no time to look into it for a while). Is the code still passing all the tests (run them in the gt-jdbc-h2 module)? Did you add any new?
If so, you can try to make your own pull request according to https://github.com/geotools/geotools/blob/master/CONTRIBUTING.md

That said, collecting information in a field seems problematic, what if there are multiple nested logical operations? The visit will accumulate state and start crossing outer filters with innner ones... does not sound like something desirable.

Sorin Dudui
June 19, 2017 at 4:09 PM

Hi,

I have pulled out the geotools code and had a look in the method NullHandlingVisitor::guardAgainstNulls. The class was commited with the pull request: https://github.com/geotools/geotools/pull/358.

I have modified a little the code and tried to keep all the "Property IS NOT NULL Filter" , in a common AND condition: Here are my changes:

class NullHandlingVisitor extends DuplicatingFilterVisitor { private FeatureType schema; private And notIsNullAllFilter; ..... private Filter guardAgainstNulls(Filter filter, Expression potentialPropertyName) { if (potentialPropertyName instanceof PropertyName) { PropertyName pn = (PropertyName) potentialPropertyName; String name = pn.getPropertyName(); if (isNillable(name)) { Not notNull = ff.not(ff.isNull(ff.property(name))); if(notIsNullAllFilter == null ) { notIsNullAllFilter = ff.and(Arrays.asList(new Filter[]{notNull})); if (filter instanceof And) { And and = (And) filter; List<Filter> children = new ArrayList<Filter>(and.getChildren()); children.add(notIsNullAllFilter); return ff.and(children); } else { return ff.and(filter, notIsNullAllFilter); } } else{ List<Filter> children = notIsNullAllFilter.getChildren(); children.add(notNull); } } } return filter; }

Do you think my code will work? I do not know all the implications.

Regards,
Sorin

Sorin Dudui
June 7, 2017 at 10:08 AM

Hi,

In order to code the issue I have to understand very well the side effects of the changing. I will try to look onto it. For the moment I have fixed the issue by using a Comparation Function: "in"

Thank you,
Sorin

Andrea Aime
June 2, 2017 at 3:13 PM
(edited)

It does not indeed. I believe that's a side effect of some work I did years ago to handle the difference between OGC two state logic and SQL three state logic (but I'm not sure, it's just a guess):
http://osgeo-org.1560.x6.nabble.com/Fun-with-filter-negation-in-sql-stores-td5101506.html

So, someone needs to rework the encoding in order to get back the performance for the simple case, but avoid the error for the negation.
If this is a matter of urgency for you I suggest you propose a pull request yourself, making sure all tests are still passing after the change, or look for commercial support in order to get this improved. Links:

Details

Assignee

Reporter

Triage

Affects versions

Components

Priority

Created June 2, 2017 at 12:33 PM
Updated June 19, 2017 at 4:45 PM