+ * DatabasePlatformProvider implementations are service loaded and custom implementations
+ * can be added and used via the service loading mechanism.
+ */
+public interface DatabasePlatformProvider {
+
+ /**
+ * Match on the lower case platform name.
+ */
+ boolean match(String name);
+
+ /**
+ * Create the platform based on the lower case platform name.
+ */
+ DatabasePlatform create(String name);
+
+ /**
+ * Match on the lower case JDBC metadata product name.
+ */
+ boolean matchByProductName(String productName);
+
+ /**
+ * Create the platform based on the lower case JDBC metadata product name.
+ */
+ DatabasePlatform create(int majorVersion, int minorVersion, DatabaseMetaData meta, Connection connection);
+
+ /**
+ * Match on the specific platform.
+ */
+ boolean matchPlatform(Platform platform);
+
+ /**
+ * Create the specific platform.
+ */
+ DatabasePlatform create(Platform platform);
+
+}
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/clickhouse/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/clickhouse/package-info.java
deleted file mode 100644
index e262c22d2..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/clickhouse/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Clickhouse DB specific support.
- */
-package io.ebean.config.dbplatform.clickhouse;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/cockroach/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/cockroach/package-info.java
deleted file mode 100644
index 3b3145b6f..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/cockroach/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Cockroach DB specific support.
- */
-package io.ebean.config.dbplatform.cockroach;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/package-info.java
deleted file mode 100644
index 5760f5232..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * DB2 specific support.
- */
-package io.ebean.config.dbplatform.db2;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/h2/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/h2/package-info.java
deleted file mode 100644
index e303b7760..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/h2/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * H2 specific support.
- */
-package io.ebean.config.dbplatform.h2;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/package-info.java
deleted file mode 100644
index 55fc12c5e..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * SAP HANA specific support.
- */
-package io.ebean.config.dbplatform.hana;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/hsqldb/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/hsqldb/package-info.java
deleted file mode 100644
index 6a5ddf752..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/hsqldb/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Hsqldb specific support.
- */
-package io.ebean.config.dbplatform.hsqldb;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/mysql/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/mysql/package-info.java
deleted file mode 100644
index 4030ba6d5..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/mysql/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * MySql specific support.
- */
-package io.ebean.config.dbplatform.mysql;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/nuodb/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/nuodb/package-info.java
deleted file mode 100644
index f33720ccd..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/nuodb/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * NuoDB specific support.
- */
-package io.ebean.config.dbplatform.nuodb;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/oracle/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/oracle/package-info.java
deleted file mode 100644
index 5889cf2aa..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/oracle/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Oracle specific support.
- */
-package io.ebean.config.dbplatform.oracle;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/postgres/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/postgres/package-info.java
deleted file mode 100644
index e94d3814c..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/postgres/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Postgres specific support.
- */
-package io.ebean.config.dbplatform.postgres;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlanywhere/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlanywhere/package-info.java
deleted file mode 100644
index 344570001..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlanywhere/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * SqlAnywhere specific support.
- */
-package io.ebean.config.dbplatform.sqlanywhere;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlite/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlite/package-info.java
deleted file mode 100644
index bc583818a..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlite/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Sqlite specific support.
- */
-package io.ebean.config.dbplatform.sqlite;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlserver/package-info.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlserver/package-info.java
deleted file mode 100644
index 41ffef0cf..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/sqlserver/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * SqlServer specific support.
- */
-package io.ebean.config.dbplatform.sqlserver;
diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/yugabyte/YugabytePlaform.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/yugabyte/YugabytePlaform.java
deleted file mode 100644
index 622f8e5f8..000000000
--- a/ebean-api/src/main/java/io/ebean/config/dbplatform/yugabyte/YugabytePlaform.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package io.ebean.config.dbplatform.yugabyte;
-
-import io.ebean.annotation.Platform;
-import io.ebean.config.dbplatform.postgres.PostgresPlatform;
-
-public class YugabytePlaform extends PostgresPlatform {
-
- public YugabytePlaform() {
- super();
- this.platform = Platform.YUGABYTE;
- }
-}
diff --git a/ebean-api/src/main/java9/module-info.java b/ebean-api/src/main/java9/module-info.java
index 75ff243e2..7c873b199 100644
--- a/ebean-api/src/main/java9/module-info.java
+++ b/ebean-api/src/main/java9/module-info.java
@@ -1,6 +1,7 @@
module io.ebean.api {
uses io.ebean.config.AutoConfigure;
+ uses io.ebean.config.dbplatform.DatabasePlatformProvider;
uses io.ebean.datasource.DataSourceAlertFactory;
uses io.ebean.metric.MetricFactory;
uses io.ebean.service.SpiContainerFactory;
diff --git a/ebean-api/src/test/java/io/ebean/config/dbplatform/PostgresPlatformTest.java b/ebean-api/src/test/java/io/ebean/config/dbplatform/PostgresPlatformTest.java
deleted file mode 100644
index b7b6d524f..000000000
--- a/ebean-api/src/test/java/io/ebean/config/dbplatform/PostgresPlatformTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.ebean.config.dbplatform;
-
-import io.ebean.Query;
-import io.ebean.config.PlatformConfig;
-import io.ebean.config.dbplatform.postgres.PostgresPlatform;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class PostgresPlatformTest {
-
- @Test
- public void testUuidType() {
-
- PostgresPlatform platform = new PostgresPlatform();
- platform.configure(new PlatformConfig(), false);
-
- DbPlatformType dbType = platform.getDbTypeMap().get(DbPlatformType.UUID);
- String columnDefn = dbType.renderType(0, 0);
-
- assertThat(columnDefn).isEqualTo("uuid");
- }
-
- @Test
- public void default_forUpdate_expect_noKeyUsed() {
-
- DatabasePlatform platform = new PostgresPlatform();
-
- PlatformConfig config = new PlatformConfig();
- platform.configure(config);
-
- assertThat(config.isForUpdateNoKey()).isFalse();
- assertThat(platform.withForUpdate("X", Query.LockWait.SKIPLOCKED, Query.LockType.DEFAULT)).isEqualTo("X for update skip locked");
- assertThat(platform.withForUpdate("X", Query.LockWait.NOWAIT, Query.LockType.DEFAULT)).isEqualTo("X for update nowait");
- assertThat(platform.withForUpdate("X", Query.LockWait.WAIT, Query.LockType.DEFAULT)).isEqualTo("X for update");
-
- assertThat(platform.withForUpdate("X", Query.LockWait.SKIPLOCKED, Query.LockType.UPDATE)).isEqualTo("X for update skip locked");
- assertThat(platform.withForUpdate("X", Query.LockWait.SKIPLOCKED, Query.LockType.NO_KEY_UPDATE)).isEqualTo("X for no key update skip locked");
- assertThat(platform.withForUpdate("X", Query.LockWait.SKIPLOCKED, Query.LockType.SHARE)).isEqualTo("X for share skip locked");
- assertThat(platform.withForUpdate("X", Query.LockWait.SKIPLOCKED, Query.LockType.KEY_SHARE)).isEqualTo("X for key share skip locked");
-
- assertThat(platform.withForUpdate("X", Query.LockWait.NOWAIT, Query.LockType.UPDATE)).isEqualTo("X for update nowait");
- assertThat(platform.withForUpdate("X", Query.LockWait.NOWAIT, Query.LockType.NO_KEY_UPDATE)).isEqualTo("X for no key update nowait");
- assertThat(platform.withForUpdate("X", Query.LockWait.NOWAIT, Query.LockType.SHARE)).isEqualTo("X for share nowait");
- assertThat(platform.withForUpdate("X", Query.LockWait.NOWAIT, Query.LockType.KEY_SHARE)).isEqualTo("X for key share nowait");
-
- assertThat(platform.withForUpdate("X", Query.LockWait.WAIT, Query.LockType.UPDATE)).isEqualTo("X for update");
- assertThat(platform.withForUpdate("X", Query.LockWait.WAIT, Query.LockType.NO_KEY_UPDATE)).isEqualTo("X for no key update");
- assertThat(platform.withForUpdate("X", Query.LockWait.WAIT, Query.LockType.SHARE)).isEqualTo("X for share");
- assertThat(platform.withForUpdate("X", Query.LockWait.WAIT, Query.LockType.KEY_SHARE)).isEqualTo("X for key share");
- }
-
- @Test
- public void lockWithKey_forUpdate() {
-
- DatabasePlatform platform = new PostgresPlatform();
-
- PlatformConfig config = new PlatformConfig();
- config.setForUpdateNoKey(true);
- platform.configure(config);
-
- assertThat(config.isForUpdateNoKey()).isTrue();
- assertThat(platform.withForUpdate("X", Query.LockWait.SKIPLOCKED, Query.LockType.DEFAULT)).isEqualTo("X for no key update skip locked");
- assertThat(platform.withForUpdate("X", Query.LockWait.NOWAIT, Query.LockType.DEFAULT)).isEqualTo("X for no key update nowait");
- assertThat(platform.withForUpdate("X", Query.LockWait.WAIT, Query.LockType.DEFAULT)).isEqualTo("X for no key update");
- }
-
-}
diff --git a/ebean-autotune/pom.xml b/ebean-autotune/pom.xml
index 0bafb7c80..97123c71b 100644
--- a/ebean-autotune/pom.xml
+++ b/ebean-autotune/pom.xml
@@ -52,6 +52,13 @@