[#7646] Support for window functions GROUPS mode

This commit is contained in:
lukaseder 2018-07-06 14:18:02 +02:00
parent 85686ef330
commit d62518fa25
6 changed files with 443 additions and 43 deletions

View File

@ -44,6 +44,7 @@ import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL_8_0;
// ...
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.POSTGRES_11;
// ...
// ...
// ...
@ -206,4 +207,73 @@ public interface WindowRowsStep<T> extends WindowFinalStep<T> {
*/
@Support({ MARIADB, MYSQL_8_0, POSTGRES })
WindowRowsAndStep<T> rangeBetweenFollowing(int number);
/**
* Add a <code>GROUPS UNBOUNDED PRECEDING</code> frame clause to the window
* function.
*/
@Support({ POSTGRES_11 })
WindowFinalStep<T> groupsUnboundedPreceding();
/**
* Add a <code>GROUPS [number] PRECEDING</code> frame clause to the window
* function.
*/
@Support({ POSTGRES_11 })
WindowFinalStep<T> groupsPreceding(int number);
/**
* Add a <code>GROUPS CURRENT ROW</code> frame clause to the window function.
*/
@Support({ POSTGRES_11 })
WindowFinalStep<T> groupsCurrentRow();
/**
* Add a <code>GROUPS UNBOUNDED FOLLOWING</code> frame clause to the window
* function.
*/
@Support({ POSTGRES_11 })
WindowFinalStep<T> groupsUnboundedFollowing();
/**
* Add a <code>GROUPS [number] FOLLOWING</code> frame clause to the window
* function.
*/
@Support({ POSTGRES_11 })
WindowFinalStep<T> groupsFollowing(int number);
/**
* Add a <code>GROUPS BETWEEN UNBOUNDED PRECEDING ...</code> frame clause to
* the window function.
*/
@Support({ POSTGRES_11 })
WindowRowsAndStep<T> groupsBetweenUnboundedPreceding();
/**
* Add a <code>GROUPS BETWEEN [number] PRECEDING ...</code> frame clause to
* the window function.
*/
@Support({ POSTGRES_11 })
WindowRowsAndStep<T> groupsBetweenPreceding(int number);
/**
* Add a <code>GROUPS BETWEEN CURRENT ROW ...</code> frame clause to
* the window function.
*/
@Support({ POSTGRES_11 })
WindowRowsAndStep<T> groupsBetweenCurrentRow();
/**
* Add a <code>GROUPS BETWEEN UNBOUNDED FOLLOWING ...</code> frame clause to
* the window function.
*/
@Support({ POSTGRES_11 })
WindowRowsAndStep<T> groupsBetweenUnboundedFollowing();
/**
* Add a <code>GROUPS BETWEEN [number] FOLLOWING ...</code> frame clause to
* the window function.
*/
@Support({ POSTGRES_11 })
WindowRowsAndStep<T> groupsBetweenFollowing(int number);
}

View File

@ -44,6 +44,7 @@ import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL_8_0;
// ...
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.POSTGRES_11;
// ...
// ...
// ...
@ -223,4 +224,74 @@ public interface WindowSpecificationRowsStep extends WindowSpecificationFinalSte
*/
@Support({ MARIADB, MYSQL_8_0, POSTGRES })
WindowSpecificationRowsAndStep rangeBetweenFollowing(int number);
/**
* Add a <code>GROUPS UNBOUNDED PRECEDING</code> frame clause to the window
* specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationFinalStep groupsUnboundedPreceding();
/**
* Add a <code>GROUPS [number] PRECEDING</code> frame clause to the window
* specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationFinalStep groupsPreceding(int number);
/**
* Add a <code>GROUPS CURRENT ROW</code> frame clause to the window
* specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationFinalStep groupsCurrentRow();
/**
* Add a <code>GROUPS UNBOUNDED FOLLOWING</code> frame clause to the window
* specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationFinalStep groupsUnboundedFollowing();
/**
* Add a <code>GROUPS [number] FOLLOWING</code> frame clause to the window
* specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationFinalStep groupsFollowing(int number);
/**
* Add a <code>GROUPS BETWEEN UNBOUNDED PRECEDING ...</code> frame clause to
* the window specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationRowsAndStep groupsBetweenUnboundedPreceding();
/**
* Add a <code>GROUPS BETWEEN [number] PRECEDING ...</code> frame clause to
* the window specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationRowsAndStep groupsBetweenPreceding(int number);
/**
* Add a <code>GROUPS BETWEEN CURRENT ROW ...</code> frame clause to the
* window specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationRowsAndStep groupsBetweenCurrentRow();
/**
* Add a <code>GROUPS BETWEEN UNBOUNDED FOLLOWING ...</code> frame clause to
* the window specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationRowsAndStep groupsBetweenUnboundedFollowing();
/**
* Add a <code>GROUPS BETWEEN [number] FOLLOWING ...</code> frame clause to
* the window specification.
*/
@Support({ POSTGRES_11 })
WindowSpecificationRowsAndStep groupsBetweenFollowing(int number);
}

