Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(jpa): unwrap literal value in NULLIF function mapping - #202

Merged
brunomendola merged 1 commit into
mainfrom
fix/nullif-literal-jpa
Aug 6, 2026
Merged

brunomendola merged 1 commit into
mainfrom
fix/nullif-literal-jpa

Conversation

@brunomendola

Copy link
Copy Markdown
Member

Fixes #201

Problem

A projection using NULLIF with a literal second argument — e.g. NULLIF(lastName, "Skywalker") — parsed fine but blew up at execution:

org.hibernate.HibernateException: Could not convert 'io.github.queritylib.querity.api.Literal'
to 'java.lang.String' using 'org.hibernate.type.descriptor.java.StringJavaType' to wrap

Reproduced on both H2 and PostgreSQL.

Root cause

JpaFunctionMapper.nullif passed the Querity Literal wrapper to CriteriaBuilder.nullif(Expression<Y>, Y), which treats Y as the raw literal value. Every other function site unwraps via toExpressionOrLiteral / cb.literal(lit.getValue()); the nullif literal branch skipped it.

This is distinct from the condition-side conversion fixed in fcab732 (JpaOperatorMapper), which does not cover the function-mapper site.

Fix

Unwrap the literal with getValue() before passing it to cb.nullif. The branches are also inverted so that anything that is not a Literal goes through toExpressionOrLiteral (which keeps the CASE WHEN workaround for property expressions and fails fast on unsupported argument types, instead of silently reaching CriteriaBuilder).

Tests

  • New integration test in the generic suite, givenSelectWithNullifFunctionAndLiteral_whenFindAllProjected_thenReturnProjectedResults, asserting the actual projected values (null for rows matching the literal). It runs on querity-jpa, querity-spring-data-jpa (H2 + PostgreSQL) and querity-spring-data-mongodb; Elasticsearch is excluded by the existing supportsFunctionExpressionsInProjections() gate. It fails on main with the exception above.
  • Strengthened the existing unit test with verify(cb).nullif(any(), eq("INACTIVE")) — it previously passed even with the bug, because the mock accepted any Object.

./mvnw clean verify is green across all 12 modules.

🤖 Generated with Claude Code

JpaFunctionMapper.nullif passed the Querity Literal wrapper straight to
CriteriaBuilder.nullif(Expression, Y), which treats Y as the raw literal
value. Hibernate then failed to convert the wrapper to the expression type:

  Could not convert 'io.github.queritylib.querity.api.Literal' to
  'java.lang.String' using 'org.hibernate.type.descriptor.java.StringJavaType'

Unwrap the literal with getValue(), mirroring what toExpressionOrLiteral
already does for every other function. Any other argument type now goes
through toExpressionOrLiteral (CASE WHEN workaround for property
expressions), so unsupported types fail fast instead of reaching
CriteriaBuilder.

Fixes #201

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

@brunomendola
brunomendola merged commit e263c3a into main Aug 6, 2026
4 checks passed
@brunomendola
brunomendola deleted the fix/nullif-literal-jpa branch August 6, 2026 10:55
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.

NULLIF(property, literal) fails at execution: raw Literal passed to CriteriaBuilder.nullif instead of its value

1 participant