• Tom Lane's avatar
    Fix lquery's NOT handling, and add ability to quantify non-'*' items. · 70dc4c50
    Tom Lane authored
    The existing implementation of the ltree ~ lquery match operator is
    sufficiently complex and undocumented that it's hard to tell exactly
    what it does.  But one thing it clearly gets wrong is the combination
    of NOT symbols (!) and '*' symbols.  A pattern such as '*.!foo.*'
    should, by any ordinary understanding of regular expression behavior,
    match any ltree that has at least one label that's not "foo".  As best
    we can tell by experimentation, what it's actually matching is any
    ltree in which *no* label is "foo".  That's surprising, and not at all
    what the documentation says.
    
    Now, that's arguably a useful behavior, so if we rewrite to fix the
    bug we should provide some other way to get it.  To do so, add the
    ability to attach lquery quantifiers to non-'*' items as well as '*'s.
    Then the pattern '!foo{,}' expresses "any ltree in which no label is
    foo".  For backwards compatibility, the default quantifier for non-'*'
    items has to be "{1}", although the default for '*' items is '{,}'.
    I wouldn't have done it like that in a green field, but it's not
    totally horrible.
    
    Armed with that, rewrite checkCond() from scratch.  Treating '*' and
    non-'*' items alike makes it simpler, not more complicated, so that
    the function actually gets a lot shorter than it was.
    
    Filip Rembiałkowski, Tom Lane, Nikita Glukhov, per a very
    ancient bug report from M. Palm
    
    Discussion: https://postgr.es/m/CAP_rww=waX2Oo6q+MbMSiZ9ktdj6eaJj0cQzNu=Ry2cCDij5fw@mail.gmail.com
    70dc4c50
ltree_io.c 15.3 KB