From 9ffabd11a695a71448374c761ee60cdb7b8250bc Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 22 May 2023 09:32:48 +0200 Subject: [PATCH] [jOOQ/jOOQ#15093] Add API support for ( UNION | INTERSECT | EXCEPT ) DISTINCT --- jOOQ/src/main/java/org/jooq/Select.java | 70 +++++++++++++++++++ .../main/java/org/jooq/SelectUnionStep.java | 58 +++++++++++++++ .../main/java/org/jooq/impl/SelectImpl.java | 15 ++++ .../java/org/jooq/impl/SelectQueryImpl.java | 15 ++++ 4 files changed, 158 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/Select.java b/jOOQ/src/main/java/org/jooq/Select.java index 7825b6cc54..4a2edecc26 100644 --- a/jOOQ/src/main/java/org/jooq/Select.java +++ b/jOOQ/src/main/java/org/jooq/Select.java @@ -110,6 +110,12 @@ extends /** * Apply the UNION set operation. + *

+ * In SQL, a UNION is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #unionDistinct(Select)}. If duplicate removal isn't required, + * or already guaranteed by the data model, it is recommended to use + * {@link #unionAll(Select)}, instead. * * @throws IllegalArgumentException If the argument select has the same * identity as this select. The jOOQ 3.x API is mutable, which @@ -121,6 +127,23 @@ extends @Support Select union(Select select); + /** + * Apply the UNION DISTINCT set operation. + *

+ * In SQL, a UNION is DISTINCT by default. + * However, it is often useful to make this explicit to express intent when + * distinct removal is really desired. + * + * @throws IllegalArgumentException If the argument select has the same + * identity as this select. The jOOQ 3.x API is mutable, which + * means that calls to the DSL API mutate this instance. Adding + * this instance as an set operation argument would lead to a + * {@link StackOverflowError} when generating the SQL. + */ + @NotNull @CheckReturnValue + @Support + Select unionDistinct(Select select); + /** * Apply the UNION ALL set operation. * @@ -136,6 +159,12 @@ extends /** * Apply the EXCEPT (or MINUS) set operation. + *

+ * In SQL, an EXCEPT is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #exceptDistinct(Select)}. If duplicate removal isn't required, + * or already guaranteed by the data model, it is recommended to use + * {@link #exceptAll(Select)}, instead, if the underlying RDBMS supports it. * * @throws IllegalArgumentException If the argument select has the same * identity as this select. The jOOQ 3.x API is mutable, which @@ -147,6 +176,23 @@ extends @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) Select except(Select select); + /** + * Apply the EXCEPT (or MINUS) set operation. + *

+ * In SQL, an EXCEPT is DISTINCT by default. + * However, it is often useful to make this explicit to express intent when + * distinct removal is really desired. + * + * @throws IllegalArgumentException If the argument select has the same + * identity as this select. The jOOQ 3.x API is mutable, which + * means that calls to the DSL API mutate this instance. Adding + * this instance as an set operation argument would lead to a + * {@link StackOverflowError} when generating the SQL. + */ + @NotNull @CheckReturnValue + @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) + Select exceptDistinct(Select select); + /** * Apply the EXCEPT ALL set operation. * @@ -162,6 +208,13 @@ extends /** * Apply the INTERSECT set operation. + *

+ * In SQL, an INTERSECT is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #intersectDistinct(Select)}. If duplicate removal isn't + * required, or already guaranteed by the data model, it is recommended to + * use {@link #intersectAll(Select)}, instead, if the underlying RDBMS + * supports it. Apply the INTERSECT set operation. * * @throws IllegalArgumentException If the argument select has the same * identity as this select. The jOOQ 3.x API is mutable, which @@ -173,6 +226,23 @@ extends @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) Select intersect(Select select); + /** + * Apply the INTERSECT set operation. + *

+ * In SQL, a INTERSECT is DISTINCT by default. + * However, it is often useful to make this explicit to express intent when + * distinct removal is really desired. + * + * @throws IllegalArgumentException If the argument select has the same + * identity as this select. The jOOQ 3.x API is mutable, which + * means that calls to the DSL API mutate this instance. Adding + * this instance as an set operation argument would lead to a + * {@link StackOverflowError} when generating the SQL. + */ + @NotNull @CheckReturnValue + @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) + Select intersectDistinct(Select select); + /** * Apply the INTERSECT ALL set operation. * diff --git a/jOOQ/src/main/java/org/jooq/SelectUnionStep.java b/jOOQ/src/main/java/org/jooq/SelectUnionStep.java index 837b6a244c..fabe44e9c5 100644 --- a/jOOQ/src/main/java/org/jooq/SelectUnionStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectUnionStep.java @@ -135,12 +135,30 @@ public interface SelectUnionStep extends SelectCorrelatedSubqu /** * Apply the UNION set operation. + *

+ * In SQL, a UNION is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #unionDistinct(Select)}. If duplicate removal isn't required, + * or already guaranteed by the data model, it is recommended to use + * {@link #unionAll(Select)}, instead. */ @Override @NotNull @CheckReturnValue @Support SelectOrderByStep union(Select select); + /** + * Apply the UNION DISTINCT set operation. + *

+ * In SQL, a UNION is DISTINCT by default. + * However, it is often useful to make this explicit to express intent when + * distinct removal is really desired. + */ + @Override + @NotNull @CheckReturnValue + @Support + SelectOrderByStep unionDistinct(Select select); + /** * Apply the UNION ALL set operation. */ @@ -151,12 +169,30 @@ public interface SelectUnionStep extends SelectCorrelatedSubqu /** * Apply the EXCEPT (or MINUS) set operation. + *

+ * In SQL, an EXCEPT is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #exceptDistinct(Select)}. If duplicate removal isn't required, + * or already guaranteed by the data model, it is recommended to use + * {@link #exceptAll(Select)}, instead, if the underlying RDBMS supports it. */ @Override @NotNull @CheckReturnValue @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) SelectOrderByStep except(Select select); + /** + * Apply the EXCEPT (or MINUS) set operation. + *

+ * In SQL, an EXCEPT is DISTINCT by default. + * However, it is often useful to make this explicit to express intent when + * distinct removal is really desired. + */ + @Override + @NotNull @CheckReturnValue + @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) + SelectOrderByStep exceptDistinct(Select select); + /** * Apply the EXCEPT ALL set operation. */ @@ -167,12 +203,34 @@ public interface SelectUnionStep extends SelectCorrelatedSubqu /** * Apply the INTERSECT set operation. + *

+ * In SQL, an INTERSECT is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #intersectDistinct(Select)}. If duplicate removal isn't + * required, or already guaranteed by the data model, it is recommended to + * use {@link #intersectAll(Select)}, instead, if the underlying RDBMS + * supports it. Apply the INTERSECT set operation. */ @Override @NotNull @CheckReturnValue @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) SelectOrderByStep intersect(Select select); + /** + * Apply the INTERSECT set operation. + *

+ * In SQL, an INTERSECT is DISTINCT by default, + * meaning, duplicates are removed from the result set. So, this is the same + * as {@link #intersectDistinct(Select)}. If duplicate removal isn't + * required, or already guaranteed by the data model, it is recommended to + * use {@link #intersectAll(Select)}, instead, if the underlying RDBMS + * supports it. Apply the INTERSECT set operation. + */ + @Override + @NotNull @CheckReturnValue + @Support({ CUBRID, DERBY, H2, HSQLDB, IGNITE, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB }) + SelectOrderByStep intersectDistinct(Select select); + /** * Apply the INTERSECT ALL set operation. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java index e1cf406556..6bfb7bdc7c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java @@ -1995,6 +1995,11 @@ implements return new SelectImpl(getDelegate().union(select)); } + @Override + public final SelectImpl unionDistinct(Select select) { + return new SelectImpl(getDelegate().unionDistinct(select)); + } + @Override public final SelectImpl unionAll(Select select) { return new SelectImpl(getDelegate().unionAll(select)); @@ -2005,6 +2010,11 @@ implements return new SelectImpl(getDelegate().except(select)); } + @Override + public final SelectImpl exceptDistinct(Select select) { + return new SelectImpl(getDelegate().exceptDistinct(select)); + } + @Override public final SelectImpl exceptAll(Select select) { return new SelectImpl(getDelegate().exceptAll(select)); @@ -2015,6 +2025,11 @@ implements return new SelectImpl(getDelegate().intersect(select)); } + @Override + public final SelectImpl intersectDistinct(Select select) { + return new SelectImpl(getDelegate().intersectDistinct(select)); + } + @Override public final SelectImpl intersectAll(Select select) { return new SelectImpl(getDelegate().intersectAll(select)); diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index 17a4698694..1859eacf45 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -4665,6 +4665,11 @@ final class SelectQueryImpl extends AbstractResultQuery imp return combine(UNION, other); } + @Override + public final SelectQueryImpl unionDistinct(Select other) { + return combine(UNION, other); + } + @Override public final SelectQueryImpl unionAll(Select other) { return combine(UNION_ALL, other); @@ -4675,6 +4680,11 @@ final class SelectQueryImpl extends AbstractResultQuery imp return combine(EXCEPT, other); } + @Override + public final SelectQueryImpl exceptDistinct(Select other) { + return combine(EXCEPT, other); + } + @Override public final SelectQueryImpl exceptAll(Select other) { return combine(EXCEPT_ALL, other); @@ -4685,6 +4695,11 @@ final class SelectQueryImpl extends AbstractResultQuery imp return combine(INTERSECT, other); } + @Override + public final SelectQueryImpl intersectDistinct(Select other) { + return combine(INTERSECT, other); + } + @Override public final SelectQueryImpl intersectAll(Select other) { return combine(INTERSECT_ALL, other);