#676458 : added support for Projectable.exists() and notExists()

This commit is contained in:
Timo Westkämper 2010-11-26 14:27:29 +00:00
parent 145fbaccc7
commit 767561fa22
17 changed files with 267 additions and 105 deletions

View File

@ -63,14 +63,23 @@ public abstract class AbstractColQuery<Q extends AbstractColQuery<Q>> extends P
}
}
@SuppressWarnings("unchecked")
private <D> Expression<D> createAlias(CollectionExpression<?,D> target, Path<D> alias){
return OperationImpl.create((Class<D>)alias.getType(), Ops.ALIAS, target, alias);
@Override
public boolean exists(){
try {
return queryEngine.exists(getMetadata(), iterables);
} catch (Exception e) {
throw new QueryException(e.getMessage(), e);
}finally{
reset();
}
}
private <D> Expression<D> createAlias(CollectionExpression<?,D> target, Path<D> alias){
return OperationImpl.create(alias.getType(), Ops.ALIAS, target, alias);
}
@SuppressWarnings("unchecked")
private <D> Expression<D> createAlias(MapExpression<?,D> target, Path<D> alias){
return OperationImpl.create((Class<D>)alias.getType(), Ops.ALIAS, target, alias);
return OperationImpl.create(alias.getType(), Ops.ALIAS, target, alias);
}
@SuppressWarnings("unchecked")

View File

@ -20,6 +20,7 @@ import com.mysema.commons.lang.IteratorAdapter;
import com.mysema.query.JoinExpression;
import com.mysema.query.JoinType;
import com.mysema.query.QueryMetadata;
import com.mysema.query.QueryModifiers;
import com.mysema.query.types.ArrayConstructorExpression;
import com.mysema.query.types.Expression;
import com.mysema.query.types.Operation;
@ -51,6 +52,21 @@ public class DefaultQueryEngine implements QueryEngine {
}
}
@Override
public boolean exists(QueryMetadata metadata, Map<Expression<?>, Iterable<?>> iterables) {
QueryModifiers modifiers = metadata.getModifiers();
metadata.setLimit(1l);
try{
if (metadata.getJoins().size() == 1){
return !evaluateSingleSource(metadata, iterables, true).isEmpty();
}else{
return !evaluateMultipleSources(metadata, iterables, true).isEmpty();
}
}finally{
metadata.setModifiers(modifiers);
}
}
@Override
public <T> List<T> list(QueryMetadata metadata, Map<Expression<?>, Iterable<?>> iterables, Expression<T> projection){
if (metadata.getJoins().size() == 1){
@ -70,7 +86,7 @@ public class DefaultQueryEngine implements QueryEngine {
}
}
return rv;
}else{
}else{
for (T o : list){
if (!rv.contains(o)){
rv.add(o);
@ -183,7 +199,6 @@ public class DefaultQueryEngine implements QueryEngine {
}
Expression<?> expr = new ArrayConstructorExpression<Object>(Object[].class, orderByExpr);
Evaluator orderEvaluator = evaluatorFactory.create(metadata, sources, expr);
Collections.sort(list, new MultiComparator(orderEvaluator, directions));
}
@ -194,4 +209,6 @@ public class DefaultQueryEngine implements QueryEngine {
return list;
}
}

View File

@ -42,4 +42,11 @@ public interface QueryEngine {
*/
<T> List<T> list(QueryMetadata metadata, Map<Expression<?>, Iterable<?>> iterables, Expression<T> projection);
/**
* @param metadata
* @param iterables
* @return
*/
boolean exists(QueryMetadata metadata, Map<Expression<?>, Iterable<?>> iterables);
}

View File

@ -0,0 +1,20 @@
package com.mysema.query.collections;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ExistsTest extends AbstractQueryTest{
@Test
public void Exists(){
assertTrue(query().from(cat, cats).where(cat.name.eq("Bob")).exists());
}
@Test
public void NotExists(){
assertTrue(query().from(cat, cats).where(cat.name.eq("Bobby")).notExists());
}
}

View File

@ -35,6 +35,16 @@ public interface Projectable {
@Nonnegative
long countDistinct();
/**
* @return true, if rows matching the given criteria exist, otherwise false
*/
boolean exists();
/**
* @return true, if no rows matching the given criteria exist, otherwise false
*/
boolean notExists();
/**
* iterate over the results for the given projection
*

View File

@ -42,6 +42,16 @@ public class ProjectableAdapter<P extends Projectable> implements Projectable {
return projectable.countDistinct();
}
@Override
public boolean exists() {
return projectable.exists();
}
@Override
public boolean notExists() {
return projectable.notExists();
}
@Override
public CloseableIterator<Object[]> iterate(Expression<?> first, Expression<?> second, Expression<?>... rest) {
return projectable.iterate(first, second, rest);
@ -117,6 +127,7 @@ public class ProjectableAdapter<P extends Projectable> implements Projectable {
return projectable.map(key, value);
}
@Override
public String toString() {
return projectable.toString();
}

View File

@ -37,6 +37,11 @@ public abstract class ProjectableQuery<Q extends ProjectableQuery<Q>>
return count();
}
@Override
public boolean notExists(){
return !exists();
}
@Override
public final CloseableIterator<Object[]> iterate(Expression<?> first, Expression<?> second, Expression<?>... rest) {
return iterate(merge(first, second, rest));

View File

@ -36,4 +36,14 @@ public class DummyProjectable extends ProjectableQuery<DummyProjectable>{
return SearchResults.emptyResults();
}
@Override
public boolean exists() {
return false;
}
@Override
public boolean notExists() {
return true;
}
}

View File

@ -44,14 +44,14 @@ import com.mysema.query.types.QTuple;
public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extends ProjectableQuery<Q>{
private static final Logger logger = LoggerFactory.getLogger(JDOQLQueryImpl.class);
private final Closeable closeable = new Closeable(){
@Override
public void close() throws IOException {
AbstractJDOQLQuery.this.close();
}
AbstractJDOQLQuery.this.close();
}
};
private final boolean detach;
private List<Object> orderedConstants = new ArrayList<Object>();
@ -59,12 +59,12 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
@Nullable
private final PersistenceManager persistenceManager;
private List<Query> queries = new ArrayList<Query>(2);
private final List<Query> queries = new ArrayList<Query>(2);
private final JDOQLTemplates templates;
private Set<String> fetchGroups = new HashSet<String>();
private final Set<String> fetchGroups = new HashSet<String>();
@Nullable
private Integer maxFetchDepth;
@ -96,6 +96,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
}
}
@Override
public long count() {
Query query = createQuery(true);
query.setUnique(true);
@ -108,15 +109,26 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
}
}
@Override
public boolean exists(){
boolean rv = limit(1).uniqueResult(getSource()) != null;
close();
return rv;
}
private Expression<?> getSource(){
return queryMixin.getMetadata().getJoins().get(0).getTarget();
}
private Query createQuery(boolean forCount) {
Expression<?> source = queryMixin.getMetadata().getJoins().get(0).getTarget();
Expression<?> source = getSource();
// serialize
JDOQLSerializer serializer = new JDOQLSerializer(getTemplates(), source);
serializer.serialize(queryMixin.getMetadata(), forCount, false);
logQuery(serializer.toString());
// create Query
Query query = persistenceManager.newQuery(serializer.toString());
orderedConstants = serializer.getConstants();
@ -130,7 +142,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
} else if (FactoryExpression.class.isAssignableFrom(exprType)){
query.setResultClass(projection.get(0).getType());
}
if (!fetchGroups.isEmpty()){
query.getFetchPlan().setGroups(fetchGroups);
}
@ -141,7 +153,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
return query;
}
protected void logQuery(String queryString){
if (logger.isDebugEnabled()){
logger.debug(queryString.replace('\n', ' '));
@ -194,6 +206,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
return new IteratorAdapter<RT>(list(projection).iterator(), closeable);
}
@Override
@SuppressWarnings("unchecked")
public List<Object[]> list(Expression<?>[] args) {
queryMixin.addToProjection(args);
@ -202,6 +215,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
return (rv instanceof List) ? ((List<Object[]>)rv) : Collections.singletonList((Object[])rv);
}
@Override
@SuppressWarnings("unchecked")
public <RT> List<RT> list(Expression<RT> expr) {
queryMixin.addToProjection(expr);
@ -237,12 +251,11 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
maxFetchDepth = depth;
return (Q)this;
}
@Override
public String toString(){
if (!queryMixin.getMetadata().getJoins().isEmpty()){
Expression<?> source = queryMixin.getMetadata().getJoins().get(0).getTarget();
Expression<?> source = getSource();
JDOQLSerializer serializer = new JDOQLSerializer(getTemplates(), source);
serializer.serialize(queryMixin.getMetadata(), false, false);
return serializer.toString().trim();
@ -251,6 +264,7 @@ public abstract class AbstractJDOQLQuery<Q extends AbstractJDOQLQuery<Q>> extend
}
}
@Override
@SuppressWarnings("unchecked")
public <RT> RT uniqueResult(Expression<RT> expr) {
queryMixin.addToProjection(expr);

View File

@ -15,12 +15,13 @@ import com.mysema.query.types.Ops;
import com.mysema.query.types.Path;
import com.mysema.query.types.Predicate;
import com.mysema.query.types.SubQueryExpression;
import com.mysema.query.types.TemplateExpressionImpl;
import com.mysema.query.types.expr.NumberExpression;
import com.mysema.query.types.expr.NumberOperation;
/**
* Base class for JDO based SQLQuery implementations
*
*
* @author tiwe
*
* @param <T>
@ -29,6 +30,8 @@ public abstract class AbstractSQLQuery<T extends AbstractSQLQuery<T>> extends Pr
private static final NumberExpression<Integer> COUNT_ALL_AGG_EXPR = NumberOperation.create(Integer.class, Ops.AggOps.COUNT_ALL_AGG);
private static final Expression<Integer> ONE = TemplateExpressionImpl.create(Integer.class, "1");
@SuppressWarnings("unchecked")
public AbstractSQLQuery(QueryMetadata metadata) {
super(new QueryMixin<T>(metadata));
@ -40,6 +43,11 @@ public abstract class AbstractSQLQuery<T extends AbstractSQLQuery<T>> extends Pr
return uniqueResult(COUNT_ALL_AGG_EXPR);
}
@Override
public boolean exists(){
return limit(1).uniqueResult(ONE) != null;
}
public T from(Expression<?>... args) {
return queryMixin.from(args);
}

View File

@ -8,6 +8,7 @@ package com.mysema.query;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Calendar;
@ -39,8 +40,7 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
public static class Projection {
public Projection(String str) {
}
public Projection(String str) {}
}
@ -60,7 +60,7 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
}
private static String productName = "ABCD";
private static String otherName = "ABC0";
@BeforeClass
@ -97,7 +97,7 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
}
private QueryExecution standardTest = new QueryExecution(Module.JDOQL, Target.H2){
private final QueryExecution standardTest = new QueryExecution(Module.JDOQL, Target.H2){
@Override
protected Pair<Projectable, List<Expression<?>>> createQuery() {
return Pair.of(
@ -112,13 +112,13 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
}
};
private QProduct product = QProduct.product;
private final QProduct product = QProduct.product;
private QProduct otherProduct = new QProduct("otherProduct");
private final QProduct otherProduct = new QProduct("otherProduct");
private QStore store = QStore.store;
private final QStore store = QStore.store;
private QStore otherStore = new QStore("otherStore");
private final QStore otherStore = new QStore("otherStore");
@Test
public void StandardTest(){
@ -194,4 +194,14 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
Param<String> name = new Param<String>(String.class,"name");
assertEquals("ABC0",query().from(product).where(product.name.eq(name)).uniqueResult(product.name));
}
@Test
public void Exists(){
assertTrue(query().from(product).where(product.name.eq("ABC0")).exists());
}
@Test
public void NotExists(){
assertTrue(query().from(product).where(product.name.eq("XXX")).notExists());
}
}

View File

@ -16,10 +16,11 @@ import com.mysema.query.types.Ops;
import com.mysema.query.types.Path;
import com.mysema.query.types.Predicate;
import com.mysema.query.types.SubQueryExpression;
import com.mysema.query.types.TemplateExpressionImpl;
/**
* Abstract super class for SQLQuery implementation for JPA and Hibernate
*
*
* @author tiwe
*
* @param <T>
@ -28,6 +29,8 @@ public abstract class AbstractSQLQuery<T extends AbstractSQLQuery<T>> extends Pr
private static final Expression<Integer> COUNT_ALL_AGG_EXPR = OperationImpl.create(Integer.class, Ops.AggOps.COUNT_ALL_AGG);
private static final Expression<Integer> ONE = TemplateExpressionImpl.create(Integer.class, "1");
@SuppressWarnings("unchecked")
public AbstractSQLQuery(QueryMetadata metadata) {
super(new QueryMixin<T>(metadata));
@ -39,6 +42,11 @@ public abstract class AbstractSQLQuery<T extends AbstractSQLQuery<T>> extends Pr
return uniqueResult(COUNT_ALL_AGG_EXPR);
}
@Override
public boolean exists(){
return limit(1).uniqueResult(ONE) != null;
}
public T from(Expression<?>... args) {
return queryMixin.from(args);
}

View File

@ -11,9 +11,11 @@ import com.mysema.query.QueryMetadata;
import com.mysema.query.support.ProjectableQuery;
import com.mysema.query.types.CollectionExpression;
import com.mysema.query.types.EntityPath;
import com.mysema.query.types.Expression;
import com.mysema.query.types.MapExpression;
import com.mysema.query.types.Path;
import com.mysema.query.types.Predicate;
import com.mysema.query.types.TemplateExpressionImpl;
/**
* JPQLQueryBase is a base Query class for JPQL queries
@ -23,6 +25,8 @@ import com.mysema.query.types.Predicate;
*/
public abstract class JPQLQueryBase<Q extends JPQLQueryBase<Q>> extends ProjectableQuery<Q> {
private static final Expression<Integer> ONE = TemplateExpressionImpl.create(Integer.class, "1");
private Map<Object,String> constants;
private final JPQLQueryMixin<Q> queryMixin;
@ -59,6 +63,11 @@ public abstract class JPQLQueryBase<Q extends JPQLQueryBase<Q>> extends Projecta
queryMixin.getMetadata().reset();
}
@Override
public boolean exists(){
return limit(1).uniqueResult(ONE) != null;
}
public Q fetch(){
return queryMixin.fetch();
}

View File

@ -169,15 +169,16 @@ public final class JPASQLQuery extends AbstractSQLQuery<JPASQLQuery> implements
return buildQueryString(false);
}
@Override
@SuppressWarnings("unchecked")
public <RT> RT uniqueResult(Expression<RT> expr) {
Query query = createQuery(expr);
reset();
try{
return (RT) query.getSingleResult();
return (RT) query.getSingleResult();
}catch(NoResultException e){
logger.debug(e.getMessage(),e);
return null;
return null;
}
}

View File

@ -9,6 +9,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
@ -53,15 +54,15 @@ public abstract class AbstractStandardTest {
}
}
public static class QProjection extends ConstructorExpression<Projection>{
private static final long serialVersionUID = -5866362075090550839L;
public QProjection(StringExpression str, QCat cat){
super(Projection.class, new Class[]{String.class, Cat.class}, new Expression[]{str, cat});
}
}
private static final QCat cat = QCat.cat;
@ -76,7 +77,8 @@ public abstract class AbstractStandardTest {
private final java.sql.Date date;
private Projections projections = new Projections(Module.HQL, getTarget()){
private final Projections projections = new Projections(Module.HQL, getTarget()){
@Override
public <A> Collection<Expression<?>> list(ListPath<A,?> expr, ListExpression<A> other, A knownElement){
// NOTE : expr.get(0) is only supported in the where clause
return Collections.<Expression<?>>singleton(expr.size());
@ -85,7 +87,7 @@ public abstract class AbstractStandardTest {
private final List<Cat> savedCats = new ArrayList<Cat>();
private QueryExecution standardTest = new QueryExecution(
private final QueryExecution standardTest = new QueryExecution(
projections, new Filters(projections, Module.HQL, getTarget()), new MatchingFilters(Module.HQL, getTarget())){
@Override
@ -149,7 +151,7 @@ public abstract class AbstractStandardTest {
cat.setBirthdate(birthDate);
save(cat);
savedCats.add(cat);
Show show = new Show();
show.acts = new HashMap<String,String>();
show.acts.put("a","A");
@ -188,13 +190,23 @@ public abstract class AbstractStandardTest {
public void Any_Simple(){
assertEquals(1, catQuery().where(cat.kittens.any().name.eq("Ruth123")).count());
}
@Test
public void Exists(){
assertTrue(catQuery().where(cat.kittens.any().name.eq("Ruth123")).exists());
}
@Test
public void NotExists(){
assertTrue(catQuery().where(cat.kittens.any().name.eq("XXX")).notExists());
}
@Test
public void Any_And(){
assertEquals(1, catQuery().where(cat.kittens.any().name.eq("Ruth123"), cat.kittens.any().bodyWeight.lt(10.0)).count());
assertEquals(0, catQuery().where(cat.kittens.any().name.eq("Ruth123"), cat.kittens.any().bodyWeight.gt(10.0)).count());
}
@Test
public void Aggregates_UniqueResult(){
// uniqueResult
@ -208,7 +220,7 @@ public abstract class AbstractStandardTest {
assertEquals(Integer.valueOf(1), catQuery().list(cat.id.min()).get(0));
assertEquals(Integer.valueOf(6), catQuery().list(cat.id.max()).get(0));
}
@Test
public void DistinctResults(){
System.out.println("-- list results");
@ -242,26 +254,26 @@ public abstract class AbstractStandardTest {
assertEquals(0, catQuery().where(cat.name.endsWith("X")).count());
assertEquals(1, catQuery().where(cat.name.endsWithIgnoreCase("H123")).count());
}
@Test
public void Contains(){
// contains
assertEquals(1, catQuery().where(cat.name.contains("eli")).count());
}
@Test
public void Length(){
// length
assertEquals(6, catQuery().where(cat.name.length().gt(0)).count());
}
@Test
public void IndexOf(){
// indexOf
assertEquals(Integer.valueOf(0), catQuery().where(cat.name.eq("Bob123")).uniqueResult(cat.name.indexOf("B")));
assertEquals(Integer.valueOf(1), catQuery().where(cat.name.eq("Bob123")).uniqueResult(cat.name.indexOf("o")));
assertEquals(Integer.valueOf(1), catQuery().where(cat.name.eq("Bob123")).uniqueResult(cat.name.indexOf("o")));
}
@Test
public void StringOperations(){
// case-sensitivity
@ -271,26 +283,26 @@ public abstract class AbstractStandardTest {
assertEquals(Integer.valueOf(2), catQuery().where(cat.name.eq("Bob123")).uniqueResult(cat.name.indexOf("b")));
}
}
@Test
public void Limit(){
// limit
List<String> names1 = Arrays.asList("Allen123","Bob123");
assertEquals(names1, catQuery().orderBy(cat.name.asc()).limit(2).list(cat.name));
assertEquals(names1, catQuery().orderBy(cat.name.asc()).limit(2).list(cat.name));
}
@Test
public void Offset(){
// offset
List<String> names2 = Arrays.asList("Felix123","Mary123","Ruth123","Some");
assertEquals(names2, catQuery().orderBy(cat.name.asc()).offset(2).list(cat.name));
assertEquals(names2, catQuery().orderBy(cat.name.asc()).offset(2).list(cat.name));
}
@Test
public void Limit_and_offset(){
// limit + offset
List<String> names3 = Arrays.asList("Felix123","Mary123");
assertEquals(names3, catQuery().orderBy(cat.name.asc()).limit(2).offset(2).list(cat.name));
assertEquals(names3, catQuery().orderBy(cat.name.asc()).limit(2).offset(2).list(cat.name));
}
@Test
@ -327,7 +339,7 @@ public abstract class AbstractStandardTest {
assertNotNull(projection);
}
}
@Test
public void ConstructorProjection2(){
List<Projection> projections = query().from(cat).list(new QProjection(cat.name, cat));
@ -354,12 +366,12 @@ public abstract class AbstractStandardTest {
Param<String> name = new Param<String>(String.class,"name");
assertEquals("Bob123",query().from(cat).where(cat.name.eq(name)).uniqueResult(cat.name));
}
@Test
public void Null_as_uniqueResult(){
assertNull(query().from(cat).where(cat.name.eq(UUID.randomUUID().toString())).uniqueResult(cat));
}
@Test
public void Map_ContainsKey(){
QShow show = QShow.show;
@ -367,7 +379,7 @@ public abstract class AbstractStandardTest {
assertEquals(1l, query().from(show).where(show.acts.containsKey("b")).count());
assertEquals(0l, query().from(show).where(show.acts.containsKey("c")).count());
}
@Test
public void Map_ContainsValue(){
QShow show = QShow.show;

View File

@ -35,15 +35,7 @@ import com.mysema.query.SearchResults;
import com.mysema.query.QueryFlag.Position;
import com.mysema.query.support.ProjectableQuery;
import com.mysema.query.support.QueryMixin;
import com.mysema.query.types.Expression;
import com.mysema.query.types.FactoryExpression;
import com.mysema.query.types.OrderSpecifier;
import com.mysema.query.types.ParamExpression;
import com.mysema.query.types.ParamNotSetException;
import com.mysema.query.types.Path;
import com.mysema.query.types.Predicate;
import com.mysema.query.types.QBean;
import com.mysema.query.types.SubQueryExpression;
import com.mysema.query.types.*;
import com.mysema.query.types.query.ListSubQuery;
import com.mysema.query.types.template.SimpleTemplate;
import com.mysema.util.ResultSetAdapter;
@ -68,7 +60,7 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
return (List<RT>) IteratorAdapter.asList(iterateMultiple());
}
}
@SuppressWarnings("unchecked")
@Override
public CloseableIterator<RT> iterate() {
@ -84,7 +76,7 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
AbstractSQLQuery.this.orderBy(o);
return this;
}
@Override
public String toString(){
return AbstractSQLQuery.this.toString();
@ -94,6 +86,8 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
private static final Logger logger = LoggerFactory.getLogger(AbstractSQLQuery.class);
private static final Expression<Integer> ONE = TemplateExpressionImpl.create(Integer.class, "1");
@Nullable
private final Connection conn;
@ -102,7 +96,7 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
@Nullable
private List<Path<?>> constantPaths;
@Nullable
private SubQueryExpression<?>[] union;
@ -119,7 +113,7 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
this.conn = conn;
this.configuration = configuration;
}
@SuppressWarnings("unchecked")
protected Q addJoinFlag(String flag){
List<JoinExpression> joins = queryMixin.getMetadata().getJoins();
@ -131,15 +125,15 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
Expression<?> flag = SimpleTemplate.create(expr.getType(), prefix + "{0}", expr);
return queryMixin.addFlag(new QueryFlag(position, flag));
}
protected Q addFlag(Position position, String flag){
return queryMixin.addFlag(new QueryFlag(position, flag));
}
protected Q addFlag(Position position, Expression<?> flag){
return queryMixin.addFlag(new QueryFlag(position, flag));
}
protected String buildQueryString(boolean forCountRow) {
SQLSerializer serializer = createSerializer();
if (union != null) {
@ -163,6 +157,11 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
}
}
@Override
public boolean exists(){
return limit(1).uniqueResult(ONE) != null;
}
protected SQLSerializer createSerializer() {
return new SQLSerializer(configuration.getTemplates());
}
@ -236,11 +235,11 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
private <T> T get(ResultSet rs, Expression<?> expr, int i, Class<T> type) throws SQLException {
return configuration.get(rs, expr instanceof Path ? (Path)expr : null, i, type);
}
private int set(PreparedStatement stmt, Path<?> path, int i, Object value) throws SQLException{
return configuration.set(stmt, path, i, value);
}
public QueryMetadata getMetadata() {
return queryMixin.getMetadata();
}
@ -311,8 +310,8 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
}
}else{
queryMixin.addToProjection(expr);
return iterateSingle(expr);
}
return iterateSingle(expr);
}
}
private CloseableIterator<Object[]> iterateMultiple() {
@ -398,7 +397,7 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
}
return (RT) rv;
} else{
return (RT) get(rs, expr, 1, expr.getType());
return get(rs, expr, 1, expr.getType());
}
} catch (IllegalAccessException e) {
close();
@ -469,14 +468,14 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
queryMixin.getMetadata().reset();
constants = null;
}
protected void setParameters(PreparedStatement stmt, List<?> objects, List<Path<?>> constantPaths, Map<ParamExpression<?>, ?> params){
if (objects.size() != constantPaths.size()){
throw new IllegalArgumentException("Expected " + objects.size() + " paths, but got " + constantPaths.size());
}
int counter = 1;
for (int i = 0; i < objects.size(); i++){
Object o = objects.get(i);
Object o = objects.get(i);
try {
if (ParamExpression.class.isInstance(o)){
if (!params.containsKey(o)){
@ -516,7 +515,7 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
}finally{
iterator.close();
}
}
private long unsafeCount() throws SQLException {
@ -546,5 +545,5 @@ public abstract class AbstractSQLQuery<Q extends AbstractSQLQuery<Q>> extends
}
}
}
}

View File

@ -62,7 +62,9 @@ import com.mysema.query.types.path.PathBuilder;
import com.mysema.query.types.query.ListSubQuery;
import com.mysema.query.types.query.NumberSubQuery;
import com.mysema.query.types.query.SimpleSubQuery;
import com.mysema.testutil.*;
import com.mysema.testutil.ExcludeIn;
import com.mysema.testutil.IncludeIn;
import com.mysema.testutil.Label;
public abstract class SelectBaseTest extends AbstractBaseTest{
@ -73,7 +75,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
}
private QueryExecution standardTest = new QueryExecution(Module.SQL, getClass().getAnnotation(Label.class).value()){
private final QueryExecution standardTest = new QueryExecution(Module.SQL, getClass().getAnnotation(Label.class).value()){
@Override
protected Pair<Projectable, List<Expression<?>>> createQuery() {
return Pair.of(
@ -248,7 +250,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
NumberPath<Long> rowCount = new NumberPath<Long>(Long.class, "rowCount");
query().from(employee).uniqueResult(Wildcard.count().as(rowCount));
}
@Test
public void Custom_Projection(){
List<Projection> tuples = query().from(employee).list(
@ -286,7 +288,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
System.out.println(name);
}
}
@Test
public void Inner_Join() throws SQLException {
query().from(employee).innerJoin(employee2)
@ -300,14 +302,14 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
.on(employee.superiorIdKey.on(employee2))
.list(employee.id, employee2.id);
}
@Test
public void Right_Join() throws SQLException {
query().from(employee).rightJoin(employee2)
.on(employee.superiorIdKey.on(employee2))
.list(employee.id, employee2.id);
}
@Test
@IncludeIn({POSTGRES})
public void Full_Join() throws SQLException {
@ -326,6 +328,16 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
}
}
@Test
public void Exists(){
assertTrue(query().from(employee).where(employee.firstname.eq("Barbara")).exists());
}
@Test
public void NotExists(){
assertTrue(query().from(employee).where(employee.firstname.eq("Barb")).notExists());
}
@Test
public void Limit() throws SQLException {
// limit
@ -333,7 +345,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
.orderBy(employee.firstname.asc())
.limit(4).list(employee.id);
}
@Test
public void Limit_And_Offset() throws SQLException {
// limit and offset
@ -341,9 +353,9 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
.orderBy(employee.firstname.asc())
.limit(4).offset(3).list(employee.id);
}
@Test
public void Limitt_and_Order(){
public void Limit_and_Order(){
// limit
List<String> names1 = Arrays.asList("Barbara","Daisy","Helen","Jennifer");
assertEquals(names1, query().from(employee)
@ -417,13 +429,13 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
public void Path_Alias(){
expectedQuery = "select e.LASTNAME, sum(e.SALARY) as salarySum from EMPLOYEE2 e group by e.LASTNAME having salarySum > ?";
NumberExpression<BigDecimal> salarySum = employee.salary.sum().as("salarySum");
NumberExpression<BigDecimal> salarySum = employee.salary.sum().as("salarySum");
query().from(employee)
.groupBy(employee.lastname)
.having(salarySum.gt(10000))
.list(employee.lastname, salarySum);
}
@Test
public void Projection() throws IOException{
CloseableIterator<Object[]> results = query().from(survey).iterate(survey.all());
@ -572,7 +584,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
query().from(employee).where(where).list(employee.firstname);
}
}
@Test
public void SubQuery_InnerJoin(){
ListSubQuery<Integer> sq = sq().from(employee2).list(employee2.id);
@ -580,7 +592,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
query().from(employee).innerJoin(sq, sqEmp).on(sqEmp.id.eq(employee.id)).list(employee.id);
}
@Test
public void SubQuery_LeftJoin(){
ListSubQuery<Integer> sq = sq().from(employee2).list(employee2.id);
@ -588,7 +600,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
query().from(employee).leftJoin(sq, sqEmp).on(sqEmp.id.eq(employee.id)).list(employee.id);
}
@Test
public void SubQuery_RightJoin(){
ListSubQuery<Integer> sq = sq().from(employee2).list(employee2.id);
@ -596,7 +608,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
query().from(employee).rightJoin(sq, sqEmp).on(sqEmp.id.eq(employee.id)).list(employee.id);
}
@Test
public void SubQuerySerialization(){
SQLSubQuery query = sq();
@ -606,13 +618,13 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
query.from(survey2);
assertEquals("from SURVEY s, SURVEY s2", query.toString());
}
@Test
public void SubQuerySerialization2(){
NumberPath<BigDecimal> sal = new NumberPath<BigDecimal>(BigDecimal.class, "sal");
PathBuilder<Object[]> sq = new PathBuilder<Object[]>(Object[].class, "sq");
SQLSerializer serializer = new SQLSerializer(SQLTemplates.DEFAULT);
serializer.handle(
sq()
.from(employee)
@ -655,7 +667,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
assertEquals(2, row.length);
assertEquals(Integer.class, row[0].getClass());
assertEquals(String.class, row[1].getClass());
}
}
}
@Test
@ -668,7 +680,7 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
assertEquals(IdName.class, row[2].getClass());
}
}
@SuppressWarnings("unchecked")
@Test
public void Union() throws SQLException {
@ -706,13 +718,13 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
// iterator
CloseableIterator<Object[]> iterator = query().union(sq1,sq2).iterate();
try{
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
assertTrue(iterator.next() != null);
assertTrue(iterator.next() != null);
assertFalse(iterator.hasNext());
}finally{
iterator.close();
}
}
}
@SuppressWarnings("unchecked")
@ -730,13 +742,13 @@ public abstract class SelectBaseTest extends AbstractBaseTest{
// iterator
CloseableIterator<Integer> iterator = query().union(sq1,sq2).iterate();
try{
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
assertTrue(iterator.next() != null);
assertTrue(iterator.next() != null);
assertFalse(iterator.hasNext());
}finally{
iterator.close();
}
}
}
@Test