Merge pull request #2090 from ebean-orm/feature/2089

#2089 - Postgres - Use NO KEY with FOR UPDATE clauses with Postgres
This commit is contained in:
Rob Bygrave
2020-11-24 21:49:28 +13:00
committed by GitHub
6 changed files with 169 additions and 12 deletions
@@ -17,6 +17,11 @@ public class PlatformConfig {
private boolean allQuotedIdentifiers;
/**
* Set this to true for Postgres FOR UPDATE to include the primary key (not use NO KEY).
*/
private boolean lockWithKey;
private DbConstraintNaming constraintNaming;
/**
@@ -77,6 +82,7 @@ public class PlatformConfig {
* Construct based on given config - typically for DbMigration generation with many platforms.
*/
public PlatformConfig(PlatformConfig platformConfig) {
this.lockWithKey = platformConfig.lockWithKey;
this.databaseBooleanFalse = platformConfig.databaseBooleanFalse;
this.databaseBooleanTrue = platformConfig.databaseBooleanTrue;
this.databaseSequenceBatchSize = platformConfig.databaseSequenceBatchSize;
@@ -133,14 +139,26 @@ public class PlatformConfig {
this.caseSensitiveCollation = caseSensitiveCollation;
}
/**
* Return true if Postgres FOR UPDATE should include the primary key (or use NO KEY).
*/
public boolean isLockWithKey() {
return lockWithKey;
}
/**
* Set to true such that Postgres FOR UPDATE should include the primary key (not use NO KEY option).
*/
public void setLockWithKey(boolean lockWithKey) {
this.lockWithKey = lockWithKey;
}
/**
* Return a value used to represent TRUE in the database.
* <p>
* This is used for databases that do not support boolean natively.
* </p>
* <p>
* The value returned is either a Integer or a String (e.g. "1", or "T").
* </p>
*/
public String getDatabaseBooleanTrue() {
return databaseBooleanTrue;
@@ -150,10 +168,8 @@ public class PlatformConfig {
* Set the value to represent TRUE in the database.
* <p>
* This is used for databases that do not support boolean natively.
* </p>
* <p>
* The value set is either a Integer or a String (e.g. "1", or "T").
* </p>
*/
public void setDatabaseBooleanTrue(String databaseBooleanTrue) {
this.databaseBooleanTrue = databaseBooleanTrue;
@@ -245,7 +261,6 @@ public class PlatformConfig {
/**
* Add a custom type mapping.
* <p>
* <pre>{@code
*
* // set the default mapping for BigDecimal.class/decimal
@@ -266,7 +281,6 @@ public class PlatformConfig {
/**
* Add a custom type mapping that applies to all platforms.
* <p>
* <pre>{@code
*
* // set the default mapping for BigDecimal/decimal
@@ -294,6 +308,7 @@ public class PlatformConfig {
public void loadSettings(PropertiesWrapper p) {
idType = p.getEnum(IdType.class, "idType", idType);
lockWithKey = p.getBoolean("lockWithKey", lockWithKey);
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
@@ -334,7 +349,6 @@ public class PlatformConfig {
*/
public enum DbUuid {
/**
* Store using native UUID in H2 and Postgres and otherwise fallback to VARCHAR(40).
*/
@@ -4,6 +4,7 @@ import io.ebean.BackgroundExecutor;
import io.ebean.Query;
import io.ebean.annotation.PartitionMode;
import io.ebean.annotation.Platform;
import io.ebean.config.PlatformConfig;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
@@ -25,6 +26,11 @@ import java.sql.Types;
*/
public class PostgresPlatform extends DatabasePlatform {
// by default using NO KEY option with FOR UPDATE clauses
private String forUpdateSkipLocked = " for no key update skip locked";
private String forUpdateNowait = " for no key update nowait";
private String forUpdate = " for no key update";
public PostgresPlatform() {
super();
this.platform = Platform.POSTGRES;
@@ -81,6 +87,16 @@ public class PostgresPlatform extends DatabasePlatform {
dbTypeMap.put(DbType.LONGVARCHAR, dbTypeText);
}
@Override
public void configure(PlatformConfig config) {
super.configure(config);
if (config.isLockWithKey()) {
this.forUpdateSkipLocked = " for update skip locked";
this.forUpdateNowait = " for update nowait";
this.forUpdate = " for update";
}
}
@Override
protected void addGeoTypes(int srid) {
dbTypeMap.put(DbType.POINT, geoType("point", srid));
@@ -116,11 +132,11 @@ public class PostgresPlatform extends DatabasePlatform {
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
switch (forUpdateMode) {
case SKIPLOCKED:
return sql + " for update skip locked";
return sql + forUpdateSkipLocked;
case NOWAIT:
return sql + " for update nowait";
return sql + forUpdateNowait;
default:
return sql + " for update";
return sql + forUpdate;
}
}