• Andrew Dunstan's avatar
    Support JSON negative array subscripts everywhere · e02d44b8
    Andrew Dunstan authored
    Previously, there was an inconsistency across json/jsonb operators that
    operate on datums containing JSON arrays -- only some operators
    supported negative array count-from-the-end subscripting.  Specifically,
    only a new-to-9.5 jsonb deletion operator had support (the new "jsonb -
    integer" operator).  This inconsistency seemed likely to be
    counter-intuitive to users.  To fix, allow all places where the user can
    supply an integer subscript to accept a negative subscript value,
    including path-orientated operators and functions, as well as other
    extraction operators.  This will need to be called out as an
    incompatibility in the 9.5 release notes, since it's possible that users
    are relying on certain established extraction operators changed here
    yielding NULL in the event of a negative subscript.
    
    For the json type, this requires adding a way of cheaply getting the
    total JSON array element count ahead of time when parsing arrays with a
    negative subscript involved, necessitating an ad-hoc lex and parse.
    This is followed by a "conversion" from a negative subscript to its
    equivalent positive-wise value using the count.  From there on, it's as
    if a positive-wise value was originally provided.
    
    Note that there is still a minor inconsistency here across jsonb
    deletion operators.  Unlike the aforementioned new "-" deletion operator
    that accepts an integer on its right hand side, the new "#-" path
    orientated deletion variant does not throw an error when it appears like
    an array subscript (input that could be recognized by as an integer
    literal) is being used on an object, which is wrong-headed.  The reason
    for not being stricter is that it could be the case that an object pair
    happens to have a key value that looks like an integer; in general,
    these two possibilities are impossible to differentiate with rhs path
    text[] argument elements.  However, we still don't allow the "#-"
    path-orientated deletion operator to perform array-style subscripting.
    Rather, we just return the original left operand value in the event of a
    negative subscript (which seems analogous to how the established
    "jsonb/json #> text[]" path-orientated operator may yield NULL in the
    event of an invalid subscript).
    
    In passing, make SetArrayPath() stricter about not accepting cases where
    there is trailing non-numeric garbage bytes rather than a clean NUL
    byte.  This means, for example, that strings like "10e10" are now not
    accepted as an array subscript of 10 by some new-to-9.5 path-orientated
    jsonb operators (e.g. the new #- operator).  Finally, remove dead code
    for jsonb subscript deletion; arguably, this should have been done in
    commit b81c7b40.
    
    Peter Geoghegan and Andrew Dunstan
    e02d44b8
json_1.out 42.4 KB