diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java b/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java index 01fe68bee..9c5ce9cb1 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/AbstractSQLQuery.java @@ -737,6 +737,11 @@ public abstract class AbstractSQLQuery & Query> return queryMixin.addFlag(new QueryFlag(QueryFlag.Position.WITH, expr)); } + public Q with(Path alias, Expression query) { + Expression expr = OperationImpl.create(alias.getType(), SQLTemplates.WITH_ALIAS, alias, query); + return queryMixin.addFlag(new QueryFlag(QueryFlag.Position.WITH, expr)); + } + private long unsafeCount() throws SQLException { final String queryString = buildQueryString(true); if (logger.isDebugEnabled()) { diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java index 648854746..05738baf5 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLSerializerTest.java @@ -1,6 +1,6 @@ /* * Copyright 2011, Mysema Ltd - * + * * Licensed 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 @@ -22,6 +22,7 @@ import java.util.List; import org.junit.Test; import com.mysema.query.BooleanBuilder; +import com.mysema.query.QueryMetadata; import com.mysema.query.Survey; import com.mysema.query.Tuple; import com.mysema.query.sql.domain.QEmployee; @@ -29,24 +30,25 @@ import com.mysema.query.sql.domain.QSurvey; import com.mysema.query.support.Expressions; import com.mysema.query.types.Expression; import com.mysema.query.types.SubQueryExpression; +import com.mysema.query.types.expr.Wildcard; import com.mysema.query.types.path.PathBuilder; public class SQLSerializerTest { - + private static final QEmployee employee = QEmployee.employee; private static final QSurvey survey = QSurvey.survey; - + @Test public void Count() { - SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); + SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); serializer.handle(employee.id.count().add(employee.id.countDistinct())); assertEquals("count(EMPLOYEE.ID) + count(distinct EMPLOYEE.ID)", serializer.toString()); } - + @Test public void Some() { - //select some((e.FIRSTNAME is not null)) from EMPLOYEE + //select some((e.FIRSTNAME is not null)) from EMPLOYEE SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); serializer.handle(SQLExpressions.any(employee.firstname.isNotNull())); assertEquals("some(EMPLOYEE.FIRSTNAME is not null)", serializer.toString()); @@ -60,7 +62,7 @@ public class SQLSerializerTest { assertEquals("s1.NAME like ? escape '\\'", serializer.toString()); assertEquals(Arrays.asList("X%"), serializer.getConstants()); } - + @Test public void From_Function() { SQLQuery query = query(); @@ -68,7 +70,7 @@ public class SQLSerializerTest { query.where(survey.name.isNotNull()); assertEquals("from functionCall()\njoin SURVEY SURVEY\nwhere SURVEY.NAME is not null", query.toString()); } - + @Test public void Join_To_Function_With_Alias() { SQLQuery query = query(); @@ -76,7 +78,7 @@ public class SQLSerializerTest { query.where(survey.name.isNotNull()); assertEquals("from SURVEY SURVEY\njoin functionCall() as fc\nwhere SURVEY.NAME is not null", query.toString()); } - + @Test public void Join_To_Function_In_Derby() { SQLQuery query = new SQLQuery(new DerbyTemplates()); @@ -84,47 +86,47 @@ public class SQLSerializerTest { query.where(survey.name.isNotNull()); assertEquals("from SURVEY SURVEY\njoin table(functionCall()) as fc\nwhere SURVEY.NAME is not null", query.toString()); } - + @Test public void Override() { Configuration conf = new Configuration(new DerbyTemplates()); conf.registerTableOverride("SURVEY", "surveys"); - + SQLQuery query = new SQLQuery(conf); query.from(survey); assertEquals("from surveys SURVEY", query.toString()); } - + @Test - public void Complex_SubQuery() { + public void Complex_SubQuery() { // create sub queries List> sq = new ArrayList>(); String[] strs = new String[]{"a","b","c"}; for(String str : strs) { Expression alias = Expressions.cases().when(survey.name.eq(str)).then(true).otherwise(false); - sq.add(sq().from(survey).distinct().unique(survey.name, alias)); + sq.add(sq().from(survey).distinct().unique(survey.name, alias)); } - + // master query - PathBuilder subAlias = new PathBuilder(Tuple.class, "sub"); + PathBuilder subAlias = new PathBuilder(Tuple.class, "sub"); SubQueryExpression master = sq() .from(sq().union(sq).as(subAlias)) .groupBy(subAlias.get("prop1")) .list(subAlias.get("prop2")); - + SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); serializer.serialize(master.getMetadata(), false); System.err.println(serializer); } - + private SQLQuery query() { return new SQLQuery(SQLTemplates.DEFAULT); } - + private SQLSubQuery sq() { return new SQLSubQuery(); } - + @Test public void Boolean() { QSurvey s = new QSurvey("s"); @@ -138,13 +140,49 @@ public class SQLSerializerTest { String str = new SQLSerializer(Configuration.DEFAULT).handle(bb1.and(bb2)).toString(); assertEquals("s.NAME = s.NAME and (s.NAME = s.NAME or s.NAME = s.NAME)", str); } - + @Test public void List_In_Query() { Expression expr = Expressions.list(survey.id, survey.name).in(sq().from(survey).list(survey.id, survey.name)); - + String str = new SQLSerializer(Configuration.DEFAULT).handle(expr).toString(); assertEquals("(SURVEY.ID, SURVEY.NAME) in (select SURVEY.ID, SURVEY.NAME\nfrom SURVEY SURVEY)", str); } - + + @Test + public void WithRecursive() { + /*with sub (id, firstname, superior_id) as ( + select id, firstname, superior_id from employee where firstname like 'Mike' + union all + select employee.id, employee.firstname, employee.superior_id from sub, employee + where employee.superior_id = sub.id) + select * from sub;*/ + + QEmployee e = QEmployee.employee; + PathBuilder sub = new PathBuilder(Tuple.class, "sub"); + SQLQuery query = new SQLQuery(SQLTemplates.DEFAULT); + query.with(sub, + sq().unionAll( + sq().from(e).where(e.firstname.eq("Mike")) + .list(e.id, e.firstname, e.superiorId), + sq().from(e, sub).where(e.superiorId.eq(sub.get(e.id))) + .list(e.id, e.firstname, e.superiorId))) + .from(sub); + + QueryMetadata md = query.getMetadata(); + md.addProjection(Wildcard.all); + SQLSerializer serializer = new SQLSerializer(Configuration.DEFAULT); + serializer.serialize(md, false); + assertEquals("with sub as ((select EMPLOYEE.ID, EMPLOYEE.FIRSTNAME, EMPLOYEE.SUPERIOR_ID\n" + + "from EMPLOYEE EMPLOYEE\n" + + "where EMPLOYEE.FIRSTNAME = ?)\n" + + "union all\n" + + "(select EMPLOYEE.ID, EMPLOYEE.FIRSTNAME, EMPLOYEE.SUPERIOR_ID\n" + + "from EMPLOYEE EMPLOYEE, sub\n" + + "where EMPLOYEE.SUPERIOR_ID = sub.ID))\n" + + "select *\n" + + "from sub", serializer.toString()); + + } + }