[#4299] Add support for PostgreSQL 9.5 - INSERT .. ON CONFLICT DO { UPDATE | NOTHING }

This commit is contained in:
lukaseder 2015-08-10 17:48:33 +02:00
parent 0002c41e89
commit e61aa8f5b1
4 changed files with 72 additions and 17 deletions

View File

@ -47,6 +47,7 @@ import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES_9_5;
// ...
// ...
@ -89,7 +90,7 @@ public interface InsertOnDuplicateStep<R extends Record> extends InsertReturning
* <p>
* These are the dialects that fulfill the above requirements:
*/
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL })
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL, POSTGRES_9_5 })
InsertOnDuplicateSetStep<R> onDuplicateKeyUpdate();
/**
@ -108,21 +109,21 @@ public interface InsertOnDuplicateStep<R extends Record> extends InsertReturning
* <th>Emulation</th>
* </tr>
* <tr>
* <td> {@link SQLDialect#MARIADB}</td>
* <td> <code><pre>INSERT IGNORE INTO ..</pre></code></td>
* <td>{@link SQLDialect#MYSQL} and {@link SQLDialect#MARIADB}</td>
* <td><code><pre>INSERT IGNORE INTO ..</pre></code></td>
* </tr>
* <tr>
* <td> {@link SQLDialect#MYSQL}</td>
* <td> <code><pre>INSERT IGNORE INTO ..</pre></code></td>
* <td>{@link SQLDialect#POSTGRES_9_5}</td>
* <td><code><pre>INSERT INTO .. ON CONFLICT DO NOTHING</pre></code></td>
* </tr>
* <tr>
* <td> {@link SQLDialect#CUBRID}</td>
* <td>{@link SQLDialect#CUBRID}</td>
* <td>
* <code><pre>INSERT INTO .. ON DUPLICATE KEY UPDATE [any-field] = [any-field]</pre></code>
* </td>
* </tr>
* <tr>
* <td> {@link SQLDialect#DB2}<br/>
* <td>{@link SQLDialect#DB2}<br/>
* {@link SQLDialect#HSQLDB}<br/>
* {@link SQLDialect#ORACLE}<br/>
* {@link SQLDialect#SQLSERVER}<br/>

View File

@ -54,6 +54,7 @@ import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.POSTGRES_9_5;
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -108,7 +109,7 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
*
* @see InsertOnDuplicateStep#onDuplicateKeyUpdate()
*/
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL })
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL, POSTGRES_9_5 })
void onDuplicateKeyUpdate(boolean flag);
/**
@ -123,17 +124,21 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
* <th>Emulation</th>
* </tr>
* <tr>
* <td> {@link SQLDialect#MYSQL}</td>
* <td> <code><pre>INSERT IGNORE INTO ..</pre></code></td>
* <td>{@link SQLDialect#MYSQL} and {@link SQLDialect#MARIADB}</td>
* <td><code><pre>INSERT IGNORE INTO ..</pre></code></td>
* </tr>
* <tr>
* <td> {@link SQLDialect#CUBRID}</td>
* <td>{@link SQLDialect#POSTGRES_9_5}</td>
* <td><code><pre>INSERT INTO .. ON CONFLICT DO NOTHING</pre></code></td>
* </tr>
* <tr>
* <td>{@link SQLDialect#CUBRID}</td>
* <td>
* <code><pre>INSERT INTO .. ON DUPLICATE KEY UPDATE [any-field] = [any-field]</pre></code>
* </td>
* </tr>
* <tr>
* <td> {@link SQLDialect#DB2}<br/>
* <td>{@link SQLDialect#DB2}<br/>
* {@link SQLDialect#HSQLDB}<br/>
* {@link SQLDialect#ORACLE}<br/>
* {@link SQLDialect#SQLSERVER}<br/>
@ -168,7 +173,7 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
*
* @see InsertOnDuplicateStep#onDuplicateKeyUpdate()
*/
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL })
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL, POSTGRES_9_5 })
<T> void addValueForUpdate(Field<T> field, T value);
/**
@ -177,7 +182,7 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
*
* @see InsertOnDuplicateStep#onDuplicateKeyUpdate()
*/
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL })
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL, POSTGRES_9_5 })
<T> void addValueForUpdate(Field<T> field, Field<T> value);
/**
@ -190,7 +195,7 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
*
* @see InsertOnDuplicateStep#onDuplicateKeyUpdate()
*/
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL })
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL, POSTGRES_9_5 })
void addValuesForUpdate(Map<? extends Field<?>, ?> map);
/**

View File

@ -46,6 +46,7 @@ import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES_9_5;
// ...
// ...
@ -86,7 +87,7 @@ public interface LoaderOptionsStep<R extends TableRecord<R>> extends LoaderSourc
* the default. This cannot be combined with {@link #onDuplicateKeyError()}
* or {@link #onDuplicateKeyIgnore()}
*/
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL })
@Support({ CUBRID, HSQLDB, MARIADB, MYSQL, POSTGRES_9_5 })
LoaderOptionsStep<R> onDuplicateKeyUpdate();
/**

View File

@ -176,6 +176,33 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
break;
}
case POSTGRES: {
toSQLInsert(ctx);
ctx.formatSeparator()
.start(INSERT_ON_DUPLICATE_KEY_UPDATE)
.keyword("on conflict")
.sql(" (");
if (table.getPrimaryKey() == null) {
ctx.sql("[unknown primary key]");
}
else {
boolean qualify = ctx.qualify();
ctx.qualify(false)
.visit(new Fields<Record>(table.getPrimaryKey().getFields()))
.qualify(qualify);
}
ctx.sql(") ")
.keyword("do update set")
.sql(' ')
.visit(updateMap)
.end(INSERT_ON_DUPLICATE_KEY_UPDATE);
break;
}
// Some dialects can't really handle this clause. Emulation should be done in two steps
case H2: {
throw new SQLDialectNotSupportedException("The ON DUPLICATE KEY UPDATE clause cannot be emulated for " + ctx.dialect());
@ -202,7 +229,7 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
// ON DUPLICATE KEY IGNORE clause
// ------------------------------
else if (onDuplicateKeyIgnore) {
switch (ctx.family()) {
switch (ctx.dialect()) {
// MySQL has a nice, native syntax for this
case MARIADB:
@ -214,6 +241,15 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
break;
}
case POSTGRES_9_5: {
toSQLInsert(ctx);
ctx.formatSeparator()
.start(INSERT_ON_DUPLICATE_KEY_UPDATE)
.keyword("on conflict do nothing")
.end(INSERT_ON_DUPLICATE_KEY_UPDATE);
break;
}
// CUBRID can emulate this using ON DUPLICATE KEY UPDATE
case CUBRID: {
FieldMapForUpdate update = new FieldMapForUpdate(INSERT_ON_DUPLICATE_KEY_UPDATE_ASSIGNMENT);
@ -234,9 +270,21 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
// Some databases allow for emulating this clause using a MERGE statement
/* [pro] xx
xxxx xxxx
xxxx xxxxxx
xxxx xxxxxxx
xxxx xxxxxxxxx
xxxx xxxxxxx
xxxx xxxxxxxxxx
xxxx xxxxxxxxxx
xxxx xxxxxxxxxx
xxxx xxxxxxxxxx
xxxx xxxxxxxxxxxxxx
xxxx xxxxxxxxxxxxxx
xxxx xxxxxxxxxxxxxx
xxxx xxxxxxx
xx [/pro] */
case HSQLDB: {