/***************************************************************** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. ****************************************************************/ package org.apache.cayenne.access; import org.apache.cayenne.Cayenne; import org.apache.cayenne.ObjectContext; import org.apache.cayenne.Persistent; import org.apache.cayenne.di.Inject; import org.apache.cayenne.query.EJBQLQuery; import org.apache.cayenne.test.jdbc.DBHelper; import org.apache.cayenne.test.jdbc.TableHelper; import org.apache.cayenne.testdo.relationships_flattened.FlattenedTest1; 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 java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @UseServerRuntime(CayenneProjects.RELATIONSHIPS_FLATTENED_PROJECT) public class DataContextEJBQLFlattenedRelationshipsIT extends ServerCase { @Inject protected ObjectContext context; @Inject protected DBHelper dbHelper; protected TableHelper ft1Helper; protected TableHelper ft2Helper; protected TableHelper ft3Helper; protected TableHelper ft4Helper; @Before public void setUp() throws Exception { ft1Helper = new TableHelper(dbHelper, "FLATTENED_TEST_1", "FT1_ID", "NAME"); ft2Helper = new TableHelper(dbHelper, "FLATTENED_TEST_2"); ft2Helper.setColumns("FT2_ID", "FT1_ID", "NAME"); ft3Helper = new TableHelper(dbHelper, "FLATTENED_TEST_3"); ft3Helper.setColumns("FT3_ID", "FT2_ID", "NAME"); ft4Helper = new TableHelper(dbHelper, "FLATTENED_TEST_4"); ft4Helper.setColumns("FT4_ID", "FT3_ID", "NAME"); } private void createFt123() throws Exception { ft1Helper.insert(1, "ft1").insert(2, "ft12"); ft2Helper.insert(1, 1, "ft2").insert(2, 2, "ft22"); ft3Helper.insert(1, 1, "ft3").insert(2, 2, "ft3-a").insert(3, 2, "ft3-b"); } private void createFt1234() throws Exception { createFt123(); ft4Helper.insert(1, 1, "ft4"); } @Test public void testCollectionMemberOfThetaJoin() throws Exception { createFt123(); String ejbql = "SELECT f FROM FlattenedTest3 f, FlattenedTest1 ft " + "WHERE f MEMBER OF ft.ft3Array AND ft = :ft"; FlattenedTest1 ft = Cayenne.objectForPK(context, FlattenedTest1.class, 2); EJBQLQuery query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); List<?> objects = context.performQuery(query); assertEquals(2, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(2)); assertTrue(ids.contains(3)); } @Test public void testCollectionMemberOfThetaJoinLongRelationshipSequence() throws Exception { createFt1234(); String ejbql = "SELECT f FROM FlattenedTest4 f, FlattenedTest1 ft " + "WHERE f MEMBER OF ft.ft4ArrayFor1 AND ft = :ft"; FlattenedTest1 ft = Cayenne.objectForPK(context, FlattenedTest1.class, 1); EJBQLQuery query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); List<?> objects = context.performQuery(query); assertEquals(1, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(1))); ft = Cayenne.objectForPK(context, FlattenedTest1.class, 2); query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); objects = context.performQuery(query); assertEquals(0, objects.size()); } @Test public void testCollectionInnerJoin() throws Exception { createFt123(); String ejbql = "SELECT ft FROM FlattenedTest1 ft INNER JOIN ft.ft3Array f WHERE ft = :ft"; FlattenedTest1 ft = Cayenne.objectForPK(context, FlattenedTest1.class, 1); EJBQLQuery query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); List<?> objects = context.performQuery(query); assertNotNull(objects); assertFalse(objects.isEmpty()); assertEquals(1, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(1))); } @Test public void testCollectionAsInnerJoin() throws Exception { createFt123(); // this query is equivalent to the previous INNER JOIN example String ejbql = "SELECT OBJECT(ft) FROM FlattenedTest1 ft, IN(ft.ft3Array) f WHERE ft = :ft"; FlattenedTest1 ft = Cayenne.objectForPK(context, FlattenedTest1.class, 1); EJBQLQuery query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); List<?> objects = context.performQuery(query); assertNotNull(objects); assertFalse(objects.isEmpty()); assertEquals(1, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(1))); } @Test public void testCollectionThetaJoin() throws Exception { createFt123(); String ejbql = "SELECT DISTINCT ft FROM FlattenedTest1 ft , FlattenedTest3 f3 WHERE f3.toFT1 = ft"; EJBQLQuery query = new EJBQLQuery(ejbql); List<?> objects = context.performQuery(query); assertNotNull(objects); assertFalse(objects.isEmpty()); assertEquals(2, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(1))); assertTrue(ids.contains(new Integer(2))); } @Test public void testCollectionIdentificationVariable() throws Exception { createFt123(); String ejbql = "SELECT ft.ft3Array FROM FlattenedTest1 ft WHERE ft = :ft"; FlattenedTest1 ft = Cayenne.objectForPK(context, FlattenedTest1.class, 2); EJBQLQuery query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); List<?> objects = context.performQuery(query); assertNotNull(objects); assertFalse(objects.isEmpty()); assertEquals(2, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(2))); assertTrue(ids.contains(new Integer(3))); } @Test public void testAssociationFieldSelect() throws Exception { createFt123(); String ejbql = "SELECT ft3.toFT1 FROM FlattenedTest3 ft3 WHERE ft3.toFT1 = :ft"; FlattenedTest1 ft = Cayenne.objectForPK(context, FlattenedTest1.class, 1); EJBQLQuery query = new EJBQLQuery(ejbql); query.setParameter("ft", ft); List<?> objects = context.performQuery(query); assertEquals(1, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(1))); } @Test public void testCollectionSubquery() throws Exception { createFt123(); String ejbql = "SELECT ft FROM FlattenedTest1 ft " + "WHERE (SELECT COUNT(f) FROM ft.ft3Array f) = 1"; EJBQLQuery query = new EJBQLQuery(ejbql); // TODO fails but not because of flattened relationship, // the reason is that property "ft3Array" inside the subquery // parses as unmapped /* * List<?> objects = context.performQuery(query); assertNotNull(objects); * assertFalse(objects.isEmpty()); assertEquals(1, objects.size()); Set<Object> * ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while * (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); * ids.add(id); } assertTrue(ids.contains(new Integer(2))); */ } @Test public void testCollectionSubquery1() throws Exception { createFt123(); String ejbql = "SELECT ft FROM FlattenedTest1 ft " + "WHERE (SELECT COUNT(f3) FROM FlattenedTest3 f3 WHERE f3 MEMBER OF ft.ft3Array) > 1"; EJBQLQuery query = new EJBQLQuery(ejbql); List<?> objects = context.performQuery(query); assertNotNull(objects); assertFalse(objects.isEmpty()); assertEquals(1, objects.size()); Set<Object> ids = new HashSet<Object>(); Iterator<?> it = objects.iterator(); while (it.hasNext()) { Object id = Cayenne.pkForObject((Persistent) it.next()); ids.add(id); } assertTrue(ids.contains(new Integer(2))); } @Test public void testGroupByFlattenedRelationship() throws Exception { createFt123(); String ejbql = "SELECT COUNT(ft3), ft3.toFT1 FROM FlattenedTest3 ft3 GROUP BY ft3.toFT1 "; EJBQLQuery query = new EJBQLQuery(ejbql); List<?> objects = context.performQuery(query); assertEquals(2, objects.size()); } }