[#2728] Add support for Amazon Redshift

This commit is contained in:
lukaseder 2015-05-04 18:33:04 +02:00
parent 531cff0060
commit c3d7b8fe70
16 changed files with 137 additions and 83 deletions

View File

@ -40,6 +40,25 @@
*/
package org.jooq;
// ...
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.SQLDialect.H2;
// ...
import static org.jooq.SQLDialect.HSQLDB;
// ...
// ...
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
/**
* A {@link Query} that can create indexes.
*
@ -50,12 +69,12 @@ public interface CreateIndexStep {
/**
* Specify the table and column expressions on which to create an index.
*/
@Support
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateIndexFinalStep on(Table<?> table, Field<?>... fields);
/**
* Specify the table and column expressions on which to create an index.
*/
@Support
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateIndexFinalStep on(String tableName, String... fieldNames);
}

View File

@ -4943,7 +4943,7 @@ public interface DSLContext extends Scope {
*
* @see DSL#createIndex(String)
*/
@Support
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateIndexStep createIndex(String index);
/**
@ -4951,7 +4951,7 @@ public interface DSLContext extends Scope {
*
* @see DSL#createIndex(Name)
*/
@Support
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
CreateIndexStep createIndex(Name index);
/**
@ -5145,7 +5145,7 @@ public interface DSLContext extends Scope {
*
* @see DSL#dropIndex(String)
*/
@Support
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DropIndexOnStep dropIndex(String index);
/**
@ -5153,7 +5153,7 @@ public interface DSLContext extends Scope {
*
* @see DSL#dropIndex(Name)
*/
@Support
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DropIndexOnStep dropIndex(Name index);
/**

View File

@ -254,7 +254,7 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
if (!many) {
if (ctx.resultSet() != null) {
Field<?>[] fields = getFields(ctx.resultSet().getMetaData());
cursor = new CursorImpl<R>(ctx, listener, fields, intern.internIndexes(fields), keepStatement(), keepResultSet(), getRecordType());
cursor = new CursorImpl<R>(ctx, listener, fields, intern.internIndexes(fields), keepStatement(), keepResultSet(), getRecordType(), maxRows);
if (!lazy) {
result = cursor.fetch();

View File

@ -59,6 +59,7 @@ import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -125,12 +126,9 @@ class BetweenCondition<T> extends AbstractCondition implements BetweenAndStep<T>
private final QueryPartInternal delegate(Configuration configuration) {
if (symmetric && asList(CUBRID, DERBY, FIREBIRD, H2, MARIADB, MYSQL, SQLITE).contains(configuration.dialect().family())) {
if (not) {
return (QueryPartInternal) field.notBetween(minValue, maxValue).and(field.notBetween(maxValue, minValue));
}
else {
return (QueryPartInternal) field.between(minValue, maxValue).or(field.between(maxValue, minValue));
}
return not
? (QueryPartInternal) field.notBetween(minValue, maxValue).and(field.notBetween(maxValue, minValue))
: (QueryPartInternal) field.between(minValue, maxValue).or(field.between(maxValue, minValue));
}
else {
return new Native();

View File

@ -99,6 +99,7 @@ class CursorImpl<R extends Record> implements Cursor<R> {
private final boolean[] intern;
private final boolean keepResultSet;
private final boolean keepStatement;
private final int maxRows;
private final RecordFactory<? extends R> factory;
private boolean isClosed;
@ -107,12 +108,13 @@ class CursorImpl<R extends Record> implements Cursor<R> {
private transient Iterator<R> iterator;
private transient int rows;
@SuppressWarnings("unchecked")
CursorImpl(ExecuteContext ctx, ExecuteListener listener, Field<?>[] fields, int[] internIndexes, boolean keepStatement, boolean keepResultSet) {
this(ctx, listener, fields, internIndexes, keepStatement, keepResultSet, (Class<? extends R>) RecordImpl.class);
this(ctx, listener, fields, internIndexes, keepStatement, keepResultSet, (Class<? extends R>) RecordImpl.class, 0);
}
CursorImpl(ExecuteContext ctx, ExecuteListener listener, Field<?>[] fields, int[] internIndexes, boolean keepStatement, boolean keepResultSet, Class<? extends R> type) {
CursorImpl(ExecuteContext ctx, ExecuteListener listener, Field<?>[] fields, int[] internIndexes, boolean keepStatement, boolean keepResultSet, Class<? extends R> type, int maxRows) {
this.ctx = ctx;
this.listener = (listener != null ? listener : new ExecuteListeners(ctx));
this.cursorFields = fields;
@ -122,6 +124,7 @@ class CursorImpl<R extends Record> implements Cursor<R> {
this.rs = new CursorResultSet();
this.rsContext = new DefaultBindingGetResultSetContext<Object>(ctx.configuration(), ctx.data(), rs, 0);
this.intern = new boolean[fields.length];
this.maxRows = maxRows;
if (internIndexes != null) {
for (int i : internIndexes) {
@ -1361,7 +1364,7 @@ class CursorImpl<R extends Record> implements Cursor<R> {
/**
* The (potentially) pre-fetched next record
*/
private R next;
private R next;
/**
* Whether the underlying {@link ResultSet} has a next record. This
@ -1372,11 +1375,16 @@ class CursorImpl<R extends Record> implements Cursor<R> {
* <li>false: there aren't any next records</li>
* </ul>
*/
private Boolean hasNext;
private Boolean hasNext;
@Override
public final boolean hasNext() {
if (hasNext == null) {
// Some databases (e.g. Redshift) do not implement JDBC's maxRows.
if (maxRows > 0 && rows >= maxRows)
return false;
next = fetchOne();
hasNext = (next != null);
}

View File

@ -62,6 +62,7 @@ import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.POSTGRES_9_3;
import static org.jooq.SQLDialect.POSTGRES_9_4;
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...

View File

@ -42,6 +42,7 @@ package org.jooq.impl;
import static java.util.Arrays.asList;
import static org.jooq.SQLDialect.POSTGRES;
// ...
import static org.jooq.SQLDialect.SQLITE;
import java.util.Map;

View File

@ -42,6 +42,7 @@ package org.jooq.impl;
import static java.util.Arrays.asList;
import static org.jooq.Comparator.IS_DISTINCT_FROM;
import static org.jooq.Comparator.IS_NOT_DISTINCT_FROM;
// ...
// ...
import static org.jooq.SQLDialect.CUBRID;
@ -53,6 +54,7 @@ import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -149,38 +151,43 @@ class IsDistinctFrom<T> extends AbstractCondition {
// MySQL knows the <=> operator
else if (asList(MARIADB, MYSQL).contains(configuration.family())) {
if (mySQLCondition == null) {
if (comparator == IS_DISTINCT_FROM) {
mySQLCondition = (QueryPartInternal) condition("{not}({0} <=> {1})", lhs, rhs);
}
else {
mySQLCondition = (QueryPartInternal) condition("{0} <=> {1}", lhs, rhs);
}
}
if (mySQLCondition == null)
mySQLCondition = (QueryPartInternal) ((comparator == IS_DISTINCT_FROM)
? condition("{not}({0} <=> {1})", lhs, rhs)
: condition("{0} <=> {1}", lhs, rhs));
return mySQLCondition;
}
// SQLite knows the IS / IS NOT predicate
else if (SQLITE == configuration.family()) {
if (sqliteCondition == null) {
if (comparator == IS_DISTINCT_FROM) {
sqliteCondition = (QueryPartInternal) condition("{0} {is not} {1}", lhs, rhs);
}
else {
sqliteCondition = (QueryPartInternal) condition("{0} {is} {1}", lhs, rhs);
}
}
if (sqliteCondition == null)
sqliteCondition = (QueryPartInternal) ((comparator == IS_DISTINCT_FROM)
? condition("{0} {is not} {1}", lhs, rhs)
: condition("{0} {is} {1}", lhs, rhs));
return sqliteCondition;
}
/* [pro] xx
xx xxxxxxxx xxxxx xx xxxxxxxx xxxx xxx xxxxxxx xxxx xx xxx xxxxxxxx xxxx
xxxx xx xxxxxxxxx xx xxxxxxxxxxxxxxxxxxxxxxx x
xx xxxxxxxxxxxxxxxxx xx xxxxx
xxxxxxxxxxxxxxxx x xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx xx xxxxxxxxxxxxxxxxxxxxx
x xxx xxxxxxxxxxxxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxxxxx
x xxx xxxxxxxxxxxxxxxxxxxxx xxxx xxxxxxxxxxxxx
xxxxxx xxxxxxxxxxxxxxxxx
x
xx [/pro] */
// These dialects natively support the IS DISTINCT FROM predicate:
// H2, Postgres
else {
if (compareCondition == null) {
if (compareCondition == null)
compareCondition = new CompareCondition(lhs, rhs, comparator);
}
return compareCondition;
}

View File

@ -75,6 +75,7 @@ class Mod<T> extends AbstractFunction<T> {
xxxxxx xxxxxxxxxx xxxxx xxxxx xxxxxxxxxxxxxx xxxxx xxxxxx
xxxx xxxx
xxxx xxxxxxxxx
xxxx xxxxxxxxxx
xx [/pro] */
case SQLITE:

View File

@ -73,6 +73,7 @@ class Rand extends AbstractFunction<BigDecimal> {
xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxx
xxxx xxxxxxx
xxxx xxxxxxxxx
xx [/pro] */
case DERBY:
case POSTGRES:

View File

@ -97,6 +97,9 @@ class RegexpLike extends AbstractCondition {
}
// [#620] Postgres has its own syntax
/* [pro] xx
xxxx xxxxxxxxx
xx [/pro] */
case POSTGRES: {
// [#1570] TODO: Replace this by SQL.condition(String, QueryPart...)

View File

@ -59,6 +59,7 @@ import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -67,14 +68,6 @@ import static org.jooq.impl.DSL.row;
import javax.annotation.Generated;
import org.jooq.BetweenAndStep1;
import org.jooq.BetweenAndStep2;
import org.jooq.BetweenAndStep3;
import org.jooq.BetweenAndStep4;
import org.jooq.BetweenAndStep5;
import org.jooq.BetweenAndStep6;
import org.jooq.BetweenAndStep7;
import org.jooq.BetweenAndStep8;
import org.jooq.BetweenAndStep9;
import org.jooq.BetweenAndStep10;
import org.jooq.BetweenAndStep11;
import org.jooq.BetweenAndStep12;
@ -85,9 +78,17 @@ import org.jooq.BetweenAndStep16;
import org.jooq.BetweenAndStep17;
import org.jooq.BetweenAndStep18;
import org.jooq.BetweenAndStep19;
import org.jooq.BetweenAndStep2;
import org.jooq.BetweenAndStep20;
import org.jooq.BetweenAndStep21;
import org.jooq.BetweenAndStep22;
import org.jooq.BetweenAndStep3;
import org.jooq.BetweenAndStep4;
import org.jooq.BetweenAndStep5;
import org.jooq.BetweenAndStep6;
import org.jooq.BetweenAndStep7;
import org.jooq.BetweenAndStep8;
import org.jooq.BetweenAndStep9;
import org.jooq.BetweenAndStepN;
import org.jooq.BindContext;
import org.jooq.Clause;
@ -98,14 +99,6 @@ import org.jooq.Field;
import org.jooq.QueryPartInternal;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
import org.jooq.Record10;
import org.jooq.Record11;
import org.jooq.Record12;
@ -116,20 +109,20 @@ import org.jooq.Record16;
import org.jooq.Record17;
import org.jooq.Record18;
import org.jooq.Record19;
import org.jooq.Record2;
import org.jooq.Record20;
import org.jooq.Record21;
import org.jooq.Record22;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Record9;
import org.jooq.RenderContext;
import org.jooq.Row;
import org.jooq.Row1;
import org.jooq.Row2;
import org.jooq.Row3;
import org.jooq.Row4;
import org.jooq.Row5;
import org.jooq.Row6;
import org.jooq.Row7;
import org.jooq.Row8;
import org.jooq.Row9;
import org.jooq.Row10;
import org.jooq.Row11;
import org.jooq.Row12;
@ -140,9 +133,17 @@ import org.jooq.Row16;
import org.jooq.Row17;
import org.jooq.Row18;
import org.jooq.Row19;
import org.jooq.Row2;
import org.jooq.Row20;
import org.jooq.Row21;
import org.jooq.Row22;
import org.jooq.Row3;
import org.jooq.Row4;
import org.jooq.Row5;
import org.jooq.Row6;
import org.jooq.Row7;
import org.jooq.Row8;
import org.jooq.Row9;
import org.jooq.RowN;
/**
@ -713,12 +714,9 @@ implements
// These dialects don't support the SYMMETRIC keyword at all
if (symmetric && asList(CUBRID, DERBY, FIREBIRD, H2, MARIADB, MYSQL, SQLITE).contains(configuration.dialect().family())) {
if (not) {
return (QueryPartInternal) r.notBetween(min, max).and(r.notBetween(max, min));
}
else {
return (QueryPartInternal) r.between(min, max).or(r.between(max, min));
}
return not
? (QueryPartInternal) r.notBetween(min, max).and(r.notBetween(max, min))
: (QueryPartInternal) r.between(min, max).or(r.between(max, min));
}
// These dialects either don't support row value expressions, or they

View File

@ -47,13 +47,13 @@ import static org.jooq.Comparator.EQUALS;
import static org.jooq.Comparator.IN;
import static org.jooq.Comparator.NOT_EQUALS;
import static org.jooq.Comparator.NOT_IN;
// ...
import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
import static org.jooq.impl.DSL.exists;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.name;
@ -137,22 +137,24 @@ class RowSubqueryCondition extends AbstractCondition {
return new Native();
}
// [#2395] These dialects have native support for = and <>
else if (
asList(H2, HSQLDB, MARIADB, MYSQL, POSTGRES).contains(family) &&
asList(EQUALS, NOT_EQUALS).contains(comparator)) {
/* [pro] xx
xx xxxxxxx xxxxx xxxxxxxx xxxx xxxxxx xxxxxxx xxx x xxx xx
xxxx xx x
xxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxx xx
xxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
return new Native();
}
xxxxxx xxx xxxxxxxxx
x
// [#2395] These dialects have native support for IN and NOT IN
else if (
asList(H2, HSQLDB, MARIADB, MYSQL, POSTGRES).contains(family) &&
asList(IN, NOT_IN).contains(comparator)) {
xx xxxxxxx xxxxx xxxxxxxx xxxx xxxxxx xxxxxxx xxx xx xxx xxx xx
xxxx xx x
xxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxx xx
xxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
return new Native();
}
xxxxxx xxx xxxxxxxxx
x
xx [/pro] */
// [#2395] All other configurations have to be emulated
else {
String table = render == null ? "t" : render.nextAlias();

View File

@ -75,6 +75,7 @@ import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -1076,7 +1077,7 @@ class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> implement
context.sql('1');
}
// Few dialects support the SQL standard empty grouping set
// Few dialects support the SQL standard "grand total" (i.e. empty grouping set)
else {
context.sql("()");
}

View File

@ -95,7 +95,7 @@ class Values<R extends Record> extends AbstractTable<R> {
public final void accept(Context<?> ctx) {
switch (ctx.family()) {
// [#915] Simulate VALUES(..) with SELECT .. UNION ALL SELECT ..
// [#915] Emulate VALUES(..) with SELECT .. UNION ALL SELECT ..
// for those dialects that do not support a VALUES() constructor
/* [pro] xx
xxxx xxxxxxx
@ -103,6 +103,7 @@ class Values<R extends Record> extends AbstractTable<R> {
xxxx xxxxxxxxx
xxxx xxxxxxx
xxxx xxxxxxx
xxxx xxxxxxxxx
xxxx xxxxxxx
xx [/pro] */
case FIREBIRD:

View File

@ -55,6 +55,7 @@ import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -124,12 +125,22 @@ public class JDBCUtils {
* "Guess" the {@link SQLDialect} from a connection URL.
*/
public static final SQLDialect dialect(String url) {
if (url == null)
if (url == null) {
return DEFAULT;
}
// The below list might not be accurate or complete. Feel free to
// contribute fixes related to new / different JDBC driver configuraitons
if (url.startsWith("jdbc:cubrid:")) {
// contribute fixes related to new / different JDBC driver configurations
/* [pro] xx
xx xxxx xxx xx xx xxxxx
xxxx xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
xxxxxx xxxxxxxxx
x
xx [/pro] */
else if (url.startsWith("jdbc:cubrid:")) {
return CUBRID;
}
else if (url.startsWith("jdbc:derby:")) {
@ -233,6 +244,8 @@ public class JDBCUtils {
xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxx xxxxxxx
xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxx xxxxxxxxx
xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxx xxxxxxxxxx
xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxx xxxxxxx