Added OrderBy.Order.NULL.

"order by null" can be used in a query with a "group by" in it to tell
the database to suppress the overhead of sorting the results.
(Supported in postgres and mysql.)

Changed the build visitors to have a whitelist of supported
Orders, and to NPE on a null value for the Order enum.

Note that previously "order by null" could be accomplished by passing
a null value to your OrderBy, but now the enum constant must be used.
I can change that if this disrupts anything.
This commit is contained in:
Ray Greenwell
2011-12-06 19:26:53 +00:00
parent acbdfc4044
commit 9838e4922c
5 changed files with 50 additions and 10 deletions
@@ -20,6 +20,10 @@ public class OrderBy implements QueryClause
/** Indicates the order of the clause. */
public enum Order
{
/** Ordering by null can be used to suppress sorting in the database when using
* a GROUP BY in your query (postgres and mysql only). */
NULL,
/** Ascending (nulls last). */
ASC,
@@ -84,6 +84,7 @@ import com.samskivert.depot.impl.operator.MultiOperator;
import com.samskivert.depot.impl.operator.Not;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.samskivert.Log.log;
/**
@@ -979,17 +980,27 @@ public abstract class BuildVisitor implements FragmentVisitor<Void>
*/
protected OrderBy.Order validateOrder (OrderBy.Order order)
{
if ((order == OrderBy.Order.ASC_NULLS_FIRST) || (order == OrderBy.Order.DESC_NULLS_LAST)) {
if (false /*Boolean.getBoolean("com.samskivert.depot.massageOrderByNulls")*/) {
order = (order == OrderBy.Order.ASC_NULLS_FIRST)
? OrderBy.Order.ASC : OrderBy.Order.DESC;
} else {
throw new RuntimeException(order + " is not supported on your database.");
}
checkNotNull(order);
if (orderSupported(order)) {
return order;
}
return order;
// Note: the following code was never "live". If needed it can be made so.
// The property name is up for debate.
// if (Boolean.getBoolean("com.samskivert.depot.massageNullOrders")) {
// switch (order) {
// case ASC_NULLS_FIRST: return OrderBy.Order.ASC;
// case DESC_NULLS_LAST: return OrderBy.Order.DESC;
// }
// }
throw new IllegalArgumentException(
"Order '" + order.name() + "' is not supported by your database.");
}
/**
* Is the specified order supported by this database?
*/
protected abstract boolean orderSupported (OrderBy.Order order);
protected BuildVisitor (DepotTypes types, boolean allowComplexIndices)
{
_types = types;
@@ -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.OrderBy;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.impl.expression.AggregateFun;
@@ -183,6 +184,15 @@ public class HSQLBuilder
@Override protected void appendIdentifier (String field) {
_builder.append("\"").append(field).append("\"");
}
@Override protected boolean orderSupported (OrderBy.Order order)
{
switch (order) {
case ASC: case DESC:
return true;
}
return false;
}
}
public HSQLBuilder (DepotTypes types)
@@ -14,6 +14,7 @@ import com.samskivert.util.StringUtil;
import com.samskivert.depot.PersistentRecord;
import com.samskivert.depot.annotation.FullTextIndex;
import com.samskivert.depot.clause.OrderBy;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.operator.FullText;
@@ -162,6 +163,15 @@ public class MySQLBuilder
{
_builder.append("() values ()");
}
@Override protected boolean orderSupported (OrderBy.Order order)
{
switch (order) {
case NULL: case ASC: case DESC:
return true;
}
return false;
}
}
protected static String massageFTQuery (FullText fullText)
@@ -119,8 +119,13 @@ public class PostgreSQLBuilder
_builder.append("\"").append(field).append("\"");
}
@Override protected OrderBy.Order validateOrder (OrderBy.Order order) {
return order;
@Override protected boolean orderSupported (OrderBy.Order order)
{
switch (order) {
case NULL: case ASC: case DESC: case ASC_NULLS_FIRST: case DESC_NULLS_LAST:
return true;
}
return false;
}
protected PGBuildVisitor (DepotTypes types)