/*****************************************************************
* 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.exp.parser;
import java.util.Date;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.Property;
import org.apache.cayenne.query.ObjectSelect;
import org.apache.cayenne.testdo.testmap.Artist;
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.Test;
import static junit.framework.TestCase.assertEquals;
/**
* @since 4.0
*/
@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
public class ASTFunctionCallStringIT extends ServerCase {
@Inject
private ObjectContext context;
private Artist createArtist(String name) throws Exception {
Artist a1 = context.newObject(Artist.class);
a1.setArtistName(name);
a1.setDateOfBirth(new Date());
context.commitChanges();
return a1;
}
@Test
public void testASTTrimInWhere() throws Exception {
Artist a1 = createArtist(" name ");
ASTTrim exp = new ASTTrim(Artist.ARTIST_NAME.path());
Property<String> trimmedName = Property.create("trimmedName", exp, String.class);
Artist a2 = ObjectSelect.query(Artist.class).where(trimmedName.eq("name")).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testASTUpperInWhere() throws Exception {
Artist a1 = createArtist("name");
ASTUpper exp = new ASTUpper(Artist.ARTIST_NAME.path());
Property<String> upperName = Property.create("upperName", exp, String.class);
Artist a2 = ObjectSelect.query(Artist.class).where(upperName.eq("NAME")).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testASTLowerInWhere() throws Exception {
Artist a1 = createArtist("NAME");
ASTLower exp = new ASTLower(Artist.ARTIST_NAME.path());
Property<String> lowerName = Property.create("lowerName", exp, String.class);
Artist a2 = ObjectSelect.query(Artist.class).where(lowerName.eq("name")).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testASTSubstringInWhere() throws Exception {
Artist a1 = createArtist("1234567890xyz");
ASTSubstring exp = new ASTSubstring(Artist.ARTIST_NAME.path(), new ASTScalar((Integer)2), new ASTScalar((Integer)8));
Property<String> substrName = Property.create("substrName", exp, String.class);
Artist a2 = ObjectSelect.query(Artist.class).where(substrName.eq("23456789")).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testASTConcat() throws Exception {
Artist a1 = createArtist("Pablo");
ASTScalar scalar1 = new ASTScalar(" ");
ASTScalar scalar2 = new ASTScalar("Picasso");
ASTConcat exp = new ASTConcat(Artist.ARTIST_NAME.path(), scalar1, scalar2);
Property<String> concatName = Property.create("concatName", exp, String.class);
Artist a2 = ObjectSelect.query(Artist.class).where(concatName.eq("Pablo Picasso")).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testASTLength() throws Exception {
Artist a1 = createArtist("123456");
ASTLength exp = new ASTLength(Artist.ARTIST_NAME.path());
Property<Integer> nameLength = Property.create("nameLength", exp, Integer.class);
Artist a2 = ObjectSelect.query(Artist.class).where(nameLength.gt(5)).selectOne(context);
assertEquals(a1, a2);
Artist a3 = ObjectSelect.query(Artist.class).where(nameLength.lt(5)).selectOne(context);
assertEquals(null, a3);
}
@Test
public void testASTLocate() throws Exception {
Artist a1 = createArtist("1267834567890abc");
ASTScalar substr = new ASTScalar("678");
// ASTScalar offset = new ASTScalar((Integer)5); // not all DBs support offset parameter, so skip it
ASTLocate exp = new ASTLocate(substr, Artist.ARTIST_NAME.path());
Property<Integer> nameLoc = Property.create("nameLoc", exp, Integer.class);
Artist a2 = ObjectSelect.query(Artist.class).where(nameLoc.eq(3)).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testCombinedFunction() throws Exception {
Artist a1 = createArtist("absdefghij klmnopq"); // substring with length 10 from 3 is "sdefghij "
ASTSubstring substring = new ASTSubstring(
Artist.ARTIST_NAME.path(),
new ASTScalar((Integer)3),
new ASTScalar((Integer)10));
ASTTrim trim = new ASTTrim(substring);
ASTUpper upper = new ASTUpper(trim);
ASTConcat concat = new ASTConcat(upper, new ASTScalar(" "), new ASTScalar("test"));
Property<String> name = Property.create("substrName", concat, String.class);
Artist a2 = ObjectSelect.query(Artist.class).where(name.eq("SDEFGHIJ test")).selectOne(context);
assertEquals(a1, a2);
}
@Test
public void testASTConcatParse() {
Expression exp = ExpressionFactory.exp("concat('abc', 'def')");
assertEquals("abcdef", exp.evaluate(new Object()));
}
@Test
public void testASTSubstringParse() {
Expression exp = ExpressionFactory.exp("substring('123456789', 3, 2)");
assertEquals("34", exp.evaluate(new Object()));
}
@Test
public void testASTTrimParse() {
Expression exp = ExpressionFactory.exp("trim(' abc ')");
assertEquals("abc", exp.evaluate(new Object()));
}
@Test
public void testASTLowerParse() {
Expression exp = ExpressionFactory.exp("lower('AbC')");
assertEquals("abc", exp.evaluate(new Object()));
}
@Test
public void testASTUpperParse() {
Expression exp = ExpressionFactory.exp("upper('aBc')");
assertEquals("ABC", exp.evaluate(new Object()));
}
@Test
public void testASTLocateParse() {
Expression exp = ExpressionFactory.exp("locate('Bc', 'aBc')");
assertEquals(2, exp.evaluate(new Object()));
}
@Test
public void testComplexParse() {
Expression exp = ExpressionFactory.exp("locate(upper('Bc'), upper('aBc')) = length(substring(trim(lower(concat(' abc', 'def '))), 3, 2))");
assertEquals(true, exp.evaluate(new Object()));
}
}