Java tutorial
/** * Copyright 2011 Aftab Mahmood * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details <http://www.gnu.org/licenses/>. **/ package org.easy.test.criteria; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.persistence.Tuple; import javax.persistence.criteria.JoinType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.easy.criteria.CriteriaComposer; import org.easy.criteria.CriteriaProcessor; import org.easy.criteria.CriteriaComposer.ComparisonOperator; import org.easy.test.criteria.model.Auditable; import org.easy.test.criteria.model.PersonTypeEnum; import org.easy.test.criteria.model.generated.Course; import org.easy.test.criteria.model.generated.CourseSession_; import org.easy.test.criteria.model.generated.Course_; import org.easy.test.criteria.model.generated.Person; import org.easy.test.criteria.model.generated.PersonType; import org.easy.test.criteria.model.generated.PersonType_; import org.easy.test.criteria.model.generated.Person_; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.easy.criteria.CriteriaComposer.AggregateFunction.*; import static org.easy.criteria.CriteriaComposer.ComparisonOperator.*; import static org.easy.criteria.CriteriaComposer.NegationOperator.*; /** * A unit test and a sample service class to show the usage of this framework. * Please note that the SQL in the method comments is for illustration only. * * * @author mahmood.aftab * */ public class CriteriaProcessorTest { private static CriteriaProcessor criteriaProcessor = null; private static boolean initContextByMe = false; private static Log log = LogFactory.getLog(CriteriaProcessorTest.class); @BeforeClass public static void setUpBeforeClass() throws Exception { log.debug("setUpBeforeClass"); // try loading Spring try { if (!DbHelper.isPopulatedWith(DbHelper.allDataFiles)) { int errorCount = DbHelper.initDb(DbHelper.CONNECTION_URL, DbHelper.allDataFiles); assertEquals(0, errorCount); initContextByMe = true; } criteriaProcessor = new CriteriaProcessor(DbHelper.getEntityManager()); } catch (Exception e) { log.error(e); } } @AfterClass public static void tearDownAfterClass() throws Exception {/* if (initContextByMe) DbHelper.close();*/ } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } /** * select * from course */ @Test public void testAllCourses1() { // create a criteria to find all courses. CriteriaComposer<Course> courseCriteria = CriteriaComposer.from(Course.class); List<Course> result = criteriaProcessor.findAllEntity(courseCriteria); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(3, result.size()); assertEquals("course1", result.get(0).getName()); } /** * * #1- Use of auditable interface make it easy to set and get data from * audtiable fields. Theses fields are usually common for all tables. * * #2- The other approach is creating auditable base class of all the entities. * EasyCriteria supports this approach too * * TODO: Write an intercepter to set auditable values. */ @Test public void testAuditPersonType() { CriteriaComposer<PersonType> studentCriteria = CriteriaComposer.from(PersonType.class); studentCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); PersonType studentType = criteriaProcessor.findUniqueEntity(studentCriteria, null); assertNotNull(studentType); assertTrue(studentType instanceof Auditable); Auditable auditable = (Auditable) studentType; assertEquals(new Long(1L), auditable.getLastUpdateBy()); } /** * * select * from course where course.last_update_date_time between ? and ? */ @Test public void testBetweenDates() { Date thatDate = null; try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); thatDate = simpleDateFormat.parse("2011-01-02 00:00:00"); } catch (ParseException e) { log.error(e); fail(e.getMessage()); } Date toDate = new Date(System.currentTimeMillis()); CriteriaComposer<Course> criteria = CriteriaComposer.from(Course.class); criteria.where(Course_.lastUpdateDateTime, ComparisonOperator.BETWEEN, thatDate, toDate); List<Course> result = criteriaProcessor.findAllEntity(criteria, true, null); assertNotNull(result); assertEquals(2, result.size()); assertEquals("course2", result.get(0).getName()); } /** * Find count total student. * * There are two way to do it. #1 Using "count" API of CriteriaProcessor; #2 using aggregation function of * CriteriaComposer * * select count(distinct person0_.id) from person where person_type_id=? * select person_type_id from person_type where persontype.name=STUDENT */ @Test public void testCountStudent1() { // find student type first. CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); PersonType studentType = criteriaProcessor.findUniqueEntity(studentTypeCriteria, null); // student criteria CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.where(Person_.personType, EQUAL, studentType); // count long result = criteriaProcessor.count(studentCriteria, true); assertEquals(9, result); } /** * Find all Students * * select * from person inner join person_type on * person.person_type_id=persontype.id where persontype.name=STUDENT */ @Test public void testFindAllStudent1() { CriteriaComposer<Person> student = CriteriaComposer.from(Person.class); CriteriaComposer<PersonType> personTypeStudent = student.join(JoinType.INNER, Person_.personType); personTypeStudent.where(PersonType_.name, EQUAL, PersonTypeEnum.STUDENT); List<Person> result = criteriaProcessor.findAllEntity(student, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(9, result.size()); } /** * Find all Students. * Same as 1 but using DOT chaining */ @Test public void testFindAllStudent1b() { // using DOT chaining CriteriaComposer<Person> student = CriteriaComposer.from(Person.class); student.join(JoinType.INNER, Person_.personType).where(PersonType_.name, EQUAL, PersonTypeEnum.STUDENT); List<Person> result = criteriaProcessor.findAllEntity(student, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(9, result.size()); } /** * Find all Students. * Same as 1 but criteria is defined in PersonCritera class. This is the * preferred way. * Makes service more readable. */ @Test public void testFindAllStudent2() { CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); CriteriaComposer<PersonType> studentTypeCriteria = studentCriteria.join(JoinType.INNER, Person_.personType); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); List<Person> result = criteriaProcessor.findAllEntity(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(9, result.size()); } /** * Find all Students * Same as 1 but using two queries. * select person_type_id as typeId from person_type where persontype.name=STUDENT * select * from person where person_type_id=typeId */ @Test public void testFindAllStudent3() { CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); PersonType studentType = criteriaProcessor.findUniqueEntity(studentTypeCriteria, null); CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.where(Person_.personType, EQUAL, studentType); List<Person> result = criteriaProcessor.findAllEntity(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(9, result.size()); } /** * Find all students enrolled in course1 * * select * from person * inner join person_type * inner join course_session * inner join course * where persontype.name=STUDENT and course3.name=COURSE1 */ @Test public void testFindAllStudentEnrolledInClass1() { CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.join(JoinType.INNER, Person_.personType, studentTypeCriteria); studentCriteria.join(JoinType.INNER, Person_.courseSessions).join(JoinType.INNER, CourseSession_.course) .where(Course_.name, EQUAL, "course1"); List<Person> result = criteriaProcessor.findAllEntity(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(6, result.size()); assertEquals("student1", result.get(0).getName()); } /** * Same as ...[1] but using dot operator to chain the method calls. */ @Test public void testFindAllStudentEnrolledInClass2() { CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.join(JoinType.INNER, Person_.personType, studentTypeCriteria); studentCriteria.join(JoinType.INNER, Person_.courseSessions).join(JoinType.INNER, CourseSession_.course) .where(Course_.name, EQUAL, "course1"); List<Person> result = criteriaProcessor.findAllEntity(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(6, result.size()); assertEquals("student1", result.get(0).getName()); } /** * Same as ...[1] but criteria is supplied externally, makes service more * readable. */ @Test public void testFindAllStudentEnrolledInClass3() { CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); CriteriaComposer<PersonType> studentTypeCriteria = studentCriteria.join(JoinType.INNER, Person_.personType); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); studentCriteria.join(JoinType.INNER, Person_.courseSessions).join(JoinType.INNER, CourseSession_.course) .where(Course_.name, EQUAL, "course1"); List<Person> result = criteriaProcessor.findAllEntity(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(6, result.size()); assertEquals("student1", result.get(0).getName()); } /** * Same as ...[1] but using more fine grained criteria API. * * select courseId from course where course.name=? * select * from person inner join person_type * inner join course_session * where persontype.name=STUDENT and course.id=courseId */ @Test public void testFindAllStudentEnrolledInClass4() { CriteriaComposer<Course> courseCriteria = CriteriaComposer.from(Course.class); courseCriteria.where(Course_.name, ComparisonOperator.EQUAL, "course1"); Course course = criteriaProcessor.findUniqueEntity(courseCriteria, null); CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.join(JoinType.INNER, Person_.personType, studentTypeCriteria); studentCriteria.join(JoinType.INNER, Person_.courseSessions).where(CourseSession_.course, EQUAL, course); List<Person> result = criteriaProcessor.findAllEntity(studentCriteria); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(6, result.size()); assertEquals("student1", result.get(0).getName()); } /** * Tuple search with selected columns * * select person.id, person.name from person * inner join person_type * where persontype.name=STUDENT */ @Test public void testFindAllStudentTuple1() { CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.select(Person_.id, Person_.name); studentCriteria.join(JoinType.INNER, Person_.personType).where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); List<Tuple> result = criteriaProcessor.findAllTuple(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(9, result.size()); assertEquals("student1", result.get(0).get("Person.name")); } /** * Tuple search with selected columns. Same as 1 but select has user defined * alias. */ @Test public void testFindAllStudentTuple2() { CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.select(Person_.id, "id"); studentCriteria.select(Person_.name, "name"); studentCriteria.join(JoinType.INNER, Person_.personType, studentTypeCriteria); List<Tuple> result = criteriaProcessor.findAllTuple(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(9, result.size()); assertEquals("student1", result.get(0).get("name")); } /** * Find unique student * * select personTypeId from person_type where persontype.name=STUDENT fetch * first 2 rows only * select * from person where person_type_id=personTypeId and * person.name=STUDENT1 fetch first 2 rows only */ @Test public void testFindUniqueStudent() { //query 1 CriteriaComposer<PersonType> studentTypeCriteria = CriteriaComposer.from(PersonType.class); studentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); PersonType studentType = criteriaProcessor.findUniqueEntity(studentTypeCriteria, null); //query 2 CriteriaComposer<Person> personCriteria = CriteriaComposer.from(Person.class); personCriteria.where(Person_.personType, EQUAL, studentType); personCriteria.and(); personCriteria.where(Person_.name, EQUAL, "student1"); Person result = criteriaProcessor.findUniqueEntity(personCriteria, null); assertNotNull(result); assertEquals("student1", result.getName()); } /** * OrderBy * * select * from course * where course.last_update_date_time between ? and ? * order by course.name desc */ @Test public void testOrderBy() { Date thatDate = null; try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); thatDate = simpleDateFormat.parse("2011-01-02 00:00:00"); } catch (ParseException e) { log.error(e); fail(e.getMessage()); } Date toDate = new Date(System.currentTimeMillis()); CriteriaComposer<Course> criteria = CriteriaComposer.from(Course.class); criteria.where(Course_.lastUpdateDateTime, ComparisonOperator.BETWEEN, thatDate, toDate); criteria.orderBy(Course_.name, false, 1); List<Course> result = criteriaProcessor.findAllEntity(criteria, true, null); assertNotNull(result); assertEquals(2, result.size()); assertEquals("course3", result.get(0).getName()); } /** * Test Order By * OrderBy can be provided for any and for multiple entities who are part of * a criteria. * OrderBy can be ranked independent of join order. * If we change rank for Course_name to 2 then this orderBy will be ignored * since higher level * entity Person has the orderBy with the same rank. * * select person.name, person.id, course.name from person * inner join person_type * inner join course_session * inner join course * where persontype.name=? and (course.name in (? , ?)) * order by course.name desc, person.name desc */ @Test public void testOrderBy2() { //select student CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.select(Person_.name, Person_.id); studentCriteria.orderBy(Person_.name, false, 2); studentCriteria.join(JoinType.INNER, Person_.personType).where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); //Note that dot chaining canot continue any more since the new join is on person table not on person type table. //select course CriteriaComposer<Course> courseCriteria = studentCriteria.join(Person_.courseSessions) .join(CourseSession_.course); courseCriteria.select(Course_.name); courseCriteria.where(Course_.name, IN, "course1", "course3"); courseCriteria.orderBy(Course_.name, false, 1); List<Tuple> result = criteriaProcessor.findAllTuple(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(11, result.size()); assertEquals("course3", result.get(0).get("Course.name")); assertEquals("student9", result.get(0).get("Person.name")); } /** * Test Order By. Same as 2 * DOT chaining some time is not easy to debug. But can be more readable. */ @Test public void testOrderBy2b() { CriteriaComposer<PersonType> stydentTypeCriteria = CriteriaComposer.from(PersonType.class); stydentTypeCriteria.where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.select(Person_.name).select(Person_.id).orderBy(Person_.name, false, 2) .join(Person_.personType, stydentTypeCriteria); studentCriteria.join(Person_.courseSessions).join(CourseSession_.course).select(Course_.name) .where(Course_.name, IN, "course1", "course3").orderBy(Course_.name, false, 1); List<Tuple> result = criteriaProcessor.findAllTuple(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(11, result.size()); assertEquals("course3", result.get(0).get("Course.name")); assertEquals("student9", result.get(0).get("Person.name")); } /** * Test Order By. Same as 2 * * Framework is flexible. You can write criteria in any format you want. */ @Test public void testOrderBy2c() { CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.select(Person_.name, Person_.id); studentCriteria.orderBy(Person_.name, false, 2); studentCriteria.join(JoinType.INNER, Person_.personType).where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Course> course = studentCriteria.join(Person_.courseSessions).join(CourseSession_.course); course.select(Course_.name); course.where(Course_.name, IN, "course1", "course3"); course.orderBy(Course_.name, false, 1); List<Tuple> result = criteriaProcessor.findAllTuple(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(11, result.size()); assertEquals("course3", result.get(0).get("Course.name")); assertEquals("student9", result.get(0).get("Person.name")); } /** * Test Order By. If there is no attribute is selected then it throws exception * * Framework is flexible. You can write criteria in any format you want. */ @Test(expected = java.lang.IllegalArgumentException.class) public void testOrderBy3() { CriteriaComposer<Person> student = CriteriaComposer.from(Person.class); student.join(JoinType.INNER, Person_.personType).where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); CriteriaComposer<Course> course = student.join(Person_.courseSessions).join(CourseSession_.course); course.where(Course_.name, IN, "course1", "course3"); List<Tuple> result = criteriaProcessor.findAllTuple(student, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(6, result.size()); assertEquals("course3", result.get(0).get("Course.name")); assertEquals("student9", result.get(0).get("Person.name")); } /** * select count(course.id) from course */ @Test public void testSelectCount() { CriteriaComposer<Course> forCourse = CriteriaComposer.from(Course.class).select(COUNT, Course_.id); Tuple result = criteriaProcessor.findUniqueTuple(forCourse); assertNotNull(result); assertEquals(3L, result.get("count.Course.id")); } /** * sum(course.unit) from course */ @Test public void testSelectSum() { CriteriaComposer<Course> forCourse = CriteriaComposer.from(Course.class).select(SUM, Course_.unit); Tuple result = criteriaProcessor.findUniqueTuple(forCourse); assertNotNull(result); assertEquals(10L, result.get("sum.Course.unit")); } /** * select person.name, sum(course.unit) from person inner join course_session inner join course group by person.name */ @Test public void testGroupBy() { CriteriaComposer<Person> forStudentUnitCount = CriteriaComposer.from(Person.class).select(Person_.name) .groupBy(Person_.name); forStudentUnitCount.join(Person_.courseSessions).join(CourseSession_.course).select(SUM, Course_.unit); List<Tuple> result = criteriaProcessor.findAllTuple(forStudentUnitCount); assertNotNull(result); assertEquals(9, result.size()); assertEquals("student1", result.get(0).get("Person.name")); assertEquals(10L, result.get(0).get("sum.Course.unit")); for (int i = 1; i < result.size(); i++) { assertTrue(!result.get(i).get("Person.name").equals(result.get(0).get("Person.name"))); } } @Test public void testNotIn() { CriteriaComposer<Person> forPerson = CriteriaComposer.from(Person.class).where(Person_.name, NOT, IN, "teacher1", "teacher2", "teacher3"); List<Person> result = criteriaProcessor.findAllEntity(forPerson); assertNotNull(result); assertEquals(9, result.size()); for (Person person : result) { assertEquals(false, person.getName().contains("teacher")); } } @Test public void testLessThan() { List<Course> result = criteriaProcessor .findAllEntity(CriteriaComposer.from(Course.class).where(Course_.unit, LESS_THAN, 5)); assertNotNull(result); assertEquals(2, result.size()); assertEquals("course1", result.get(0).getName()); assertEquals("course3", result.get(1).getName()); } @Test public void testGreaterThan() { List<Course> result = criteriaProcessor .findAllEntity(CriteriaComposer.from(Course.class).where(Course_.unit, GREATER_THAN, 3)); assertNotNull(result); assertEquals(1, result.size()); assertEquals("course2", result.get(0).getName()); assertEquals(5, result.get(0).getUnit().intValue()); } @Test public void testDelayedOrderBy() { //select course where course name is in ... CriteriaComposer<Course> courseCriteria = CriteriaComposer.from(Course.class); courseCriteria.select(Course_.name).where(Course_.name, IN, "course1", "course3"); //slect student who has taken these courses CriteriaComposer<Person> studentCriteria = CriteriaComposer.from(Person.class); studentCriteria.select(Person_.name, Person_.id); studentCriteria.join(Person_.personType).where(PersonType_.name, ComparisonOperator.EQUAL, PersonTypeEnum.STUDENT); studentCriteria.join(Person_.courseSessions).join(CourseSession_.course, courseCriteria); //------2.0 alpha test. See orderBy is done seperate from the above criteria. setOrderByForDelayOrderByTest(studentCriteria); List<Tuple> result = criteriaProcessor.findAllTuple(studentCriteria, true, null); assertNotNull(result); assertTrue(result.size() > 0); assertEquals(11, result.size()); assertEquals("course3", result.get(0).get("Course.name")); assertEquals("student9", result.get(0).get("Person.name")); } /** * Some time orderBy need to be done separately from the main criteria. * This information may be provided dynamically. This can be done now like this. * * @param studentCriteria * */ private void setOrderByForDelayOrderByTest(CriteriaComposer<Person> studentCriteria) { studentCriteria.orderBy(Person_.name, false, 2); studentCriteria.join(Person_.courseSessions).join(CourseSession_.course).orderBy(Course_.name, false, 1); } /** * select person.name, sum(course2_.unit) * from person * join course_session, inner join course * group by person.name * having sum(course2_.unit)=2 */ @Test public void testHaving() { CriteriaComposer<Person> forStudentUnitCount = CriteriaComposer.from(Person.class).select(Person_.name) .groupBy(Person_.name); forStudentUnitCount.join(Person_.courseSessions).join(CourseSession_.course).select(SUM, Course_.unit) .having(SUM, Course_.unit, EQUAL, 2); List<Tuple> result = criteriaProcessor.findAllTuple(forStudentUnitCount); assertNotNull(result); assertEquals(3, result.size()); assertEquals("student7", result.get(0).get("Person.name")); assertEquals(2L, result.get(0).get("sum.Course.unit")); for (int i = 1; i < result.size(); i++) { assertTrue(!result.get(i).get("Person.name").equals(result.get(0).get("Person.name"))); } } @Test public void testMerge() { } @Test public void testMergeSelect() { } @Test public void testMergeWhere() { } @Test public void testMergeHaving() { } @Test public void testMergeOrderBy() { } @Test public void testMergeGroupBy() { } }