From a15c83fc25e06bba36a4e21e873605fe82e0eb7a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 26 Sep 2012 22:38:44 +0200 Subject: [PATCH] [#1844] Add Table Table.join(TableLike, JoinType) to allow for dynamic joining --- .../org/jooq/test/_/testcases/JoinTests.java | 14 ++++ .../main/java/org/jooq/SelectJoinStep.java | 80 ++++++++++-------- .../java/org/jooq/SelectOptionalOnStep.java | 82 +++++++++++++++++++ jOOQ/src/main/java/org/jooq/Table.java | 82 +++++++++++-------- .../java/org/jooq/TableOptionalOnStep.java | 48 +++++++++++ .../java/org/jooq/impl/AbstractTable.java | 22 +++-- .../main/java/org/jooq/impl/JoinTable.java | 4 +- .../main/java/org/jooq/impl/SelectImpl.java | 60 ++++++++------ 8 files changed, 289 insertions(+), 103 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/SelectOptionalOnStep.java create mode 100644 jOOQ/src/main/java/org/jooq/TableOptionalOnStep.java diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/JoinTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/JoinTests.java index 1469303533..75d107ff0e 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/JoinTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/JoinTests.java @@ -55,6 +55,7 @@ import static org.jooq.impl.Factory.zero; import java.util.List; import org.jooq.Field; +import org.jooq.JoinType; import org.jooq.Record; import org.jooq.Result; import org.jooq.SQLDialect; @@ -277,6 +278,19 @@ extends BaseTest Refer to the manual for more details - * + * * @author Lukas Eder */ public interface SelectJoinStep extends SelectWhereStep { + /** + * Convenience method to join a table to the last table added to the + * FROM clause using {@link Table#join(TableLike, JoinType)} + *

+ * Depending on the JoinType, a subsequent + * {@link SelectOnStep#on(Condition...)} or + * {@link SelectOnStep#using(Field...)} clause is required. If it is + * required but omitted, the JOIN clause will be ignored + */ + @Support + SelectOptionalOnStep join(TableLike table, JoinType type); + /** * Convenience method to INNER JOIN a table to the last table * added to the FROM clause using {@link Table#join(TableLike)} - * + * * @see Table#join(TableLike) */ @Support @@ -112,7 +124,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#join(String) */ @@ -128,7 +140,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#join(String, Object...) */ @@ -144,7 +156,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#join(String, QueryPart...) */ @@ -162,7 +174,7 @@ public interface SelectJoinStep extends SelectWhereStep { * A cross join B * A join B on 1 = 1 * - * + * * @see Table#crossJoin(TableLike) */ @Support @@ -184,7 +196,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#crossJoin(String) */ @@ -207,7 +219,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#crossJoin(String, Object...) */ @@ -230,7 +242,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#crossJoin(String, QueryPart...) */ @@ -241,7 +253,7 @@ public interface SelectJoinStep extends SelectWhereStep { * Convenience method to LEFT OUTER JOIN a table to the last * table added to the FROM clause using * {@link Table#leftOuterJoin(TableLike)} - * + * * @see Table#leftOuterJoin(TableLike) */ @Support @@ -256,7 +268,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#leftOuterJoin(String) */ @@ -272,7 +284,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#leftOuterJoin(String, Object...) */ @@ -288,7 +300,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#leftOuterJoin(String, QueryPart...) */ @@ -301,7 +313,7 @@ public interface SelectJoinStep extends SelectWhereStep { * {@link Table#rightOuterJoin(TableLike)} *

* This is only possible where the underlying RDBMS supports it - * + * * @see Table#rightOuterJoin(TableLike) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -318,7 +330,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#rightOuterJoin(String) */ @@ -336,7 +348,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#rightOuterJoin(String, Object...) */ @@ -354,7 +366,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#rightOuterJoin(String, QueryPart...) */ @@ -367,7 +379,7 @@ public interface SelectJoinStep extends SelectWhereStep { * {@link Table#fullOuterJoin(TableLike)} *

* This is only possible where the underlying RDBMS supports it - * + * * @see Table#fullOuterJoin(TableLike) */ @Support({ DB2, FIREBIRD, HSQLDB, INGRES, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -384,7 +396,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#fullOuterJoin(String) */ @@ -402,7 +414,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#fullOuterJoin(String, Object...) */ @@ -420,7 +432,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#fullOuterJoin(String, QueryPart...) */ @@ -434,7 +446,7 @@ public interface SelectJoinStep extends SelectWhereStep { *

* Natural joins are supported by most RDBMS. If they aren't supported, they * are simulated if jOOQ has enough information. - * + * * @see Table#naturalJoin(TableLike) */ @Support @@ -452,7 +464,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#naturalJoin(String) */ @@ -471,7 +483,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#naturalJoin(String, Object...) */ @@ -490,7 +502,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#naturalJoin(String, QueryPart...) */ @@ -504,7 +516,7 @@ public interface SelectJoinStep extends SelectWhereStep { *

* Natural joins are supported by most RDBMS. If they aren't supported, they * are simulated if jOOQ has enough information. - * + * * @see Table#naturalLeftOuterJoin(TableLike) */ @Support @@ -522,7 +534,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#naturalLeftOuterJoin(String) */ @@ -541,7 +553,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#naturalLeftOuterJoin(String, Object...) */ @@ -560,7 +572,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#naturalLeftOuterJoin(String, QueryPart...) */ @@ -574,7 +586,7 @@ public interface SelectJoinStep extends SelectWhereStep { *

* Natural joins are supported by most RDBMS. If they aren't supported, they * are simulated if jOOQ has enough information. - * + * * @see Table#naturalRightOuterJoin(TableLike) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -592,7 +604,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) * @see Table#naturalRightOuterJoin(String) */ @@ -611,7 +623,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) * @see Table#naturalRightOuterJoin(String, Object...) */ @@ -630,7 +642,7 @@ public interface SelectJoinStep extends SelectWhereStep { * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) * @see Table#naturalRightOuterJoin(String, QueryPart...) */ diff --git a/jOOQ/src/main/java/org/jooq/SelectOptionalOnStep.java b/jOOQ/src/main/java/org/jooq/SelectOptionalOnStep.java new file mode 100644 index 0000000000..2edb132478 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/SelectOptionalOnStep.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +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 SelectOptionalOnStep extends SelectJoinStep, SelectJoinPartitionByStep { + +} diff --git a/jOOQ/src/main/java/org/jooq/Table.java b/jOOQ/src/main/java/org/jooq/Table.java index df605bd432..05cf243c17 100644 --- a/jOOQ/src/main/java/org/jooq/Table.java +++ b/jOOQ/src/main/java/org/jooq/Table.java @@ -57,7 +57,7 @@ import org.jooq.impl.Factory; /** * A table to be used in queries - * + * * @param The record type associated with this table * @author Lukas Eder */ @@ -78,7 +78,7 @@ public interface Table extends org.jooq.Type, AliasProvider /** * Create an alias for this table - * + * * @param alias The alias name * @return The table alias */ @@ -101,7 +101,7 @@ public interface Table extends org.jooq.Type, AliasProvider *

* Note: Unfortunately, this is not supported in the Oracle dialect, where * identities simulated by triggers cannot be formally detected. - * + * * @return The table's IDENTITY information, or * null, if no such information is available. */ @@ -109,7 +109,7 @@ public interface Table extends org.jooq.Type, AliasProvider /** * Get the list of FOREIGN KEY's of this table - * + * * @return This table's FOREIGN KEY's. This is never * null. */ @@ -118,7 +118,7 @@ public interface Table extends org.jooq.Type, AliasProvider /** * Get a list of FOREIGN KEY's of this table, referencing a * specific table. - * + * * @param The other table's record type * @param other The other table of the foreign key relationship * @return This table's FOREIGN KEY's towards an other table. @@ -137,7 +137,7 @@ public interface Table extends org.jooq.Type, AliasProvider *

  • Other dialects by using some means of simulation (not yet officially * supported)
  • * - * + * * @param aggregateFunctions The aggregate functions used for pivoting. * @return A DSL object to create the PIVOT expression */ @@ -149,7 +149,7 @@ public interface Table extends org.jooq.Type, AliasProvider * into another form *

    * For more details, see {@link #pivot(Field...)} - * + * * @param aggregateFunctions The aggregate functions used for pivoting. * @return A DSL object to create the PIVOT expression * @see #pivot(Field...) @@ -166,7 +166,7 @@ public interface Table extends org.jooq.Type, AliasProvider *

          * Assume the following cross join / cartesian product
          * C = A × B
    -     *
    +     * 
          * Then it can be said that
          * A = C ÷ B
          * B = C ÷ A
    @@ -199,10 +199,12 @@ public interface Table extends org.jooq.Type, AliasProvider
          * examples, see
          * 
          * 

    * This has been observed to work with all dialects @@ -210,6 +212,18 @@ public interface Table extends org.jooq.Type, AliasProvider @Support DivideByOnStep divideBy(Table divisor); + /** + * Join a table to this table using a {@link JoinType} + *

    + * Depending on the JoinType, a subsequent + * {@link TableOnStep#on(Condition...)} or + * {@link TableOnStep#using(Field...)} clause is required. If it is required + * but omitted, a {@link Factory#trueCondition()}, i.e. 1 = 1 + * condition will be rendered + */ + @Support + TableOptionalOnStep join(TableLike table, JoinType type); + /** * INNER JOIN a table to this table. */ @@ -223,7 +237,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support @@ -236,7 +250,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support @@ -249,7 +263,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support @@ -268,7 +282,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support @@ -281,7 +295,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support @@ -294,7 +308,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support @@ -317,7 +331,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -332,7 +346,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -347,7 +361,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -370,7 +384,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support({ DB2, FIREBIRD, HSQLDB, INGRES, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -385,7 +399,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support({ DB2, FIREBIRD, HSQLDB, INGRES, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -400,7 +414,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support({ DB2, FIREBIRD, HSQLDB, INGRES, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -433,7 +447,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support @@ -453,7 +467,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support @@ -473,7 +487,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support @@ -498,7 +512,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support @@ -514,7 +528,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support @@ -530,7 +544,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support @@ -555,7 +569,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support @@ -571,7 +585,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support @@ -587,7 +601,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support @@ -612,7 +626,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -628,7 +642,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, Object...) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) @@ -644,7 +658,7 @@ public interface Table extends org.jooq.Type, AliasProvider * guarantee syntax integrity. You may also create the possibility of * malicious SQL injection. Be sure to properly use bind variables and/or * escape literals when concatenated into SQL clauses! - * + * * @see Factory#table(String, QueryPart...) */ @Support({ ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, MYSQL, ORACLE, POSTGRES, SQLSERVER, SYBASE }) diff --git a/jOOQ/src/main/java/org/jooq/TableOptionalOnStep.java b/jOOQ/src/main/java/org/jooq/TableOptionalOnStep.java new file mode 100644 index 0000000000..05e80b30b4 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/TableOptionalOnStep.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq; + +/** + * An intermediate type for the construction of a JOIN clause, + * where there may optionally be a join criteria added using an ON + * clause (with a {@link Condition}), or using a USING clause (with + * a list of {@link Field}) + * + * @author Lukas Eder + */ +public interface TableOptionalOnStep extends TablePartitionByStep, Table { + +} diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java b/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java index 6c188a71b1..eafc5ac5b4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java @@ -56,6 +56,7 @@ import org.jooq.Table; import org.jooq.TableField; import org.jooq.TableLike; import org.jooq.TableOnStep; +import org.jooq.TableOptionalOnStep; import org.jooq.TablePartitionByStep; abstract class AbstractTable extends AbstractFieldProviderQueryPart implements Table { @@ -185,9 +186,14 @@ abstract class AbstractTable extends AbstractFieldProviderQuer // XXX: JOIN API // ------------------------------------------------------------------------ + @Override + public TableOptionalOnStep join(TableLike table, JoinType type) { + return new JoinTable(this, table, type); + } + @Override public final TableOnStep join(TableLike table) { - return new JoinTable(this, table, JoinType.JOIN); + return join(table, JoinType.JOIN); } @Override @@ -207,7 +213,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final TablePartitionByStep leftOuterJoin(TableLike table) { - return new JoinTable(this, table, JoinType.LEFT_OUTER_JOIN); + return join(table, JoinType.LEFT_OUTER_JOIN); } @Override @@ -227,7 +233,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final TablePartitionByStep rightOuterJoin(TableLike table) { - return new JoinTable(this, table, JoinType.RIGHT_OUTER_JOIN); + return join(table, JoinType.RIGHT_OUTER_JOIN); } @Override @@ -247,7 +253,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final TableOnStep fullOuterJoin(TableLike table) { - return new JoinTable(this, table, JoinType.FULL_OUTER_JOIN); + return join(table, JoinType.FULL_OUTER_JOIN); } @Override @@ -267,7 +273,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final Table crossJoin(TableLike table) { - return new JoinTable(this, table, JoinType.CROSS_JOIN); + return join(table, JoinType.CROSS_JOIN); } @Override @@ -287,7 +293,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final Table naturalJoin(TableLike table) { - return new JoinTable(this, table, JoinType.NATURAL_JOIN); + return join(table, JoinType.NATURAL_JOIN); } @Override @@ -307,7 +313,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final Table naturalLeftOuterJoin(TableLike table) { - return new JoinTable(this, table, JoinType.NATURAL_LEFT_OUTER_JOIN); + return join(table, JoinType.NATURAL_LEFT_OUTER_JOIN); } @Override @@ -327,7 +333,7 @@ abstract class AbstractTable extends AbstractFieldProviderQuer @Override public final Table naturalRightOuterJoin(TableLike table) { - return new JoinTable(this, table, JoinType.NATURAL_RIGHT_OUTER_JOIN); + return join(table, JoinType.NATURAL_RIGHT_OUTER_JOIN); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/JoinTable.java b/jOOQ/src/main/java/org/jooq/impl/JoinTable.java index 05f8818a44..dad357291f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JoinTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/JoinTable.java @@ -73,7 +73,7 @@ import org.jooq.TableField; import org.jooq.TableLike; import org.jooq.TableOnConditionStep; import org.jooq.TableOnStep; -import org.jooq.TablePartitionByStep; +import org.jooq.TableOptionalOnStep; import org.jooq.exception.DataAccessException; /** @@ -81,7 +81,7 @@ import org.jooq.exception.DataAccessException; * * @author Lukas Eder */ -class JoinTable extends AbstractTable implements TableOnConditionStep, TablePartitionByStep { +class JoinTable extends AbstractTable implements TableOptionalOnStep, TableOnConditionStep { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java index dac1fe2c65..e374f98bff 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java @@ -57,11 +57,11 @@ import org.jooq.SelectConditionStep; import org.jooq.SelectConnectByConditionStep; import org.jooq.SelectForUpdateOfStep; import org.jooq.SelectHavingConditionStep; -import org.jooq.SelectJoinPartitionByStep; import org.jooq.SelectJoinStep; import org.jooq.SelectOffsetStep; import org.jooq.SelectOnConditionStep; import org.jooq.SelectOnStep; +import org.jooq.SelectOptionalOnStep; import org.jooq.SelectQuery; import org.jooq.SelectSelectStep; import org.jooq.SortField; @@ -79,7 +79,7 @@ class SelectImpl extends AbstractDelegatingSelect implements // Cascading interface implementations for Select behaviour SelectSelectStep, - SelectJoinPartitionByStep, + SelectOptionalOnStep, SelectOnConditionStep, SelectConditionStep, SelectConnectByConditionStep, @@ -689,59 +689,69 @@ class SelectImpl extends AbstractDelegatingSelect implements @Override public final SelectImpl join(TableLike table) { - return join0(table, JoinType.JOIN); + return join(table, JoinType.JOIN); } @Override public final SelectImpl leftOuterJoin(TableLike table) { - return join0(table, JoinType.LEFT_OUTER_JOIN); + return join(table, JoinType.LEFT_OUTER_JOIN); } @Override public final SelectImpl rightOuterJoin(TableLike table) { - return join0(table, JoinType.RIGHT_OUTER_JOIN); + return join(table, JoinType.RIGHT_OUTER_JOIN); } @Override public final SelectOnStep fullOuterJoin(TableLike table) { - return join0(table, JoinType.FULL_OUTER_JOIN); + return join(table, JoinType.FULL_OUTER_JOIN); } - private final SelectImpl join0(TableLike table, JoinType type) { - conditionStep = ConditionStep.ON; - joinTable = table; - joinType = type; - joinPartitionBy = null; - joinConditions = null; - return this; + @Override + public final SelectImpl join(TableLike table, JoinType type) { + switch (type) { + case CROSS_JOIN: + case NATURAL_JOIN: + case NATURAL_LEFT_OUTER_JOIN: + case NATURAL_RIGHT_OUTER_JOIN: { + getQuery().addJoin(table, type); + joinTable = null; + joinPartitionBy = null; + joinType = null; + + return this; + } + + default: { + conditionStep = ConditionStep.ON; + joinTable = table; + joinType = type; + joinPartitionBy = null; + joinConditions = null; + + return this; + } + } } @Override public final SelectJoinStep crossJoin(TableLike table) { - return simpleJoin0(table, JoinType.CROSS_JOIN); + return join(table, JoinType.CROSS_JOIN); } @Override public final SelectImpl naturalJoin(TableLike table) { - return simpleJoin0(table, JoinType.NATURAL_JOIN); + return join(table, JoinType.NATURAL_JOIN); } @Override public final SelectImpl naturalLeftOuterJoin(TableLike table) { - return simpleJoin0(table, JoinType.NATURAL_LEFT_OUTER_JOIN); + return join(table, JoinType.NATURAL_LEFT_OUTER_JOIN); } @Override public final SelectImpl naturalRightOuterJoin(TableLike table) { - return simpleJoin0(table, JoinType.NATURAL_RIGHT_OUTER_JOIN); - } - - private final SelectImpl simpleJoin0(TableLike table, JoinType type) { - getQuery().addJoin(table, type); - joinTable = null; - joinPartitionBy = null; - joinType = null; - return this; + return join(table, JoinType.NATURAL_RIGHT_OUTER_JOIN); } @Override