diff --git a/jOOQ/src/main/java/org/jooq/SelectLimitAfterOffsetStep.java b/jOOQ/src/main/java/org/jooq/SelectLimitAfterOffsetStep.java index 57f5c8be64..afc98885f5 100644 --- a/jOOQ/src/main/java/org/jooq/SelectLimitAfterOffsetStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectLimitAfterOffsetStep.java @@ -106,7 +106,7 @@ public interface SelectLimitAfterOffsetStep extends SelectForU * function and nested SELECT statements. */ @Support - SelectWithTiesAfterOffsetStep limit(int numberOfRows); + SelectLimitPercentAfterOffsetStep limit(int numberOfRows); /** * Add a LIMIT clause to the query using named parameters @@ -121,6 +121,6 @@ public interface SelectLimitAfterOffsetStep extends SelectForU * statements. */ @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) - SelectWithTiesAfterOffsetStep limit(Param numberOfRows); + SelectLimitPercentAfterOffsetStep limit(Param numberOfRows); } diff --git a/jOOQ/src/main/java/org/jooq/SelectLimitPercentAfterOffsetStep.java b/jOOQ/src/main/java/org/jooq/SelectLimitPercentAfterOffsetStep.java new file mode 100644 index 0000000000..82f3022b2d --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/SelectLimitPercentAfterOffsetStep.java @@ -0,0 +1,96 @@ +/* + * 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. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +// ... +// ... + +/** + * This type is used for the {@link Select}'s DSL API when selecting generic + * {@link Record} types. + *

+ * Example:

+ * -- get all authors' first and last names, and the number
+ * -- of books they've written in German, if they have written
+ * -- more than five books in German in the last three years
+ * -- (from 2011), and sort those authors by last names
+ * -- limiting results to the second and third row
+ *
+ *   SELECT T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME, COUNT(*)
+ *     FROM T_AUTHOR
+ *     JOIN T_BOOK ON T_AUTHOR.ID = T_BOOK.AUTHOR_ID
+ *    WHERE T_BOOK.LANGUAGE = 'DE'
+ *      AND T_BOOK.PUBLISHED > '2008-01-01'
+ * GROUP BY T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME
+ *   HAVING COUNT(*) > 5
+ * ORDER BY T_AUTHOR.LAST_NAME ASC NULLS FIRST
+ *    LIMIT 2
+ *   OFFSET 1
+ *      FOR UPDATE
+ *       OF FIRST_NAME, LAST_NAME
+ *       NO WAIT
+ * 
Its equivalent in jOOQ
+ * create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
+ *       .from(T_AUTHOR)
+ *       .join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
+ *       .where(TBook.LANGUAGE.equal("DE"))
+ *       .and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
+ *       .groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
+ *       .having(create.count().greaterThan(5))
+ *       .orderBy(TAuthor.LAST_NAME.asc().nullsFirst())
+ *       .limit(2)
+ *       .offset(1)
+ *       .forUpdate()
+ *       .of(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
+ *       .noWait();
+ * 
Refer to the manual for more details + * + * @author Lukas Eder + */ +public interface SelectLimitPercentAfterOffsetStep extends SelectWithTiesAfterOffsetStep { + + + + + + + + + + +} diff --git a/jOOQ/src/main/java/org/jooq/SelectLimitPercentStep.java b/jOOQ/src/main/java/org/jooq/SelectLimitPercentStep.java new file mode 100644 index 0000000000..36799bb8ae --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/SelectLimitPercentStep.java @@ -0,0 +1,96 @@ +/* + * 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. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +// ... +// ... + +/** + * This type is used for the {@link Select}'s DSL API when selecting generic + * {@link Record} types. + *

+ * Example:

+ * -- get all authors' first and last names, and the number
+ * -- of books they've written in German, if they have written
+ * -- more than five books in German in the last three years
+ * -- (from 2011), and sort those authors by last names
+ * -- limiting results to the second and third row
+ *
+ *   SELECT T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME, COUNT(*)
+ *     FROM T_AUTHOR
+ *     JOIN T_BOOK ON T_AUTHOR.ID = T_BOOK.AUTHOR_ID
+ *    WHERE T_BOOK.LANGUAGE = 'DE'
+ *      AND T_BOOK.PUBLISHED > '2008-01-01'
+ * GROUP BY T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME
+ *   HAVING COUNT(*) > 5
+ * ORDER BY T_AUTHOR.LAST_NAME ASC NULLS FIRST
+ *    LIMIT 2
+ *   OFFSET 1
+ *      FOR UPDATE
+ *       OF FIRST_NAME, LAST_NAME
+ *       NO WAIT
+ * 
Its equivalent in jOOQ
+ * create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
+ *       .from(T_AUTHOR)
+ *       .join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
+ *       .where(TBook.LANGUAGE.equal("DE"))
+ *       .and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
+ *       .groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
+ *       .having(create.count().greaterThan(5))
+ *       .orderBy(TAuthor.LAST_NAME.asc().nullsFirst())
+ *       .limit(2)
+ *       .offset(1)
+ *       .forUpdate()
+ *       .of(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
+ *       .noWait();
+ * 
Refer to the manual for more details + * + * @author Lukas Eder + */ +public interface SelectLimitPercentStep extends SelectWithTiesStep { + + + + + + + + + + +} diff --git a/jOOQ/src/main/java/org/jooq/SelectLimitStep.java b/jOOQ/src/main/java/org/jooq/SelectLimitStep.java index 85fd0bff61..70898549e7 100644 --- a/jOOQ/src/main/java/org/jooq/SelectLimitStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectLimitStep.java @@ -110,7 +110,7 @@ public interface SelectLimitStep extends SelectForUpdateStep.limit(numberOfRows).offset(0) */ @Support - SelectWithTiesStep limit(int numberOfRows); + SelectLimitPercentStep limit(int numberOfRows); /** * Add a LIMIT clause to the query using named parameters @@ -128,7 +128,7 @@ public interface SelectLimitStep extends SelectForUpdateStep.limit(numberOfRows).offset(0) */ @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) - SelectWithTiesStep limit(Param numberOfRows); + SelectLimitPercentStep limit(Param numberOfRows); /** * Add a LIMIT clause to the query @@ -157,7 +157,7 @@ public interface SelectLimitStep extends SelectForUpdateStepSELECT statements. */ @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) - SelectWithTiesAfterOffsetStep limit(int offset, Param numberOfRows); + SelectLimitPercentAfterOffsetStep limit(int offset, Param numberOfRows); /** * Add a LIMIT clause to the query using named parameters @@ -172,7 +172,7 @@ public interface SelectLimitStep extends SelectForUpdateStepSELECT statements. */ @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) - SelectWithTiesAfterOffsetStep limit(Param offset, int numberOfRows); + SelectLimitPercentAfterOffsetStep limit(Param offset, int numberOfRows); /** * Add a LIMIT clause to the query using named parameters @@ -187,7 +187,7 @@ public interface SelectLimitStep extends SelectForUpdateStepSELECT statements. */ @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) - SelectWithTiesAfterOffsetStep limit(Param offset, Param numberOfRows); + SelectLimitPercentAfterOffsetStep limit(Param offset, Param numberOfRows); /** * Add an OFFSET clause to the query diff --git a/jOOQ/src/main/java/org/jooq/SelectQuery.java b/jOOQ/src/main/java/org/jooq/SelectQuery.java index 2c445c58e8..3f38bd82bb 100644 --- a/jOOQ/src/main/java/org/jooq/SelectQuery.java +++ b/jOOQ/src/main/java/org/jooq/SelectQuery.java @@ -53,6 +53,7 @@ import static org.jooq.SQLDialect.MARIADB; import static org.jooq.SQLDialect.MYSQL; import static org.jooq.SQLDialect.MYSQL_8_0; // ... +// ... import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.SQLDialect.POSTGRES_9_5; // ... @@ -708,6 +709,16 @@ public interface SelectQuery extends Select, ConditionProvi @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE }) void addLimit(Param offset, Param numberOfRows); + + + + + + + + + + /** * Add the WITH TIES clause to a LIMIT clause. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/Limit.java b/jOOQ/src/main/java/org/jooq/impl/Limit.java index 6a390867da..37bb16b969 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Limit.java +++ b/jOOQ/src/main/java/org/jooq/impl/Limit.java @@ -48,6 +48,7 @@ import static org.jooq.impl.Keywords.K_FETCH_NEXT; import static org.jooq.impl.Keywords.K_FIRST; import static org.jooq.impl.Keywords.K_LIMIT; import static org.jooq.impl.Keywords.K_OFFSET; +import static org.jooq.impl.Keywords.K_PERCENT; import static org.jooq.impl.Keywords.K_ROWS; import static org.jooq.impl.Keywords.K_ROWS_ONLY; import static org.jooq.impl.Keywords.K_ROWS_WITH_TIES; @@ -86,12 +87,15 @@ final class Limit extends AbstractQueryPart { private boolean rendersParams; private boolean withTies; - @Override - public final void accept(Context context) { - ParamType paramType = context.paramType(); - CastMode castMode = context.castMode(); - switch (context.dialect()) { + + + @Override + public final void accept(Context ctx) { + ParamType paramType = ctx.paramType(); + CastMode castMode = ctx.castMode(); + + switch (ctx.dialect()) { // True LIMIT / OFFSET support provided by the following dialects // ----------------------------------------------------------------- @@ -125,12 +129,12 @@ final class Limit extends AbstractQueryPart { // LIMIT [offset], [limit] supported by CUBRID // ------------------------------------------- case CUBRID: { - context.castMode(NEVER) - .formatSeparator() - .visit(K_LIMIT) - .sql(' ').visit(offsetOrZero) - .sql(", ").visit(numberOfRowsOrMax) - .castMode(castMode); + ctx.castMode(NEVER) + .formatSeparator() + .visit(K_LIMIT) + .sql(' ').visit(offsetOrZero) + .sql(", ").visit(numberOfRowsOrMax) + .castMode(castMode); break; } @@ -140,13 +144,13 @@ final class Limit extends AbstractQueryPart { case FIREBIRD: case FIREBIRD_2_5: case FIREBIRD_3_0: { - context.castMode(NEVER) - .formatSeparator() - .visit(K_ROWS) - .sql(' ').visit(getLowerRownum().add(inline(1, SQLDataType.INTEGER))) - .sql(' ').visit(K_TO) - .sql(' ').visit(getUpperRownum()) - .castMode(castMode); + ctx.castMode(NEVER) + .formatSeparator() + .visit(K_ROWS) + .sql(' ').visit(getLowerRownum().add(inline(1, SQLDataType.INTEGER))) + .sql(' ').visit(K_TO) + .sql(' ').visit(getUpperRownum()) + .castMode(castMode); break; } @@ -171,19 +175,25 @@ final class Limit extends AbstractQueryPart { case DERBY: { // Casts are not supported here... - context.castMode(NEVER) - .formatSeparator() - .visit(K_OFFSET) - .sql(' ').visit(offsetOrZero) - .sql(' ').visit(K_ROWS); + ctx.castMode(NEVER) + .formatSeparator() + .visit(K_OFFSET) + .sql(' ').visit(offsetOrZero) + .sql(' ').visit(K_ROWS); - if (!limitZero()) - context.sql(' ').visit(K_FETCH_NEXT) - .sql(' ').visit(numberOfRows) - .sql(' ').visit(withTies ? K_ROWS_WITH_TIES : K_ROWS_ONLY); + if (!limitZero()) { + ctx.sql(' ').visit(K_FETCH_NEXT) + .sql(' ').visit(numberOfRows); - context.castMode(castMode); + + + + + ctx.sql(' ').visit(withTies ? K_ROWS_WITH_TIES : K_ROWS_ONLY); + } + + ctx.castMode(castMode); break; } @@ -265,9 +275,6 @@ final class Limit extends AbstractQueryPart { - - - @@ -279,17 +286,17 @@ final class Limit extends AbstractQueryPart { case MYSQL_8_0: case MYSQL: case SQLITE: { - context.castMode(NEVER) + ctx.castMode(NEVER) .formatSeparator() .visit(K_LIMIT) .sql(' ').visit(numberOfRowsOrMax); if (!offsetZero()) - context.formatSeparator() + ctx.formatSeparator() .visit(K_OFFSET) .sql(' ').visit(offsetOrZero); - context.castMode(castMode); + ctx.castMode(castMode); break; } @@ -305,19 +312,19 @@ final class Limit extends AbstractQueryPart { // A default implementation is necessary for hashCode() and toString() default: { - context.castMode(NEVER); + ctx.castMode(NEVER); if (!limitZero()) - context.formatSeparator() + ctx.formatSeparator() .visit(K_LIMIT) .sql(' ').visit(numberOfRows); if (!offsetZero()) - context.formatSeparator() + ctx.formatSeparator() .visit(K_OFFSET) .sql(' ').visit(offsetOrZero); - context.castMode(castMode); + ctx.castMode(castMode); break; } } @@ -337,6 +344,9 @@ final class Limit extends AbstractQueryPart { + + + @Override public final Clause[] clauses(Context ctx) { return null; @@ -414,6 +424,18 @@ final class Limit extends AbstractQueryPart { this.rendersParams = true; } + + + + + + + + + + + + final void setWithTies(boolean withTies) { this.withTies = withTies; } diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java index 2919d7d3b9..17af85d389 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java @@ -94,6 +94,8 @@ import org.jooq.SelectHavingConditionStep; import org.jooq.SelectIntoStep; import org.jooq.SelectJoinStep; import org.jooq.SelectLimitAfterOffsetStep; +import org.jooq.SelectLimitPercentAfterOffsetStep; +import org.jooq.SelectLimitPercentStep; import org.jooq.SelectOnConditionStep; import org.jooq.SelectOnStep; import org.jooq.SelectOptionalOnStep; @@ -123,8 +125,6 @@ import org.jooq.SelectSeekStep8; import org.jooq.SelectSeekStep9; import org.jooq.SelectSeekStepN; import org.jooq.SelectSelectStep; -import org.jooq.SelectWithTiesAfterOffsetStep; -import org.jooq.SelectWithTiesStep; import org.jooq.Table; import org.jooq.TableField; import org.jooq.TableLike; @@ -175,9 +175,9 @@ final class SelectImpl, SelectSeekLimitStep, - SelectWithTiesStep, + SelectLimitPercentStep, SelectLimitAfterOffsetStep, - SelectWithTiesAfterOffsetStep, + SelectLimitPercentAfterOffsetStep, SelectForUpdateOfStep { /** @@ -1784,6 +1784,16 @@ final class SelectImpl extends AbstractResultQuery imp getLimit().setNumberOfRows(numberOfRows); } + + + + + + + + + @Override public final void setWithTies(boolean withTies) { getLimit().setWithTies(withTies);