mirror of
https://github.com/querydsl/querydsl.git
synced 2026-06-13 21:01:01 +08:00
#408 Add stubs for WindoFunctions
This commit is contained in:
parent
b4f1e9bb1a
commit
f2d6a9f3ed
@ -333,6 +333,113 @@ public final class SQLExpressions {
|
||||
return DateOperation.create((Class)date.getType(), Ops.DateTimeOps.ADD_DAYS, date, ConstantImpl.create(days));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Number> WindowOver<T> sum(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), Ops.AggOps.SUM_AGG, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static WindowOver<Long> count(Expression<?> expr) {
|
||||
return new WindowOver<Long>(Long.class, Ops.AggOps.COUNT_AGG, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Number> WindowOver<T> avg(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), Ops.AggOps.AVG_AGG, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Comparable> WindowOver<T> min(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), Ops.AggOps.MIN_AGG, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T extends Comparable> WindowOver<T> max(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), Ops.AggOps.MAX_AGG, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* expr evaluated at the row that is one row after the current row within the partition;
|
||||
*
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T> WindowOver<T> lead(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), SQLTemplates.LEAD, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* expr evaluated at the row that is one row before the current row within the partition
|
||||
*
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T> WindowOver<T> lag(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), SQLTemplates.LAG, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* rank of the current row with gaps; same as row_number of its first peer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static WindowOver<Long> rank() {
|
||||
return new WindowOver<Long>(Long.class, SQLTemplates.RANK);
|
||||
}
|
||||
|
||||
/**
|
||||
* rank of the current row without gaps; this function counts peer groups
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static WindowOver<Long> denseRank() {
|
||||
return new WindowOver<Long>(Long.class, SQLTemplates.DENSERANK);
|
||||
}
|
||||
|
||||
/**
|
||||
* number of the current row within its partition, counting from 1
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static WindowOver<Long> rowNumber() {
|
||||
return new WindowOver<Long>(Long.class, SQLTemplates.ROWNUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns value evaluated at the row that is the first row of the window frame
|
||||
*
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T> WindowOver<T> first(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), SQLTemplates.FIRST, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns value evaluated at the row that is the last row of the window frame
|
||||
*
|
||||
* @param expr
|
||||
* @return
|
||||
*/
|
||||
public static <T> WindowOver<T> last(Expression<T> expr) {
|
||||
return new WindowOver<T>((Class<T>)expr.getType(), SQLTemplates.LAST, expr);
|
||||
}
|
||||
|
||||
private SQLExpressions() {}
|
||||
|
||||
}
|
||||
|
||||
@ -46,6 +46,20 @@ public class SQLTemplates extends Templates {
|
||||
|
||||
public static final Operator<Object> NEXTVAL = new OperatorImpl<Object>("SQL_NEXTVAL");
|
||||
|
||||
public static final Operator<Long> ROWNUMBER = new OperatorImpl<Long>("ROWNUMBER");
|
||||
|
||||
public static final Operator<Long> RANK = new OperatorImpl<Long>("RANK");
|
||||
|
||||
public static final Operator<Long> DENSERANK = new OperatorImpl<Long>("DENSERANK");
|
||||
|
||||
public static final Operator<Object> FIRST = new OperatorImpl<Object>("FIRST");
|
||||
|
||||
public static final Operator<Object> LAST = new OperatorImpl<Object>("LAST");
|
||||
|
||||
public static final Operator<Object> LEAD = new OperatorImpl<Object>("LAST");
|
||||
|
||||
public static final Operator<Object> LAG = new OperatorImpl<Object>("LAST");
|
||||
|
||||
public static final SQLTemplates DEFAULT = new SQLTemplates("\"",'\\',false);
|
||||
|
||||
public static abstract class Builder {
|
||||
@ -260,6 +274,14 @@ public class SQLTemplates extends Templates {
|
||||
add(UNION_ALL, "{0}\nunion all\n{1}", 1);
|
||||
add(NEXTVAL, "nextval('{0s}')");
|
||||
|
||||
add(ROWNUMBER, "row_number()");
|
||||
add(RANK, "rank()");
|
||||
add(DENSERANK, "dense_rank()");
|
||||
add(FIRST, "first({0})");
|
||||
add(LAST, "last({0})");
|
||||
add(LEAD, "lead({0})");
|
||||
add(LAG, "lag({0})");
|
||||
|
||||
add(Ops.AggOps.BOOLEAN_ANY, "some({0})");
|
||||
add(Ops.AggOps.BOOLEAN_ALL, "every({0})");
|
||||
|
||||
|
||||
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mysema.query.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.MutableExpressionBase;
|
||||
import com.mysema.query.types.Visitor;
|
||||
import com.mysema.query.types.expr.SimpleExpression;
|
||||
import com.mysema.query.types.template.SimpleTemplate;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*/
|
||||
public class WindowFunction<A> extends MutableExpressionBase<A> {
|
||||
|
||||
private static final long serialVersionUID = -4130672293308756779L;
|
||||
|
||||
// TODO : change this to List<OrderSpecifier<?>>
|
||||
private List<Expression<?>> orderBy = new ArrayList<Expression<?>>();
|
||||
|
||||
@Nullable
|
||||
private Expression<?> partitionBy;
|
||||
|
||||
private final Expression<A> target;
|
||||
|
||||
private volatile SimpleExpression<A> value;
|
||||
|
||||
public WindowFunction(Expression<A> expr) {
|
||||
super(expr.getType());
|
||||
this.target = expr;
|
||||
}
|
||||
|
||||
public SimpleExpression<A> getValue() {
|
||||
if (value == null) {
|
||||
List<Expression<?>> args = new ArrayList<Expression<?>>();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("{0} over (");
|
||||
args.add(target);
|
||||
if (partitionBy != null) {
|
||||
builder.append("partition by {1}");
|
||||
args.add(partitionBy);
|
||||
}
|
||||
if (!orderBy.isEmpty()) {
|
||||
if (partitionBy != null) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append("order by ");
|
||||
boolean first = true;
|
||||
for (Expression<?> expr : orderBy) {
|
||||
if (!first) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append("{" + args.size()+"}");
|
||||
args.add(expr);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
builder.append(")");
|
||||
value = SimpleTemplate.<A>create(
|
||||
(Class<A>)target.getType(),
|
||||
builder.toString(),
|
||||
args.toArray(new Expression[args.size()]));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R,C> R accept(Visitor<R,C> v, C context) {
|
||||
return getValue().accept(v, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
} else if (o instanceof WindowFunction) {
|
||||
WindowFunction<?> so = (WindowFunction<?>)o;
|
||||
return so.target.equals(target)
|
||||
&& so.partitionBy.equals(partitionBy)
|
||||
&& so.orderBy.equals(orderBy);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public WindowFunction<A> orderBy(Expression<?>... orderBy) {
|
||||
value = null;
|
||||
this.orderBy.addAll(Arrays.asList(orderBy));
|
||||
return this;
|
||||
}
|
||||
|
||||
public WindowFunction<A> partition(Expression<?> partitionBy) {
|
||||
value = null;
|
||||
this.partitionBy = partitionBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mysema.query.sql;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.Operator;
|
||||
import com.mysema.query.types.expr.SimpleOperation;
|
||||
|
||||
/**
|
||||
* WindowOver is the first part of a WindowFunction construction
|
||||
*
|
||||
* @author tiwe
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class WindowOver<T> extends SimpleOperation<T> {
|
||||
|
||||
private static final long serialVersionUID = 464583892898579544L;
|
||||
|
||||
public WindowOver(Class<T> type, Operator<? super T> op) {
|
||||
super(type, op, ImmutableList.<Expression<?>>of());
|
||||
}
|
||||
|
||||
public WindowOver(Class<T> type, Operator<? super T> op, Expression<?> arg) {
|
||||
super(type, op, ImmutableList.<Expression<?>>of(arg));
|
||||
}
|
||||
|
||||
public WindowFunction<T> over() {
|
||||
return new WindowFunction<T>(this);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.mysema.query.sql;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mysema.query.support.Expressions;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.path.NumberPath;
|
||||
|
||||
public class WindowFunctionTest {
|
||||
|
||||
private static String toString(Expression<?> e) {
|
||||
return new SQLSerializer(SQLTemplates.DEFAULT).handle(e).toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Complex() {
|
||||
NumberPath<Long> path = Expressions.numberPath(Long.class, "path");
|
||||
NumberPath<Long> path2 = Expressions.numberPath(Long.class, "path2");
|
||||
Expression<?> wf = SQLExpressions.sum(path).over().partition(path2).orderBy(path);
|
||||
assertEquals("sum(path) over (partition by path2 order by path)", toString(wf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void All() {
|
||||
NumberPath<Long> path = Expressions.numberPath(Long.class, "path");
|
||||
assertEquals("sum(path)", toString(SQLExpressions.sum(path)));
|
||||
assertEquals("count(path)", toString(SQLExpressions.count(path)));
|
||||
assertEquals("avg(path)", toString(SQLExpressions.avg(path)));
|
||||
assertEquals("min(path)", toString(SQLExpressions.min(path)));
|
||||
assertEquals("max(path)", toString(SQLExpressions.max(path)));
|
||||
assertEquals("lead(path)", toString(SQLExpressions.lead(path)));
|
||||
assertEquals("lag(path)", toString(SQLExpressions.lag(path)));
|
||||
assertEquals("rank()", toString(SQLExpressions.rank()));
|
||||
assertEquals("dense_rank()", toString(SQLExpressions.denseRank()));
|
||||
assertEquals("row_number()", toString(SQLExpressions.rowNumber()));
|
||||
assertEquals("first(path)", toString(SQLExpressions.first(path)));
|
||||
assertEquals("last(path)", toString(SQLExpressions.last(path)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user