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

ntimofeev pushed a commit to branch 5.0-FIX-CAY-2844-joint-prefetch+qualifier
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 2b989f6a85d3cec78a63c1d1e0ce2ac80414f471
Author: Nikita Timofeev <[email protected]>
AuthorDate: Mon Feb 19 16:28:42 2024 +0400

    DRAFT: CAY-2844 joint prefetch with qualifier
---
 .../translator/select/PrefetchNodeStage.java       | 12 +++++--
 .../access/translator/select/TableTree.java        | 10 ++++--
 .../access/translator/select/TableTreeNode.java    | 11 ++++++-
 .../translator/select/TableTreeQualifierStage.java | 38 +++++++++++-----------
 .../translator/select/TranslatorContext.java       | 11 +++++++
 5 files changed, 57 insertions(+), 25 deletions(-)

diff --git 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
index e4d010c71..836bbaca8 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/PrefetchNodeStage.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.exp.path.CayennePath;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.exp.parser.ASTPath;
 import org.apache.cayenne.exp.path.CayennePathSegment;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -81,9 +82,11 @@ class PrefetchNodeStage implements TranslationStage {
 
         for(PrefetchTreeNode node : prefetch.adjacentJointNodes()) {
             Expression prefetchExp = ExpressionFactory.pathExp(node.getPath());
+            ObjRelationship targetRel = (ObjRelationship) 
prefetchExp.evaluate(objEntity);
             ASTDbPath dbPrefetch = (ASTDbPath) 
objEntity.translateToDbPath(prefetchExp);
             CayennePath dbPath = dbPrefetch.getPath();
             DbEntity dbEntity = objEntity.getDbEntity();
+            Expression targetQualifier = 
targetRel.getTargetEntity().getDeclaredQualifier();
 
             CayennePath fullPath = 
CayennePath.EMPTY_PATH.withMarker(CayennePath.PREFETCH_MARKER);
 
@@ -94,13 +97,16 @@ class PrefetchNodeStage implements TranslationStage {
                 }
 
                 fullPath = fullPath.dot(c);
-                context.getTableTree().addJoinTable(fullPath, rel, 
JoinType.LEFT_OUTER);
+                if(targetQualifier != null && c == dbPath.last()) {
+                    targetQualifier = 
targetRel.getTargetEntity().translateToDbPath(targetQualifier);
+                    
context.getTableTree().addJoinTable(fullPath.withModifier(CayennePath.PREFETCH),
 rel, JoinType.LEFT_OUTER, targetQualifier);
+                } else {
+                    
context.getTableTree().addJoinTable(fullPath.withModifier(CayennePath.PREFETCH),
 rel, JoinType.LEFT_OUTER);
+                }
                 dbEntity = rel.getTargetEntity();
             }
 
-            ObjRelationship targetRel = (ObjRelationship) 
prefetchExp.evaluate(objEntity);
             ClassDescriptor prefetchClassDescriptor = 
context.getResolver().getClassDescriptor(targetRel.getTargetEntityName());
-
             DescriptorColumnExtractor columnExtractor = new 
DescriptorColumnExtractor(context, prefetchClassDescriptor);
             
columnExtractor.extract(dbPath.withMarker(CayennePath.PREFETCH_MARKER));
 
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
index 43fbbda33..fe3f5fe26 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTree.java
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.path.CayennePath;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
@@ -57,11 +58,16 @@ class TableTree {
     }
 
     void addJoinTable(CayennePath path, DbRelationship relationship, JoinType 
joinType) {
-        if (tableNodes.get(path) != null) {
+        addJoinTable(path, relationship, joinType, null);
+    }
+
+    void addJoinTable(String path, DbRelationship relationship, JoinType 
joinType, Expression additionalQualifier) {
+        TableTreeNode treeNode = tableNodes.get(path);
+        if (treeNode != null) {
             return;
         }
 
-        TableTreeNode node = new TableTreeNode(path, relationship, 
nextTableAlias(), joinType);
+        TableTreeNode node = new TableTreeNode(path, relationship, 
nextTableAlias(), joinType, additionalQualifier);
         tableNodes.put(path, node);
     }
 
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeNode.java
 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeNode.java
index b4a09117a..c2b68563b 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeNode.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeNode.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.access.translator.select;
 
+import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.path.CayennePath;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
@@ -38,20 +39,24 @@ class TableTreeNode {
     // relationship that connects this node with parent (or null if this is 
root)
     private final DbRelationship relationship;
 
+    private final Expression additionalQualifier;
+
     TableTreeNode(DbEntity entity, String tableAlias) {
         this.attributePath = CayennePath.EMPTY_PATH;
         this.entity = entity;
         this.tableAlias = tableAlias;
         this.relationship = null;
         this.joinType = null;
+        this.additionalQualifier = null;
     }
 
-    TableTreeNode(CayennePath path, DbRelationship relationship, String 
tableAlias, JoinType joinType) {
+    TableTreeNode(CayennePath path, DbRelationship relationship, String 
tableAlias, JoinType joinType, Expression additionalQualifier) {
         this.attributePath = path;
         this.entity = relationship.getTargetEntity();
         this.tableAlias = tableAlias;
         this.relationship = relationship;
         this.joinType = joinType;
+        this.additionalQualifier = additionalQualifier;
     }
 
     public CayennePath getAttributePath() {
@@ -73,4 +78,8 @@ class TableTreeNode {
     public DbRelationship getRelationship() {
         return relationship;
     }
+
+    public Expression getAdditionalQualifier() {
+        return additionalQualifier;
+    }
 }
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeQualifierStage.java
 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeQualifierStage.java
index ba7eaec7b..f75390398 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeQualifierStage.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TableTreeQualifierStage.java
@@ -37,29 +37,29 @@ class TableTreeQualifierStage implements TranslationStage {
     @Override
     public void perform(TranslatorContext context) {
         context.getTableTree().visit(node -> {
-            Expression dbQualifier = node.getEntity().getQualifier();
-            if (dbQualifier != null) {
-                CayennePath pathToRoot = node.getAttributePath();
-                dbQualifier = dbQualifier.transform(input -> {
-                    if (input instanceof ASTPath) {
-                        CayennePath path = pathToRoot.dot(((ASTPath) 
input).getPath());
-                        return new ASTDbPath(path);
-                    }
-                    return input;
-                });
-                Node rootQualifier = context.getQualifierNode();
-                Node translatedQualifier = 
context.getQualifierTranslator().translate(dbQualifier);
-                if (rootQualifier != null) {
-                    NodeBuilder expressionNodeBuilder = 
exp(node(rootQualifier)).and(node(translatedQualifier));
-                    context.setQualifierNode(expressionNodeBuilder.build());
-                } else {
-                    context.setQualifierNode(translatedQualifier);
-                }
-            }
+            appendQualifier(context, node, node.getEntity().getQualifier());
+            appendQualifier(context, node, node.getAdditionalQualifier());
         });
 
         if(context.getQualifierNode() != null) {
             context.getSelectBuilder().where(context.getQualifierNode());
         }
     }
+
+    private static void appendQualifier(TranslatorContext context, 
TableTreeNode node, Expression dbQualifier) {
+        if (dbQualifier == null) {
+            return;
+        }
+
+        CayennePath pathToRoot = node.getAttributePath();
+        dbQualifier = dbQualifier.transform(input -> {
+            if (input instanceof ASTPath) {
+                CayennePath path = pathToRoot.dot(((ASTPath) input).getPath());
+                return new ASTDbPath(path);
+            }
+            return input;
+        });
+        Node translatedQualifier = 
context.getQualifierTranslator().translate(dbQualifier);
+        context.appendQualifierNode(translatedQualifier);
+    }
 }
diff --git 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
index 0c9894549..237cfac07 100644
--- 
a/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
+++ 
b/cayenne/src/main/java/org/apache/cayenne/access/translator/select/TranslatorContext.java
@@ -42,6 +42,9 @@ import org.apache.cayenne.map.SQLResult;
 import org.apache.cayenne.query.Ordering;
 import org.apache.cayenne.query.QueryMetadata;
 
+import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.exp;
+import static org.apache.cayenne.access.sqlbuilder.SQLBuilder.node;
+
 /**
  * Context that holds all data necessary for query translation as well as a 
result of that translation.
  *
@@ -291,6 +294,14 @@ public class TranslatorContext implements 
SQLGenerationContext {
         this.qualifierNode = qualifierNode;
     }
 
+    void appendQualifierNode(Node qualifierNode) {
+        if(this.qualifierNode == null) {
+            this.qualifierNode = qualifierNode;
+        } else {
+            this.qualifierNode = 
exp(node(this.qualifierNode)).and(node(qualifierNode)).build();
+        }
+    }
+
     Node getQualifierNode() {
         return qualifierNode;
     }

Reply via email to