Skip to content

[OPENJPA-2956] Unwrap ID(), honour null precedence and reject set operations in memory - #178

Open
rzo1 wants to merge 1 commit into
masterfrom
OPENJPA-2956
Open

[OPENJPA-2956] Unwrap ID(), honour null precedence and reject set operations in memory#178
rzo1 wants to merge 1 commit into
masterfrom
OPENJPA-2956

Conversation

@rzo1

@rzo1 rzo1 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Three separate defects, all reachable: the in-memory executor is selected whenever a candidate collection is supplied, when the store does not support datastore execution (openjpa-xmlstore), or when dirty instances are queried with FlushBeforeQueries disabled.

ID() returned the internal identity wrapper rather than the raw key, so a comparison against the plain key threw ClassCastException out of Filters.convert for numeric ids, never matched for an @EmbeddedId (OpenJPAId.equals requires class equality), and matched only by accident for a String id. It now unwraps exactly as the JDBC projection does. One correction to the review comment: JDBC does not unwrap the comparison operand — it normalises the other side, and its only unwrap is GetNativeObjectId.load(). The wrapper-returning getObjectId() is unchanged.

NULLS FIRST/NULLS LAST were ignored: the comparator hard-coded nulls last when ascending and first when descending, so two of the four combinations were already right and two were silently wrong. The requested precedence is now threaded through, falling back to the previous policy when none is given — so rejecting these instead would have been a regression.

Set operations produced a NullPointerException from a compound QueryExpressions with no filter, or an empty result. They are now rejected with a message saying why the query is running in memory and how to avoid it. Implementing them would be a feature, not a fix: the executor is built for a single candidate extent, setCandidateCollection has no defined meaning across operands, and the kernel has no multiset semantics for the ALL variants.

Note that the in-memory path cannot yet be exercised end to end from JPQL with an identification variable: JPQLExpressionBuilder casts the value from getThis() to Path, and the in-memory factory returns a Val, so it fails with a ClassCastException. That is an older, separate defect and wants its own issue; it is why the ID() change has no end-to-end test here.

…rations in memory

Three separate defects on the in-memory path, all reachable: the executor
is selected whenever a candidate collection is supplied, when the store
does not support datastore execution, or when dirty instances are queried
with FlushBeforeQueries disabled.

ID() returned the internal identity wrapper rather than the raw key, so a
comparison against the plain key threw a ClassCastException out of
Filters.convert for numeric ids, never matched for an @EmbeddedId, and
matched only by accident for a String id. It now unwraps exactly as the
JDBC projection does. The wrapper-returning getObjectId() is unchanged.

NULLS FIRST and NULLS LAST were ignored: the comparator hard coded nulls
last when ascending and first when descending, so two of the four
combinations were right by chance and two were silently wrong. The
requested precedence is now threaded through, falling back to the previous
policy when none is given.

Set operations produced a NullPointerException from a compound expression
with no filter, or an empty result. They are now rejected with a message
that says why the query is running in memory and how to avoid it: the
executor is built for one candidate extent and has no multiset semantics,
and a candidate collection has no defined meaning across operands.

Note that the in-memory path cannot yet be exercised end to end from JPQL
with an identification variable: JPQLExpressionBuilder casts the value from
getThis() to Path, and the in-memory factory returns a Val, so it fails with
a ClassCastException. That is an older, separate defect and wants its own
issue.
@rzo1 rzo1 self-assigned this Sep 2, 2026
@rzo1
rzo1 requested review from cristof and solomax September 2, 2026 19:18

@solomax solomax 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.

Do we need tests for this?

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.

2 participants