From 2b746f75ee78f8a648495e5729a816b3be35bf73 Mon Sep 17 00:00:00 2001 From: Reuben D'Netto Date: Mon, 12 Feb 2018 11:40:26 +1100 Subject: [PATCH] Refactored AbstractSQLQuery subtypes to support generic return types, to facilitate subtyping. --- .../sql/mssql/AbstractSQLServerQuery.java | 54 ++++ .../querydsl/sql/mssql/SQLServerQuery.java | 31 +-- .../sql/mysql/AbstractMySQLQuery.java | 238 ++++++++++++++++++ .../com/querydsl/sql/mysql/MySQLQuery.java | 234 ++--------------- .../sql/oracle/AbstractOracleQuery.java | 113 +++++++++ .../com/querydsl/sql/oracle/OracleQuery.java | 91 +------ .../postgresql/AbstractPostgreSQLQuery.java | 98 ++++++++ .../sql/postgresql/PostgreSQLQuery.java | 80 +----- .../sql/teradata/AbstractTeradataQuery.java | 59 +++++ .../querydsl/sql/teradata/TeradataQuery.java | 16 +- 10 files changed, 622 insertions(+), 392 deletions(-) create mode 100644 querydsl-sql/src/main/java/com/querydsl/sql/mssql/AbstractSQLServerQuery.java create mode 100644 querydsl-sql/src/main/java/com/querydsl/sql/mysql/AbstractMySQLQuery.java create mode 100644 querydsl-sql/src/main/java/com/querydsl/sql/oracle/AbstractOracleQuery.java create mode 100644 querydsl-sql/src/main/java/com/querydsl/sql/postgresql/AbstractPostgreSQLQuery.java create mode 100644 querydsl-sql/src/main/java/com/querydsl/sql/teradata/AbstractTeradataQuery.java diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/mssql/AbstractSQLServerQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/mssql/AbstractSQLServerQuery.java new file mode 100644 index 000000000..622538b67 --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/mssql/AbstractSQLServerQuery.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) + * + * 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.querydsl.sql.mssql; + +import com.querydsl.core.JoinFlag; +import com.querydsl.core.QueryMetadata; +import com.querydsl.sql.AbstractSQLQuery; +import com.querydsl.sql.Configuration; + +import javax.inject.Provider; +import java.sql.Connection; + +/** + * {@code AbstractSQLServerQuery} provides SQL Server related extensions to SQLQuery + * + * @param result type + * @param the concrete subtype + * + * @author tiwe + */ +public abstract class AbstractSQLServerQuery> extends AbstractSQLQuery { + public AbstractSQLServerQuery(Connection conn, Configuration configuration, QueryMetadata metadata) { + super(conn, configuration, metadata); + } + + public AbstractSQLServerQuery(Provider connProvider, Configuration configuration, QueryMetadata metadata) { + super(connProvider, configuration, metadata); + } + + /** + * Set the table hints + * + * @param tableHints table hints + * @return the current object + */ + public C tableHints(SQLServerTableHints... tableHints) { + if (tableHints.length > 0) { + String hints = SQLServerGrammar.tableHints(tableHints); + addJoinFlag(hints, JoinFlag.Position.END); + } + return (C) this; + } +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/mssql/SQLServerQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/mssql/SQLServerQuery.java index d59a56373..f5bd107e6 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/mssql/SQLServerQuery.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/mssql/SQLServerQuery.java @@ -13,28 +13,27 @@ */ package com.querydsl.sql.mssql; -import java.sql.Connection; - -import javax.inject.Provider; - import com.querydsl.core.DefaultQueryMetadata; -import com.querydsl.core.JoinFlag; import com.querydsl.core.QueryMetadata; import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; -import com.querydsl.sql.AbstractSQLQuery; import com.querydsl.sql.Configuration; import com.querydsl.sql.SQLServerTemplates; import com.querydsl.sql.SQLTemplates; +import javax.inject.Provider; +import java.sql.Connection; + /** * {@code SQLServerQuery} provides SQL Server related extensions to SQLQuery * + * If you need to subtype this, use the base class instead. + * * @param result type * * @author tiwe */ -public class SQLServerQuery extends AbstractSQLQuery> { +public class SQLServerQuery extends AbstractSQLServerQuery> { public SQLServerQuery(Connection conn) { this(conn, SQLServerTemplates.DEFAULT, new DefaultQueryMetadata()); @@ -53,7 +52,7 @@ public class SQLServerQuery extends AbstractSQLQuery> { } public SQLServerQuery(Connection conn, Configuration configuration) { - super(conn, configuration); + super(conn, configuration, new DefaultQueryMetadata()); } public SQLServerQuery(Provider connProvider, Configuration configuration, QueryMetadata metadata) { @@ -61,21 +60,7 @@ public class SQLServerQuery extends AbstractSQLQuery> { } public SQLServerQuery(Provider connProvider, Configuration configuration) { - super(connProvider, configuration); - } - - /** - * Set the table hints - * - * @param tableHints table hints - * @return the current object - */ - public SQLServerQuery tableHints(SQLServerTableHints... tableHints) { - if (tableHints.length > 0) { - String hints = SQLServerGrammar.tableHints(tableHints); - addJoinFlag(hints, JoinFlag.Position.END); - } - return this; + super(connProvider, configuration, new DefaultQueryMetadata()); } @Override diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/mysql/AbstractMySQLQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/mysql/AbstractMySQLQuery.java new file mode 100644 index 000000000..cf7971ec7 --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/mysql/AbstractMySQLQuery.java @@ -0,0 +1,238 @@ +/* + * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) + * + * 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.querydsl.sql.mysql; + +import com.google.common.base.Joiner; +import com.querydsl.core.JoinFlag; +import com.querydsl.core.QueryFlag.Position; +import com.querydsl.core.QueryMetadata; +import com.querydsl.sql.AbstractSQLQuery; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.SQLQuery; + +import javax.inject.Provider; +import java.io.File; +import java.sql.Connection; + +/** + * {@code MySQLQuery} provides MySQL related extensions to SQLQuery. + * + * @author tiwe + * @see SQLQuery + * @param result type + * @param the concrete subtype + */ +public abstract class AbstractMySQLQuery> extends AbstractSQLQuery { + + protected static final String WITH_ROLLUP = "\nwith rollup "; + + protected static final String STRAIGHT_JOIN = "straight_join "; + + protected static final String SQL_SMALL_RESULT = "sql_small_result "; + + protected static final String SQL_NO_CACHE = "sql_no_cache "; + + protected static final String LOCK_IN_SHARE_MODE = "\nlock in share mode "; + + protected static final String HIGH_PRIORITY = "high_priority "; + + protected static final String SQL_CALC_FOUND_ROWS = "sql_calc_found_rows "; + + protected static final String SQL_CACHE = "sql_cache "; + + protected static final String SQL_BUFFER_RESULT = "sql_buffer_result "; + + protected static final String SQL_BIG_RESULT = "sql_big_result "; + + protected static final Joiner JOINER = Joiner.on(", "); + + public AbstractMySQLQuery(Connection conn, Configuration configuration, QueryMetadata metadata) { + super(conn, configuration, metadata); + } + + public AbstractMySQLQuery(Provider connProvider, Configuration configuration, QueryMetadata metadata) { + super(connProvider, configuration, metadata); + } + + /** + * For SQL_BIG_RESULT, MySQL directly uses disk-based temporary tables if needed, and prefers + * sorting to using a temporary table with a key on the GROUP BY elements. + * + * @return the current object + */ + public C bigResult() { + return addFlag(Position.AFTER_SELECT, SQL_BIG_RESULT); + } + + /** + * SQL_BUFFER_RESULT forces the result to be put into a temporary table. This helps MySQL free + * the table locks early and helps in cases where it takes a long time to send the result set + * to the client. This option can be used only for top-level SELECT statements, not for + * subqueries or following UNION. + * + * @return the current object + */ + public C bufferResult() { + return addFlag(Position.AFTER_SELECT, SQL_BUFFER_RESULT); + } + + /** + * SQL_CACHE tells MySQL to store the result in the query cache if it is cacheable and the value + * of the query_cache_type system variable is 2 or DEMAND. + * + * @return the current object + */ + public C cache() { + return addFlag(Position.AFTER_SELECT, SQL_CACHE); + } + + /** + * SQL_CALC_FOUND_ROWS tells MySQL to calculate how many rows there would be in the result set, + * disregarding any LIMIT clause. The number of rows can then be retrieved with SELECT FOUND_ROWS(). + * + * @return the current object + */ + public C calcFoundRows() { + return addFlag(Position.AFTER_SELECT, SQL_CALC_FOUND_ROWS); + } + + /** + * HIGH_PRIORITY gives the SELECT higher priority than a statement that updates a table. + * You should use this only for queries that are very fast and must be done at once. + * + * @return the current object + */ + public C highPriority() { + return addFlag(Position.AFTER_SELECT, HIGH_PRIORITY); + } + + /** + * SELECT ... INTO var_list selects column values and stores them into variables. + * + * @param var variable name + * @return the current object + */ + public C into(String var) { + return addFlag(Position.END, "\ninto " + var); + } + + /** + * SELECT ... INTO DUMPFILE writes a single row to a file without any formatting. + * + * @param file file to write to + * @return the current object + */ + public C intoDumpfile(File file) { + return addFlag(Position.END, "\ninto dumpfile '" + file.getPath() + "'"); + } + + /** + * SELECT ... INTO OUTFILE writes the selected rows to a file. Column and line terminators c + * an be specified to produce a specific output format. + * + * @param file file to write to + * @return the current object + */ + public C intoOutfile(File file) { + return addFlag(Position.END, "\ninto outfile '" + file.getPath() + "'"); + } + + /** + * Using LOCK IN SHARE MODE sets a shared lock that permits other transactions to read the examined + * rows but not to update or delete them. + * + * @return the current object + */ + public C lockInShareMode() { + return addFlag(Position.END, LOCK_IN_SHARE_MODE); + } + + /** + * With SQL_NO_CACHE, the server does not use the query cache. It neither checks the query cache + * to see whether the result is already cached, nor does it cache the query result. + * + * @return the current object + */ + public C noCache() { + return addFlag(Position.AFTER_SELECT, SQL_NO_CACHE); + } + + /** + * For SQL_SMALL_RESULT, MySQL uses fast temporary tables to store the resulting table instead + * of using sorting. This should not normally be needed. + * + * @return the current object + */ + public C smallResult() { + return addFlag(Position.AFTER_SELECT, SQL_SMALL_RESULT); + } + + /** + * STRAIGHT_JOIN forces the optimizer to join the tables in the order in which they are listed + * in the FROM clause. You can use this to speed up a query if the optimizer joins the tables + * in nonoptimal order. STRAIGHT_JOIN also can be used in the table_references list. + * + * @return the current object + */ + public C straightJoin() { + return addFlag(Position.AFTER_SELECT, STRAIGHT_JOIN); + } + + /** + * You can use FORCE INDEX, which acts like USE INDEX (index_list) but with the addition that a + * table scan is assumed to be very expensive. In other words, a table scan is used only if there + * is no way to use one of the given indexes to find rows in the table. + * + * @param indexes index names + * @return the current object + */ + public C forceIndex(String... indexes) { + return addJoinFlag(" force index (" + JOINER.join(indexes) + ")", JoinFlag.Position.END); + } + + /** + * The alternative syntax IGNORE INDEX (index_list) can be used to tell MySQL to not use some + * particular index or indexes. + * + * @param indexes index names + * @return the current object + */ + public C ignoreIndex(String... indexes) { + return addJoinFlag(" ignore index (" + JOINER.join(indexes) + ")", JoinFlag.Position.END); + } + + /** + * By specifying USE INDEX (index_list), you can tell MySQL to use only one of the named indexes + * to find rows in the table. + * + * @param indexes index names + * @return the current object + */ + public C useIndex(String... indexes) { + return addJoinFlag(" use index (" + JOINER.join(indexes) + ")", JoinFlag.Position.END); + } + + /** + * The GROUP BY clause permits a WITH ROLLUP modifier that causes extra rows to be added to the + * summary output. These rows represent higher-level (or super-aggregate) summary operations. + * ROLLUP thus enables you to answer questions at multiple levels of analysis with a single query. + * It can be used, for example, to provide support for OLAP (Online Analytical Processing) operations. + * + * @return the current object + */ + public C withRollup() { + return addFlag(Position.AFTER_GROUP_BY, WITH_ROLLUP); + } + +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/mysql/MySQLQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/mysql/MySQLQuery.java index b35153c0e..ed4c50dd0 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/mysql/MySQLQuery.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/mysql/MySQLQuery.java @@ -13,51 +13,25 @@ */ package com.querydsl.sql.mysql; -import java.io.File; -import java.sql.Connection; - -import javax.inject.Provider; - -import com.google.common.base.Joiner; import com.querydsl.core.DefaultQueryMetadata; -import com.querydsl.core.JoinFlag; -import com.querydsl.core.QueryFlag.Position; import com.querydsl.core.QueryMetadata; import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; -import com.querydsl.sql.*; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.MySQLTemplates; +import com.querydsl.sql.SQLTemplates; + +import javax.inject.Provider; +import java.sql.Connection; /** - * {@code MySQLQuery} provides MySQL related extensions to SQLQuery + * {@code MySQLQuery} provides MySQL related extensions to SQLQuery. * - * @author tiwe - * @see SQLQuery - * @param result type + * If you need to subtype this, use the base class instead. + * + * @param the result type */ -public class MySQLQuery extends AbstractSQLQuery> { - - private static final String WITH_ROLLUP = "\nwith rollup "; - - private static final String STRAIGHT_JOIN = "straight_join "; - - private static final String SQL_SMALL_RESULT = "sql_small_result "; - - private static final String SQL_NO_CACHE = "sql_no_cache "; - - private static final String LOCK_IN_SHARE_MODE = "\nlock in share mode "; - - private static final String HIGH_PRIORITY = "high_priority "; - - private static final String SQL_CALC_FOUND_ROWS = "sql_calc_found_rows "; - - private static final String SQL_CACHE = "sql_cache "; - - private static final String SQL_BUFFER_RESULT = "sql_buffer_result "; - - private static final String SQL_BIG_RESULT = "sql_big_result "; - - private static final Joiner JOINER = Joiner.on(", "); - +public class MySQLQuery extends AbstractMySQLQuery> { public MySQLQuery(Connection conn) { this(conn, new Configuration(MySQLTemplates.DEFAULT), new DefaultQueryMetadata()); } @@ -79,177 +53,7 @@ public class MySQLQuery extends AbstractSQLQuery> { } public MySQLQuery(Provider connProvider, Configuration configuration) { - super(connProvider, configuration); - } - - /** - * For SQL_BIG_RESULT, MySQL directly uses disk-based temporary tables if needed, and prefers - * sorting to using a temporary table with a key on the GROUP BY elements. - * - * @return the current object - */ - public MySQLQuery bigResult() { - return addFlag(Position.AFTER_SELECT, SQL_BIG_RESULT); - } - - /** - * SQL_BUFFER_RESULT forces the result to be put into a temporary table. This helps MySQL free - * the table locks early and helps in cases where it takes a long time to send the result set - * to the client. This option can be used only for top-level SELECT statements, not for - * subqueries or following UNION. - * - * @return the current object - */ - public MySQLQuery bufferResult() { - return addFlag(Position.AFTER_SELECT, SQL_BUFFER_RESULT); - } - - /** - * SQL_CACHE tells MySQL to store the result in the query cache if it is cacheable and the value - * of the query_cache_type system variable is 2 or DEMAND. - * - * @return the current object - */ - public MySQLQuery cache() { - return addFlag(Position.AFTER_SELECT, SQL_CACHE); - } - - /** - * SQL_CALC_FOUND_ROWS tells MySQL to calculate how many rows there would be in the result set, - * disregarding any LIMIT clause. The number of rows can then be retrieved with SELECT FOUND_ROWS(). - * - * @return the current object - */ - public MySQLQuery calcFoundRows() { - return addFlag(Position.AFTER_SELECT, SQL_CALC_FOUND_ROWS); - } - - /** - * HIGH_PRIORITY gives the SELECT higher priority than a statement that updates a table. - * You should use this only for queries that are very fast and must be done at once. - * - * @return the current object - */ - public MySQLQuery highPriority() { - return addFlag(Position.AFTER_SELECT, HIGH_PRIORITY); - } - - /** - * SELECT ... INTO var_list selects column values and stores them into variables. - * - * @param var variable name - * @return the current object - */ - public MySQLQuery into(String var) { - return addFlag(Position.END, "\ninto " + var); - } - - /** - * SELECT ... INTO DUMPFILE writes a single row to a file without any formatting. - * - * @param file file to write to - * @return the current object - */ - public MySQLQuery intoDumpfile(File file) { - return addFlag(Position.END, "\ninto dumpfile '" + file.getPath() + "'"); - } - - /** - * SELECT ... INTO OUTFILE writes the selected rows to a file. Column and line terminators c - * an be specified to produce a specific output format. - * - * @param file file to write to - * @return the current object - */ - public MySQLQuery intoOutfile(File file) { - return addFlag(Position.END, "\ninto outfile '" + file.getPath() + "'"); - } - - /** - * Using LOCK IN SHARE MODE sets a shared lock that permits other transactions to read the examined - * rows but not to update or delete them. - * - * @return the current object - */ - public MySQLQuery lockInShareMode() { - return addFlag(Position.END, LOCK_IN_SHARE_MODE); - } - - /** - * With SQL_NO_CACHE, the server does not use the query cache. It neither checks the query cache - * to see whether the result is already cached, nor does it cache the query result. - * - * @return the current object - */ - public MySQLQuery noCache() { - return addFlag(Position.AFTER_SELECT, SQL_NO_CACHE); - } - - /** - * For SQL_SMALL_RESULT, MySQL uses fast temporary tables to store the resulting table instead - * of using sorting. This should not normally be needed. - * - * @return the current object - */ - public MySQLQuery smallResult() { - return addFlag(Position.AFTER_SELECT, SQL_SMALL_RESULT); - } - - /** - * STRAIGHT_JOIN forces the optimizer to join the tables in the order in which they are listed - * in the FROM clause. You can use this to speed up a query if the optimizer joins the tables - * in nonoptimal order. STRAIGHT_JOIN also can be used in the table_references list. - * - * @return the current object - */ - public MySQLQuery straightJoin() { - return addFlag(Position.AFTER_SELECT, STRAIGHT_JOIN); - } - - /** - * You can use FORCE INDEX, which acts like USE INDEX (index_list) but with the addition that a - * table scan is assumed to be very expensive. In other words, a table scan is used only if there - * is no way to use one of the given indexes to find rows in the table. - * - * @param indexes index names - * @return the current object - */ - public MySQLQuery forceIndex(String... indexes) { - return addJoinFlag(" force index (" + JOINER.join(indexes) + ")", JoinFlag.Position.END); - } - - /** - * The alternative syntax IGNORE INDEX (index_list) can be used to tell MySQL to not use some - * particular index or indexes. - * - * @param indexes index names - * @return the current object - */ - public MySQLQuery ignoreIndex(String... indexes) { - return addJoinFlag(" ignore index (" + JOINER.join(indexes) + ")", JoinFlag.Position.END); - } - - /** - * By specifying USE INDEX (index_list), you can tell MySQL to use only one of the named indexes - * to find rows in the table. - * - * @param indexes index names - * @return the current object - */ - public MySQLQuery useIndex(String... indexes) { - return addJoinFlag(" use index (" + JOINER.join(indexes) + ")", JoinFlag.Position.END); - } - - /** - * The GROUP BY clause permits a WITH ROLLUP modifier that causes extra rows to be added to the - * summary output. These rows represent higher-level (or super-aggregate) summary operations. - * ROLLUP thus enables you to answer questions at multiple levels of analysis with a single query. - * It can be used, for example, to provide support for OLAP (Online Analytical Processing) operations. - * - * @return the current object - */ - public MySQLQuery withRollup() { - return addFlag(Position.AFTER_GROUP_BY, WITH_ROLLUP); + super(connProvider, configuration, new DefaultQueryMetadata()); } @Override @@ -262,17 +66,19 @@ public class MySQLQuery extends AbstractSQLQuery> { @Override public MySQLQuery select(Expression expr) { queryMixin.setProjection(expr); - @SuppressWarnings("unchecked") // This is the new type - MySQLQuery newType = (MySQLQuery) this; - return newType; + + @SuppressWarnings("unchecked") + MySQLQuery res = (MySQLQuery) this; + return res; } @Override public MySQLQuery select(Expression... exprs) { queryMixin.setProjection(exprs); - @SuppressWarnings("unchecked") // This is the new type - MySQLQuery newType = (MySQLQuery) this; - return newType; + + @SuppressWarnings("unchecked") + MySQLQuery res = (MySQLQuery) this; + return res; } } diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/oracle/AbstractOracleQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/oracle/AbstractOracleQuery.java new file mode 100644 index 000000000..712f8ec6b --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/oracle/AbstractOracleQuery.java @@ -0,0 +1,113 @@ +/* + * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) + * + * 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.querydsl.sql.oracle; + +import com.querydsl.core.QueryFlag.Position; +import com.querydsl.core.QueryMetadata; +import com.querydsl.core.types.Expression; +import com.querydsl.core.types.Predicate; +import com.querydsl.sql.AbstractSQLQuery; +import com.querydsl.sql.Configuration; + +import javax.inject.Provider; +import java.sql.Connection; + +/** + * {@code OracleQuery} provides Oracle specific extensions to the base SQL query type + * + * @author tiwe + * @param result type + * @param the concrete subtype + */ +public abstract class AbstractOracleQuery> extends AbstractSQLQuery { + + protected static final String CONNECT_BY = "\nconnect by "; + + protected static final String CONNECT_BY_NOCYCLE_PRIOR = "\nconnect by nocycle prior "; + + protected static final String CONNECT_BY_PRIOR = "\nconnect by prior "; + + protected static final String ORDER_SIBLINGS_BY = "\norder siblings by "; + + protected static final String START_WITH = "\nstart with "; + + public AbstractOracleQuery(Connection conn, Configuration configuration, QueryMetadata metadata) { + super(conn, configuration, metadata); + } + + public AbstractOracleQuery(Provider connProvider, Configuration configuration, QueryMetadata metadata) { + super(connProvider, configuration, metadata); + } + + /** + * CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. + * + * @param cond condition + * @return the current object + */ + public C connectByPrior(Predicate cond) { + return addFlag(Position.BEFORE_ORDER, CONNECT_BY_PRIOR, cond); + } + + /** + * CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. + * + * @param cond condition + * @return the current object + */ + public C connectBy(Predicate cond) { + return addFlag(Position.BEFORE_ORDER, CONNECT_BY, cond); + } + + /** + * CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. + * + * @param cond condition + * @return the current object + */ + public C connectByNocyclePrior(Predicate cond) { + return addFlag(Position.BEFORE_ORDER, CONNECT_BY_NOCYCLE_PRIOR, cond); + } + + /** + * START WITH specifies the root row(s) of the hierarchy. + * + * @param cond condition + * @return the current object + */ + public C startWith(Predicate cond) { + return addFlag(Position.BEFORE_ORDER, START_WITH, cond); + } + + /** + * ORDER SIBLINGS BY preserves any ordering specified in the hierarchical query clause and then + * applies the order_by_clause to the siblings of the hierarchy. + * + * @param path path + * @return the current object + */ + public C orderSiblingsBy(Expression path) { + return addFlag(Position.BEFORE_ORDER, ORDER_SIBLINGS_BY, path); + } + + // TODO : connect by root + + // TODO : connect by iscycle + + // TODO : connect by isleaf (pseudocolumn) + + // TODO : sys connect path +} + + diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/oracle/OracleQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/oracle/OracleQuery.java index 0e8424cbf..e42953871 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/oracle/OracleQuery.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/oracle/OracleQuery.java @@ -13,39 +13,26 @@ */ package com.querydsl.sql.oracle; -import java.sql.Connection; - -import javax.inject.Provider; - import com.querydsl.core.DefaultQueryMetadata; -import com.querydsl.core.QueryFlag.Position; import com.querydsl.core.QueryMetadata; import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; -import com.querydsl.core.types.Predicate; -import com.querydsl.sql.AbstractSQLQuery; import com.querydsl.sql.Configuration; import com.querydsl.sql.OracleTemplates; import com.querydsl.sql.SQLTemplates; +import javax.inject.Provider; +import java.sql.Connection; + /** * {@code OracleQuery} provides Oracle specific extensions to the base SQL query type * + * If you need to subtype this, use the base class instead. + * * @author tiwe * @param result type */ -public class OracleQuery extends AbstractSQLQuery> { - - private static final String CONNECT_BY = "\nconnect by "; - - private static final String CONNECT_BY_NOCYCLE_PRIOR = "\nconnect by nocycle prior "; - - private static final String CONNECT_BY_PRIOR = "\nconnect by prior "; - - private static final String ORDER_SIBLINGS_BY = "\norder siblings by "; - - private static final String START_WITH = "\nstart with "; - +public class OracleQuery extends AbstractOracleQuery> { public OracleQuery(Connection conn) { this(conn, OracleTemplates.DEFAULT, new DefaultQueryMetadata()); } @@ -71,59 +58,9 @@ public class OracleQuery extends AbstractSQLQuery> { } public OracleQuery(Provider connProvider, Configuration configuration) { - super(connProvider, configuration); + super(connProvider, configuration, new DefaultQueryMetadata()); } - /** - * CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. - * - * @param cond condition - * @return the current object - */ - public OracleQuery connectByPrior(Predicate cond) { - return addFlag(Position.BEFORE_ORDER, CONNECT_BY_PRIOR, cond); - } - - /** - * CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. - * - * @param cond condition - * @return the current object - */ - public OracleQuery connectBy(Predicate cond) { - return addFlag(Position.BEFORE_ORDER, CONNECT_BY, cond); - } - - /** - * CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy. - * - * @param cond condition - * @return the current object - */ - public OracleQuery connectByNocyclePrior(Predicate cond) { - return addFlag(Position.BEFORE_ORDER, CONNECT_BY_NOCYCLE_PRIOR, cond); - } - - /** - * START WITH specifies the root row(s) of the hierarchy. - * - * @param cond condition - * @return the current object - */ - public OracleQuery startWith(Predicate cond) { - return addFlag(Position.BEFORE_ORDER, START_WITH, cond); - } - - /** - * ORDER SIBLINGS BY preserves any ordering specified in the hierarchical query clause and then - * applies the order_by_clause to the siblings of the hierarchy. - * - * @param path path - * @return the current object - */ - public OracleQuery orderSiblingsBy(Expression path) { - return addFlag(Position.BEFORE_ORDER, ORDER_SIBLINGS_BY, path); - } @Override public OracleQuery clone(Connection conn) { @@ -132,19 +69,11 @@ public class OracleQuery extends AbstractSQLQuery> { return q; } - // TODO : connect by root - - // TODO : connect by iscycle - - // TODO : connect by isleaf (pseudocolumn) - - // TODO : sys connect path - @Override public OracleQuery select(Expression expr) { queryMixin.setProjection(expr); @SuppressWarnings("unchecked") // This is the new type - OracleQuery newType = (OracleQuery) this; + OracleQuery newType = (OracleQuery) this; return newType; } @@ -152,9 +81,7 @@ public class OracleQuery extends AbstractSQLQuery> { public OracleQuery select(Expression... exprs) { queryMixin.setProjection(exprs); @SuppressWarnings("unchecked") // This is the new type - OracleQuery newType = (OracleQuery) this; + OracleQuery newType = (OracleQuery) this; return newType; } } - - diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/AbstractPostgreSQLQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/AbstractPostgreSQLQuery.java new file mode 100644 index 000000000..bcafcf46b --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/AbstractPostgreSQLQuery.java @@ -0,0 +1,98 @@ +/* + * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) + * + * 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.querydsl.sql.postgresql; + +import com.querydsl.core.QueryFlag; +import com.querydsl.core.QueryFlag.Position; +import com.querydsl.core.QueryMetadata; +import com.querydsl.core.types.Expression; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.sql.AbstractSQLQuery; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.RelationalPath; +import com.querydsl.sql.SQLQuery; + +import javax.inject.Provider; +import java.sql.Connection; + +/** + * {@code PostgreSQLQuery} provides PostgreSQL related extensions to SQLQuery + * + * @param result type + * @param the concrete subtype + * + * @see SQLQuery + * @author tiwe + */ +public abstract class AbstractPostgreSQLQuery> extends AbstractSQLQuery { + public AbstractPostgreSQLQuery(Connection conn, Configuration configuration, QueryMetadata metadata) { + super(conn, configuration, metadata); + } + + public AbstractPostgreSQLQuery(Provider connProvider, Configuration configuration, QueryMetadata metadata) { + super(connProvider, configuration, metadata); + } + + /** + * FOR SHARE causes the rows retrieved by the SELECT statement to be locked as though for update. + * + * @return the current object + */ + public C forShare() { + // global forShare support was added later, delegating to super implementation + return super.forShare(); + } + + /** + * With NOWAIT, the statement reports an error, rather than waiting, if a selected row cannot + * be locked immediately. + * + * @return the current object + */ + public C noWait() { + QueryFlag noWaitFlag = configuration.getTemplates().getNoWaitFlag(); + return addFlag(noWaitFlag); + } + + /** + * FOR UPDATE / FOR SHARE OF tables + * + * @param paths tables + * @return the current object + */ + public C of(RelationalPath... paths) { + StringBuilder builder = new StringBuilder(" of "); + for (RelationalPath path : paths) { + if (builder.length() > 4) { + builder.append(", "); + } + builder.append(getConfiguration().getTemplates().quoteIdentifier(path.getTableName())); + } + return addFlag(Position.END, builder.toString()); + } + + /** + * adds a DISTINCT ON clause + * + * @param exprs + * @return + */ + public C distinctOn(Expression... exprs) { + return addFlag(Position.AFTER_SELECT, + Expressions.template(Object.class, "distinct on({0}) ", + ExpressionUtils.list(Object.class, exprs))); + } + +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/PostgreSQLQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/PostgreSQLQuery.java index e2bfafd1f..a12634532 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/PostgreSQLQuery.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/postgresql/PostgreSQLQuery.java @@ -13,29 +13,25 @@ */ package com.querydsl.sql.postgresql; -import java.sql.Connection; - -import javax.inject.Provider; - import com.querydsl.core.DefaultQueryMetadata; -import com.querydsl.core.QueryFlag; -import com.querydsl.core.QueryFlag.Position; import com.querydsl.core.QueryMetadata; import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; -import com.querydsl.core.types.ExpressionUtils; -import com.querydsl.core.types.dsl.Expressions; -import com.querydsl.sql.*; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.PostgreSQLTemplates; +import com.querydsl.sql.SQLTemplates; + +import javax.inject.Provider; +import java.sql.Connection; /** - * {@code PostgreSQLQuery} provides PostgreSQL related extensions to SQLQuery + * {@code PostgreSQLQuery} provides Postgres related extensions to SQLQuery. * - * @param result type + * If you need to subtype this, use the base class instead. * - * @see SQLQuery - * @author tiwe + * @param the result type */ -public class PostgreSQLQuery extends AbstractSQLQuery> { +public class PostgreSQLQuery extends AbstractPostgreSQLQuery> { public PostgreSQLQuery(Connection conn) { this(conn, new Configuration(PostgreSQLTemplates.DEFAULT), new DefaultQueryMetadata()); @@ -58,57 +54,7 @@ public class PostgreSQLQuery extends AbstractSQLQuery> } public PostgreSQLQuery(Provider connProvider, Configuration configuration) { - super(connProvider, configuration); - } - - /** - * FOR SHARE causes the rows retrieved by the SELECT statement to be locked as though for update. - * - * @return the current object - */ - public PostgreSQLQuery forShare() { - // global forShare support was added later, delegating to super implementation - return super.forShare(); - } - - /** - * With NOWAIT, the statement reports an error, rather than waiting, if a selected row cannot - * be locked immediately. - * - * @return the current object - */ - public PostgreSQLQuery noWait() { - QueryFlag noWaitFlag = configuration.getTemplates().getNoWaitFlag(); - return addFlag(noWaitFlag); - } - - /** - * FOR UPDATE / FOR SHARE OF tables - * - * @param paths tables - * @return the current object - */ - public PostgreSQLQuery of(RelationalPath... paths) { - StringBuilder builder = new StringBuilder(" of "); - for (RelationalPath path : paths) { - if (builder.length() > 4) { - builder.append(", "); - } - builder.append(getConfiguration().getTemplates().quoteIdentifier(path.getTableName())); - } - return addFlag(Position.END, builder.toString()); - } - - /** - * adds a DISTINCT ON clause - * - * @param exprs - * @return - */ - public PostgreSQLQuery distinctOn(Expression... exprs) { - return addFlag(Position.AFTER_SELECT, - Expressions.template(Object.class, "distinct on({0}) ", - ExpressionUtils.list(Object.class, exprs))); + super(connProvider, configuration, new DefaultQueryMetadata()); } @@ -123,7 +69,7 @@ public class PostgreSQLQuery extends AbstractSQLQuery> public PostgreSQLQuery select(Expression expr) { queryMixin.setProjection(expr); @SuppressWarnings("unchecked") // This is the new type - PostgreSQLQuery newType = (PostgreSQLQuery) this; + PostgreSQLQuery newType = (PostgreSQLQuery) this; return newType; } @@ -131,7 +77,7 @@ public class PostgreSQLQuery extends AbstractSQLQuery> public PostgreSQLQuery select(Expression... exprs) { queryMixin.setProjection(exprs); @SuppressWarnings("unchecked") // This is the new type - PostgreSQLQuery newType = (PostgreSQLQuery) this; + PostgreSQLQuery newType = (PostgreSQLQuery) this; return newType; } } diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/teradata/AbstractTeradataQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/teradata/AbstractTeradataQuery.java new file mode 100644 index 000000000..1480cf0bf --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/teradata/AbstractTeradataQuery.java @@ -0,0 +1,59 @@ +/* + * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) + * + * 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.querydsl.sql.teradata; + +import com.querydsl.core.DefaultQueryMetadata; +import com.querydsl.core.QueryMetadata; +import com.querydsl.sql.AbstractSQLQuery; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.SQLTemplates; +import com.querydsl.sql.TeradataTemplates; + +import javax.inject.Provider; +import java.sql.Connection; + +/** + * {@code AbstractTeradataQuery} provides Teradata related extensions to SQLQuery + * + * @param result type + * @param the concrete subtype. + * + * @author tiwe + */ +public abstract class AbstractTeradataQuery> extends AbstractSQLQuery { + public AbstractTeradataQuery(Connection conn) { + this(conn, new Configuration(TeradataTemplates.DEFAULT), new DefaultQueryMetadata()); + } + + public AbstractTeradataQuery(Connection conn, SQLTemplates templates) { + this(conn, new Configuration(templates), new DefaultQueryMetadata()); + } + + public AbstractTeradataQuery(Connection conn, Configuration configuration) { + this(conn, configuration, new DefaultQueryMetadata()); + } + + public AbstractTeradataQuery(Connection conn, Configuration configuration, QueryMetadata metadata) { + super(conn, configuration, metadata); + } + + public AbstractTeradataQuery(Provider connProvider, Configuration configuration, QueryMetadata metadata) { + super(connProvider, configuration, metadata); + } + + public AbstractTeradataQuery(Provider connProvider, Configuration configuration) { + super(connProvider, configuration); + } + +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/teradata/TeradataQuery.java b/querydsl-sql/src/main/java/com/querydsl/sql/teradata/TeradataQuery.java index 540571d50..f3439cf12 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/teradata/TeradataQuery.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/teradata/TeradataQuery.java @@ -13,10 +13,6 @@ */ package com.querydsl.sql.teradata; -import java.sql.Connection; - -import javax.inject.Provider; - import com.querydsl.core.DefaultQueryMetadata; import com.querydsl.core.QueryFlag; import com.querydsl.core.QueryMetadata; @@ -24,16 +20,24 @@ import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; import com.querydsl.core.types.ExpressionUtils; import com.querydsl.core.types.Predicate; -import com.querydsl.sql.*; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.SQLOps; +import com.querydsl.sql.SQLTemplates; +import com.querydsl.sql.TeradataTemplates; + +import javax.inject.Provider; +import java.sql.Connection; /** * {@code TeradataQuery} provides Teradata related extensions to SQLQuery * + * If you need to subtype this, use the base class instead. + * * @param result type * * @author tiwe */ -public class TeradataQuery extends AbstractSQLQuery> { +public class TeradataQuery extends AbstractTeradataQuery> { public TeradataQuery(Connection conn) { this(conn, new Configuration(TeradataTemplates.DEFAULT), new DefaultQueryMetadata());