Skip to content

[OPENJPA-2961] Include subclasses of the treated class in the TREAT discriminator filter - #189

Merged
solomax merged 6 commits into
masterfrom
OPENJPA-2961
Sep 16, 2026
Merged

solomax merged 6 commits into
masterfrom
OPENJPA-2961

Conversation

@rzo1

@rzo1 rzo1 commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

The TREAT discriminator filter only matched the exact treated class (disc = value), so TREAT(x AS Middle) dropped instances of Middle's subclasses. It now reuses the discriminator's class conditions, like InstanceofExpression, which emit IN (...) over the treated class and its subclasses. Note that for LEFT JOIN TREAT(...) rows without a related entity are now kept (disc IS NULL OR ...); TestTreatSubclassDiscriminator covers a three-level single-table hierarchy.

…iscriminator filter

Build the TREAT condition through the discriminator strategy's class
conditions, so that subclasses of the treated type are matched with an IN
over their discriminator values.
@rzo1 rzo1 self-assigned this Sep 14, 2026
@rzo1
rzo1 requested review from cristof and solomax September 14, 2026 18:34
@cristof

cristof commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

@rzo1 , could you add, in your tests, a revision number for both software and game, and a genre for game, and add the following tests? It seems to fail when using WHERE TREAT:

   public void testTreatInWhereExclusiveProperty() {
        try (EntityManager em = emf.createEntityManager()){
            List<String> results = em.createQuery(
                "SELECT p.name FROM TProduct p WHERE TREAT(p AS TGameProduct).genre = 'FPS'",
                String.class).getResultList();
            assertEquals(List.of("Game"), results);
        } 
    }

    public void testTreatInWhereCommonProperty() {
        try (EntityManager em = emf.createEntityManager()){
            List<String> results = em.createQuery(
                "SELECT p.name FROM TProduct p WHERE TREAT(p AS TGameProduct).revisionNumber = 2.0",
                String.class).getResultList();
            assertEquals(List.of("Game"), results);
        } 
    }

…type

A TREAT(x AS Type) path in a WHERE clause only overrode the metadata of the
path, so rows of other types matched a predicate on an attribute they share
with the treated type. As defined by the specification, such a predicate is
now false if x is not an instance of Type or one of its subclasses. The
restriction is added to the predicate containing the TREAT path, so other
branches of an OR are not affected.
@rzo1

rzo1 commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, good catch. The exclusive-property case only passed because genre is null on the other rows; the common-property one returned [Software, Game]. A TREAT path in WHERE didn't restrict the type at all. A predicate over TREAT(x AS Type) is now false when x isn't a Type or one of its subclasses (spec 4.4.9). The restriction is applied to that predicate only, so other OR branches still match. I added both of your tests, plus one for an OR condition and one for TREAT on a join variable.

@cristof
cristof requested a review from solomax September 15, 2026 16:30
@cristof

cristof commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

@solomax, as I've added some code, could you please review and merge?

@solomax
solomax merged commit 94d3457 into master Sep 16, 2026
4 checks passed
@solomax
solomax deleted the OPENJPA-2961 branch September 16, 2026 03:49
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.

3 participants