Implement SELECT DISTINCT [ON <exp>] as a QueryClause.
This commit is contained in:
@@ -178,6 +178,25 @@ public class Query<T extends PersistentRecord>
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the query to return only distinct rows.
|
||||
*/
|
||||
public Query<T> distinct ()
|
||||
{
|
||||
return distinct(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the query to return rows for which the given expression evaluates distinctly.
|
||||
*/
|
||||
public Query<T> distinct (SQLExpression<?> distinctOn)
|
||||
{
|
||||
checkState(_distinct == null, "Distinct clause is already configured.");
|
||||
Query<T> query = clone();
|
||||
query._distinct = new Distinct(distinctOn);
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a {@link GroupBy} clause on the supplied group expressions.
|
||||
*/
|
||||
@@ -610,6 +629,7 @@ public class Query<T extends PersistentRecord>
|
||||
addIfNotNull(clauses, _where);
|
||||
addAll(clauses, _joins);
|
||||
addIfNotNull(clauses, _orderBy);
|
||||
addIfNotNull(clauses, _distinct);
|
||||
addIfNotNull(clauses, _groupBy);
|
||||
addIfNotNull(clauses, _limit);
|
||||
addIfNotNull(clauses, _fromOverride);
|
||||
@@ -636,6 +656,7 @@ public class Query<T extends PersistentRecord>
|
||||
checkState(_where != null, "Where clause must be specified for delete.");
|
||||
checkState(_joins == null, "Join clauses not supported by delete.");
|
||||
checkState(_orderBy == null, "OrderBy clause not applicable for delete.");
|
||||
checkState(_distinct == null, "Distinct clause not applicable for delete.");
|
||||
checkState(_groupBy == null, "GroupBy clause not applicable for delete.");
|
||||
checkState(_fromOverride == null, "FromOverride clause not applicable for delete.");
|
||||
checkState(_fieldDefs == null, "FieldDefinition clauses not applicable for delete.");
|
||||
@@ -678,6 +699,7 @@ public class Query<T extends PersistentRecord>
|
||||
|
||||
protected WhereClause _where;
|
||||
protected OrderBy _orderBy;
|
||||
protected Distinct _distinct;
|
||||
protected GroupBy _groupBy;
|
||||
protected Limit _limit;
|
||||
protected FromOverride _fromOverride;
|
||||
|
||||
@@ -64,6 +64,10 @@ public class SelectClause
|
||||
} else if (clause instanceof FieldDefinition) {
|
||||
_disMap.put(((FieldDefinition) clause).getField(), ((FieldDefinition) clause));
|
||||
|
||||
} else if (clause instanceof Distinct) {
|
||||
checkArgument(_orderBy == null, "Query can't contain multiple Distinct clauses.");
|
||||
_distinct = (Distinct) clause;
|
||||
|
||||
} else if (clause instanceof OrderBy) {
|
||||
checkArgument(_orderBy == null, "Query can't contain multiple OrderBy clauses.");
|
||||
_orderBy = (OrderBy) clause;
|
||||
@@ -128,6 +132,11 @@ public class SelectClause
|
||||
return _orderBy;
|
||||
}
|
||||
|
||||
public Distinct getDistinct ()
|
||||
{
|
||||
return _distinct;
|
||||
}
|
||||
|
||||
public GroupBy getGroupBy ()
|
||||
{
|
||||
return _groupBy;
|
||||
@@ -182,6 +191,9 @@ public class SelectClause
|
||||
if (_orderBy != null) {
|
||||
builder.append(", orderBy=").append(_orderBy);
|
||||
}
|
||||
if (_distinct != null) {
|
||||
builder.append(", distinct=").append(_distinct);
|
||||
}
|
||||
if (_groupBy != null) {
|
||||
builder.append(", groupBy=").append(_groupBy);
|
||||
}
|
||||
@@ -215,6 +227,9 @@ public class SelectClause
|
||||
/** The order by clause, if any. */
|
||||
protected OrderBy _orderBy;
|
||||
|
||||
/** The distinct clause, if any. */
|
||||
protected Distinct _distinct;
|
||||
|
||||
/** The group by clause, if any. */
|
||||
protected GroupBy _groupBy;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Set;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import com.samskivert.depot.clause.Distinct;
|
||||
import com.samskivert.util.ByteEnum;
|
||||
import com.samskivert.util.Tuple;
|
||||
|
||||
@@ -278,6 +279,17 @@ public abstract class BuildVisitor implements FragmentVisitor<Void>
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit (Distinct distinct)
|
||||
{
|
||||
_builder.append("distinct ");
|
||||
if (distinct.getDistinctOn() != null) {
|
||||
_builder.append("on ");
|
||||
distinct.getDistinctOn().accept(this);
|
||||
_builder.append(" ");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit (Join join)
|
||||
{
|
||||
switch (join.getType()) {
|
||||
@@ -345,6 +357,10 @@ public abstract class BuildVisitor implements FragmentVisitor<Void>
|
||||
checkArgument(!_definitions.containsKey(pClass),
|
||||
"Can not yet nest SELECTs on the same persistent record.");
|
||||
|
||||
if (selectClause.getDistinct() != null) {
|
||||
selectClause.getDistinct().accept(this);
|
||||
}
|
||||
|
||||
Map<String, FieldDefinition> definitionMap = Maps.newHashMap();
|
||||
for (FieldDefinition definition : selectClause.getFieldDefinitions()) {
|
||||
definitionMap.put(definition.getField(), definition);
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.lang.reflect.Field;
|
||||
import com.samskivert.depot.Key;
|
||||
import com.samskivert.depot.PersistentRecord;
|
||||
|
||||
import com.samskivert.depot.clause.Distinct;
|
||||
import com.samskivert.depot.clause.FieldDefinition;
|
||||
import com.samskivert.depot.clause.ForUpdate;
|
||||
import com.samskivert.depot.clause.FromOverride;
|
||||
@@ -252,6 +253,11 @@ public class ExpressionEvaluator
|
||||
throw new IllegalArgumentException("Can't evaluate expression: " + exists);
|
||||
}
|
||||
|
||||
public Object visit (Distinct distinct)
|
||||
{
|
||||
throw new IllegalArgumentException("Can't evaluate expression: " + distinct);
|
||||
}
|
||||
|
||||
public Object visit (GroupBy groupBy)
|
||||
{
|
||||
throw new IllegalArgumentException("Can't evaluate expression: " + groupBy);
|
||||
|
||||
@@ -6,6 +6,7 @@ package com.samskivert.depot.impl;
|
||||
|
||||
import com.samskivert.depot.Key;
|
||||
|
||||
import com.samskivert.depot.clause.Distinct;
|
||||
import com.samskivert.depot.clause.FieldDefinition;
|
||||
import com.samskivert.depot.clause.ForUpdate;
|
||||
import com.samskivert.depot.clause.FromOverride;
|
||||
@@ -81,6 +82,7 @@ public interface FragmentVisitor<T>
|
||||
public T visit (FullText.Rank match);
|
||||
public T visit (ColumnExp<?> columnExp);
|
||||
public T visit (Not not);
|
||||
public T visit (Distinct distinct);
|
||||
public T visit (GroupBy groupBy);
|
||||
public T visit (ForUpdate forUpdate);
|
||||
public T visit (OrderBy orderBy);
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.samskivert.depot.Ops;
|
||||
import com.samskivert.depot.PersistentRecord;
|
||||
import com.samskivert.depot.annotation.FullTextIndex;
|
||||
import com.samskivert.depot.annotation.GeneratedValue;
|
||||
import com.samskivert.depot.clause.Distinct;
|
||||
import com.samskivert.depot.clause.OrderBy;
|
||||
import com.samskivert.depot.expression.ColumnExp;
|
||||
import com.samskivert.depot.expression.SQLExpression;
|
||||
@@ -132,6 +133,14 @@ public class HSQLBuilder
|
||||
return super.visit(operator);
|
||||
}
|
||||
|
||||
public Void visit (Distinct distinct)
|
||||
{
|
||||
if (distinct.getDistinctOn() != null) {
|
||||
throw new IllegalArgumentException("MySQL does not support DISTINCT ON");
|
||||
}
|
||||
return super.visit(distinct);
|
||||
}
|
||||
|
||||
@Override public Void visit (DatePart exp) {
|
||||
|
||||
if (exp.getPart() == Part.EPOCH) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.samskivert.depot.clause.Distinct;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.samskivert.depot.PersistentRecord;
|
||||
@@ -69,6 +70,14 @@ public class MySQLBuilder
|
||||
return appendFunctionCall("truncate", exp.getArg());
|
||||
}
|
||||
|
||||
public Void visit (Distinct distinct)
|
||||
{
|
||||
if (distinct.getDistinctOn() != null) {
|
||||
throw new IllegalArgumentException("MySQL does not support DISTINCT ON");
|
||||
}
|
||||
return super.visit(distinct);
|
||||
}
|
||||
|
||||
@Override public Void visit (DatePart exp) {
|
||||
return appendFunctionCall(getDateFunction(exp.getPart()), exp.getArg());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user