diff --git a/.github/workflows/yugabyte.yml b/.github/workflows/yugabyte.yml new file mode 100644 index 000000000..b060cc54d --- /dev/null +++ b/.github/workflows/yugabyte.yml @@ -0,0 +1,38 @@ + +name: Yugabyte + +on: + workflow_dispatch: + schedule: + - cron: '10 3 * * *' + +jobs: + build: + + runs-on: ${{ matrix.os }} + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + java_version: [11] + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v2 + - name: Set up Java + uses: actions/setup-java@v2 + with: + java-version: ${{ matrix.java_version }} + distribution: 'adopt' + - name: Maven cache + uses: actions/cache@v2 + env: + cache-name: maven-cache + with: + path: + ~/.m2 + key: build-${{ env.cache-name }} + - name: yugabyte + run: mvn clean test -Dprops.file=testconfig/ebean-yugabyte.properties diff --git a/ebean-api/src/main/java/io/ebean/ScriptRunner.java b/ebean-api/src/main/java/io/ebean/ScriptRunner.java index 15057741e..ff2e9d668 100644 --- a/ebean-api/src/main/java/io/ebean/ScriptRunner.java +++ b/ebean-api/src/main/java/io/ebean/ScriptRunner.java @@ -1,6 +1,7 @@ package io.ebean; import java.net.URL; +import java.nio.file.Path; import java.util.Map; /** @@ -23,10 +24,10 @@ public interface ScriptRunner { /** * Run a script given the resource path (that should start with "/"). */ - void run(String path); + void run(String resourcePath); /** - * Run a script given the resource path (that should start with "/") and place holders. + * Run a script given the resource path (that should start with "/") and place-holders. * *
{@code
    *
@@ -38,7 +39,7 @@ public interface ScriptRunner {
    *
    * }
*/ - void run(String path, Map placeholderMap); + void run(String resourcePath, Map placeholderMap); /** * Run a DDL or SQL script given the resource. @@ -46,10 +47,20 @@ public interface ScriptRunner { void run(URL resource); /** - * Run a DDL or SQL script given the resource and place holders. + * Run a DDL or SQL script given the resource and place-holders. */ void run(URL resource, Map placeholderMap); + /** + * Run a DDL or SQL script given the file. + */ + void run(Path file); + + /** + * Run a DDL or SQL script given the file and place-holders. + */ + void run(Path file, Map placeholderMap); + /** * Run the raw provided DDL or SQL script. * diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2LegacyPlatform.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2LegacyPlatform.java index 51f03c2a4..896bdf9b0 100644 --- a/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2LegacyPlatform.java +++ b/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2LegacyPlatform.java @@ -1,5 +1,6 @@ package io.ebean.config.dbplatform.db2; +import io.ebean.annotation.PersistBatch; import io.ebean.annotation.Platform; /** @@ -16,5 +17,6 @@ public class DB2LegacyPlatform extends BaseDB2Platform { // TOOD: Check if we need to introduce a new platform (DB2_LUW_11 ?) this.maxTableNameLength = 18; this.maxConstraintNameLength = 18; + this.persistBatchOnCascade = PersistBatch.NONE; } } diff --git a/ebean-autotune/pom.xml b/ebean-autotune/pom.xml index ef4f137b4..59f32d816 100644 --- a/ebean-autotune/pom.xml +++ b/ebean-autotune/pom.xml @@ -63,7 +63,7 @@ true - io.ebean.tile:enhancement:12.14.1 + io.ebean.tile:enhancement:12.15.0 io.avaje.tile:moditech-module:1.0 diff --git a/ebean-core/pom.xml b/ebean-core/pom.xml index df8c17690..0672b81a0 100644 --- a/ebean-core/pom.xml +++ b/ebean-core/pom.xml @@ -130,7 +130,7 @@ org.postgresql postgresql - 42.2.24 + 42.3.2 true diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DScriptRunner.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DScriptRunner.java index fb2fbd0a2..fdb24bd0d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DScriptRunner.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DScriptRunner.java @@ -8,15 +8,15 @@ import io.ebeaninternal.api.SpiEbeanServer; import io.ebeaninternal.util.UrlHelper; import javax.persistence.PersistenceException; -import java.io.IOException; -import java.io.InputStream; -import java.io.LineNumberReader; -import java.io.Reader; +import java.io.*; import java.net.URL; +import java.nio.file.Path; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; +import static java.util.Objects.requireNonNull; + final class DScriptRunner implements ScriptRunner { private static final String NEWLINE = "\n"; @@ -30,8 +30,8 @@ final class DScriptRunner implements ScriptRunner { } @Override - public void run(String path) { - run(path, null); + public void run(String resourcePath) { + run(resourcePath, null); } @Override @@ -49,27 +49,42 @@ final class DScriptRunner implements ScriptRunner { run(resource, null, placeholderMap); } + @Override + public void run(Path file) { + run(file, null); + } + + @Override + public void run(Path file, Map placeholderMap) { + requireNonNull(file); + String scriptName = file.toFile().getName(); + String content = fileContent(file); + runScript(content, scriptName, placeholderMap, false); + } + private void run(URL resource, String scriptName, Map placeholderMap) { - if (resource == null) { - throw new IllegalArgumentException("resource is null?"); - } + requireNonNull(resource); if (scriptName == null) { scriptName = resource.getFile(); } - String content = content(resource); runScript(content, scriptName, placeholderMap, false); } - private String content(URL resource) { - if (resource == null) { - throw new IllegalArgumentException("resource is null?"); - } - - try (InputStream inputStream = UrlHelper.openNoCache(resource); - Reader reader = IOUtils.newReader(inputStream)) { + private String fileContent(Path file) { + try (InputStream inputStream = new FileInputStream(file.toFile()); + Reader reader = IOUtils.newReader(inputStream)) { return readContent(reader); + } catch (IOException e) { + throw new PersistenceException("Failed to read script content", e); + } + } + private String content(URL resource) { + requireNonNull(resource); + try (InputStream inputStream = UrlHelper.openNoCache(resource); + Reader reader = IOUtils.newReader(inputStream)) { + return readContent(reader); } catch (IOException e) { throw new PersistenceException("Failed to read script content", e); } @@ -85,10 +100,9 @@ final class DScriptRunner implements ScriptRunner { */ private void runScript(String content, String scriptName, Map placeholderMap, boolean useAutoCommit) { try { - if (placeholderMap != null) { + if (placeholderMap != null && !placeholderMap.isEmpty()) { content = ScriptTransform.build(null, placeholderMap).transform(content); } - try (Connection connection = obtainConnection()) { DdlRunner runner = new DdlRunner(useAutoCommit, scriptName, platformName); runner.runAll(content, connection); @@ -110,7 +124,6 @@ final class DScriptRunner implements ScriptRunner { } private String readContent(Reader reader) throws IOException { - StringBuilder buf = new StringBuilder(); try (LineNumberReader lineReader = new LineNumberReader(reader)) { String line; diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java index 0d4a3b28c..305525bb3 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java @@ -86,6 +86,8 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { private final ConcurrentHashMap elDeployCache = new ConcurrentHashMap<>(); private final ConcurrentHashMap> comparatorCache = new ConcurrentHashMap<>(); private final ConcurrentHashMap dynamicProperty = new ConcurrentHashMap<>(); + private final ConcurrentHashMap> pathMaps = new ConcurrentHashMap<>(); + private final Map namedRawSql; private final Map namedQuery; private final boolean multiValueSupported; @@ -2775,6 +2777,22 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { return draftableElement; } + @Override + public Map pathMap(String prefix) { + return pathMaps.computeIfAbsent(prefix, s -> { + HashMap m = new HashMap<>(); + for (STreePropertyAssocMany many : propsMany()) { + String name = many.name(); + m.put(name, prefix + "." + name); + } + for (STreePropertyAssocOne one : propsOne()) { + String name = one.name(); + m.put(name, prefix + "." + name); + } + return m.isEmpty() ? Collections.emptyMap() : m; + }); + } + @Override public boolean isEmbeddedPath(String propertyPath) { ElPropertyDeploy elProp = elPropertyDeploy(propertyPath); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/persist/BatchedPstmt.java b/ebean-core/src/main/java/io/ebeaninternal/server/persist/BatchedPstmt.java index 0a14d485a..7b3e74085 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/persist/BatchedPstmt.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/persist/BatchedPstmt.java @@ -6,8 +6,6 @@ import io.ebeaninternal.api.SpiTransaction; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -23,18 +21,12 @@ import java.util.List; */ public final class BatchedPstmt implements SpiProfileTransactionEvent { - /** - * The underlying statement. - */ + private static final DB2GetKeys DB2_HACK = new DB2GetKeys(); + private PreparedStatement pstmt; - - /** - * True if an insert that uses generated keys. - */ private final boolean isGenKeys; - /** - * The list of BatchPostExecute used to perform post processing. + * The list of BatchPostExecute used to perform post-processing. */ private final List list = new ArrayList<>(); private final String sql; @@ -44,18 +36,6 @@ public final class BatchedPstmt implements SpiProfileTransactionEvent { private int[] results; private List inputStreams; - private static Class DB2_PREPARED_STATEMENT; - private static Method GET_DB_GENERATED_KEYS; - - static { - try { - DB2_PREPARED_STATEMENT = (Class) Class.forName("com.ibm.db2.jcc.DB2PreparedStatement"); - GET_DB_GENERATED_KEYS = DB2_PREPARED_STATEMENT.getDeclaredMethod("getDBGeneratedKeys"); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException cnf) { - // NOP - } - - } /** * Create with a given statement. */ @@ -183,40 +163,15 @@ public final class BatchedPstmt implements SpiProfileTransactionEvent { } } - protected void getGeneratedKeys() throws SQLException { - int index = 0; - if (DB2_PREPARED_STATEMENT != null) { - PreparedStatement db2Stmt = null; - if (DB2_PREPARED_STATEMENT.isInstance(pstmt)) { - db2Stmt = pstmt; - } else if (pstmt.isWrapperFor(DB2_PREPARED_STATEMENT)) { - db2Stmt = pstmt.unwrap(DB2_PREPARED_STATEMENT); - } - if (db2Stmt != null) { - // WTF: https://stackoverflow.com/questions/41725492/how-to-get-auto-generated-keys-of-batch-insert-statement - ResultSet[] result; - try { - result = (ResultSet[]) GET_DB_GENERATED_KEYS.invoke(db2Stmt); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new SQLException("Could not get generated keys for DB2", e); - } - for (int i = 0; i < result.length; i++) { - while (result[i].next()) { - ResultSet rset = result[i]; - Object idValue = rset.getObject(1); - list.get(index).setGeneratedKey(idValue); - index++; - } - } - return; - } + private void getGeneratedKeys() throws SQLException { + if (DB2_HACK.getGeneratedKeys(pstmt, list)) { + return; } - + int index = 0; try (ResultSet rset = pstmt.getGeneratedKeys()) { while (rset.next()) { Object idValue = rset.getObject(1); - list.get(index).setGeneratedKey(idValue); - index++; + list.get(index++).setGeneratedKey(idValue); } } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/persist/DB2GetKeys.java b/ebean-core/src/main/java/io/ebeaninternal/server/persist/DB2GetKeys.java new file mode 100644 index 000000000..a077be908 --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/persist/DB2GetKeys.java @@ -0,0 +1,55 @@ +package io.ebeaninternal.server.persist; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +/** + * Horrible DB2 hack. + */ +final class DB2GetKeys { + + private static Class DB2_PREPARED_STATEMENT; + private static Method GET_DB_GENERATED_KEYS; + + static { + try { + DB2_PREPARED_STATEMENT = (Class) Class.forName("com.ibm.db2.jcc.DB2PreparedStatement"); + GET_DB_GENERATED_KEYS = DB2_PREPARED_STATEMENT.getDeclaredMethod("getDBGeneratedKeys"); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException cnf) { + // NOP + } + } + + static boolean getGeneratedKeys(PreparedStatement pstmt, List list) throws SQLException { + if (DB2_PREPARED_STATEMENT != null) { + PreparedStatement db2Stmt = null; + if (DB2_PREPARED_STATEMENT.isInstance(pstmt)) { + db2Stmt = pstmt; + } else if (pstmt.isWrapperFor(DB2_PREPARED_STATEMENT)) { + db2Stmt = pstmt.unwrap(DB2_PREPARED_STATEMENT); + } + if (db2Stmt != null) { + // WTF: https://stackoverflow.com/questions/41725492/how-to-get-auto-generated-keys-of-batch-insert-statement + ResultSet[] result; + try { + result = (ResultSet[]) GET_DB_GENERATED_KEYS.invoke(db2Stmt); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new SQLException("Could not get generated keys for DB2", e); + } + int index = 0; + for (ResultSet resultSet : result) { + while (resultSet.next()) { + Object idValue = resultSet.getObject(1); + list.get(index++).setGeneratedKey(idValue); + } + } + return true; + } + } + return false; + } +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQuery.java index 1870c1b6f..22e2e1f37 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQuery.java @@ -581,20 +581,17 @@ public final class CQuery implements DbReadContext, CancelableQuery, SpiProfi @Override public void registerBeanInherit(BeanPropertyAssocOne property, EntityBeanIntercept ebi) { - String path = getPath(property.name()); - request.loadContext().register(path, ebi, property); + request.loadContext().register(path(property.name()), ebi, property); } @Override public void register(String path, EntityBeanIntercept ebi) { - path = getPath(path); - request.loadContext().register(path, ebi); + request.loadContext().register(path(path), ebi); } @Override public void register(BeanPropertyAssocMany many, BeanCollection bc) { - String path = getPath(many.name()); - request.loadContext().register(path, many, bc); + request.loadContext().register(path(many.name()), many, bc); } /** @@ -663,18 +660,14 @@ public final class CQuery implements DbReadContext, CancelableQuery, SpiProfi return autoTuneProfiling && query.isUsageProfiling(); } - private String getPath(String propertyName) { + private String path(String propertyName) { if (currentPrefix == null) { return propertyName; } else if (propertyName == null) { return currentPrefix; } String path = currentPathMap.get(propertyName); - if (path != null) { - return path; - } else { - return currentPrefix + "." + propertyName; - } + return path != null ? path : currentPrefix + "." + propertyName; } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/STreeType.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/STreeType.java index 3bb58dd1c..88e3b851a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/STreeType.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/STreeType.java @@ -7,6 +7,8 @@ import io.ebeaninternal.server.deploy.DbReadContext; import io.ebeaninternal.server.deploy.InheritInfo; import io.ebeaninternal.server.deploy.id.IdBinder; +import java.util.Map; + /** * Bean type interface for Sql query tree. */ @@ -136,4 +138,8 @@ public interface STreeType { */ void markAsDeleted(EntityBean bean); + /** + * Return the "path map" to toMany or toOne properties using the given prefix. + */ + Map pathMap(String prefix); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeLoadBean.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeLoadBean.java index 516a00537..aa3cf9d1f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeLoadBean.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeLoadBean.java @@ -46,12 +46,12 @@ class SqlTreeLoadBean implements SqlTreeLoad { this.temporalMode = node.temporalMode; this.temporalVersions = node.temporalVersions; this.nodeBeanProp = node.nodeBeanProp; - this.readId = node.readId;//!aggregationRoot && withId && desc.hasId(); + this.readId = node.readId; this.readIdNormal = readId && !temporalVersions; - this.disableLazyLoad = node.disableLazyLoad;// disableLazyLoad || !readIdNormal || desc.isRawSqlBased(); - this.partialObject = node.partialObject;//props.isPartialObject(); - this.properties = node.properties;//props.getProps(); - this.pathMap = node.pathMap;//createPathMap(prefix, desc); + this.disableLazyLoad = node.disableLazyLoad; + this.partialObject = node.partialObject; + this.properties = node.properties; + this.pathMap = node.pathMap; this.children = node.createLoadChildren(); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java index 6214137c1..d5ec71aa4 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java @@ -15,14 +15,13 @@ import java.util.*; class SqlTreeNodeBean implements SqlTreeNode { private static final SqlTreeLoad[] NO_LOAD_CHILDREN = new SqlTreeLoad[0]; - private static final SqlTreeNode[] NO_CHILDREN = new SqlTreeNode[0]; final STreeType desc; final IdBinder idBinder; /** * The children which will be other SelectBean or SelectProxyBean. */ - final SqlTreeNode[] children; + final List children; /** * Set to true if this is a partial object fetch. */ @@ -94,8 +93,8 @@ class SqlTreeNodeBean implements SqlTreeNode { this.disableLazyLoad = disableLazyLoad || !readIdNormal || desc.isRawSqlBased(); this.partialObject = props.isPartialObject(); this.properties = props.getProps(); - this.children = myChildren == null ? NO_CHILDREN : myChildren.toArray(new SqlTreeNode[0]); - pathMap = createPathMap(prefix, desc); + this.children = myChildren == null ? Collections.emptyList() : myChildren; + this.pathMap = createPathMap(prefix, desc); } @Override @@ -104,10 +103,10 @@ class SqlTreeNodeBean implements SqlTreeNode { } protected SqlTreeLoad[] createLoadChildren() { - if (children.length == 0) { + if (children.isEmpty()) { return NO_LOAD_CHILDREN; } - List loadChildren = new ArrayList<>(children.length); + List loadChildren = new ArrayList<>(children.size()); for (SqlTreeNode child : children) { SqlTreeLoad load = child.createLoad(); if (load != null) { @@ -119,24 +118,15 @@ class SqlTreeNodeBean implements SqlTreeNode { @Override public final boolean isSingleProperty() { - return properties != null && properties.length == 1 && children.length == 0; + return properties != null && properties.length == 1 && children.isEmpty(); } private Map createPathMap(String prefix, STreeType desc) { - HashMap m = new HashMap<>(); - for (STreePropertyAssocMany many : desc.propsMany()) { - String name = many.name(); - m.put(name, getPath(prefix, name)); - } - return m; + return prefix == null ? Collections.emptyMap() : desc.pathMap(prefix); } - private String getPath(String prefix, String propertyName) { - if (prefix == null) { - return propertyName; - } else { - return prefix + "." + propertyName; - } + private String path(String prefix, String propertyName) { + return prefix == null ? propertyName : prefix + "." + propertyName; } @Override @@ -144,7 +134,7 @@ class SqlTreeNodeBean implements SqlTreeNode { if (readId) { if (inheritInfo != null) { // discriminator column always proceeds id column - selectChain.add(getPath(prefix, inheritInfo.getDiscriminatorColumn())); + selectChain.add(path(prefix, inheritInfo.getDiscriminatorColumn())); } idBinder.buildRawSqlSelectChain(prefix, selectChain); } @@ -399,7 +389,7 @@ class SqlTreeNodeBean implements SqlTreeNode { } return false; } - + @Override public void unselectLobs() { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java index 1de2f2dc8..d9089f925 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java @@ -101,6 +101,7 @@ public final class DefaultTypeManager implements TypeManager { private final TypeJsonManager jsonManager; private final boolean offlineMigrationGeneration; private final EnumType defaultEnumType; + private final DatabasePlatform databasePlatform; // OPTIONAL ScalarTypes registered if Jackson/JsonNode is in the classpath @@ -138,7 +139,8 @@ public final class DefaultTypeManager implements TypeManager { this.typeMap = new ConcurrentHashMap<>(); this.nativeMap = new ConcurrentHashMap<>(); this.logicalMap = new ConcurrentHashMap<>(); - this.postgres = isPostgres(config.getDatabasePlatform()); + this.databasePlatform = config.getDatabasePlatform(); + this.postgres = isPostgresCompatible(config.getDatabasePlatform()); this.objectMapperPresent = config.getClassLoadConfig().isJacksonObjectMapperPresent(); this.objectMapper = (objectMapperPresent) ? initObjectMapper(config) : null; this.jsonManager = (objectMapperPresent) ? new TypeJsonManager(postgres, objectMapper, config.getJsonMutationDetection()) : null; @@ -205,8 +207,13 @@ public final class DefaultTypeManager implements TypeManager { } } - private boolean isPostgres(DatabasePlatform databasePlatform) { - return databasePlatform.getPlatform().base() == Platform.POSTGRES; + private boolean isPostgresCompatible(DatabasePlatform databasePlatform) { + return databasePlatform.isPlatform(Platform.POSTGRES) + || databasePlatform.isPlatform(Platform.YUGABYTE); + } + + private boolean hstoreSupport() { + return databasePlatform.isPlatform(Platform.POSTGRES); } /** @@ -310,7 +317,7 @@ public final class DefaultTypeManager implements TypeManager { @Override public ScalarType getDbMapScalarType() { - return (postgres) ? hstoreType : ScalarTypeJsonMap.typeFor(false, Types.VARCHAR, false); + return hstoreSupport() ? hstoreType : ScalarTypeJsonMap.typeFor(false, Types.VARCHAR, false); } @Override @@ -748,7 +755,7 @@ public final class DefaultTypeManager implements TypeManager { jsonNodeVarchar = new ScalarTypeJsonNode.Varchar(mapper); jsonNodeJson = jsonNodeClob; // Default for non-Postgres databases jsonNodeJsonb = jsonNodeClob; // Default for non-Postgres databases - if (isPostgres(config.getDatabasePlatform())) { + if (postgres) { jsonNodeJson = new ScalarTypeJsonNodePostgres.JSON(mapper); jsonNodeJsonb = new ScalarTypeJsonNodePostgres.JSONB(mapper); } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java index ac89c21e2..44585c73b 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java @@ -47,6 +47,7 @@ public class DB2Ddl extends PlatformDdl { String[] nullableColumns) { StringBuilder sb = new StringBuilder(300); if (nullableColumns == null || nullableColumns.length == 0) { + sb.append("alter table ").append(lowerTableName(tableName)); sb.append(" add constraint ").append(maxConstraintName(uqName)).append(" unique "); appendColumns(columns, sb); diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/H2Ddl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/H2Ddl.java index 542bc695a..952fa9858 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/H2Ddl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/H2Ddl.java @@ -7,6 +7,8 @@ import io.ebean.config.dbplatform.DatabasePlatform; */ public class H2Ddl extends PlatformDdl { + private static boolean useV1Syntax = Boolean.getBoolean("ebean.h2.useV1Syntax"); + public H2Ddl(DatabasePlatform platform) { super(platform); this.historyDdl = new H2HistoryDdl(); @@ -22,6 +24,9 @@ public class H2Ddl extends PlatformDdl { @Override protected String convertArrayType(String logicalArrayType) { + if (useV1Syntax) { + return "array"; + } int pos = logicalArrayType.indexOf('['); if (pos == -1) { return logicalArrayType; diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java index 5bc946fa7..90fd27228 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java @@ -561,6 +561,16 @@ public class MTable { return newCol; } + public MColumn addColumnScalar(String dbColumn, String columnDefn) { + MColumn existingColumn = getColumn(dbColumn); + if (existingColumn != null) { + return existingColumn; + } + MColumn newCol = new MColumn(dbColumn, columnDefn); + addColumn(newCol); + return newCol; + } + /** * Add a 'new column' to the AddColumn migration object. */ diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java index 398bee86f..56748d993 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java @@ -246,14 +246,13 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { lastColumn = null; return; } - // using non-strict mode to render the DB type such that we have a // "logical" type like jsonb(200) that can map to JSONB or VARCHAR(200) - MColumn col = new MColumn(p.dbColumn(), ctx.getColumnDefn(p, false)); + MColumn col = table.addColumnScalar(p.dbColumn(), ctx.getColumnDefn(p, false)); + //MColumn col = new MColumn(p.dbColumn(), ctx.getColumnDefn(p, false)); col.setComment(p.dbComment()); col.setDraftOnly(p.isDraftOnly()); col.setHistoryExclude(p.isExcludedFromHistory()); - if (p.isId() || p.isImportedPrimaryKey()) { col.setPrimaryKey(true); if (p.descriptor().isUseIdGenerator()) { @@ -279,7 +278,6 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { } col.setDbMigrationInfos(p.dbMigrationInfos()); - if (p.isUnique() && !p.isId()) { col.setUnique(uniqueConstraintName(col.getName())); indexSetAdd(col.getName()); @@ -293,9 +291,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { col.setCheckConstraint(buildCheckConstraint(p.dbColumn(), checkConstraintValues)); col.setCheckConstraintName(checkConstraintName(col.getName())); } - lastColumn = col; - table.addColumn(col); } /** diff --git a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandlerTest.java b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandlerTest.java index 87c48bb85..550d508ad 100644 --- a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandlerTest.java +++ b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandlerTest.java @@ -18,6 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat; public class BaseDdlHandlerTest extends BaseTestCase { + private static boolean useV1Syntax = Boolean.getBoolean("ebean.h2.useV1Syntax"); + private final DatabaseConfig serverConfig = new DatabaseConfig(); private DdlHandler handler(DatabasePlatform platform) { @@ -107,7 +109,11 @@ public class BaseDdlHandlerTest extends BaseTestCase { write = new DdlWrite(); h2Handler().generate(write, Helper.getAlterTableAddDbArrayColumnWithLength()); - assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_ninety varchar array;\n\n"); + if (useV1Syntax) { + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_ninety array;\n\n"); + } else { + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_ninety varchar array;\n\n"); + } write = new DdlWrite(); sqlserverHandler().generate(write, Helper.getAlterTableAddDbArrayColumnWithLength()); @@ -127,7 +133,11 @@ public class BaseDdlHandlerTest extends BaseTestCase { write = new DdlWrite(); h2Handler().generate(write, Helper.getAlterTableAddDbArrayColumnIntegerWithLength()); - assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer integer array;\n\n"); + if (useV1Syntax) { + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer array;\n\n"); + } else { + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer integer array;\n\n"); + } write = new DdlWrite(); sqlserverHandler().generate(write, Helper.getAlterTableAddDbArrayColumnIntegerWithLength()); diff --git a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java index 3141eef74..2ae1118f1 100644 --- a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java +++ b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java @@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class PlatformDdl_AlterColumnTest { + private static boolean useV1Syntax = Boolean.getBoolean("ebean.h2.useV1Syntax"); + private final PlatformDdl h2Ddl = PlatformDdlBuilder.create(new H2Platform()); private final PlatformDdl pgDdl = PlatformDdlBuilder.create(new PostgresPlatform()); private final PlatformDdl mysqlDdl = PlatformDdlBuilder.create(new MySqlPlatform()); @@ -57,10 +59,17 @@ public class PlatformDdl_AlterColumnTest { @Test public void convertArrayType_h2() { - assertThat(h2Ddl.convertArrayType("varchar[](90)")).isEqualTo("varchar array"); - assertThat(h2Ddl.convertArrayType("integer[](60)")).isEqualTo("integer array"); - assertThat(h2Ddl.convertArrayType("varchar[]")).isEqualTo("varchar array"); - assertThat(h2Ddl.convertArrayType("integer[]")).isEqualTo("integer array"); + if (useV1Syntax) { + assertThat(h2Ddl.convertArrayType("varchar[](90)")).isEqualTo("array"); + assertThat(h2Ddl.convertArrayType("integer[](60)")).isEqualTo("array"); + assertThat(h2Ddl.convertArrayType("varchar[]")).isEqualTo("array"); + assertThat(h2Ddl.convertArrayType("integer[]")).isEqualTo("array"); + } else { + assertThat(h2Ddl.convertArrayType("varchar[](90)")).isEqualTo("varchar array"); + assertThat(h2Ddl.convertArrayType("integer[](60)")).isEqualTo("integer array"); + assertThat(h2Ddl.convertArrayType("varchar[]")).isEqualTo("varchar array"); + assertThat(h2Ddl.convertArrayType("integer[]")).isEqualTo("integer array"); + } } @Test diff --git a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/MTableTest.java b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/MTableTest.java index f3e2d5648..012df7d49 100644 --- a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/MTableTest.java +++ b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/MTableTest.java @@ -13,14 +13,13 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; -public class MTableTest { +class MTableTest { static MTable base() { MTable table = new MTable("tab"); table.addColumn(new MColumn("id", "bigint")); table.addColumn(new MColumn("name", "varchar(20)")); table.addColumn(new MColumn("status", "varchar(3)")); - return table; } @@ -29,7 +28,6 @@ public class MTableTest { table.addColumn(new MColumn("id", "bigint")); table.addColumn(new MColumn("name", "varchar(20)")); table.addColumn(new MColumn("comment", "varchar(1000)")); - return table; } @@ -55,7 +53,7 @@ public class MTableTest { } @Test - public void schema() { + void schema() { MTable table = new MTable("tab"); assertNull(table.getSchema()); @@ -65,8 +63,29 @@ public class MTableTest { } @Test - public void test_allHistoryColumns() throws Exception { + void addColumnScalar_when_new() { + MTable table = new MTable("tab"); + MColumn mColumn = table.addColumnScalar("billing_id", "bigint"); + assertThat(mColumn).isNotNull(); + assertThat(mColumn.getName()).isEqualTo("billing_id"); + assertThat(mColumn.getType()).isEqualTo("bigint"); + } + + @Test + void addColumnScalar_when_existingColumnDefined() { + MTable table = new MTable("tab"); + MColumn col = new MColumn("billing_id", "bigint"); + col.setForeignKeyName("fk_tab_billing_id"); + col.setForeignKeyIndex("ix_tab_billing_id"); + table.addColumn(col); + + MColumn mColumn = table.addColumnScalar("billing_id", "bigint"); + assertThat(mColumn).isSameAs(col); + } + + @Test + void test_allHistoryColumns() { MTable base = base(); base.registerPendingDropColumn("fullName"); base.registerPendingDropColumn("last"); @@ -76,16 +95,14 @@ public class MTableTest { } @Test - public void test_dropTable() { - + void test_dropTable() { MTable base = base(); DropTable dropTable = base.dropTable(); assertThat(dropTable.getName()).isEqualTo(base.getName()); } @Test - public void test_compare_addColumnDropColumn() throws Exception { - + void test_compare_addColumnDropColumn() { ModelDiff diff = new ModelDiff(); diff.compareTables(base(), newTable()); @@ -104,8 +121,7 @@ public class MTableTest { } @Test - public void test_compare_addTwoColumnsToSameTable() throws Exception { - + void test_compare_addTwoColumnsToSameTable() { ModelDiff diff = new ModelDiff(); diff.compareTables(base(), newTableAdd2Columns()); @@ -117,12 +133,10 @@ public class MTableTest { assertThat(addColumn.getColumn()).extracting("type").contains("varchar(1000)", "varchar(2000)"); assertThat(diff.getDropChanges()).hasSize(0); - } @Test - public void test_compare_modifyColumn() throws Exception { - + void test_compare_modifyColumn() { ModelDiff diff = new ModelDiff(); diff.compareTables(base(), newTableModifiedColumn()); @@ -138,12 +152,10 @@ public class MTableTest { assertThat(alterColumn.getReferences()).isNull(); assertThat(diff.getDropChanges()).hasSize(0); - } @Test - public void test_apply_dropColumn() { - + void test_apply_dropColumn() { MTable base = base(); DropColumn dropColumn = new DropColumn(); @@ -155,7 +167,7 @@ public class MTableTest { } @Test - public void test_apply_dropColumn_doesNotExist() { + void test_apply_dropColumn_doesNotExist() { MTable base = base(); DropColumn dropColumn = new DropColumn(); @@ -165,7 +177,7 @@ public class MTableTest { } @Test - public void test_apply_alterColumn_doesNotExist() { + void test_apply_alterColumn_doesNotExist() { MTable base = base(); AlterColumn alterColumn = new AlterColumn(); @@ -177,8 +189,7 @@ public class MTableTest { } @Test - public void test_apply_alterColumn_type() { - + void test_apply_alterColumn_type() { MTable base = base(); AlterColumn alterColumn = new AlterColumn(); @@ -191,8 +202,7 @@ public class MTableTest { } @Test - public void test_compare_addAndDropColumn() throws Exception { - + void test_compare_addAndDropColumn() { MTable base = base(); MTable newTable = newTable(); @@ -204,8 +214,7 @@ public class MTableTest { } @Test - public void test_compare_addHistoryToTable() { - + void test_compare_addHistoryToTable() { MTable base = base(); MTable withHistory = base(); withHistory.setWithHistory(true); @@ -219,8 +228,7 @@ public class MTableTest { } @Test - public void test_compare_removeHistoryFromTable() throws Exception { - + void test_compare_removeHistoryFromTable() { MTable withHistory = base(); withHistory.setWithHistory(true); diff --git a/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.1.sql b/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.1.sql index b68a9e881..37c9d9db5 100644 --- a/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.1.sql +++ b/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.1.sql @@ -20,112 +20,52 @@ create table migtest_mtm_m_migtest_mtm_c ( alter table migtest_ckey_detail add column one_key integer; alter table migtest_ckey_detail add column two_key varchar(127); -alter table migtest_ckey_detail add constraint fk_migtest_ckey_detail_parent foreign key (one_key,two_key) references migtest_ckey_parent (one_key,two_key) on delete restrict; +alter table migtest_ckey_detail add constraint fk_mgtst_ck_e1qkb5 foreign key (one_key,two_key) references migtest_ckey_parent (one_key,two_key) on delete restrict; alter table migtest_ckey_parent add column assoc_id integer; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_FK_CASCADE_ONE_ID' and tabname = 'MIGTEST_FK_CASCADE') then - prepare stmt from 'alter table migtest_fk_cascade drop constraint fk_migtest_fk_cascade_one_id'; - execute stmt; -end if; -end$$; -alter table migtest_fk_cascade add constraint fk_migtest_fk_cascade_one_id foreign key (one_id) references migtest_fk_cascade_one (id) on delete restrict; -alter table migtest_fk_none add constraint fk_migtest_fk_none_one_id foreign key (one_id) references migtest_fk_one (id) on delete restrict; -alter table migtest_fk_none_via_join add constraint fk_migtest_fk_none_via_join_one_id foreign key (one_id) references migtest_fk_one (id) on delete restrict; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_FK_SET_NULL_ONE_ID' and tabname = 'MIGTEST_FK_SET_NULL') then - prepare stmt from 'alter table migtest_fk_set_null drop constraint fk_migtest_fk_set_null_one_id'; - execute stmt; -end if; -end$$; -alter table migtest_fk_set_null add constraint fk_migtest_fk_set_null_one_id foreign key (one_id) references migtest_fk_one (id) on delete restrict; +alter table migtest_fk_cascade drop constraint fk_mgtst_fk_65kf6l; +alter table migtest_fk_cascade add constraint fk_mgtst_fk_65kf6l foreign key (one_id) references migtest_fk_cascade_one (id) on delete restrict; +alter table migtest_fk_none add constraint fk_mgtst_fk_nn_n_d foreign key (one_id) references migtest_fk_one (id) on delete restrict; +alter table migtest_fk_none_via_join add constraint fk_mgtst_fk_9tknzj foreign key (one_id) references migtest_fk_one (id) on delete restrict; +alter table migtest_fk_set_null drop constraint fk_mgtst_fk_wicx8x; +alter table migtest_fk_set_null add constraint fk_mgtst_fk_wicx8x foreign key (one_id) references migtest_fk_one (id) on delete restrict; update migtest_e_basic set status = 'A' where status is null; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_BASIC_STATUS' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint ck_migtest_e_basic_status'; - execute stmt; -end if; -end$$; +alter table migtest_e_basic drop constraint ck_mgtst__bsc_stts; alter table migtest_e_basic alter column status set default 'A'; alter table migtest_e_basic alter column status set not null; -alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_BASIC_STATUS2' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint ck_migtest_e_basic_status2'; - execute stmt; -end if; -end$$; +alter table migtest_e_basic add constraint ck_mgtst__bsc_stts check ( status in ('N','A','I','?')); +alter table migtest_e_basic drop constraint ck_mgtst__b_z543fg; alter table migtest_e_basic alter column status2 set data type varchar(127); alter table migtest_e_basic alter column status2 drop default; alter table migtest_e_basic alter column status2 drop not null; -call sysproc.admin_cmd('reorg table migtest_e_basic') /* reorg #1 */; --- db2 does not support parial null indices :( - so we have to clean; -update migtest_e_basic set status = 'N' where id = 1; +-- rename all collisions; create unique index uq_migtest_e_basic_description on migtest_e_basic(description) exclude null keys; insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; -alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict; +alter table migtest_e_basic add constraint fk_mgtst__bsc_sr_d foreign key (user_id) references migtest_e_user (id) on delete restrict; alter table migtest_e_basic alter column user_id drop not null; alter table migtest_e_basic add column new_string_field varchar(255) default 'foo''bar' not null; alter table migtest_e_basic add column new_boolean_field boolean default true not null; -call sysproc.admin_cmd('reorg table migtest_e_basic') /* reorg #2 */; update migtest_e_basic set new_boolean_field = old_boolean; alter table migtest_e_basic add column new_boolean_field2 boolean default true not null; alter table migtest_e_basic add column progress integer default 0 not null; -alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add constraint ck_mgtst__b_l39g41 check ( progress in (0,1,2)); alter table migtest_e_basic add column new_integer integer default 42 not null; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_INDEXTEST2' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_indextest2'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_INDEXTEST2') then - prepare stmt from 'drop index uq_migtest_e_basic_indextest2'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_INDEXTEST6' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_indextest6'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_INDEXTEST6') then - prepare stmt from 'drop index uq_migtest_e_basic_indextest6'; - execute stmt; -end if; -end$$; +alter table migtest_e_basic drop constraint uq_mgtst__b_4aybzy; +alter table migtest_e_basic drop constraint uq_mgtst__b_4ayc02; create unique index uq_migtest_e_basic_status_indextest1 on migtest_e_basic(status,indextest1) exclude null keys; create unique index uq_migtest_e_basic_name on migtest_e_basic(name) exclude null keys; create unique index uq_migtest_e_basic_indextest4 on migtest_e_basic(indextest4) exclude null keys; create unique index uq_migtest_e_basic_indextest5 on migtest_e_basic(indextest5) exclude null keys; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_ENUM_TEST_STATUS' and tabname = 'MIGTEST_E_ENUM') then - prepare stmt from 'alter table migtest_e_enum drop constraint ck_migtest_e_enum_test_status'; - execute stmt; -end if; -end$$; +alter table migtest_e_enum drop constraint ck_mgtst__n_773sok; comment on column migtest_e_history.test_string is 'Column altered to long now'; alter table migtest_e_history alter column test_string set data type bigint; comment on table migtest_e_history is 'We have history now'; -call sysproc.admin_cmd('reorg table migtest_e_history') /* reorg #3 */; -- NOTE: table has @History - special migration may be necessary update migtest_e_history2 set test_string = 'unknown' where test_string is null; alter table migtest_e_history2 alter column test_string set default 'unknown'; @@ -138,8 +78,6 @@ alter table migtest_e_history4 alter column test_number set data type bigint; alter table migtest_e_history5 add column test_boolean boolean default false not null; -call sysproc.admin_cmd('reorg table migtest_e_history2') /* reorg #4 */; -call sysproc.admin_cmd('reorg table migtest_e_history4') /* reorg #5 */; -- NOTE: table has @History - special migration may be necessary update migtest_e_history6 set test_number1 = 42 where test_number1 is null; alter table migtest_e_history6 alter column test_number1 set default 42; @@ -149,37 +87,24 @@ alter table migtest_e_softdelete add column deleted boolean default false not nu alter table migtest_oto_child add column master_id bigint; -call sysproc.admin_cmd('reorg table migtest_e_history6') /* reorg #6 */; -create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); -create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'IX_MIGTEST_E_BASIC_INDEXTEST1') then - prepare stmt from 'drop index ix_migtest_e_basic_indextest1'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'IX_MIGTEST_E_BASIC_INDEXTEST5') then - prepare stmt from 'drop index ix_migtest_e_basic_indextest5'; - execute stmt; -end if; -end$$; -create index ix_migtest_mtm_c_migtest_mtm_m_migtest_mtm_c on migtest_mtm_c_migtest_mtm_m (migtest_mtm_c_id); -alter table migtest_mtm_c_migtest_mtm_m add constraint fk_migtest_mtm_c_migtest_mtm_m_migtest_mtm_c foreign key (migtest_mtm_c_id) references migtest_mtm_c (id) on delete restrict; +create index ix_mgtst__b_eu8css on migtest_e_basic (indextest3); +create index ix_mgtst__b_eu8csv on migtest_e_basic (indextest6); +drop index ix_mgtst__b_eu8csq; +drop index ix_mgtst__b_eu8csu; +create index ix_mgtst_mt_3ug4ok on migtest_mtm_c_migtest_mtm_m (migtest_mtm_c_id); +alter table migtest_mtm_c_migtest_mtm_m add constraint fk_mgtst_mt_93awga foreign key (migtest_mtm_c_id) references migtest_mtm_c (id) on delete restrict; -create index ix_migtest_mtm_c_migtest_mtm_m_migtest_mtm_m on migtest_mtm_c_migtest_mtm_m (migtest_mtm_m_id); -alter table migtest_mtm_c_migtest_mtm_m add constraint fk_migtest_mtm_c_migtest_mtm_m_migtest_mtm_m foreign key (migtest_mtm_m_id) references migtest_mtm_m (id) on delete restrict; +create index ix_mgtst_mt_3ug4ou on migtest_mtm_c_migtest_mtm_m (migtest_mtm_m_id); +alter table migtest_mtm_c_migtest_mtm_m add constraint fk_mgtst_mt_93awgk foreign key (migtest_mtm_m_id) references migtest_mtm_m (id) on delete restrict; -create index ix_migtest_mtm_m_migtest_mtm_c_migtest_mtm_m on migtest_mtm_m_migtest_mtm_c (migtest_mtm_m_id); -alter table migtest_mtm_m_migtest_mtm_c add constraint fk_migtest_mtm_m_migtest_mtm_c_migtest_mtm_m foreign key (migtest_mtm_m_id) references migtest_mtm_m (id) on delete restrict; +create index ix_mgtst_mt_b7nbcu on migtest_mtm_m_migtest_mtm_c (migtest_mtm_m_id); +alter table migtest_mtm_m_migtest_mtm_c add constraint fk_mgtst_mt_ggi34k foreign key (migtest_mtm_m_id) references migtest_mtm_m (id) on delete restrict; -create index ix_migtest_mtm_m_migtest_mtm_c_migtest_mtm_c on migtest_mtm_m_migtest_mtm_c (migtest_mtm_c_id); -alter table migtest_mtm_m_migtest_mtm_c add constraint fk_migtest_mtm_m_migtest_mtm_c_migtest_mtm_c foreign key (migtest_mtm_c_id) references migtest_mtm_c (id) on delete restrict; +create index ix_mgtst_mt_b7nbck on migtest_mtm_m_migtest_mtm_c (migtest_mtm_c_id); +alter table migtest_mtm_m_migtest_mtm_c add constraint fk_mgtst_mt_ggi34a foreign key (migtest_mtm_c_id) references migtest_mtm_c (id) on delete restrict; -create index ix_migtest_ckey_parent_assoc_id on migtest_ckey_parent (assoc_id); -alter table migtest_ckey_parent add constraint fk_migtest_ckey_parent_assoc_id foreign key (assoc_id) references migtest_ckey_assoc (id) on delete restrict; +create index ix_mgtst_ck_x45o21 on migtest_ckey_parent (assoc_id); +alter table migtest_ckey_parent add constraint fk_mgtst_ck_da00mr foreign key (assoc_id) references migtest_ckey_assoc (id) on delete restrict; -alter table migtest_oto_child add constraint fk_migtest_oto_child_master_id foreign key (master_id) references migtest_oto_master (id) on delete restrict; +alter table migtest_oto_child add constraint fk_mgtst_t__csyl38 foreign key (master_id) references migtest_oto_master (id) on delete restrict; diff --git a/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.3.sql b/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.3.sql index 4b5fdcf13..ab2148795 100644 --- a/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.3.sql +++ b/ebean-ddl-generator/src/test/resources/dbmigration/migrationtest/db2/1.3.sql @@ -5,166 +5,44 @@ create table migtest_e_ref ( name varchar(127) not null, constraint pk_migtest_e_ref primary key (id) ); -alter table migtest_e_ref add constraint uq_migtest_e_ref_name unique (name); +alter table migtest_e_ref add constraint uq_mgtst__rf_nm unique (name); -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_CKEY_DETAIL_PARENT' and tabname = 'MIGTEST_CKEY_DETAIL') then - prepare stmt from 'alter table migtest_ckey_detail drop constraint fk_migtest_ckey_detail_parent'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_FK_CASCADE_ONE_ID' and tabname = 'MIGTEST_FK_CASCADE') then - prepare stmt from 'alter table migtest_fk_cascade drop constraint fk_migtest_fk_cascade_one_id'; - execute stmt; -end if; -end$$; -alter table migtest_fk_cascade add constraint fk_migtest_fk_cascade_one_id foreign key (one_id) references migtest_fk_cascade_one (id) on delete cascade; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_FK_NONE_ONE_ID' and tabname = 'MIGTEST_FK_NONE') then - prepare stmt from 'alter table migtest_fk_none drop constraint fk_migtest_fk_none_one_id'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_FK_NONE_VIA_JOIN_ONE_ID' and tabname = 'MIGTEST_FK_NONE_VIA_JOIN') then - prepare stmt from 'alter table migtest_fk_none_via_join drop constraint fk_migtest_fk_none_via_join_one_id'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_FK_SET_NULL_ONE_ID' and tabname = 'MIGTEST_FK_SET_NULL') then - prepare stmt from 'alter table migtest_fk_set_null drop constraint fk_migtest_fk_set_null_one_id'; - execute stmt; -end if; -end$$; -alter table migtest_fk_set_null add constraint fk_migtest_fk_set_null_one_id foreign key (one_id) references migtest_fk_one (id) on delete set null; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_BASIC_STATUS' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint ck_migtest_e_basic_status'; - execute stmt; -end if; -end$$; +alter table migtest_ckey_detail drop constraint fk_mgtst_ck_e1qkb5; +alter table migtest_fk_cascade drop constraint fk_mgtst_fk_65kf6l; +alter table migtest_fk_cascade add constraint fk_mgtst_fk_65kf6l foreign key (one_id) references migtest_fk_cascade_one (id) on delete cascade; +alter table migtest_fk_none drop constraint fk_mgtst_fk_nn_n_d; +alter table migtest_fk_none_via_join drop constraint fk_mgtst_fk_9tknzj; +alter table migtest_fk_set_null drop constraint fk_mgtst_fk_wicx8x; +alter table migtest_fk_set_null add constraint fk_mgtst_fk_wicx8x foreign key (one_id) references migtest_fk_one (id) on delete set null; +alter table migtest_e_basic drop constraint ck_mgtst__bsc_stts; alter table migtest_e_basic alter column status drop default; alter table migtest_e_basic alter column status drop not null; -alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic add constraint ck_mgtst__bsc_stts check ( status in ('N','A','I')); -call sysproc.admin_cmd('reorg table migtest_e_basic') /* reorg #1 */; update migtest_e_basic set status2 = 'N' where status2 is null; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_BASIC_STATUS2' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint ck_migtest_e_basic_status2'; - execute stmt; -end if; -end$$; +alter table migtest_e_basic drop constraint ck_mgtst__b_z543fg; alter table migtest_e_basic alter column status2 set data type varchar(1); alter table migtest_e_basic alter column status2 set default 'N'; alter table migtest_e_basic alter column status2 set not null; -alter table migtest_e_basic add constraint ck_migtest_e_basic_status2 check ( status2 in ('N','A','I')); -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_DESCRIPTION' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_description'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_DESCRIPTION') then - prepare stmt from 'drop index uq_migtest_e_basic_description'; - execute stmt; -end if; -end$$; +alter table migtest_e_basic add constraint ck_mgtst__b_z543fg check ( status2 in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_mgtst__b_vs45xo; -call sysproc.admin_cmd('reorg table migtest_e_basic') /* reorg #2 */; update migtest_e_basic set user_id = 23 where user_id is null; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'FK_MIGTEST_E_BASIC_USER_ID' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint fk_migtest_e_basic_user_id'; - execute stmt; -end if; -end$$; +alter table migtest_e_basic drop constraint fk_mgtst__bsc_sr_d; alter table migtest_e_basic alter column user_id set default 23; alter table migtest_e_basic alter column user_id set not null; alter table migtest_e_basic add column old_boolean boolean default false not null; alter table migtest_e_basic add column old_boolean2 boolean; alter table migtest_e_basic add column eref_id integer; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_STATUS_INDEXTEST1' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_status_indextest1'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_STATUS_INDEXTEST1') then - prepare stmt from 'drop index uq_migtest_e_basic_status_indextest1'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_NAME' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_name'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_NAME') then - prepare stmt from 'drop index uq_migtest_e_basic_name'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_INDEXTEST4' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_indextest4'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_INDEXTEST4') then - prepare stmt from 'drop index uq_migtest_e_basic_indextest4'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'UQ_MIGTEST_E_BASIC_INDEXTEST5' and tabname = 'MIGTEST_E_BASIC') then - prepare stmt from 'alter table migtest_e_basic drop constraint uq_migtest_e_basic_indextest5'; - execute stmt; -end if; -end$$ -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'UQ_MIGTEST_E_BASIC_INDEXTEST5') then - prepare stmt from 'drop index uq_migtest_e_basic_indextest5'; - execute stmt; -end if; -end$$; -call sysproc.admin_cmd('reorg table migtest_e_basic') /* reorg #3 */; +alter table migtest_e_basic drop constraint uq_mgtst__b_ucfcne; +alter table migtest_e_basic drop constraint uq_mgtst__bsc_nm; +alter table migtest_e_basic drop constraint uq_mgtst__b_4ayc00; +alter table migtest_e_basic drop constraint uq_mgtst__b_4ayc01; create unique index uq_migtest_e_basic_indextest2 on migtest_e_basic(indextest2) exclude null keys; create unique index uq_migtest_e_basic_indextest6 on migtest_e_basic(indextest6) exclude null keys; -delimiter $$ -begin -if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_ENUM_TEST_STATUS' and tabname = 'MIGTEST_E_ENUM') then - prepare stmt from 'alter table migtest_e_enum drop constraint ck_migtest_e_enum_test_status'; - execute stmt; -end if; -end$$; -alter table migtest_e_enum add constraint ck_migtest_e_enum_test_status check ( test_status in ('N','A','I')); +alter table migtest_e_enum drop constraint ck_mgtst__n_773sok; +alter table migtest_e_enum add constraint ck_mgtst__n_773sok check ( test_status in ('N','A','I')); comment on column migtest_e_history.test_string is ''; comment on table migtest_e_history is ''; alter table migtest_e_history2 alter column test_string drop default; @@ -176,30 +54,14 @@ alter table migtest_e_history4 alter column test_number set data type integer; alter table migtest_e_history6 alter column test_number1 drop default; alter table migtest_e_history6 alter column test_number1 drop not null; -call sysproc.admin_cmd('reorg table migtest_e_history2') /* reorg #4 */; -call sysproc.admin_cmd('reorg table migtest_e_history6') /* reorg #5 */; -call sysproc.admin_cmd('reorg table migtest_e_history4') /* reorg #6 */; -- NOTE: table has @History - special migration may be necessary update migtest_e_history6 set test_number2 = 7 where test_number2 is null; alter table migtest_e_history6 alter column test_number2 set default 7; alter table migtest_e_history6 alter column test_number2 set not null; -call sysproc.admin_cmd('reorg table migtest_e_history6') /* reorg #7 */; -create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); -create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'IX_MIGTEST_E_BASIC_INDEXTEST3') then - prepare stmt from 'drop index ix_migtest_e_basic_indextest3'; - execute stmt; -end if; -end$$; -delimiter $$ -begin -if exists (select indname from syscat.indexes where indschema = current_schema and indname = 'IX_MIGTEST_E_BASIC_INDEXTEST6') then - prepare stmt from 'drop index ix_migtest_e_basic_indextest6'; - execute stmt; -end if; -end$$; -create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); -alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict; +create index ix_mgtst__b_eu8csq on migtest_e_basic (indextest1); +create index ix_mgtst__b_eu8csu on migtest_e_basic (indextest5); +drop index ix_mgtst__b_eu8css; +drop index ix_mgtst__b_eu8csv; +create index ix_mgtst__bsc_rf_d on migtest_e_basic (eref_id); +alter table migtest_e_basic add constraint fk_mgtst__bsc_rf_d foreign key (eref_id) references migtest_e_ref (id) on delete restrict; diff --git a/ebean-externalmapping-xml/pom.xml b/ebean-externalmapping-xml/pom.xml index 4ed9a2e8a..602f416c8 100644 --- a/ebean-externalmapping-xml/pom.xml +++ b/ebean-externalmapping-xml/pom.xml @@ -89,7 +89,7 @@ - io.ebean.tile:enhancement:12.14.1 + io.ebean.tile:enhancement:12.15.0 io.avaje.tile:moditech-module:1.0 diff --git a/ebean-kotlin/pom.xml b/ebean-kotlin/pom.xml index c16952aa1..d4aa3c30d 100644 --- a/ebean-kotlin/pom.xml +++ b/ebean-kotlin/pom.xml @@ -91,7 +91,7 @@ true - io.ebean.tile:enhancement:12.13.1 + io.ebean.tile:enhancement:12.15.0 diff --git a/ebean-postgis/pom.xml b/ebean-postgis/pom.xml index 96b3f75b8..ac99bf2e1 100644 --- a/ebean-postgis/pom.xml +++ b/ebean-postgis/pom.xml @@ -44,7 +44,7 @@ org.postgresql postgresql - 42.2.24 + 42.3.2 provided @@ -52,7 +52,7 @@ org.slf4j slf4j-api - 1.7.30 + 1.7.33 provided @@ -105,7 +105,7 @@ true - io.ebean.tile:enhancement:12.14.1 + io.ebean.tile:enhancement:12.15.0 io.avaje.tile:moditech-module:1.0 diff --git a/ebean-querybean/pom.xml b/ebean-querybean/pom.xml index 674598683..9c9f3ad93 100644 --- a/ebean-querybean/pom.xml +++ b/ebean-querybean/pom.xml @@ -100,7 +100,7 @@ true - io.ebean.tile:enhancement:12.14.1 + io.ebean.tile:enhancement:12.15.0 io.avaje.tile:moditech-module:1.0 diff --git a/ebean-redis/pom.xml b/ebean-redis/pom.xml index ba479df6c..d0b3ad2f1 100644 --- a/ebean-redis/pom.xml +++ b/ebean-redis/pom.xml @@ -16,7 +16,7 @@ redis.clients jedis - 4.1.0 + 4.1.1 @@ -80,7 +80,7 @@ true - io.ebean.tile:enhancement:12.14.1 + io.ebean.tile:enhancement:12.15.0 io.avaje.tile:moditech-module:1.0 diff --git a/ebean-test/pom.xml b/ebean-test/pom.xml index 403ff25b1..1d10a397a 100644 --- a/ebean-test/pom.xml +++ b/ebean-test/pom.xml @@ -62,14 +62,14 @@ org.assertj assertj-core - 3.14.0 + 3.22.0 org.glassfish.jaxb jaxb-runtime - 2.3.2 + 2.3.6 @@ -98,7 +98,7 @@ io.avaje mod-uuid - 1.1 + 1.3 test @@ -147,7 +147,7 @@ org.postgresql postgresql - 42.2.24 + 42.3.2 org.checkerframework @@ -226,7 +226,7 @@ ch.qos.logback logback-classic - 1.2.9 + 1.2.10 test @@ -249,7 +249,7 @@ true - io.ebean.tile:enhancement:12.14.1 + io.ebean.tile:enhancement:12.15.0 io.avaje.tile:moditech-module:1.0 diff --git a/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java b/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java index 8cd4f6395..5366597a1 100644 --- a/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java +++ b/ebean-test/src/main/java/io/ebean/test/config/AutoConfigureForTesting.java @@ -10,6 +10,8 @@ import org.slf4j.LoggerFactory; import java.util.Properties; +import javax.sql.DataSource; + /** * Automatically configure ServerConfig for testing purposes. *

@@ -47,6 +49,29 @@ public class AutoConfigureForTesting implements AutoConfigure { @Override public void postConfigure(DatabaseConfig config) { setupProviders(config); + + if (org.h2.engine.Constants.VERSION_MAJOR == 1) { + // This code may be removed later, when droppinv H2 1.xxx compatibility + System.err.println("Running tests in H2 1.xxx compatibility mode"); + System.setProperty("ebean.h2.useV1Syntax", "true"); + makeV1Compatible(config.getDataSourceConfig()); + makeV1Compatible(config.getReadOnlyDataSourceConfig()); + } + } + + private void makeV1Compatible(DataSourceConfig ds) { + if (ds == null) { + return; + } + String url = ds.getUrl(); + if (url == null || !url.startsWith("jdbc:h2:")) { + return; + } + // remove illegal URL options + url = url.replace(";MODE=LEGACY", ""); + url = url.replace(";NON_KEYWORDS=KEY,VALUE", ""); + url = url.replace(";NON_KEYWORDS=KEY", ""); + ds.setUrl(url); } /** diff --git a/ebean-test/src/main/java/io/ebean/test/config/platform/PlatformAutoConfig.java b/ebean-test/src/main/java/io/ebean/test/config/platform/PlatformAutoConfig.java index deefcd0fb..3569db727 100644 --- a/ebean-test/src/main/java/io/ebean/test/config/platform/PlatformAutoConfig.java +++ b/ebean-test/src/main/java/io/ebean/test/config/platform/PlatformAutoConfig.java @@ -35,18 +35,14 @@ public class PlatformAutoConfig { KNOWN_PLATFORMS.put("cockroach", new CockroachSetup()); KNOWN_PLATFORMS.put("hana", new HanaSetup()); KNOWN_PLATFORMS.put("db2", new Db2Setup()); + KNOWN_PLATFORMS.put("yugabyte", new YugabyteSetup()); } private final DatabaseConfig config; - private final Properties properties; - private String db; - private String platform; - private PlatformSetup platformSetup; - private String databaseName; public PlatformAutoConfig(String db, DatabaseConfig config) { diff --git a/ebean-test/src/main/java/io/ebean/test/config/platform/PostgresSetup.java b/ebean-test/src/main/java/io/ebean/test/config/platform/PostgresSetup.java index e5d1206f7..836532f76 100644 --- a/ebean-test/src/main/java/io/ebean/test/config/platform/PostgresSetup.java +++ b/ebean-test/src/main/java/io/ebean/test/config/platform/PostgresSetup.java @@ -6,41 +6,33 @@ class PostgresSetup implements PlatformSetup { @Override public Properties setup(Config config) { - int defaultPort = config.isUseDocker() ? 6432 : 5432; - config.ddlMode("dropCreate"); config.setDefaultPort(defaultPort); config.setUsernameDefault(); config.setPasswordDefault(); config.setUrl("jdbc:postgresql://${host}:${port}/${databaseName}"); - String schema = config.getSchema(); if (schema != null && !schema.equals(config.getUsername())) { config.urlAppend("?currentSchema=" + schema); } config.setDriver("org.postgresql.Driver"); config.datasourceDefaults(); - return dockerProperties(config); } private Properties dockerProperties(Config config) { - if (!config.isUseDocker()) { return new Properties(); } - - config.setDockerVersion("12"); + config.setDockerVersion("14"); config.setExtensions("hstore,pgcrypto"); return config.getDockerProperties(); } @Override public void setupExtraDbDataSource(Config config) { - int defaultPort = config.isUseDocker() ? 6432 : 5432; - config.setDefaultPort(defaultPort); config.setExtraUsernameDefault(); config.setExtraDbPasswordDefault(); diff --git a/ebean-test/src/main/java/io/ebean/test/config/platform/YugabyteSetup.java b/ebean-test/src/main/java/io/ebean/test/config/platform/YugabyteSetup.java new file mode 100644 index 000000000..eb14158e3 --- /dev/null +++ b/ebean-test/src/main/java/io/ebean/test/config/platform/YugabyteSetup.java @@ -0,0 +1,49 @@ +package io.ebean.test.config.platform; + +import java.util.Properties; + +class YugabyteSetup implements PlatformSetup { + + @Override + public Properties setup(Config config) { + int defaultPort = config.isUseDocker() ? 6433 : 5433; + config.ddlMode("dropCreate"); + config.setDefaultPort(defaultPort); + config.setUsernameDefault(); + config.setPasswordDefault(); + config.setUrl("jdbc:postgresql://${host}:${port}/${databaseName}"); + String schema = config.getSchema(); + if (schema != null && !schema.equals(config.getUsername())) { + config.urlAppend("?currentSchema=" + schema); + } + config.setDriver("org.postgresql.Driver"); + config.datasourceDefaults(); + return dockerProperties(config); + } + + private Properties dockerProperties(Config config) { + if (!config.isUseDocker()) { + return new Properties(); + } + config.setDockerVersion("2.11.2.0-b89"); + config.setExtensions("pgcrypto"); + return config.getDockerProperties(); + } + + @Override + public void setupExtraDbDataSource(Config config) { + int defaultPort = config.isUseDocker() ? 6433 : 5433; + config.setDefaultPort(defaultPort); + config.setExtraUsernameDefault(); + config.setExtraDbPasswordDefault(); + config.setUrl("jdbc:postgresql://${host}:${port}/${databaseName}"); + config.setDriver("org.postgresql.Driver"); + config.extraDatasourceDefaults(); + } + + @Override + public boolean isLocal() { + return false; + } + +} diff --git a/ebean-test/src/test/java/io/ebean/BaseTestCase.java b/ebean-test/src/test/java/io/ebean/BaseTestCase.java index 6e9ad234f..e7b591c3d 100644 --- a/ebean-test/src/test/java/io/ebean/BaseTestCase.java +++ b/ebean-test/src/test/java/io/ebean/BaseTestCase.java @@ -199,6 +199,10 @@ public abstract class BaseTestCase { return Platform.POSTGRES == platform().base(); } + public boolean isYugabyte() { + return Platform.YUGABYTE == platform().base(); + } + public boolean isMySql() { return Platform.MYSQL == platform(); } diff --git a/ebean-test/src/test/java/io/ebean/EbeanServer_refresh.java b/ebean-test/src/test/java/io/ebean/EbeanServer_refresh.java index 86c25de9b..1ff650b7d 100644 --- a/ebean-test/src/test/java/io/ebean/EbeanServer_refresh.java +++ b/ebean-test/src/test/java/io/ebean/EbeanServer_refresh.java @@ -6,18 +6,39 @@ import org.tests.model.basic.Order; import org.tests.model.basic.OrderDetail; import org.tests.model.basic.ResetBasicData; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; -public class EbeanServer_refresh { +class EbeanServer_refresh { + + private Path createSqlFile() throws IOException { + File f = File.createTempFile("test-script", ".sql"); + Path path = f.toPath(); + List lines = new ArrayList<>(); + lines.add("select * from o_customer;"); + Files.write(path, lines, StandardOpenOption.TRUNCATE_EXISTING); + return path; + } @Test - public void basic() { + void script_run_asFile() throws IOException { + ResetBasicData.reset(); + Path path = createSqlFile(); + DB.script().run(path); + DB.script().run(path, Collections.emptyMap()); + } + + @Test + void basic() { Map map = new HashMap<>(); map.put("tableName", "e_basic"); @@ -47,8 +68,7 @@ public class EbeanServer_refresh { } @Test - public void refresh_when_oneToManyLoaded() { - + void refresh_when_oneToManyLoaded() { ResetBasicData.reset(); Order order = DB.find(Order.class, 1); @@ -59,8 +79,7 @@ public class EbeanServer_refresh { } @Test - public void refresh_when_oneToManyVanilla() { - + void refresh_when_oneToManyVanilla() { ResetBasicData.reset(); Order order = DB.find(Order.class, 1); @@ -71,8 +90,7 @@ public class EbeanServer_refresh { } @Test - public void refresh_when_oneToManyNull() { - + void refresh_when_oneToManyNull() { ResetBasicData.reset(); Order order = DB.find(Order.class, 1); @@ -82,15 +100,11 @@ public class EbeanServer_refresh { DB.refresh(order); } - - @Test - public void refresh_on_details_new() { - + void refresh_on_details_new() { ResetBasicData.reset(); Order order = DB.find(Order.class, 1); - DB.refresh(order); // call refresh BEFORE first access on "getDetail"; assertThat(order.getDetails()).hasSize(3); @@ -100,13 +114,9 @@ public class EbeanServer_refresh { DB.save(detail); try { - assertThat(order.getDetails()).hasSize(3); - DB.refresh(order); - assertThat(order.getDetails()).hasSize(4); - } finally { DB.delete(detail); // restore old state } @@ -116,13 +126,9 @@ public class EbeanServer_refresh { assertThat(order.getDetails()).hasSize(3); } - - @Test - public void refresh_on_details_changed() { - + void refresh_on_details_changed() { ResetBasicData.reset(); - Order order = DB.find(Order.class, 1); DB.refresh(order); // call refresh BEFORE first access on "getDetail" @@ -139,11 +145,8 @@ public class EbeanServer_refresh { try { assertThat(order.getDetails().get(0).getOrderQty()).isEqualTo(5); - DB.refresh(order); - assertThat(order.getDetails().get(0).getOrderQty()).isEqualTo(42); - } finally { // restore old value detail.setOrderQty(5); @@ -151,8 +154,6 @@ public class EbeanServer_refresh { } DB.refresh(order); - assertThat(order.getDetails().get(0).getOrderQty()).isEqualTo(5); - } } diff --git a/ebean-test/src/test/java/io/ebean/config/PlatformNoGeneratedKeysTest.java b/ebean-test/src/test/java/io/ebean/config/PlatformNoGeneratedKeysTest.java index 6c57e56bb..37d02bbb8 100644 --- a/ebean-test/src/test/java/io/ebean/config/PlatformNoGeneratedKeysTest.java +++ b/ebean-test/src/test/java/io/ebean/config/PlatformNoGeneratedKeysTest.java @@ -112,7 +112,7 @@ public class PlatformNoGeneratedKeysTest { config.setDdlRun(true); config.getClasses().add(EBasicVer.class); config.getClasses().add(BasicDraftableBean.class); - + config.loadFromProperties(); // trigger auto config for H2 1.x return DatabaseFactory.create(config); } diff --git a/ebean-test/src/test/java/io/ebean/test/DbJsonTest.java b/ebean-test/src/test/java/io/ebean/test/DbJsonTest.java index 17ecd262b..21e28d2a3 100644 --- a/ebean-test/src/test/java/io/ebean/test/DbJsonTest.java +++ b/ebean-test/src/test/java/io/ebean/test/DbJsonTest.java @@ -1,6 +1,7 @@ package io.ebean.test; import com.fasterxml.jackson.databind.JsonNode; +import io.ebean.BaseTestCase; import io.ebean.DB; import org.etest.BSimpleFor; import org.junit.jupiter.api.Test; @@ -11,10 +12,10 @@ import static io.ebean.test.DbJson.readResource; import static org.assertj.core.api.Assertions.assertThat; -public class DbJsonTest { +class DbJsonTest extends BaseTestCase { @Test - public void of() { + void of() { DB.find(BSimpleFor.class).delete(); @@ -34,14 +35,19 @@ public class DbJsonTest { final List beans = DB.find(BSimpleFor.class).findList(); + if (isH2() || isPostgres()) { + DbJson.of(beans) + //.withPlaceholder("_") + .replace("id", "whenModified") + .assertContentMatches("/bean/example-list-match.json"); + } + DbJson.of(beans) - //.withPlaceholder("_") - .replace("id", "whenModified") - .assertContentMatches("/bean/example-list.json"); + .assertContainsResource("/bean/example-list-contains.json"); } @Test - public void assertContains_pass() { + void assertContains_pass() { BSimpleFor bean = new BSimpleFor("something-contains-me", "YeahNah"); DB.save(bean); @@ -55,7 +61,7 @@ public class DbJsonTest { } @Test - public void asJson() { + void asJson() { BSimpleFor bean = new BSimpleFor("other"); DB.save(bean); diff --git a/ebean-test/src/test/java/main/StartYugabyte.java b/ebean-test/src/test/java/main/StartYugabyte.java index b45f2b7f2..01b670c21 100644 --- a/ebean-test/src/test/java/main/StartYugabyte.java +++ b/ebean-test/src/test/java/main/StartYugabyte.java @@ -11,9 +11,10 @@ public class StartYugabyte { YugabyteConfig config = new YugabyteConfig("2.11.2.0-b89"); config.setDbName("unit"); config.setUser("unit"); + config.setExtensions("pgcrypto"); YugabyteContainer container = new YugabyteContainer(config); - container.start(); + container.startWithDropCreate(); // Run container ut_yugabyte with host:localhost port:6433 db:unit user:unit/test shutdown:None // docker run -d --name ut_yugabyte -p 6433:5433 -p 7000:7000 -p 9000:9000 -p 9042:9042 yugabytedb/yugabyte:2.11.2.0-b89 bin/yugabyted start --daemon=false diff --git a/ebean-test/src/test/java/org/tests/basic/TestMetaAnnotation.java b/ebean-test/src/test/java/org/tests/basic/TestMetaAnnotation.java index b9e8aa409..13073c583 100644 --- a/ebean-test/src/test/java/org/tests/basic/TestMetaAnnotation.java +++ b/ebean-test/src/test/java/org/tests/basic/TestMetaAnnotation.java @@ -49,7 +49,7 @@ public class TestMetaAnnotation extends BaseTestCase { * This test writes 101 spaces to "line1" which is annotated with @Size(max=100). */ @Test - @IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB, Platform.DB2}) // pg & mssql does not fail if string is too long. + @IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB, Platform.DB2, Platform.YUGABYTE}) // pg & mssql does not fail if string is too long. public void testWrite101SpacesToLine1() { Address address = new Address(); @@ -66,7 +66,7 @@ public class TestMetaAnnotation extends BaseTestCase { * This test writes 101 spaces to "line1" which is meta-annotated with {@link SizeMedium}. */ @Test - @IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB, Platform.DB2}) + @IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB, Platform.DB2, Platform.YUGABYTE}) public void testWrite101SpacesToLine2() { Address address = new Address(); diff --git a/ebean-test/src/test/java/org/tests/basic/type/TestInetAddressType.java b/ebean-test/src/test/java/org/tests/basic/type/TestInetAddressType.java index ec226169b..fad06a837 100644 --- a/ebean-test/src/test/java/org/tests/basic/type/TestInetAddressType.java +++ b/ebean-test/src/test/java/org/tests/basic/type/TestInetAddressType.java @@ -27,7 +27,7 @@ public class TestInetAddressType extends TransactionalTestCase { @Test public void testIp6() throws UnknownHostException { - if (isPostgres()) { + if (isPostgres() || isYugabyte()) { insertUpdateDeleteFind("2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334", "2001:4f8:3:ba::/64", "2001:4f8:3:ba::/64"); } else { insertUpdateDeleteFind("2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3:0:0:8a2e:370:7334", "192.168.100.128/25", "192.168.100.128/25"); diff --git a/ebean-test/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java b/ebean-test/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java index 30cdafd84..01d89b277 100644 --- a/ebean-test/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java +++ b/ebean-test/src/test/java/org/tests/expression/bitwise/TestBitwiseExpressions.java @@ -2,29 +2,21 @@ package org.tests.expression.bitwise; import io.ebean.BaseTestCase; import io.ebean.DB; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -public class TestBitwiseExpressions extends BaseTestCase { +class TestBitwiseExpressions extends BaseTestCase { @Test - public void where() { - - setup(); - bitwiseNot(); - bitwiseAnd(); - bitwiseAny(); - bitwiseAll(); - } - - private void bitwiseNot() { - + void bitwiseNot() { List notColour = DB.find(BwBean.class) // HAS_COLOUR not set ... .where().bitwiseNot("flags", BwFlags.HAS_COLOUR) + .orderBy("name") .findList(); assertThat(notColour).hasSize(2); @@ -32,8 +24,8 @@ public class TestBitwiseExpressions extends BaseTestCase { assertThat(notColour.get(1).getName()).isEqualTo("SizeOnly"); } - private void bitwiseAnd() { - + @Test + void bitwiseAnd() { List list = DB.find(BwBean.class) // not bulk set AND size set .where().bitwiseAnd("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE, BwFlags.HAS_SIZE) @@ -59,10 +51,11 @@ public class TestBitwiseExpressions extends BaseTestCase { assertThat(list.get(0).getName()).isEqualTo("ColourOnly"); } - private void bitwiseAny() { - + @Test + void bitwiseAny() { List list = DB.find(BwBean.class) .where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE) + .order().asc("id") .findList(); assertThat(list).hasSize(3); @@ -70,21 +63,23 @@ public class TestBitwiseExpressions extends BaseTestCase { assertThat(list.get(1).getName()).isEqualTo("ColourAndBulk"); assertThat(list.get(2).getName()).isEqualTo("Everything"); - list = DB.find(BwBean.class) .where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE + BwFlags.HAS_COLOUR) + .order().asc("id") .findList(); assertThat(list).hasSize(4); list = DB.find(BwBean.class) .where().bitwiseAny("flags", BwFlags.HAS_SIZE + BwFlags.HAS_COLOUR) + .order().asc("id") .findList(); assertThat(list).hasSize(4); list = DB.find(BwBean.class) .where().bitwiseAny("flags", BwFlags.HAS_SIZE) + .order().asc("id") .findList(); assertThat(list).hasSize(2); @@ -93,6 +88,7 @@ public class TestBitwiseExpressions extends BaseTestCase { list = DB.find(BwBean.class) .where().bitwiseAny("flags", BwFlags.HAS_COLOUR) + .order().asc("id") .findList(); assertThat(list).hasSize(3); @@ -101,8 +97,8 @@ public class TestBitwiseExpressions extends BaseTestCase { assertThat(list.get(2).getName()).isEqualTo("Everything"); } - private void bitwiseAll() { - + @Test + void bitwiseAll() { List list = DB.find(BwBean.class) .where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_SIZE) .findList(); @@ -137,11 +133,10 @@ public class TestBitwiseExpressions extends BaseTestCase { assertThat(list.get(0).getName()).isEqualTo("ColourOnly"); assertThat(list.get(1).getName()).isEqualTo("ColourAndBulk"); assertThat(list.get(2).getName()).isEqualTo("Everything"); - } - private void setup() { - + @BeforeAll + static void setup() { DB.find(BwBean.class).delete(); new BwBean("Nothing", BwFlags.NOTHING).save(); @@ -149,6 +144,5 @@ public class TestBitwiseExpressions extends BaseTestCase { new BwBean("SizeOnly", BwFlags.HAS_SIZE).save(); new BwBean("ColourAndBulk", BwFlags.HAS_COLOUR + BwFlags.HAS_BULK).save(); new BwBean("Everything", BwFlags.HAS_COLOUR + BwFlags.HAS_BULK + BwFlags.HAS_SIZE).save(); - } } diff --git a/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java b/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java index b4bb8f788..38798bba1 100644 --- a/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java +++ b/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java @@ -369,7 +369,7 @@ public class TestCacheViaComplexNaturalKey3 extends BaseTestCase { if (isH2()) { assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku,'-',t0.code) in (?,?) order by t0.sku desc; --bind(def,Array[2]={2-1000,3-1000})"); - } else if (isPostgres() || isOracle() || isDb2()) { + } else if (isPostgres() || isOracle() || isDb2() || isYugabyte()) { assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and (t0.sku||'-'||t0.code)"); } else if (isHana()) { assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku, '-'||t0.code)"); @@ -412,7 +412,7 @@ public class TestCacheViaComplexNaturalKey3 extends BaseTestCase { if (isH2()) { assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku,':',t0.code,'-foo') in (?,?) order by t0.sku desc; --bind(def,Array[2]={2:1000-foo,3:1000-foo})"); - } else if (isPostgres() || isOracle() || isDb2()){ + } else if (isPostgres() || isOracle() || isDb2() || isYugabyte()){ assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and (t0.sku||':'||t0.code||'-foo')"); } else if (isHana()){ assertSql(sql.get(0)).contains("from o_cached_natkey3 t0 where t0.store = ? and concat(t0.sku, ':'||t0.code||'-foo')"); diff --git a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasic.java b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasic.java index b214a3381..6524d0e7f 100644 --- a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasic.java +++ b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasic.java @@ -10,14 +10,14 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -public class TestElementCollectionBasic extends BaseTestCase { +class TestElementCollectionBasic extends BaseTestCase { private List eventLog() { return EcPersonPersistAdapter.eventLog(); } @Test - public void insertThen_UpdateWhenNotChanged_expect_noChanges() { + void insertThen_UpdateWhenNotChanged_expect_noChanges() { EcPerson person = new EcPerson("Nothing021"); person.getPhoneNumbers().add("021 1234"); @@ -51,9 +51,10 @@ public class TestElementCollectionBasic extends BaseTestCase { } @Test - public void test() { + void test() { eventLog(); + DB.find(EcPerson.class).where().eq("name", "Fiona021").delete(); LoggedSql.start(); EcPerson person = new EcPerson("Fiona021"); @@ -95,8 +96,8 @@ public class TestElementCollectionBasic extends BaseTestCase { List phoneNumbers1 = found.get(1).getPhoneNumbers(); phoneNumbers0.size(); - assertThat(phoneNumbers0).containsExactly("021 1234", "021 4321"); - assertThat(phoneNumbers1).containsExactly("09 1234", "09 4321"); + assertThat(phoneNumbers0).containsExactlyInAnyOrder("021 1234", "021 4321"); + assertThat(phoneNumbers1).containsExactlyInAnyOrder("09 1234", "09 4321"); sql = LoggedSql.collect(); assertThat(sql).hasSize(2); @@ -126,7 +127,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateBasic(EcPerson bean) { - bean.setName("Fiona021-mod-0"); DB.save(bean); @@ -140,7 +140,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateBasicInBatch(EcPerson bean) { - try (Transaction txn = DB.beginTransaction()) { txn.setBatchMode(true); bean.setName("Fiona021-mod-0-batch"); @@ -158,7 +157,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateBoth(EcPerson bean) { - bean.setName("Fiona021-mod-both"); bean.getPhoneNumbers().add("01-22123"); DB.save(bean); @@ -187,7 +185,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateBothInBatch(EcPerson bean) { - try (Transaction txn = DB.beginTransaction()) { txn.setBatchMode(true); bean.setName("Fiona021-mod-both-batch"); @@ -210,7 +207,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateNothing(EcPerson bean) { - DB.save(bean); List sql = LoggedSql.collect(); @@ -222,7 +218,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateOnlyCollectionInBatch(EcPerson bean) { - try (Transaction txn = DB.beginTransaction()) { txn.setBatchMode(true); bean.getPhoneNumbers().add("01-4321"); @@ -243,7 +238,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void updateOnlyCollection(EcPerson bean) { - bean.getPhoneNumbers().add("01-4321"); DB.save(bean); @@ -272,7 +266,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void delete(EcPerson bean) { - DB.delete(bean); List sql = LoggedSql.collect(); @@ -284,7 +277,6 @@ public class TestElementCollectionBasic extends BaseTestCase { } private void jsonToFrom(EcPerson foundFirst) { - String asJson = DB.json().toJson(foundFirst); EcPerson fromJson = DB.json().toBean(EcPerson.class, asJson); assertThat(fromJson.getPhoneNumbers()).containsAll(foundFirst.getPhoneNumbers()); diff --git a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasicSet.java b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasicSet.java index fa99f45da..65359a683 100644 --- a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasicSet.java +++ b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionBasicSet.java @@ -52,8 +52,8 @@ class TestElementCollectionBasicSet extends BaseTestCase { Set phoneNumbers1 = found.get(1).getPhoneNumbers(); phoneNumbers0.size(); - assertThat(phoneNumbers0).containsExactly("021 1234", "021 4321"); - assertThat(phoneNumbers1).containsExactly("09 1234", "09 4321", "09 9876"); + assertThat(phoneNumbers0).containsExactlyInAnyOrder("021 1234", "021 4321"); + assertThat(phoneNumbers1).containsExactlyInAnyOrder("09 1234", "09 4321", "09 9876"); sql = LoggedSql.collect(); assertThat(sql).hasSize(2); diff --git a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache.java b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache.java index 80e2d9bd1..6b5c62b3b 100644 --- a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache.java +++ b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache.java @@ -15,8 +15,8 @@ class TestElementCollectionEmbeddedListCache extends BaseTestCase { void test() { EcblPerson person = new EcblPerson("CacheL"); - person.getPhoneNumbers().add(new EcPhone("64", "021","1234")); - person.getPhoneNumbers().add(new EcPhone("64","021","4321")); + person.getPhoneNumbers().add(new EcPhone("64", "021", "1234")); + person.getPhoneNumbers().add(new EcPhone("64", "021", "4321")); DB.save(person); EcblPerson one = DB.find(EcblPerson.class) @@ -42,7 +42,7 @@ class TestElementCollectionEmbeddedListCache extends BaseTestCase { assertThat(sql).isEmpty(); // cache hit two.getPhoneNumbers().add(new EcPhone("61", "07", "11")); - two.getPhoneNumbers().remove(1); + removeByNumber(two.getPhoneNumbers(), "4321"); DB.save(two); @@ -72,7 +72,7 @@ class TestElementCollectionEmbeddedListCache extends BaseTestCase { three.setName("mod-3"); - three.getPhoneNumbers().remove(0); + removeByNumber(three.getPhoneNumbers(), "1234"); DB.save(three); @@ -92,4 +92,12 @@ class TestElementCollectionEmbeddedListCache extends BaseTestCase { LoggedSql.stop(); } + + private void removeByNumber(List phoneNumbers, String num) { + phoneNumbers + .stream() + .filter(ecPhone1 -> ecPhone1.number.equals(num)) + .findFirst() + .ifPresent(phoneNumbers::remove); + } } diff --git a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache2.java b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache2.java index 1a361c33b..ea6d47d90 100644 --- a/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache2.java +++ b/ebean-test/src/test/java/org/tests/model/elementcollection/TestElementCollectionEmbeddedListCache2.java @@ -3,7 +3,6 @@ package org.tests.model.elementcollection; import io.ebean.BaseTestCase; import io.ebean.DB; import io.ebean.test.LoggedSql; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.List; @@ -17,8 +16,8 @@ class TestElementCollectionEmbeddedListCache2 extends BaseTestCase { EcblPerson2 person = new EcblPerson2(); person.setName("CacheL"); - person.getPhoneNumbers().add(new EcPhone("64", "021","1234")); - person.getPhoneNumbers().add(new EcPhone("64","021","4321")); + person.getPhoneNumbers().add(new EcPhone("64", "021", "1234")); + person.getPhoneNumbers().add(new EcPhone("64", "021", "4321")); DB.save(person); EcblPerson2 one = DB.find(EcblPerson2.class) @@ -33,7 +32,7 @@ class TestElementCollectionEmbeddedListCache2 extends BaseTestCase { List sql = LoggedSql.collect(); assertThat(sql).isEmpty(); - EcblPerson2 two = DB.find(EcblPerson2.class ) + EcblPerson2 two = DB.find(EcblPerson2.class) .setId(person.getId()) .findOne(); @@ -44,7 +43,7 @@ class TestElementCollectionEmbeddedListCache2 extends BaseTestCase { assertThat(sql).isEmpty(); // cache hit two.getPhoneNumbers().add(new EcPhone("61", "07", "11")); - two.getPhoneNumbers().remove(1); + removeByNumber(two.getPhoneNumbers(), "4321"); DB.save(two); @@ -62,38 +61,43 @@ class TestElementCollectionEmbeddedListCache2 extends BaseTestCase { assertSql(sql.get(2)).contains("insert into ecbl_person2_phone_numbers (person_id,country_code,area,phnum) values (?,?,?,?)"); } - EcblPerson2 three = DB.find(EcblPerson2.class ) + EcblPerson2 three = DB.find(EcblPerson2.class) .setId(person.getId()) .findOne(); - assertThat(three.getPhoneNumbers().toString()).contains("61-07-11", "64-021-1234"); assertThat(three.getPhoneNumbers()).hasSize(2); + assertThat(three.getPhoneNumbers().toString()).contains("61-07-11", "64-021-1234"); sql = LoggedSql.collect(); assertThat(sql).isEmpty(); // cache hit - three.setName("mod-3"); - three.getPhoneNumbers().remove(0); + removeByNumber(three.getPhoneNumbers(), "1234"); DB.save(three); sql = LoggedSql.collect(); assertThat(sql).hasSize(5); - EcblPerson2 four = DB.find(EcblPerson2.class ) + EcblPerson2 four = DB.find(EcblPerson2.class) .setId(person.getId()) .findOne(); assertThat(four.getPhoneNumbers().toString()).contains("61-07-11"); assertThat(four.getPhoneNumbers()).hasSize(1); - DB.delete(four); sql = LoggedSql.collect(); assertThat(sql).hasSize(2); - LoggedSql.stop(); } + + private void removeByNumber(List phoneNumbers, String num) { + phoneNumbers + .stream() + .filter(ecPhone1 -> ecPhone1.number.equals(num)) + .findFirst() + .ifPresent(phoneNumbers::remove); + } } diff --git a/ebean-test/src/test/java/org/tests/transaction/TestCommitAndContinue.java b/ebean-test/src/test/java/org/tests/transaction/TestCommitAndContinue.java index 144d8f5e3..e8197fc33 100644 --- a/ebean-test/src/test/java/org/tests/transaction/TestCommitAndContinue.java +++ b/ebean-test/src/test/java/org/tests/transaction/TestCommitAndContinue.java @@ -15,14 +15,14 @@ import org.tests.model.m2m.MnyB; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -public class TestCommitAndContinue extends BaseTestCase { +class TestCommitAndContinue extends BaseTestCase { private static final Logger logger = LoggerFactory.getLogger("org.avaje.ebean.TXN"); @Test @Transactional @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB, Platform.COCKROACH}) // they will dead lock - public void transactional_partialSuccess() { + void transactional_partialSuccess() { MnyB a = new MnyB("a100"); MnyB b = new MnyB("b200"); @@ -57,8 +57,8 @@ public class TestCommitAndContinue extends BaseTestCase { * The @Transactional is nicer to me. */ @Test - @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB, Platform.COCKROACH}) // they will dead lock - public void tryFinally_partialSuccess() { + @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB, Platform.COCKROACH, Platform.YUGABYTE}) // they will dead lock + void tryFinally_partialSuccess() { MnyB a = new MnyB("a100"); MnyB b = new MnyB("b200"); @@ -69,7 +69,6 @@ public class TestCommitAndContinue extends BaseTestCase { a.save(); // commit at this point txn.commitAndContinue(); - try { b.save(); @@ -102,7 +101,7 @@ public class TestCommitAndContinue extends BaseTestCase { @Test @Transactional @IgnorePlatform({Platform.SQLSERVER, Platform.HSQLDB, Platform.COCKROACH}) // they will dead lock - public void transactional_partialSuccess_secondTransactionInsert() { + void transactional_partialSuccess_secondTransactionInsert() { MnyB a = new MnyB("a100"); MnyB b = new MnyB("b200"); @@ -150,8 +149,7 @@ public class TestCommitAndContinue extends BaseTestCase { } @Test - public void basic() { - + void basic() { MnyB a = new MnyB("a"); MnyB b = new MnyB("b"); MnyB c = new MnyB("c"); @@ -176,7 +174,7 @@ public class TestCommitAndContinue extends BaseTestCase { @Test @Transactional - public void runTransactional() { + void runTransactional() { new MnyB("a100").save(); new MnyB("a101").save(); diff --git a/ebean-test/src/test/java/org/tests/transaction/TestNestedBeginRequiresNew.java b/ebean-test/src/test/java/org/tests/transaction/TestNestedBeginRequiresNew.java index b7c7fd3e0..ca6b62bc7 100644 --- a/ebean-test/src/test/java/org/tests/transaction/TestNestedBeginRequiresNew.java +++ b/ebean-test/src/test/java/org/tests/transaction/TestNestedBeginRequiresNew.java @@ -4,54 +4,42 @@ import io.ebean.*; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.tests.model.basic.Address; import org.tests.model.basic.Country; -import org.tests.model.basic.Customer; import org.tests.model.basic.Product; -public class TestNestedBeginRequiresNew extends BaseTestCase { +class TestNestedBeginRequiresNew extends BaseTestCase { Logger logger = LoggerFactory.getLogger(TestNestedBeginRequiresNew.class); Database server = DB.getDefault(); @Test - public void test() { - + void test() { someOuterMethod(); } private void someOuterMethod() { - Transaction txn = server.beginTransaction(TxScope.requiresNew()); try { - - server.find(Country.class).findCount(); - - someInnerMethod(); - server.find(Product.class).findCount(); - + someInnerMethod(); + server.find(Address.class).findCount(); txn.commit(); - } finally { txn.end(); } - } private void someInnerMethod() { - logger.debug("someInnerMethod() ..."); Transaction txn = server.beginTransaction(TxScope.requiresNew()); try { - - server.find(Customer.class).findCount(); + server.find(Country.class).findCount(); txn.commit(); - } finally { txn.end(); } logger.debug("someInnerMethod() ... done"); - } } diff --git a/ebean-test/src/test/java/org/tests/update/TestSqlUpdateUpsert.java b/ebean-test/src/test/java/org/tests/update/TestSqlUpdateUpsert.java index 515540ea3..ffa1bd26b 100644 --- a/ebean-test/src/test/java/org/tests/update/TestSqlUpdateUpsert.java +++ b/ebean-test/src/test/java/org/tests/update/TestSqlUpdateUpsert.java @@ -11,6 +11,8 @@ import static org.assertj.core.api.Assertions.assertThat; public class TestSqlUpdateUpsert extends BaseTestCase { + private static boolean useV1Syntax = Boolean.getBoolean("ebean.h2.useV1Syntax"); + @ForPlatform(Platform.H2) @Test public void h2Merge() throws InterruptedException { @@ -39,7 +41,11 @@ public class TestSqlUpdateUpsert extends BaseTestCase { .setParameter("online", false); Object key2 = sqlUpdate2.executeGetKey(); - assertThat(key2).isEqualTo(key); + if (useV1Syntax) { + assertThat(key2).isNull(); + } else { + assertThat(key2).isEqualTo(key); + } EPersonOnline found2 = DB.find(EPersonOnline.class).where().eq("email", email).findOne(); diff --git a/ebean-test/src/test/resources/bean/example-list-contains.json b/ebean-test/src/test/resources/bean/example-list-contains.json new file mode 100644 index 000000000..dc7599b10 --- /dev/null +++ b/ebean-test/src/test/resources/bean/example-list-contains.json @@ -0,0 +1,9 @@ +[ { + "name": "something", + "other": null, + "version": 1 +}, { + "name": "other", + "other": null, + "version": 1 +} ] diff --git a/ebean-test/src/test/resources/bean/example-list.json b/ebean-test/src/test/resources/bean/example-list-match.json similarity index 100% rename from ebean-test/src/test/resources/bean/example-list.json rename to ebean-test/src/test/resources/bean/example-list-match.json diff --git a/ebean-test/src/test/resources/extra-ddl.xml b/ebean-test/src/test/resources/extra-ddl.xml index 764b63a81..f93a47acd 100644 --- a/ebean-test/src/test/resources/extra-ddl.xml +++ b/ebean-test/src/test/resources/extra-ddl.xml @@ -5,7 +5,7 @@ drop view order_agg_vw if exists; - + create or replace view order_agg_vw as select d.order_id, sum(d.order_qty * d.unit_price) as order_total, sum(d.ship_qty * d.unit_price) as ship_total diff --git a/ebean-test/testconfig/ebean-yugabyte.properties b/ebean-test/testconfig/ebean-yugabyte.properties new file mode 100644 index 000000000..126360434 --- /dev/null +++ b/ebean-test/testconfig/ebean-yugabyte.properties @@ -0,0 +1,3 @@ +ebean.test.platform=yugabyte +datasource.default=yugabyte +ebean.test.dbName=unit diff --git a/pom.xml b/pom.xml index a11a7caa0..a70b81c76 100644 --- a/pom.xml +++ b/pom.xml @@ -43,11 +43,11 @@ 2.1.210 1.2 1.1 - 12.13.1 + 12.15.0 4.2 7.5 - 12.14.1 - 12.14.1 + 12.15.0 + 12.15.0 @@ -118,6 +118,12 @@ release + + h2v1 + + 1.4.199 + + default diff --git a/tests/test-java16/pom.xml b/tests/test-java16/pom.xml index f107e1d40..a45c0ca20 100644 --- a/tests/test-java16/pom.xml +++ b/tests/test-java16/pom.xml @@ -20,19 +20,19 @@ io.ebean ebean - 12.14.2-FOC1-SNAPSHOT + 12.15.0-SNAPSHOT ch.qos.logback logback-classic - 1.2.9 + 1.2.10 io.ebean ebean-test - 12.14.2-FOC1-SNAPSHOT + 12.15.0-SNAPSHOT test @@ -58,7 +58,7 @@ io.ebean querybean-generator - 12.14.2-SNAPSHOT + 12.15.0-SNAPSHOT diff --git a/tests/test-kotlin/pom.xml b/tests/test-kotlin/pom.xml index 513f79f78..07d81c933 100644 --- a/tests/test-kotlin/pom.xml +++ b/tests/test-kotlin/pom.xml @@ -36,21 +36,21 @@ io.ebean ebean-test - 12.14.2-FOC1-SNAPSHOT + 12.15.0-SNAPSHOT test io.ebean ebean-core - 12.14.2-FOC1-SNAPSHOT + 12.15.0-SNAPSHOT test ch.qos.logback logback-classic - 1.2.9 + 1.2.10 test