You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2020/08/28 09:44:41 UTC

[cayenne] branch master updated: CAY-2671 QualifierTranslator fails to translate expressions with compound PKs/FKs

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 62e7548  CAY-2671 QualifierTranslator fails to translate expressions with compound PKs/FKs
62e7548 is described below

commit 62e7548423b54e4e8e09a1f7eafcae1f28a52852
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Fri Aug 28 12:44:27 2020 +0300

    CAY-2671 QualifierTranslator fails to translate expressions with compound PKs/FKs
---
 RELEASE-NOTES.txt                                  |  1 +
 .../translator/select/QualifierTranslator.java     | 25 +++++++-
 .../translator/select/QualifierTranslatorIT.java   | 66 ++++++++++++++++++++++
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 72693b0..550fcf8 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -25,6 +25,7 @@ CAY-2670 CommitLog does not include FKs for deleted objects with one-way relatio
 Bug Fixes:
 
 CAY-2591 Modeler: project becomes dirty after click on dbImport or cgen tab
+CAY-2671 QualifierTranslator fails to translate expressions with compound PKs/FKs
 
 ----------------------------------
 Release: 4.2.M1
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 494ae79..765b149 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
@@ -29,7 +29,15 @@ import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
 import org.apache.cayenne.access.sqlbuilder.sqltree.*;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.TraversalHandler;
-import org.apache.cayenne.exp.parser.*;
+import org.apache.cayenne.exp.parser.ASTCustomOperator;
+import org.apache.cayenne.exp.parser.ASTDbIdPath;
+import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.exp.parser.ASTFullObject;
+import org.apache.cayenne.exp.parser.ASTFunctionCall;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.ASTSubquery;
+import org.apache.cayenne.exp.parser.PatternMatchNode;
+import org.apache.cayenne.exp.parser.SimpleNode;
 import org.apache.cayenne.exp.property.Property;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -291,10 +299,23 @@ class QualifierTranslator implements TraversalHandler {
             valueSnapshot = relationship.srcFkSnapshotWithTargetSnapshot(valueSnapshot);
         }
 
+        // build compound PK/FK comparison node
+        Node multiValueComparison = buildMultiValueComparison(result, valueSnapshot);
+
+        // replace current node with multi value comparison
+        Node currentNodeParent = currentNode.getParent();
+        currentNodeParent.replaceChild(currentNodeParent.getChildrenCount() - 1, multiValueComparison);
+        multiValueComparison.setParent(currentNodeParent);
+        currentNode = currentNodeParent;
+
+        // we should skip all related nodes as we build this part of the tree manually
         expressionsToSkip.add(node);
         expressionsToSkip.add(parentNode);
+        for(int i=0; i<parentNode.getOperandCount(); i++) {
+            expressionsToSkip.add(parentNode.getOperand(i));
+        }
 
-        return buildMultiValueComparison(result, valueSnapshot);
+        return null;
     }
 
     private Map<String, Object> getMultiAttributeValueSnapshot(Expression node, Expression parentNode) {
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java
new file mode 100644
index 0000000..9073e85
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/QualifierTranslatorIT.java
@@ -0,0 +1,66 @@
+package org.apache.cayenne.access.translator.select;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.access.sqlbuilder.SQLGenerationVisitor;
+import org.apache.cayenne.access.sqlbuilder.StringBuilderAppendable;
+import org.apache.cayenne.access.sqlbuilder.sqltree.Node;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.compound.CompoundFkTestEntity;
+import org.apache.cayenne.testdo.compound.CompoundPkTestEntity;
+import org.apache.cayenne.unit.UnitDbAdapter;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@UseServerRuntime(CayenneProjects.COMPOUND_PROJECT)
+public class QualifierTranslatorIT extends ServerCase {
+
+    @Inject
+    private ServerRuntime runtime;
+
+    @Inject
+    private ObjectContext context;
+
+    @Inject
+    protected DBHelper dbHelper;
+
+    @Before
+    public void setUp() throws Exception {
+        TableHelper tCompoundPKTest = new TableHelper(dbHelper, "COMPOUND_PK_TEST");
+        tCompoundPKTest.setColumns("KEY1", "KEY2", "NAME");
+        tCompoundPKTest.insert("PK1", "PK2", "BBB");
+    }
+
+    @Test
+    public void testCompoundPK() {
+        CompoundPkTestEntity testEntity = ObjectSelect.query(CompoundPkTestEntity.class).selectFirst(context);
+        assertNotNull(testEntity);
+
+        ObjectSelect<CompoundFkTestEntity> query = ObjectSelect.query(CompoundFkTestEntity.class)
+                .where(CompoundFkTestEntity.TO_COMPOUND_PK.eq(testEntity))
+                .and(CompoundFkTestEntity.NAME.like("test%"))
+                .and(CompoundFkTestEntity.NAME.contains("a"));
+
+        DefaultSelectTranslator translator
+                = new DefaultSelectTranslator(query, runtime.getDataDomain().getDefaultNode().getAdapter(), context.getEntityResolver());
+
+        QualifierTranslator qualifierTranslator = translator.getContext().getQualifierTranslator();
+
+        Node node = qualifierTranslator.translate(query.getWhere());
+
+        SQLGenerationVisitor visitor = new SQLGenerationVisitor(new StringBuilderAppendable());
+        node.visit(visitor);
+
+        assertEquals(" ( ( ( t0.F_KEY1 = 'PK1' ) AND ( t0.F_KEY2 = 'PK2' ) ) AND t0.NAME LIKE 'test%' ) AND t0.NAME LIKE '%a%'", visitor.getSQLString());
+    }
+
+}