View File

@ -62,6 +62,7 @@ import static org.jooq.SQLDialect.MYSQL_8_0;
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.POSTGRES_11;
import static org.jooq.SQLDialect.POSTGRES_9_3;
import static org.jooq.SQLDialect.POSTGRES_9_4;
import static org.jooq.SQLDialect.POSTGRES_9_5;
@ -17715,6 +17716,86 @@ public class DSL {
return new WindowSpecificationImpl().rangeBetweenFollowing(number);
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationFinalStep groupsUnboundedPreceding() {
return new WindowSpecificationImpl().groupsUnboundedPreceding();
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationFinalStep groupsPreceding(int number) {
return new WindowSpecificationImpl().groupsPreceding(number);
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationFinalStep groupsCurrentRow() {
return new WindowSpecificationImpl().groupsCurrentRow();
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationFinalStep groupsUnboundedFollowing() {
return new WindowSpecificationImpl().groupsUnboundedFollowing();
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationFinalStep groupsFollowing(int number) {
return new WindowSpecificationImpl().groupsFollowing(number);
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationRowsAndStep groupsBetweenUnboundedPreceding() {
return new WindowSpecificationImpl().groupsBetweenUnboundedPreceding();
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationRowsAndStep groupsBetweenPreceding(int number) {
return new WindowSpecificationImpl().groupsBetweenPreceding(number);
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationRowsAndStep groupsBetweenCurrentRow() {
return new WindowSpecificationImpl().groupsBetweenCurrentRow();
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationRowsAndStep groupsBetweenUnboundedFollowing() {
return new WindowSpecificationImpl().groupsBetweenUnboundedFollowing();
}
/**
* Create a {@link WindowSpecification} with a <code>GROUPS</code> clause.
*/
@Support({ POSTGRES_11 })
public static WindowSpecificationRowsAndStep groupsBetweenFollowing(int number) {
return new WindowSpecificationImpl().groupsBetweenFollowing(number);
}
// -------------------------------------------------------------------------
// XXX Window functions
// -------------------------------------------------------------------------

View File

@ -822,6 +822,66 @@ class Function<T> extends AbstractField<T> implements
return this;
}
@Override
public final WindowFinalStep<T> groupsUnboundedPreceding() {
windowSpecification.groupsUnboundedPreceding();
return this;
}
@Override
public final WindowFinalStep<T> groupsPreceding(int number) {
windowSpecification.groupsPreceding(number);
return this;
}
@Override
public final WindowFinalStep<T> groupsCurrentRow() {
windowSpecification.groupsCurrentRow();
return this;
}
@Override
public final WindowFinalStep<T> groupsUnboundedFollowing() {
windowSpecification.groupsUnboundedFollowing();
return this;
}
@Override
public final WindowFinalStep<T> groupsFollowing(int number) {
windowSpecification.groupsFollowing(number);
return this;
}
@Override
public final WindowRowsAndStep<T> groupsBetweenUnboundedPreceding() {
windowSpecification.groupsBetweenUnboundedPreceding();
return this;
}
@Override
public final WindowRowsAndStep<T> groupsBetweenPreceding(int number) {
windowSpecification.groupsBetweenPreceding(number);
return this;
}
@Override
public final WindowRowsAndStep<T> groupsBetweenCurrentRow() {
windowSpecification.groupsBetweenCurrentRow();
return this;
}
@Override
public final WindowRowsAndStep<T> groupsBetweenUnboundedFollowing() {
windowSpecification.groupsBetweenUnboundedFollowing();
return this;
}
@Override
public final WindowRowsAndStep<T> groupsBetweenFollowing(int number) {
windowSpecification.groupsBetweenFollowing(number);
return this;
}
@Override
public final WindowFinalStep<T> andUnboundedPreceding() {
windowSpecification.andUnboundedPreceding();

View File

@ -104,6 +104,16 @@ import static org.jooq.impl.DSL.greatest;
import static org.jooq.impl.DSL.grouping;
import static org.jooq.impl.DSL.groupingId;
import static org.jooq.impl.DSL.groupingSets;
import static org.jooq.impl.DSL.groupsBetweenCurrentRow;
import static org.jooq.impl.DSL.groupsBetweenFollowing;
import static org.jooq.impl.DSL.groupsBetweenPreceding;
import static org.jooq.impl.DSL.groupsBetweenUnboundedFollowing;
import static org.jooq.impl.DSL.groupsBetweenUnboundedPreceding;
import static org.jooq.impl.DSL.groupsCurrentRow;
import static org.jooq.impl.DSL.groupsFollowing;
import static org.jooq.impl.DSL.groupsPreceding;
import static org.jooq.impl.DSL.groupsUnboundedFollowing;
import static org.jooq.impl.DSL.groupsUnboundedPreceding;
import static org.jooq.impl.DSL.hour;
import static org.jooq.impl.DSL.ifnull;
import static org.jooq.impl.DSL.iif;
@ -1272,58 +1282,79 @@ final class ParserImpl implements Parser {
boolean rows = parseKeywordIf(ctx, "ROWS");
boolean range = !rows && parseKeywordIf(ctx, "RANGE");
boolean groups = !rows && !range && parseKeywordIf(ctx, "GROUPS");
if ((rows || range) &&!orderByAllowed)
if ((rows || range || groups) && !orderByAllowed)
throw ctx.exception("ROWS or RANGE not allowed");
if (rows || range) {
if (rows || range || groups) {
Long n;
if (parseKeywordIf(ctx, "BETWEEN")) {
if (parseKeywordIf(ctx, "UNBOUNDED"))
if (parseKeywordIf(ctx, "PRECEDING"))
s3 = s2 == null
? rows
? rows
? rowsBetweenUnboundedPreceding()
: rangeBetweenUnboundedPreceding()
: rows
: range
? rangeBetweenUnboundedPreceding()
: groupsBetweenUnboundedPreceding()
: rows
? s2.rowsBetweenUnboundedPreceding()
: s2.rangeBetweenUnboundedPreceding();
: range
? s2.rangeBetweenUnboundedPreceding()
: s2.groupsBetweenUnboundedPreceding();
else if (parseKeywordIf(ctx, "FOLLOWING"))
s3 = s2 == null
? rows
? rows
? rowsBetweenUnboundedFollowing()
: rangeBetweenUnboundedFollowing()
: rows
: range
? rangeBetweenUnboundedFollowing()
: groupsBetweenUnboundedFollowing()
: rows
? s2.rowsBetweenUnboundedFollowing()
: s2.rangeBetweenUnboundedFollowing();
: range
? s2.rangeBetweenUnboundedFollowing()
: s2.groupsBetweenUnboundedFollowing();
else
throw ctx.expected("FOLLOWING", "PRECEDING");
else if (parseKeywordIf(ctx, "CURRENT ROW"))
s3 = s2 == null
? rows
? rows
? rowsBetweenCurrentRow()
: rangeBetweenCurrentRow()
: rows
: range
? rangeBetweenCurrentRow()
: groupsBetweenCurrentRow()
: rows
? s2.rowsBetweenCurrentRow()
: s2.rangeBetweenCurrentRow();
: range
? s2.rangeBetweenCurrentRow()
: s2.groupsBetweenCurrentRow();
else if ((n = parseUnsignedIntegerIf(ctx)) != null)
if (parseKeywordIf(ctx, "PRECEDING"))
s3 = s2 == null
? rows
? rows
? rowsBetweenPreceding(n.intValue())
: rangeBetweenPreceding(n.intValue())
: rows
: range
? rangeBetweenPreceding(n.intValue())
: groupsBetweenPreceding(n.intValue())
: rows
? s2.rowsBetweenPreceding(n.intValue())
: s2.rangeBetweenPreceding(n.intValue());
: range
? s2.rangeBetweenPreceding(n.intValue())
: s2.groupsBetweenPreceding(n.intValue());
else if (parseKeywordIf(ctx, "FOLLOWING"))
s3 = s2 == null
? rows
? rows
? rowsBetweenFollowing(n.intValue())
: rangeBetweenFollowing(n.intValue())
: rows
: range
? rangeBetweenFollowing(n.intValue())
: groupsBetweenFollowing(n.intValue())
: rows
? s2.rowsBetweenFollowing(n.intValue())
: s2.rangeBetweenFollowing(n.intValue());
: range
? s2.rangeBetweenFollowing(n.intValue())
: s2.groupsBetweenFollowing(n.intValue());
else
throw ctx.expected("FOLLOWING", "PRECEDING");
else
@ -1353,47 +1384,67 @@ final class ParserImpl implements Parser {
else if (parseKeywordIf(ctx, "UNBOUNDED"))
if (parseKeywordIf(ctx, "PRECEDING"))
return s2 == null
? rows
? rows
? rowsUnboundedPreceding()
: rangeUnboundedPreceding()
: rows
: range
? rangeUnboundedPreceding()
: groupsUnboundedPreceding()
: rows
? s2.rowsUnboundedPreceding()
: s2.rangeUnboundedPreceding();
: range
? s2.rangeUnboundedPreceding()
: s2.groupsUnboundedPreceding();
else if (parseKeywordIf(ctx, "FOLLOWING"))
return s2 == null
? rows
? rows
? rowsUnboundedFollowing()
: rangeUnboundedFollowing()
: rows
: range
? rangeUnboundedFollowing()
: groupsUnboundedFollowing()
: rows
? s2.rowsUnboundedFollowing()
: s2.rangeUnboundedFollowing();
: range
? s2.rangeUnboundedFollowing()
: s2.groupsUnboundedFollowing();
else
throw ctx.expected("FOLLOWING", "PRECEDING");
else if (parseKeywordIf(ctx, "CURRENT ROW"))
return s2 == null
? rows
? rows
? rowsCurrentRow()
: rangeCurrentRow()
: rows
: range
? rangeCurrentRow()
: groupsCurrentRow()
: rows
? s2.rowsCurrentRow()
: s2.rangeCurrentRow();
: range
? s2.rangeCurrentRow()
: s2.groupsCurrentRow();
else if ((n = parseUnsignedInteger(ctx)) != null)
if (parseKeywordIf(ctx, "PRECEDING"))
return s2 == null
? rows
? rows
? rowsPreceding(n.intValue())
: rangePreceding(n.intValue())
: rows
: range
? rangePreceding(n.intValue())
: groupsPreceding(n.intValue())
: rows
? s2.rowsPreceding(n.intValue())
: s2.rangePreceding(n.intValue());
: range
? s2.rangePreceding(n.intValue())
: s2.groupsPreceding(n.intValue());
else if (parseKeywordIf(ctx, "FOLLOWING"))
return s2 == null
? rows
? rows
? rowsFollowing(n.intValue())
: rangeFollowing(n.intValue())
: rows
: range
? rangeFollowing(n.intValue())
: groupsFollowing(n.intValue())
: rows
? s2.rowsFollowing(n.intValue())
: s2.rangeFollowing(n.intValue());
: range
? s2.rangeFollowing(n.intValue())
: s2.groupsFollowing(n.intValue());
else
throw ctx.expected("FOLLOWING", "PRECEDING");
else

View File

@ -52,6 +52,7 @@ import static org.jooq.impl.Keywords.K_PARTITION_BY;
import static org.jooq.impl.Keywords.K_PRECEDING;
import static org.jooq.impl.Keywords.K_UNBOUNDED_FOLLOWING;
import static org.jooq.impl.Keywords.K_UNBOUNDED_PRECEDING;
import static org.jooq.impl.WindowSpecificationImpl.FrameUnits.GROUPS;
import static org.jooq.impl.WindowSpecificationImpl.FrameUnits.RANGE;
import static org.jooq.impl.WindowSpecificationImpl.FrameUnits.ROWS;
@ -324,6 +325,71 @@ final class WindowSpecificationImpl extends AbstractQueryPart implements
return this;
}
@Override
public final WindowSpecificationFinalStep groupsUnboundedPreceding() {
frameUnits = GROUPS;
frameStart = Integer.MIN_VALUE;
return this;
}
@Override
public final WindowSpecificationFinalStep groupsPreceding(int number) {
frameUnits = GROUPS;
frameStart = -number;
return this;
}
@Override
public final WindowSpecificationFinalStep groupsCurrentRow() {
frameUnits = GROUPS;
frameStart = 0;
return this;
}
@Override
public final WindowSpecificationFinalStep groupsUnboundedFollowing() {
frameUnits = GROUPS;
frameStart = Integer.MAX_VALUE;
return this;
}
@Override
public final WindowSpecificationFinalStep groupsFollowing(int number) {
frameUnits = GROUPS;
frameStart = number;
return this;
}
@Override
public final WindowSpecificationRowsAndStep groupsBetweenUnboundedPreceding() {
groupsUnboundedPreceding();
return this;
}
@Override
public final WindowSpecificationRowsAndStep groupsBetweenPreceding(int number) {
groupsPreceding(number);
return this;
}
@Override
public final WindowSpecificationRowsAndStep groupsBetweenCurrentRow() {
groupsCurrentRow();
return this;
}
@Override
public final WindowSpecificationRowsAndStep groupsBetweenUnboundedFollowing() {
groupsUnboundedFollowing();
return this;
}
@Override
public final WindowSpecificationRowsAndStep groupsBetweenFollowing(int number) {
groupsFollowing(number);
return this;
}
@Override
public final WindowSpecificationFinalStep andUnboundedPreceding() {
frameEnd = Integer.MIN_VALUE;
@ -356,7 +422,8 @@ final class WindowSpecificationImpl extends AbstractQueryPart implements
enum FrameUnits {
ROWS("rows"),
RANGE("range");
RANGE("range"),
GROUPS("groups");
private final Keyword keyword;