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 <stari...@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()); + } + +}