This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch STABLE-4.2
in repository https://gitbox.apache.org/repos/asf/cayenne.git


The following commit(s) were added to refs/heads/STABLE-4.2 by this push:
     new 1c01488fd CAY-2863 DbEntity qualifiers are no longer applied to JOIN 
conditions
1c01488fd is described below

commit 1c01488fdde87cc5dfdd9694854bd96d8d98332d
Author: Nikita Timofeev <[email protected]>
AuthorDate: Tue Nov 11 15:32:21 2025 +0400

    CAY-2863 DbEntity qualifiers are no longer applied to JOIN conditions
---
 .../access/translator/select/DbPathProcessor.java      |  7 +++++++
 .../access/translator/select/QualifierTranslator.java  |  4 ++++
 .../cayenne/access/translator/select/TableTree.java    | 18 ++++++++++++++++++
 .../access/translator/select/TableTreeStage.java       |  8 +++++++-
 .../org/apache/cayenne/CDOQualifiedEntitiesIT.java     | 18 ++++++++++++++++++
 5 files changed, 54 insertions(+), 1 deletion(-)

diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DbPathProcessor.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DbPathProcessor.java
index c01bd0582..5463905f1 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DbPathProcessor.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DbPathProcessor.java
@@ -63,6 +63,13 @@ class DbPathProcessor extends PathProcessor<DbEntity> {
             return;
         }
 
+        // special case when the path should be processed in the context of 
the current join clause
+        if(TableTree.CURRENT_ALIAS.equals(next)) {
+            entity = context.getTableTree().nonNullActiveNode().getEntity();
+            appendCurrentPath(next);
+            return;
+        }
+
         throw new IllegalStateException("Unable to resolve path: " + 
currentDbPath.toString() + "." + next);
     }
 
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
index 37717fcbc..e6794465f 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/QualifierTranslator.java
@@ -247,6 +247,10 @@ class QualifierTranslator implements TraversalHandler {
             return new EmptyNode();
         } else {
             String alias = 
context.getTableTree().aliasForPath(result.getLastAttributePath());
+            // special case when the path should be processed in the context 
of the current join clause
+            if(TableTree.CURRENT_ALIAS.equals(alias)) {
+                alias = 
context.getTableTree().nonNullActiveNode().getTableAlias();
+            }
             return table(alias).column(result.getLastAttribute()).build();
         }
     }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
index 7b04a4464..047b5f6e9 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
@@ -34,6 +34,9 @@ import org.apache.cayenne.util.Util;
  * @since 4.2
  */
 class TableTree {
+
+    static final String CURRENT_ALIAS = "__current_join_table";
+
     /**
      * Tables mapped by db path it's spawned by.
      * Can be following:
@@ -47,6 +50,7 @@ class TableTree {
 
     private final TableTreeNode rootNode;
 
+    private TableTreeNode activeNode;
     private int tableAliasSequence;
 
     TableTree(DbEntity root, TableTree parentTree) {
@@ -74,6 +78,9 @@ class TableTree {
         if(Util.isEmptyString(attributePath)) {
             return rootNode.getTableAlias();
         }
+        if(CURRENT_ALIAS.equals(attributePath)) {
+            return CURRENT_ALIAS;
+        }
         TableTreeNode node = tableNodes.get(attributePath);
         if (node == null) {
             throw new CayenneRuntimeException("No table for attribute '%s' 
found", attributePath);
@@ -98,6 +105,17 @@ class TableTree {
         return 't' + String.valueOf(tableAliasSequence++);
     }
 
+    TableTreeNode nonNullActiveNode() {
+        if(activeNode == null) {
+            throw new CayenneRuntimeException("No active TableTree node 
found");
+        }
+        return activeNode;
+    }
+
+    void setActiveNode(TableTreeNode activeNode) {
+        this.activeNode = activeNode;
+    }
+
     public int getNodeCount() {
         return tableNodes.size() + 1;
     }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTreeStage.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTreeStage.java
index aa32bce03..39b1a2e71 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTreeStage.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/TableTreeStage.java
@@ -93,7 +93,10 @@ class TableTreeStage implements TranslationStage {
         }
 
         dbQualifier = translateToDbPath(node, dbQualifier);
+        // mark table tree node as current to process qualifier
+        context.getTableTree().setActiveNode(node);
         Node translatedQualifier = 
context.getQualifierTranslator().translate(dbQualifier);
+        context.getTableTree().setActiveNode(null);
         return joinBuilder.and(() -> translatedQualifier);
     }
 
@@ -102,8 +105,11 @@ class TableTreeStage implements TranslationStage {
         dbQualifier = dbQualifier.transform(input -> {
             if (input instanceof ASTPath) {
                 String path = ((ASTPath) input).getPath();
+                // we do not really care about the parent path, as we do not 
need to join any new table here.
+                // so we must tell the path processor that we are processing 
exactly this table
+                // TODO: should check qualifiers via related tables if that is 
even the thing
                 if(!pathToRoot.isEmpty()) {
-                    path = pathToRoot + '.' + path;
+                    path = TableTree.CURRENT_ALIAS + '.' + path;
                 }
                 return new ASTDbPath(path);
             }
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/CDOQualifiedEntitiesIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/CDOQualifiedEntitiesIT.java
index 18a0890de..b1053728e 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/CDOQualifiedEntitiesIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/CDOQualifiedEntitiesIT.java
@@ -101,9 +101,13 @@ public class CDOQualifiedEntitiesIT extends ServerCase {
     private void createJoinDataSet() throws Exception {
         tQualified3.insert(1, "O1", null);
         tQualified3.insert(2, "O2", accessStackAdapter.supportsBoolean() ? 
true : 1);
+        tQualified3.insert(3, "11", null);
+        tQualified3.insert(4, "12", accessStackAdapter.supportsBoolean() ? 
true : 1);
 
         tQualified4.insert(1, "SHOULD_SELECT", null, 1);
         tQualified4.insert(2, "SHOULD_NOT_SELECT", null, 2);
+        tQualified4.insert(3, "SHOULD_SELECT_TOO", null, 3);
+        tQualified4.insert(4, "SHOULD_NOT_SELECT_TOO", null, 4);
     }
 
     @Test
@@ -229,6 +233,20 @@ public class CDOQualifiedEntitiesIT extends ServerCase {
         assertEquals("SHOULD_SELECT", result.get(0).getName());
     }
 
+    @Test
+    public void joinWithQualifierAndAliases() throws Exception {
+        createJoinDataSet();
+
+        List<Qualified4> result = ObjectSelect.query(Qualified4.class)
+                
.where(Qualified4.QUALIFIED3.alias("a1").dot(Qualified3.NAME).like("O%"))
+                
.or(Qualified4.QUALIFIED3.alias("a2").dot(Qualified3.NAME).like("1%"))
+                .select(context);
+
+        assertEquals(2, result.size());
+        assertEquals("SHOULD_SELECT", result.get(0).getName());
+        assertEquals("SHOULD_SELECT_TOO", result.get(1).getName());
+    }
+
     @Test
     public void joinWithCustomDbQualifier() throws Exception {
         createJoinDataSet();

Reply via email to