Skip to content

BETWEEN with a column bound fails three different ways, for every column type #381

Description

@fupelaqu

BETWEEN works with literal bounds and fails with a column bound. The failure differs by whether a schema is attached, so both paths are given separately below — an earlier draft showed the schema-less emission under text that read as though it were the general case.

All re-measured at 80f76b1a. Pre-existing; verified against a control clone of the merge-base.

This also corrects an earlier note describing it as "d BETWEEN ts AND ts fails — same column twice": the repetition is irrelevant, and it is not restricted to dates.

Schema-LESS — a client-side throw, before any query is built

Measured through the bridge, which is the production path when no schema is attached:

d BETWEEN ts AND ts2   ->  IllegalArgumentException: Unsupported out type for range query: ANY
n BETWEEN lo AND hi    ->  IllegalArgumentException: Unsupported out type for range query: ANY

d BETWEEN '2025-01-01' AND '2025-12-31'
  ->  {"range":{"d":{"gte":"2025-01-01","lte":"2025-12-31"}}}                       ✅

The numeric row is the point: this is not a temporal defect.

The mixed literal/column form, same path

A range query is emitted carrying a Painless expression — and a re-quoted literal — as string bounds:

{"range":{"d":{"gte":"\"2025-01-01\"","lte":"(doc['ts'].size() == 0 ? null : doc['ts'].value)"}}}

Executed against a real index:

400 parse_exception: failed to parse date field ["2025-01-01"] with format
    [strict_date_optional_time||epoch_millis]

Schema-CARRYING — a script, and a different failure

Here the same SQL reaches Painless instead. Column bounds emit relational operators:

d BETWEEN ts AND ts2   ->  param1 >= param2 && param1 <= param3
n BETWEEN lo AND hi    ->  param1 >= param2 && param1 <= param3

Correct for numerics (executed: true). On temporals the doc-values are ZonedDateTime objects:

400 class_cast_exception: Cannot apply [>] operation to types
    [java.time.ZonedDateTime] and [java.time.ZonedDateTime]

The mixed form takes a third shape again — compareTo against the literal, and against the column:

d BETWEEN '2025-01-01' AND ts
  ->  param1.compareTo("2025-01-01") >= 0 && param1.compareTo(param2) <= 0

ZonedDateTime.compareTo(String) does not exist.

Relationship to the column-vs-column fix

#373's item 4 fixed this family for binary comparison — a column compared with another column now runs as a script. BETWEEN never reaches that code: schema-less it throws while the range query is being built, and schema-carrying it takes the check path that emits raw >=/<= rather than the temporal isBefore/isAfter dispatch. The control diff confirms that fix moved none of these shapes.

Adjacent

A BETWEEN whose bounds reference an undeclared column was invisible to the computed-column reference walk until #376, because the bounds live in a FromTo, which is not a PainlessScript. That half is fixed; this one is not.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions