package com.querydsl.sql; import static com.querydsl.core.Target.*; import static com.querydsl.sql.Constants.*; import static com.querydsl.sql.SQLExpressions.select; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.math.BigDecimal; import java.sql.SQLException; import java.util.Arrays; import java.util.List; import org.junit.Test; import com.google.common.collect.ImmutableList; import com.querydsl.core.testutil.ExcludeIn; import com.querydsl.core.types.SubQueryExpression; import com.querydsl.core.types.dsl.*; import com.querydsl.sql.domain.Employee; import com.querydsl.sql.domain.QEmployee; public class SubqueriesBase extends AbstractBaseTest { @Test @ExcludeIn({CUBRID, DERBY, FIREBIRD, H2, HSQLDB, SQLITE, SQLSERVER}) public void keys() { QEmployee employee2 = new QEmployee("employee2"); ForeignKey<Employee> nameKey1 = new ForeignKey<Employee>(employee, ImmutableList.of(employee.firstname, employee.lastname), ImmutableList.of("a", "b")); ForeignKey<Employee> nameKey2 = new ForeignKey<Employee>(employee, ImmutableList.of(employee.firstname, employee.lastname), ImmutableList.of("a", "b")); query().from(employee) .where(nameKey1.in(query().from(employee2).select(nameKey2.getProjection()))) .select(employee.id).fetch(); } @Test @ExcludeIn({CUBRID, DERBY, FIREBIRD, H2, HSQLDB, SQLITE, SQLSERVER}) public void list_in_query() { QEmployee employee2 = new QEmployee("employee2"); query().from(employee) .where(Expressions.list(employee.id, employee.lastname) .in(query().from(employee2).select(employee2.id, employee2.lastname))) .select(employee.id).fetch(); } @Test @SkipForQuoted @ExcludeIn(DB2) // ID is reserved IN DB2 public void subQueries() throws SQLException { // subquery in where block expectedQuery = "select e.ID from EMPLOYEE e " + "where e.ID = (select max(e.ID) " + "from EMPLOYEE e)"; List<Integer> list = query().from(employee) .where(employee.id.eq(query().from(employee).select(employee.id.max()))) .select(employee.id).fetch(); assertFalse(list.isEmpty()); } @Test public void subQuery_alias() { query().from(query().from(employee).select(employee.all()).as(employee2)).select(employee2.all()).fetch(); } @Test @ExcludeIn(SQLITE) public void subQuery_all() { query().from(employee).where(employee.id.gtAll( query().from(employee2).select(employee2.id))).fetchCount(); } @Test @ExcludeIn(SQLITE) public void subQuery_any() { query().from(employee).where(employee.id.gtAny( query().from(employee2).select(employee2.id))).fetchCount(); } @Test public void subQuery_innerJoin() { SubQueryExpression<Integer> sq = query().from(employee2).select(employee2.id); QEmployee sqEmp = new QEmployee("sq"); query().from(employee).innerJoin(sq, sqEmp).on(sqEmp.id.eq(employee.id)).select(employee.id).fetch(); } @Test public void subQuery_leftJoin() { SubQueryExpression<Integer> sq = query().from(employee2).select(employee2.id); QEmployee sqEmp = new QEmployee("sq"); query().from(employee).leftJoin(sq, sqEmp).on(sqEmp.id.eq(employee.id)).select(employee.id).fetch(); } @Test @ExcludeIn({MYSQL, POSTGRESQL, DERBY, SQLSERVER, TERADATA}) public void subQuery_params() { Param<String> aParam = new Param<String>(String.class, "param"); SQLQuery<?> subQuery = select(Wildcard.all).from(employee).where(employee.firstname.eq(aParam)); subQuery.set(aParam, "Mike"); assertEquals(1, query().from(subQuery).fetchCount()); } @Test @ExcludeIn(SQLITE) public void subQuery_rightJoin() { SubQueryExpression<Integer> sq = query().from(employee2).select(employee2.id); QEmployee sqEmp = new QEmployee("sq"); query().from(employee).rightJoin(sq, sqEmp).on(sqEmp.id.eq(employee.id)).select(employee.id).fetch(); } @Test public void subQuery_with_alias() { List<Integer> ids1 = query().from(employee).select(employee.id).fetch(); List<Integer> ids2 = query().from(query().from(employee).select(employee.id), employee).select(employee.id).fetch(); assertEquals(ids1, ids2); } @Test public void subQuery_with_alias2() { List<Integer> ids1 = query().from(employee).select(employee.id).fetch(); List<Integer> ids2 = query().from(query().from(employee).select(employee.id).as(employee)).select(employee.id).fetch(); assertEquals(ids1, ids2); } @Test @SkipForQuoted public void subQuerySerialization() { SQLQuery<?> query = query(); query.from(survey); assertEquals("from SURVEY s", query.toString()); query.from(survey2); assertEquals("from SURVEY s, SURVEY s2", query.toString()); } @Test public void subQuerySerialization2() { NumberPath<BigDecimal> sal = Expressions.numberPath(BigDecimal.class, "sal"); PathBuilder<Object[]> sq = new PathBuilder<Object[]>(Object[].class, "sq"); SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); serializer.handle( query() .from(employee) .select(employee.salary.add(employee.salary).add(employee.salary).as(sal)) .as(sq)); assertEquals( "(select (e.SALARY + e.SALARY + e.SALARY) as sal\nfrom EMPLOYEE e) as sq", serializer.toString()); } @Test public void scalarSubQueryInClause() { SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); serializer.handle( this.query() .from(employee) .where( SQLExpressions .select(employee.firstname) .from(employee) .orderBy(employee.salary.asc()) .limit(1) .in(Arrays.asList("Mike", "Mary")) )); expectedQuery = "(\nfrom EMPLOYEE e\n" + "where (select e.FIRSTNAME\n" + "from EMPLOYEE e\n" + "order by e.SALARY asc\n" + "limit ?) in (?, ?))"; assertEquals(expectedQuery, serializer.toString()); } @Test public void scalarSubQueryInClause2() { SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); serializer.handle( this.query() .from(employee) .where( SQLExpressions .select(employee.firstname) .from(employee) .orderBy(employee.salary.asc()) .limit(1) .in("Mike", "Mary") )); expectedQuery = "(\nfrom EMPLOYEE e\n" + "where (select e.FIRSTNAME\n" + "from EMPLOYEE e\n" + "order by e.SALARY asc\n" + "limit ?) in (?, ?))"; assertEquals(expectedQuery, serializer.toString()); } }