Skip to content

fix: evaluate array access after AND short-circuit guards - #4373

Open
arimu1 wants to merge 1 commit into
h2database:masterfrom
arimu1:fix/4364-array-index-where-join
Open

arimu1 wants to merge 1 commit into
h2database:masterfrom
arimu1:fix/4364-array-index-where-join

Conversation

@arimu1

@arimu1 arimu1 commented Aug 1, 2026

Copy link
Copy Markdown

Summary

Fixes #4364.

H2 flattens INNER JOIN ... ON predicates into the query WHERE clause. ConditionAndOr then reorders AND sides by cost. A cheaper array[i] comparison could therefore run before a more expensive cardinality/bounds guard from the join, raising ARRAY_ELEMENT_ERROR for indexes the join would have excluded (e.g. Hibernate-style unnest with system_range).

This change keeps cost-based reordering, then for AND only moves expressions that may raise SQL array element errors to the right so short-circuit can skip them when a safer guard already failed. JSON array accessors still return NULL for missing indexes; bare out-of-range array[index] still raises as documented/SQL-standard.

Changes

  • ConditionAndOr.optimize: after cost reorder, if left may raise array element error and right does not, swap
  • ConditionAndOrN.optimize: for AND, stable-sort so may-raise expressions are last
  • Regression in datatypes/array.sql (issue Unnecessary WHERE condition evaluation leading to error #4364 repro + related forms)
  • Changelog entry

Test plan

  • JDK 21 (Temurin 21.0.12)
  • Repro from issue Unnecessary WHERE condition evaluation leading to error #4364: returns 0 rows (no error); match on element = 2 returns row
  • Bare ARRAY[1,2,3][4] still raises ARRAY_ELEMENT_ERROR_2
  • Focused TestScript: datatypes/array.sql, indexes.sql, range_table.sql, queries/joins.sql, queries/query-optimisations.sql, other/conditions.sql, predicates/null.sql, functions/system/array-get.sql — green

INNER JOIN ON predicates are flattened into WHERE. Cost-based AND
reordering could evaluate a[i] before a cardinality/bounds guard,
raising ARRAY_ELEMENT_ERROR for indexes the join would exclude.

Prefer AND sides that cannot raise array element errors first so
short-circuit skips out-of-range array access. JSON accessors still
return null; bare out-of-range array[index] still errors.

Fixes h2database#4364

@katzyn katzyn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for your contribution!

Unfortunately, this is not a proper solution, it's just a workaround.

The proper fix is to move a premature query transformation from Parser.parseSelectFromPart() into place when we can determine whether transformation is possible or not.

Determination of unsafe expressions also should be performed by a new type of ExpressionVisitor, because array element reference is not the only one dangerous operation, so we need more flexibility here.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unnecessary WHERE condition evaluation leading to error

2 participants