/*****************************************************************
* 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.query;
import org.apache.cayenne.CayenneContext;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.parser.ASTEqual;
import org.apache.cayenne.exp.parser.ASTList;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
import org.apache.cayenne.testdo.mt.ClientMtTable1;
import org.apache.cayenne.testdo.mt.ClientMtTable2;
import org.apache.cayenne.unit.di.client.ClientCase;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.UseServerRuntime;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
@UseServerRuntime(CayenneProjects.MULTI_TIER_PROJECT)
public class ClientExpressionIT extends ClientCase {
@Inject
private CayenneContext context;
@Inject
private DBHelper dbHelper;
private TableHelper tMtTable1;
private TableHelper tMtTable2;
@Before
public void setUp() throws Exception {
tMtTable1 = new TableHelper(dbHelper, "MT_TABLE1");
tMtTable1.setColumns("TABLE1_ID", "GLOBAL_ATTRIBUTE1", "SERVER_ATTRIBUTE1");
tMtTable2 = new TableHelper(dbHelper, "MT_TABLE2");
tMtTable2.setColumns("TABLE2_ID", "TABLE1_ID", "GLOBAL_ATTRIBUTE");
}
protected void createDataSet() throws Exception {
for(int i = 1; i <= 10; i++) {
tMtTable1.insert(i ,"1_global" + i, "server" + i);
tMtTable2.insert(i , i, "2_global" + i);
tMtTable2.insert(i + 10, i, "2_global" + (i + 10));
}
}
@Test
public void testPersistentValueInExpression() throws Exception {
ClientMtTable1 t1 = context.newObject(ClientMtTable1.class);
ClientMtTable1 t2 = context.newObject(ClientMtTable1.class);
context.commitChanges();
Expression scalar = ExpressionFactory.matchExp(null, t1);
Expression list = ExpressionFactory.matchAllExp("|", Arrays.asList(t1, t2));
assertEquals(t1.getObjectId(), scalar.getOperand(1));
assertEquals(t1.getObjectId(), ((ASTEqual)list.getOperand(0)).getOperand(1));
assertEquals(t2.getObjectId(), ((ASTEqual)list.getOperand(1)).getOperand(1));
}
@Test
public void testListInASTList() throws Exception {
ClientMtTable1 t1 = context.newObject(ClientMtTable1.class);
ClientMtTable1 t2 = context.newObject(ClientMtTable1.class);
context.commitChanges();
List<ClientMtTable1> table1List = new ArrayList<ClientMtTable1>();
table1List.add(t1);
table1List.add(t2);
// send list in expression factory
Expression list = ExpressionFactory.inExp(ClientMtTable2.TABLE1_PROPERTY, table1List);
Object[] values = (Object[])((ASTList)list.getOperand(1)).getOperand(0);
assertEquals(t1.getObjectId(), values[0]);
assertEquals(t2.getObjectId(), values[1]);
ObjectId t1Id = new ObjectId("MtTable1", "TABLE1_ID", 1);
ObjectId t2Id = new ObjectId("MtTable1", "TABLE1_ID", 2);
t1.setObjectId(t1Id);
t2.setObjectId(t2Id);
//Expression and client have different copies of object
assertNotSame(t1.getObjectId(), values[0]);
assertNotSame(t2.getObjectId(), values[1]);
}
@Test
public void testArrayInASTList() throws Exception {
ClientMtTable1 t1 = context.newObject(ClientMtTable1.class);
ClientMtTable1 t2 = context.newObject(ClientMtTable1.class);
ClientMtTable1 t3 = context.newObject(ClientMtTable1.class);
context.commitChanges();
Object[] tArray = new Object[3];
tArray[0] = t1;
tArray[1] = t2;
// send array in expression factory
Expression list = ExpressionFactory.inExp(ClientMtTable2.TABLE1_PROPERTY, tArray);
tArray[2] = t3;
Object[] values = (Object[])((ASTList)list.getOperand(1)).getOperand(0);
assertEquals(tArray.length, values.length);
assertNotSame(tArray[2], values[2]);
assertEquals(t1.getObjectId(), values[0]);
assertEquals(t2.getObjectId(), values[1]);
ObjectId t1Id = new ObjectId("MtTable1", "TABLE1_ID", 1);
ObjectId t2Id = new ObjectId("MtTable1", "TABLE1_ID", 2);
t1.setObjectId(t1Id);
t2.setObjectId(t2Id);
// Expression and client have different arrays
assertNotSame(t1.getObjectId(), values[0]);
assertNotSame(t2.getObjectId(), values[1]);
}
@Test
public void testExpressionFactoryMatch() throws Exception {
createDataSet();
SelectQuery<ClientMtTable1> table1Query = new SelectQuery<ClientMtTable1>(ClientMtTable1.class);
table1Query.addOrdering(new Ordering("db:TABLE1_ID", SortOrder.ASCENDING));
List<ClientMtTable1> table1List = context.select(table1Query);
assertNotNull(table1List);
ClientMtTable1 element_1 = table1List.get(0);
ClientMtTable1 element_2 = table1List.get(1);
Expression exp = ExpressionFactory.matchExp(ClientMtTable2.TABLE1_PROPERTY, element_1);
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
List<ClientMtTable2> table2List = context.select(table2Query);
assertNotNull(table2List);
assertEquals(2, table2List.size());
exp = ExpressionFactory.matchExp(element_2);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertNotNull(table2List);
assertEquals(2, table2List.size());
}
@Test
public void testExpressionFactoryMatchAll() throws Exception {
createDataSet();
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class);
table2Query.addOrdering(new Ordering("db:TABLE2_ID", SortOrder.ASCENDING));
List<ClientMtTable2> table2List = context.select(table2Query);
ClientMtTable2 element_1 = table2List.get(0);
ClientMtTable2 element_2 = table2List.get(10);
assertEquals(element_1.getTable1(), element_2.getTable1());
Expression exp = ExpressionFactory.matchAllExp("|"+ClientMtTable1.TABLE2ARRAY_PROPERTY, Arrays.asList(element_1, element_2));
SelectQuery<ClientMtTable1> table1Query = new SelectQuery<ClientMtTable1>(ClientMtTable1.class, exp);
List<ClientMtTable1> table1List = context.select(table1Query);
assertEquals(1, table1List.size());
}
@Test
public void testExpressionFactoryMatchAny() throws Exception {
createDataSet();
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class);
table2Query.addOrdering(new Ordering("db:TABLE2_ID", SortOrder.ASCENDING));
List<ClientMtTable2> table2List = context.select(table2Query);
ClientMtTable2 element_1 = table2List.get(0);
ClientMtTable2 element_2 = table2List.get(10);
Expression exp = ExpressionFactory.matchAnyExp(element_1, element_2);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(2, table2List.size());
}
@Test
public void testExpressionFactoryIn() throws Exception {
createDataSet();
SelectQuery<ClientMtTable1> table1Query = new SelectQuery<ClientMtTable1>(ClientMtTable1.class);
table1Query.addOrdering(new Ordering("db:TABLE1_ID", SortOrder.ASCENDING));
List<ClientMtTable1> table1List = context.select(table1Query);
ClientMtTable1 element_3 = table1List.get(2);
ClientMtTable1 element_8 = table1List.get(7);
// IN expression via Collection
Expression exp = ExpressionFactory.inExp(ClientMtTable2.TABLE1_PROPERTY, table1List.subList(3, 6));
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
List<ClientMtTable2> table2List = context.select(table2Query);
assertEquals(6, table2List.size());
// IN expression via Array
exp = ExpressionFactory.inExp(ClientMtTable2.TABLE1_PROPERTY, element_3, element_8);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(4, table2List.size());
}
@Test
public void testExpressionFactoryBetween() throws Exception {
createDataSet();
SelectQuery<ClientMtTable1> table1Query = new SelectQuery<ClientMtTable1>(ClientMtTable1.class);
table1Query.addOrdering(new Ordering("db:TABLE1_ID", SortOrder.ASCENDING));
List<ClientMtTable1> table1List = context.select(table1Query);
ClientMtTable1 element_1 = table1List.get(0);
ClientMtTable1 element_7 = table1List.get(6);
// between
Expression exp = ExpressionFactory.betweenExp(ClientMtTable2.TABLE1_PROPERTY, element_1, element_7);
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
List<ClientMtTable2> table2List = context.select(table2Query);
assertEquals(14, table2List.size());
// not between
exp = ExpressionFactory.notBetweenExp(ClientMtTable2.TABLE1_PROPERTY, element_1, element_7);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(6, table2List.size());
}
@Test
public void testExpressionFactoryOperators() throws Exception {
createDataSet();
SelectQuery<ClientMtTable1> table1Query = new SelectQuery<ClientMtTable1>(ClientMtTable1.class);
table1Query.addOrdering(new Ordering("db:TABLE1_ID", SortOrder.ASCENDING));
List<ClientMtTable1> table1List = context.select(table1Query);
ClientMtTable1 element_7 = table1List.get(6);
// greater than, ">"
Expression exp = ExpressionFactory.greaterExp(ClientMtTable2.TABLE1_PROPERTY, element_7);
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
List<ClientMtTable2> table2List = context.select(table2Query);
assertEquals(6, table2List.size());
// greater than or equal, ">="
exp = ExpressionFactory.greaterOrEqualExp(ClientMtTable2.TABLE1_PROPERTY, element_7);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(8, table2List.size());
// less than, "<"
exp = ExpressionFactory.lessExp(ClientMtTable2.TABLE1_PROPERTY, element_7);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(12, table2List.size());
// less than or equal, "<="
exp = ExpressionFactory.lessOrEqualExp(ClientMtTable2.TABLE1_PROPERTY, element_7);
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(14, table2List.size());
}
@Test
public void testParams() throws Exception {
createDataSet();
SelectQuery<ClientMtTable1> table1Query = new SelectQuery<ClientMtTable1>(ClientMtTable1.class);
table1Query.addOrdering(new Ordering("db:TABLE1_ID", SortOrder.ASCENDING));
List<ClientMtTable1> table1List = context.select(table1Query);
ClientMtTable1 element_1 = table1List.get(0);
ClientMtTable1 element_5 = table1List.get(4);
Expression exp = ExpressionFactory.exp("table1 = $attr");
exp = exp.params(Collections.singletonMap("attr", element_1));
SelectQuery<ClientMtTable2> table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
List<ClientMtTable2> table2List = context.select(table2Query);
assertEquals(2, table2List.size());
exp = exp.andExp(ExpressionFactory.exp("table1 = $attr")).params(Collections.singletonMap("attr", element_5));
table2Query = new SelectQuery<ClientMtTable2>(ClientMtTable2.class, exp);
table2List = context.select(table2Query);
assertEquals(0, table2List.size());
}
}