mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge branch 'master' into wip/h2database-v2
This commit is contained in:
@@ -3,8 +3,8 @@ name: JDK 18-ea
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# schedule:
|
||||
# - cron: '30 6 * * *'
|
||||
schedule:
|
||||
- cron: '30 6 * * 1,3,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
|
||||
name: MariaDB 10.6
|
||||
|
||||
on: [workflow_dispatch]
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 7 * * 1,4'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
|
||||
name: SqlServer 2017 latest
|
||||
|
||||
on: [workflow_dispatch]
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 7 * * 2,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -27,7 +27,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>1.5</version>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -66,6 +66,8 @@ public class PlatformConfig {
|
||||
|
||||
private boolean caseSensitiveCollation = true;
|
||||
|
||||
private boolean useMigrationStoredProcedures = false;
|
||||
|
||||
/**
|
||||
* Modify the default mapping of standard types such as default precision for DECIMAL etc.
|
||||
*/
|
||||
@@ -90,6 +92,7 @@ public class PlatformConfig {
|
||||
this.geometrySRID = platformConfig.geometrySRID;
|
||||
this.dbUuid = platformConfig.dbUuid;
|
||||
this.caseSensitiveCollation = platformConfig.caseSensitiveCollation;
|
||||
this.useMigrationStoredProcedures = platformConfig.useMigrationStoredProcedures;
|
||||
this.allQuotedIdentifiers = platformConfig.allQuotedIdentifiers;
|
||||
this.databaseInetAddressVarchar = platformConfig.databaseInetAddressVarchar;
|
||||
this.customDbTypeMappings = platformConfig.customDbTypeMappings;
|
||||
@@ -142,6 +145,20 @@ public class PlatformConfig {
|
||||
this.caseSensitiveCollation = caseSensitiveCollation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if force use of helper stored procedures for migrations.
|
||||
*/
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set true to force use of helper stored procedures for migrations.
|
||||
*/
|
||||
public void setUseMigrationStoredProcedures(boolean useMigrationStoredProcedures) {
|
||||
this.useMigrationStoredProcedures = useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Postgres FOR UPDATE should use the NO KEY option.
|
||||
*/
|
||||
@@ -317,6 +334,7 @@ public class PlatformConfig {
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar);
|
||||
caseSensitiveCollation = p.getBoolean("caseSensitiveCollation", caseSensitiveCollation);
|
||||
useMigrationStoredProcedures = p.getBoolean("useMigrationStoredProcedures", useMigrationStoredProcedures);
|
||||
|
||||
DbUuid dbUuid = p.getEnum(DbUuid.class, "dbuuid", null);
|
||||
if (dbUuid != null) {
|
||||
|
||||
@@ -7,13 +7,10 @@ public class BasicSqlAnsiLimiter implements BasicSqlLimiter {
|
||||
|
||||
@Override
|
||||
public String limit(String dbSql, int firstRow, int maxRows) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
|
||||
sb.append(dbSql);
|
||||
if (firstRow > 0) {
|
||||
sb.append(" ").append("offset");
|
||||
sb.append(" ").append(firstRow).append(" rows");
|
||||
sb.append(" offset ").append(firstRow).append(" rows");
|
||||
}
|
||||
if (maxRows > 0) {
|
||||
sb.append(" fetch next ").append(maxRows).append(" rows only");
|
||||
|
||||
@@ -53,6 +53,8 @@ public class DatabasePlatform {
|
||||
|
||||
protected boolean supportsSavepointId = true;
|
||||
|
||||
protected boolean useMigrationStoredProcedures = false;
|
||||
|
||||
/**
|
||||
* The behaviour used when ending a read only transaction at read committed isolation level.
|
||||
*/
|
||||
@@ -237,6 +239,7 @@ public class DatabasePlatform {
|
||||
public void configure(PlatformConfig config) {
|
||||
this.sequenceBatchSize = config.getDatabaseSequenceBatchSize();
|
||||
this.caseSensitiveCollation = config.isCaseSensitiveCollation();
|
||||
this.useMigrationStoredProcedures = config.isUseMigrationStoredProcedures();
|
||||
configureIdType(config.getIdType());
|
||||
configure(config, config.isAllQuotedIdentifiers());
|
||||
}
|
||||
@@ -343,6 +346,13 @@ public class DatabasePlatform {
|
||||
return supportsSavepointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if migrations should use stored procedures.
|
||||
*/
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports LIMIT with sql update.
|
||||
*/
|
||||
@@ -573,6 +583,10 @@ public class DatabasePlatform {
|
||||
this.supportsResultSetConcurrencyModeUpdatable = supportsResultSetConcurrencyModeUpdatable;
|
||||
}
|
||||
|
||||
public void setUseMigrationStoredProcedures(final boolean useMigrationStoredProcedures) {
|
||||
this.useMigrationStoredProcedures = useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally not needed - overridden in CockroachPlatform.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package io.ebean.config.dbplatform.mariadb;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.config.dbplatform.mysql.BaseMySqlPlatform;
|
||||
|
||||
/**
|
||||
@@ -11,6 +15,14 @@ public class MariaDbPlatform extends BaseMySqlPlatform {
|
||||
public MariaDbPlatform() {
|
||||
super();
|
||||
this.platform = Platform.MARIADB;
|
||||
this.sequenceBatchMode = false;
|
||||
this.historySupport = new MariaDbHistorySupport();
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new MariaDbSequence(be, ds, seqName, stepSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.ebean.config.dbplatform.mariadb;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
public class MariaDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
private final String nextSql;
|
||||
|
||||
/**
|
||||
* Construct where batchSize is the sequence step size.
|
||||
*/
|
||||
public MariaDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize);
|
||||
this.nextSql = "select next value for " + seqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return nextSql;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public class Oracle11Platform extends OraclePlatform {
|
||||
public Oracle11Platform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE11;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.sqlLimiter = new OracleRownumSqlLimiter();
|
||||
this.basicSqlLimiter = new OracleRownumBasicLimiter();
|
||||
dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.ebean.config.dbplatform.oracle;
|
||||
|
||||
/**
|
||||
* Oracle 12 platform using column alias.
|
||||
*/
|
||||
public class Oracle12Platform extends OraclePlatform {
|
||||
|
||||
public Oracle12Platform() {
|
||||
super();
|
||||
//this.platform = Platform.ORACLE12;
|
||||
this.columnAliasPrefix = "c";
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
public OraclePlatform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.maxTableNameLength = 30;
|
||||
this.maxConstraintNameLength = 30;
|
||||
@@ -35,11 +34,9 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
dbIdentity.setSupportsSequence(true);
|
||||
dbIdentity.setSupportsIdentity(true);
|
||||
dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
|
||||
this.dbDefaultValue.setFalse("0");
|
||||
this.dbDefaultValue.setTrue("1");
|
||||
this.dbDefaultValue.setNow("current_timestamp");
|
||||
|
||||
this.treatEmptyStringsAsNull = true;
|
||||
this.likeClauseRaw = "like ?";
|
||||
|
||||
@@ -56,7 +53,6 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
|
||||
booleanDbType = Types.INTEGER;
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("number(1)"));
|
||||
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("number", 10));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("number", 19));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("number", 19, 4));
|
||||
@@ -65,12 +61,10 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("number", 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 16, 3));
|
||||
dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("varchar2", 255));
|
||||
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("blob"));
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("clob"));
|
||||
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("raw", 255));
|
||||
dbTypeMap.put(DbType.BINARY, new DbPlatformType("raw", 255));
|
||||
|
||||
dbTypeMap.put(DbType.TIME, new DbPlatformType("timestamp"));
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -119,4 +119,9 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
// for update are hints on from clause of base table
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* Errorhandler to handle load errors and may be recover correct value.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface LoadErrorHandler {
|
||||
void handleLoadError(EntityBean bean, Property prop, String fullName, Exception e);
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import java.util.Locale;
|
||||
* try {
|
||||
* File f = new File("src/test/resources/test1.csv");
|
||||
*
|
||||
* FileReader reader = new FileReader(f);
|
||||
* FileReader reader = new FileReader(f, encoding);
|
||||
*
|
||||
* CsvReader<Customer> csvReader = DB.createCsvReader(Customer.class);
|
||||
*
|
||||
|
||||
@@ -71,6 +71,20 @@ public class AnnotationUtil {
|
||||
return typeGet(clazz, annotation) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an element is annotated with an annotation of given type searching meta-annotations.
|
||||
*/
|
||||
public static boolean metaHas(AnnotatedElement element, Class<?> annotationType) {
|
||||
return !metaFindAll(element, annotationType).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the annotations of a given type searching meta-annotations.
|
||||
*/
|
||||
public static Set<Annotation> metaFindAll(AnnotatedElement element, Class<?> annotationType) {
|
||||
return metaFindAllFor(element, Collections.singleton(annotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the annotations for the filter searching meta-annotations.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package io.ebean.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Utilities for IO. It uses UTF-8 as encoding when reading/writing and uses
|
||||
* buffered IO for better performance.
|
||||
*/
|
||||
public class IOUtils {
|
||||
|
||||
/**
|
||||
* Read from stream as UTF-8.
|
||||
*/
|
||||
public static BufferedReader newReader(InputStream is) {
|
||||
return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from file as UTF-8.
|
||||
*/
|
||||
public static BufferedReader newReader(File file) throws FileNotFoundException {
|
||||
return newReader(new FileInputStream(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to stream as UTF-8
|
||||
*/
|
||||
public static BufferedWriter newWriter(OutputStream os) {
|
||||
return new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to file as UTF-8
|
||||
*/
|
||||
public static BufferedWriter newWriter(File file) throws FileNotFoundException {
|
||||
return newWriter(new FileOutputStream(file));
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+15
-15
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -71,88 +71,88 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -41,19 +41,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -3,13 +3,13 @@ package io.ebeaninternal.server.core;
|
||||
import io.ebean.ScriptRunner;
|
||||
import io.ebean.ddlrunner.DdlRunner;
|
||||
import io.ebean.ddlrunner.ScriptTransform;
|
||||
import io.ebean.util.IOUtils;
|
||||
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.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
@@ -66,8 +66,9 @@ final class DScriptRunner implements ScriptRunner {
|
||||
throw new IllegalArgumentException("resource is null?");
|
||||
}
|
||||
|
||||
try (InputStream inputStream = UrlHelper.openNoCache(resource)) {
|
||||
return readContent(new InputStreamReader(inputStream));
|
||||
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);
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.ebean.config.dbplatform.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.Oracle11Platform;
|
||||
import io.ebean.config.dbplatform.oracle.Oracle12Platform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import io.ebean.config.dbplatform.postgres.Postgres9Platform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
@@ -25,11 +26,7 @@ import io.ebeaninternal.api.DbOffline;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.*;
|
||||
|
||||
/**
|
||||
* Create a DatabasePlatform from the configuration.
|
||||
@@ -87,6 +84,9 @@ public class DatabasePlatformFactory {
|
||||
if (dbName.equals("oracle11") || dbName.equals("oracle10") || dbName.equals("oracle9")) {
|
||||
return new Oracle11Platform();
|
||||
}
|
||||
if (dbName.equals("oracle12")) {
|
||||
return new Oracle12Platform();
|
||||
}
|
||||
if (dbName.equals("oracle")) {
|
||||
return new OraclePlatform();
|
||||
}
|
||||
@@ -173,7 +173,13 @@ public class DatabasePlatformFactory {
|
||||
}
|
||||
|
||||
private DatabasePlatform oracleVersion(int majorVersion) {
|
||||
return majorVersion < 12 ? new Oracle11Platform() : new OraclePlatform();
|
||||
if (majorVersion < 12) {
|
||||
return new Oracle11Platform();
|
||||
}
|
||||
if (majorVersion < 13) {
|
||||
return new Oracle12Platform();
|
||||
}
|
||||
return new OraclePlatform();
|
||||
}
|
||||
|
||||
private DatabasePlatform mysqlVersion(int majorVersion, int minorVersion) {
|
||||
|
||||
@@ -226,7 +226,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
*/
|
||||
@Override
|
||||
public void addBeanToCollectionWithCreate(EntityBean parentBean, EntityBean detailBean, boolean withCheck) {
|
||||
BeanCollection<?> bc = (BeanCollection<?>) super.getValue(parentBean);
|
||||
BeanCollection<?> bc = beanCollection(parentBean);
|
||||
if (bc == null) {
|
||||
bc = help.createEmpty(parentBean);
|
||||
setValue(parentBean, bc);
|
||||
@@ -234,6 +234,15 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
help.add(bc, detailBean, withCheck);
|
||||
}
|
||||
|
||||
private BeanCollection<?> beanCollection(EntityBean parentBean) {
|
||||
try {
|
||||
return (BeanCollection<?>) super.getValue(parentBean);
|
||||
} catch (ClassCastException e) {
|
||||
// fetching element collection, ok for now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is considered 'empty' from a save perspective.
|
||||
*/
|
||||
|
||||
+1
-6
@@ -10,23 +10,18 @@ public final class DbExpressionHandlerFactory {
|
||||
* Create and return the appropriate platform specific handing of expressions.
|
||||
*/
|
||||
public static DbExpressionHandler from(DatabasePlatform databasePlatform) {
|
||||
Platform platform = databasePlatform.getPlatform();
|
||||
Platform platform = databasePlatform.getPlatform().base();
|
||||
switch (platform) {
|
||||
case H2:
|
||||
return new H2DbExpression();
|
||||
case POSTGRES:
|
||||
case POSTGRES9:
|
||||
return new PostgresDbExpression();
|
||||
case MARIADB:
|
||||
return new MariaDbExpression();
|
||||
case MYSQL55:
|
||||
case MYSQL:
|
||||
return new MySqlDbExpression();
|
||||
case ORACLE:
|
||||
case ORACLE11:
|
||||
return new OracleDbExpression();
|
||||
case SQLSERVER16:
|
||||
case SQLSERVER17:
|
||||
case SQLSERVER:
|
||||
return new SqlServerDbExpression();
|
||||
case HANA:
|
||||
|
||||
@@ -333,6 +333,13 @@ public final class DefaultPersister implements Persister {
|
||||
* Recursively delete the bean. This calls back to the EbeanServer.
|
||||
*/
|
||||
private int deleteRecurse(EntityBean detailBean, Transaction t, DeleteMode deleteMode) {
|
||||
return deleteRequest(createDeleteCascade(detailBean, t, deleteMode.persistType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete without being a cascade.
|
||||
*/
|
||||
private int delete(EntityBean detailBean, Transaction t, DeleteMode deleteMode) {
|
||||
return deleteRequest(createDeleteRequest(detailBean, t, deleteMode.persistType()));
|
||||
}
|
||||
|
||||
@@ -560,7 +567,7 @@ public final class DefaultPersister implements Persister {
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteList(List<?> beanList, SpiTransaction t, DeleteMode deleteMode, boolean children) {
|
||||
private void deleteCascade(List<?> beanList, SpiTransaction t, DeleteMode deleteMode, boolean children) {
|
||||
if (children) {
|
||||
t.depth(-1);
|
||||
t.checkBatchEscalationOnCollection();
|
||||
@@ -604,7 +611,7 @@ public final class DefaultPersister implements Persister {
|
||||
for (Object id : ids) {
|
||||
EntityBean bean = descriptor.createEntityBean();
|
||||
descriptor.convertSetId(id, bean);
|
||||
int rowCount = deleteRecurse(bean, transaction, deleteMode);
|
||||
int rowCount = delete(bean, transaction, deleteMode);
|
||||
if (rowCount == -1) {
|
||||
total = -1;
|
||||
} else if (total != -1) {
|
||||
@@ -656,7 +663,7 @@ public final class DefaultPersister implements Persister {
|
||||
t.logSummary("-- DeleteById of " + descriptor.name() + " ids[" + idList + "] requires fetch of foreign key values");
|
||||
}
|
||||
List<?> beanList = server.findList(q, t);
|
||||
deleteList(beanList, t, deleteMode, false);
|
||||
deleteCascade(beanList, t, deleteMode, false);
|
||||
return beanList.size();
|
||||
|
||||
} else {
|
||||
@@ -994,6 +1001,8 @@ public final class DefaultPersister implements Persister {
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
|
||||
} else {
|
||||
// TODO: Review first checking if many property is loaded and using the loaded beans
|
||||
// ... and only using findIdsByParentId() when the many property isn't loaded
|
||||
// Delete recurse using the Id values of the children
|
||||
Object parentId = desc.getId(parentBean);
|
||||
List<Object> idsByParentId = many.findIdsByParentId(parentId, null, t, excludeDetailIds, deleteMode.isHard());
|
||||
@@ -1017,7 +1026,7 @@ public final class DefaultPersister implements Persister {
|
||||
for (Object id : childIds) {
|
||||
refList.add(targetDesc.createReference(id, null));
|
||||
}
|
||||
deleteList(refList, t, deleteMode, true);
|
||||
deleteCascade(refList, t, deleteMode, true);
|
||||
} else {
|
||||
// perform delete by statement if possible
|
||||
delete(targetDesc, null, childIds, t, deleteMode);
|
||||
@@ -1157,6 +1166,10 @@ public final class DefaultPersister implements Persister {
|
||||
return createDeleteRequest(bean, t, type, Flags.ZERO);
|
||||
}
|
||||
|
||||
private <T> PersistRequestBean<T> createDeleteCascade(EntityBean bean, Transaction t, Type type) {
|
||||
return createDeleteRequest(bean, t, type, Flags.RECURSE);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private <T> PersistRequestBean<T> createDeleteRequest(Object bean, Transaction t, PersistRequest.Type type, int flags) {
|
||||
BeanManager<T> mgr = beanManager(bean.getClass());
|
||||
@@ -1167,7 +1180,7 @@ public final class DefaultPersister implements Persister {
|
||||
type = Type.DELETE_SOFT;
|
||||
}
|
||||
|
||||
PersistRequestBean<T> request = new PersistRequestBean<>(server, (T)bean, null, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
PersistRequestBean<T> request = new PersistRequestBean<>(server, (T) bean, null, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
request.initForSoftDelete();
|
||||
return request;
|
||||
}
|
||||
@@ -1186,7 +1199,7 @@ public final class DefaultPersister implements Persister {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> BeanManager<T> beanManager(Class<?> cls) {
|
||||
BeanManager<T> mgr = (BeanManager<T>)beanDescriptorManager.beanManager(cls);
|
||||
BeanManager<T> mgr = (BeanManager<T>) beanDescriptorManager.beanManager(cls);
|
||||
if (mgr == null) {
|
||||
throw new PersistenceException(errNotRegistered(cls));
|
||||
}
|
||||
|
||||
@@ -13,11 +13,8 @@ import io.ebeaninternal.server.persist.dmlbind.BindableList;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static io.ebean.annotation.Platform.MARIADB;
|
||||
import static io.ebean.annotation.Platform.MYSQL;
|
||||
|
||||
/**
|
||||
* Meta data for insert handler. The meta data is for a particular bean type. It
|
||||
* Metadata for insert handler. The metadata is for a particular bean type. It
|
||||
* is considered immutable and is thread safe.
|
||||
*/
|
||||
final class InsertMeta {
|
||||
@@ -153,31 +150,25 @@ final class InsertMeta {
|
||||
private String genSql(boolean nullId, String table, boolean draftTable) {
|
||||
GenerateDmlRequest request = new GenerateDmlRequest();
|
||||
request.setInsertSetMode();
|
||||
|
||||
request.append("insert into ").append(table);
|
||||
if (nullId && noColumnsForInsert(draftTable)) {
|
||||
return request.append(defaultValues()).toString();
|
||||
}
|
||||
|
||||
request.append(" (");
|
||||
if (!nullId) {
|
||||
id.dmlAppend(request);
|
||||
}
|
||||
|
||||
if (shadowFKey != null) {
|
||||
shadowFKey.dmlAppend(request);
|
||||
}
|
||||
|
||||
if (discriminator != null) {
|
||||
discriminator.dmlAppend(request);
|
||||
}
|
||||
|
||||
if (draftTable) {
|
||||
all.dmlAppend(request);
|
||||
} else {
|
||||
allExcludeDraftOnly.dmlAppend(request);
|
||||
}
|
||||
|
||||
request.append(") values (");
|
||||
request.append(request.getInsertBindBuffer());
|
||||
request.append(")");
|
||||
@@ -185,7 +176,14 @@ final class InsertMeta {
|
||||
}
|
||||
|
||||
private String defaultValues() {
|
||||
return platform.base() == MYSQL || platform.base() == MARIADB ? " values (default)" : " default values";
|
||||
switch (platform.base()) {
|
||||
case MYSQL:
|
||||
case MARIADB:
|
||||
case ORACLE:
|
||||
return " values (default)";
|
||||
default:
|
||||
return " default values";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-1
@@ -4,11 +4,13 @@ import io.ebean.ProfileLocation;
|
||||
import io.ebean.config.ProfilingConfig;
|
||||
import io.ebean.plugin.Plugin;
|
||||
import io.ebean.plugin.SpiServer;
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
import io.ebeaninternal.api.SpiProfileHandler;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
@@ -123,7 +125,7 @@ public final class DefaultProfileHandler implements SpiProfileHandler, Plugin {
|
||||
try {
|
||||
String now = DTF.format(LocalDateTime.now());
|
||||
File file = new File(dir, "txprofile-" + now + ".tprofile");
|
||||
out = new BufferedWriter(new FileWriter(file));
|
||||
out = IOUtils.newWriter(file);
|
||||
} catch (IOException e) {
|
||||
log.error("Not expected", e);
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
List<? extends ScalarType<?>> types = plugin.createTypes(config, objectMapper);
|
||||
for (ScalarType<?> type : types) {
|
||||
log.debug("adding ScalarType {}", type.getClass());
|
||||
addCustomType(type);
|
||||
add(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,25 +211,6 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
logAdd(scalarType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the ScalarType for an enum. This is special in the sense that an Enum
|
||||
* can have many classes if it uses method overrides and we need to register all
|
||||
* the variations/classes for the enum.
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Override
|
||||
public void addEnumType(ScalarType<?> scalarType, Class<? extends Enum> enumClass) {
|
||||
Set<Class<?>> mappedClasses = new HashSet<>();
|
||||
mappedClasses.add(enumClass);
|
||||
for (Object value : EnumSet.allOf(enumClass).toArray()) {
|
||||
mappedClasses.add(value.getClass());
|
||||
}
|
||||
for (Class<?> cls : mappedClasses) {
|
||||
typeMap.put(cls, scalarType);
|
||||
}
|
||||
logAdd(scalarType);
|
||||
}
|
||||
|
||||
private void logAdd(ScalarType<?> scalarType) {
|
||||
if (log.isTraceEnabled()) {
|
||||
String msg = "ScalarType register [" + scalarType.getClass().getName() + "]";
|
||||
@@ -275,16 +256,43 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
"ScalarType of Joda LocalTime not defined. You need to set DatabaseConfig.jodaLocalTimeMode to"
|
||||
+ " either 'normal' or 'utc'. UTC is the old mode using UTC timezone but local time zone is now preferred as 'normal' mode.");
|
||||
}
|
||||
found = checkInterfaceTypes(type);
|
||||
found = checkInheritedTypes(type);
|
||||
}
|
||||
return found;
|
||||
return found != ScalarTypeNotFound.INSTANCE ? found : null; // Do not return ScalarTypeNotFound, otherwise checks will fail
|
||||
}
|
||||
|
||||
private ScalarType<?> checkInterfaceTypes(Class<?> type) {
|
||||
if (java.nio.file.Path.class.isAssignableFrom(type)) {
|
||||
return typeMap.get(java.nio.file.Path.class);
|
||||
/**
|
||||
* Checks the typeMap for inherited types.
|
||||
*
|
||||
* If e.g. <code>type</code> is a <code>GregorianCalendar</code>, then this method
|
||||
* will check the class hierarchy and will probably return a
|
||||
* <code>ScalarTypeCalendar</code> To speed up a second lookup, it will write
|
||||
* back the found scalarType to typeMap.
|
||||
*
|
||||
* @param type the for which to search for a <code>ScalarType</code>
|
||||
* @return either a valid <code>ScalarType</code> if one could be found or {@link ScalarTypeNotFound#INSTANCE} if not
|
||||
*/
|
||||
private ScalarType<?> checkInheritedTypes(Class<?> type) {
|
||||
// first step loop through inheritance chain
|
||||
Class<?> parent = type;
|
||||
while (parent != null && parent != Object.class) {
|
||||
ScalarType<?> found = typeMap.get(parent);
|
||||
if (found != null && found != ScalarTypeNotFound.INSTANCE) {
|
||||
typeMap.put(type, found); // store type for next lookup
|
||||
return found;
|
||||
}
|
||||
// second step - loop through interfaces of this type
|
||||
for (Class<?> iface: parent.getInterfaces()) {
|
||||
found = checkInheritedTypes(iface);
|
||||
if (found != null && found != ScalarTypeNotFound.INSTANCE) {
|
||||
typeMap.put(type, found); // store type for next lookup
|
||||
return found;
|
||||
}
|
||||
}
|
||||
parent = parent.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
typeMap.put(type, ScalarTypeNotFound.INSTANCE);
|
||||
return ScalarTypeNotFound.INSTANCE; // no success
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -389,7 +397,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
private DocPropertyType getDocType(Type genericType) {
|
||||
if (genericType instanceof Class<?>) {
|
||||
ScalarType<?> found = typeMap.get(genericType);
|
||||
ScalarType<?> found = getScalarType((Class<?>)genericType);
|
||||
if (found != null) {
|
||||
return found.getDocType();
|
||||
}
|
||||
@@ -447,7 +455,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
scalarType = typeMap.get(type);
|
||||
scalarType = getScalarType(type);
|
||||
if (scalarType != null) {
|
||||
if (jdbcType == 0 || scalarType.getJdbcType() == jdbcType) {
|
||||
// matching type
|
||||
@@ -565,7 +573,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
// use JPA normal Enum type (without mapping)
|
||||
scalarEnum = createEnumScalarTypePerSpec(enumType, type);
|
||||
}
|
||||
addEnumType(scalarEnum, enumType);
|
||||
add(scalarEnum);
|
||||
return scalarEnum;
|
||||
}
|
||||
|
||||
@@ -655,16 +663,13 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
scalarType = cls.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
}
|
||||
addCustomType(scalarType);
|
||||
add(scalarType);
|
||||
} catch (Exception e) {
|
||||
log.error("Error loading ScalarType [" + cls.getName() + "]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addCustomType(ScalarType<?> scalarType) {
|
||||
add(scalarType);
|
||||
}
|
||||
|
||||
private Object initObjectMapper(DatabaseConfig config) {
|
||||
Object objectMapper = config.getObjectMapper();
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.text.TextException;
|
||||
import io.ebean.text.json.EJson;
|
||||
import io.ebean.util.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -75,14 +76,14 @@ abstract class ScalarTypeJsonMap extends ScalarTypeBase<Map> {
|
||||
try {
|
||||
if (keepSource) {
|
||||
StringWriter jsonBuffer = new StringWriter();
|
||||
try (InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
|
||||
try (Reader streamReader = IOUtils.newReader(is)) {
|
||||
transferTo(streamReader, jsonBuffer);
|
||||
}
|
||||
String rawJson = jsonBuffer.toString();
|
||||
reader.pushJson(rawJson);
|
||||
return parse(rawJson);
|
||||
} else {
|
||||
try (InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
|
||||
try (Reader streamReader = IOUtils.newReader(is)) {
|
||||
return parse(streamReader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.text.TextException;
|
||||
import io.ebean.util.IOUtils;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.SQLException;
|
||||
@@ -68,7 +68,7 @@ abstract class ScalarTypeJsonNode extends ScalarTypeBase<JsonNode> {
|
||||
if (is == null) {
|
||||
return null;
|
||||
}
|
||||
try (InputStreamReader reader = new InputStreamReader(is)) {
|
||||
try (Reader reader = IOUtils.newReader(is)) {
|
||||
return parse(reader);
|
||||
} catch (IOException e) {
|
||||
throw new SQLException("Error reading Blob stream from DB", e);
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
|
||||
/**
|
||||
* Class is required as "null" key in ConcurrentHashMap.
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
class ScalarTypeNotFound implements ScalarType<Void> {
|
||||
|
||||
public static final ScalarTypeNotFound INSTANCE = new ScalarTypeNotFound();
|
||||
private ScalarTypeNotFound() { }
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJdbcNative() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Void> getType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void read(DataReader reader) throws SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadIgnore(DataReader reader) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBinder binder, Void value) throws SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toJdbcType(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void toBeanType(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Void value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void parse(String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocPropertyType getDocType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(Void value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void convertFromMillis(long dateTime) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void readData(DataInput dataInput) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeData(DataOutput dataOutput, Void v) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void jsonRead(JsonParser parser) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator writer, Void value) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public final class SimpleAesEncryptor implements Encryptor {
|
||||
}
|
||||
|
||||
private IvParameterSpec getIvParameterSpec(String initialVector) {
|
||||
return new IvParameterSpec(initialVector.getBytes());
|
||||
return new IvParameterSpec(initialVector.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,12 +17,6 @@ public interface TypeManager {
|
||||
*/
|
||||
void add(ScalarType<?> scalarType);
|
||||
|
||||
/**
|
||||
* Register a ScalarType for an Enum with can have multiple classes.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
void addEnumType(ScalarType<?> type, Class<? extends Enum> myEnumClass);
|
||||
|
||||
/**
|
||||
* Return the scalar type for the given logical type.
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean ddl generation</name>
|
||||
@@ -22,20 +22,20 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>12.12.1</version>
|
||||
<version>12.13.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.ddlrunner.DdlRunner;
|
||||
import io.ebean.ddlrunner.ScriptTransform;
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebean.util.JdbcClose;
|
||||
import io.ebeaninternal.api.SpiDdlGenerator;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
@@ -17,13 +18,11 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -50,6 +49,7 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
private final ScriptTransform scriptTransform;
|
||||
private final Platform platform;
|
||||
private final String platformName;
|
||||
private final boolean useMigrationStoredProcedures;
|
||||
|
||||
private CurrentModel currentModel;
|
||||
private String dropAllContent;
|
||||
@@ -71,9 +71,11 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
log.warn("DDL can't be run on startup with TenantMode " + config.getTenantMode());
|
||||
this.runDdl = false;
|
||||
this.ddlAutoCommit = false;
|
||||
this.useMigrationStoredProcedures = false;
|
||||
} else {
|
||||
this.runDdl = config.isDdlRun();
|
||||
this.ddlAutoCommit = databasePlatform.isDdlAutoCommit();
|
||||
this.useMigrationStoredProcedures = config.getDatabasePlatform().isUseMigrationStoredProcedures();
|
||||
}
|
||||
this.scriptTransform = createScriptTransform(config);
|
||||
this.baseDir = initBaseDir();
|
||||
@@ -187,7 +189,7 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
|
||||
protected void runDropSql(Connection connection) throws IOException {
|
||||
if (!createOnly) {
|
||||
if (extraDdl && jaxbPresent) {
|
||||
if (extraDdl && jaxbPresent && useMigrationStoredProcedures) {
|
||||
String extraApply = ExtraDdlXmlReader.buildExtra(platform, true);
|
||||
if (extraApply != null) {
|
||||
runScript(connection, false, extraApply, "extra-ddl");
|
||||
@@ -268,7 +270,7 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
if (is == null) {
|
||||
log.warn("sql script {} was not found as a resource", sqlScript);
|
||||
} else {
|
||||
String content = readContent(new InputStreamReader(is));
|
||||
String content = readContent(IOUtils.newReader(is)); // 'is' is closed
|
||||
runScript(connection, false, content, sqlScript);
|
||||
}
|
||||
}
|
||||
@@ -337,7 +339,7 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
|
||||
protected void writeFile(String fileName, String fileContent) throws IOException {
|
||||
File f = new File(baseDir, fileName);
|
||||
try (FileWriter fw = new FileWriter(f)) {
|
||||
try (Writer fw = IOUtils.newWriter(f)) {
|
||||
fw.write(fileContent);
|
||||
fw.flush();
|
||||
}
|
||||
@@ -348,7 +350,9 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
if (!f.exists()) {
|
||||
return null;
|
||||
}
|
||||
return readContent(new FileReader(f));
|
||||
try (Reader reader = IOUtils.newReader(f)) {
|
||||
return readContent(reader);
|
||||
}
|
||||
}
|
||||
|
||||
protected String readContent(Reader reader) throws IOException {
|
||||
|
||||
+25
-17
@@ -1,8 +1,22 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import static io.ebeaninternal.api.PlatformMatch.matchPlatform;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.ClassLoadConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.DbConstraintNaming;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
@@ -27,6 +41,8 @@ import io.ebean.config.dbplatform.sqlite.SQLitePlatform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer16Platform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer17Platform;
|
||||
import io.ebean.dbmigration.DbMigration;
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.api.DbOffline;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
@@ -42,17 +58,6 @@ import io.ebeaninternal.dbmigration.model.PlatformDdlWriter;
|
||||
import io.ebeaninternal.extraddl.model.DdlScript;
|
||||
import io.ebeaninternal.extraddl.model.ExtraDdl;
|
||||
import io.ebeaninternal.extraddl.model.ExtraDdlXmlReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static io.ebeaninternal.api.PlatformMatch.matchPlatform;
|
||||
|
||||
/**
|
||||
* Generates DB Migration xml and sql scripts.
|
||||
@@ -392,19 +397,22 @@ public class DefaultDbMigration implements DbMigration {
|
||||
private void generateExtraDdl(File migrationDir, DatabasePlatform dbPlatform, boolean tablePartitioning) throws IOException {
|
||||
if (dbPlatform != null) {
|
||||
if (tablePartitioning && includeBuiltInPartitioning) {
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltinTablePartitioning());
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltinTablePartitioning(), false);
|
||||
}
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltin());
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.read());
|
||||
// skip built-in migration stored procedures based on isUseMigrationStoredProcedures
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltin(), true);
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.read(), false);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateExtraDdlFor(File migrationDir, DatabasePlatform dbPlatform, ExtraDdl extraDdl) throws IOException {
|
||||
private void generateExtraDdlFor(File migrationDir, DatabasePlatform dbPlatform, ExtraDdl extraDdl, boolean checkSkip) throws IOException {
|
||||
if (extraDdl != null) {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (!script.isDrop() && matchPlatform(dbPlatform.getPlatform(), script.getPlatforms())) {
|
||||
writeExtraDdl(migrationDir, script);
|
||||
if (!checkSkip || dbPlatform.isUseMigrationStoredProcedures()) {
|
||||
writeExtraDdl(migrationDir, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,7 +425,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
String fullName = repeatableMigrationName(script.isInit(), script.getName());
|
||||
logger.debug("writing repeatable script {}", fullName);
|
||||
File file = new File(migrationDir, fullName);
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
try (Writer writer = IOUtils.newWriter(file)) {
|
||||
writer.write(script.getValue());
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.migration.MigrationVersion;
|
||||
import io.ebean.util.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -50,17 +51,17 @@ class IndexMigration {
|
||||
|
||||
private void generateIndex() throws IOException {
|
||||
Collections.sort(all);
|
||||
FileWriter writer = new FileWriter(indexFile);
|
||||
for (Entry entry : all) {
|
||||
writeChecksumPadded(writer, entry.checksum);
|
||||
writer.write(entry.fileName);
|
||||
try (Writer writer = IOUtils.newWriter(indexFile)) {
|
||||
for (Entry entry : all) {
|
||||
writeChecksumPadded(writer, entry.checksum);
|
||||
writer.write(entry.fileName);
|
||||
writer.write(eol);
|
||||
}
|
||||
writer.write(eol);
|
||||
}
|
||||
writer.write(eol);
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private void writeChecksumPadded(FileWriter writer, int checksum) throws IOException {
|
||||
private void writeChecksumPadded(Writer writer, int checksum) throws IOException {
|
||||
final String asStr = String.valueOf(checksum);
|
||||
writer.write(asStr);
|
||||
writer.write(',');
|
||||
|
||||
@@ -4,6 +4,8 @@ import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import io.ebean.util.IOUtils;
|
||||
|
||||
/**
|
||||
* Calculates the checksum for the given file content.
|
||||
*/
|
||||
@@ -13,9 +15,8 @@ class MChecksum {
|
||||
* Returns the checksum of the file. Agnostic of encoding and new line character.
|
||||
*/
|
||||
static int calculate(File file) {
|
||||
try {
|
||||
try (BufferedReader bufferedReader = IOUtils.newReader(file)) {
|
||||
final CRC32 crc32 = new CRC32();
|
||||
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
final byte[] lineBytes = line.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
+12
@@ -18,12 +18,15 @@ public class MySqlDdl extends PlatformDdl {
|
||||
// this flag is for compatibility. Use it with care.
|
||||
private static final boolean USE_CHECK_CONSTRAINT = Boolean.getBoolean("ebean.mysql.useCheckConstraint");
|
||||
|
||||
private final boolean useMigrationStoredProcedures;
|
||||
|
||||
public MySqlDdl(DatabasePlatform platform) {
|
||||
super(platform);
|
||||
this.alterColumn = "modify";
|
||||
this.dropUniqueConstraint = "drop index";
|
||||
this.historyDdl = new MySqlHistoryDdl();
|
||||
this.inlineComments = true;
|
||||
this.useMigrationStoredProcedures = platform.isUseMigrationStoredProcedures();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,6 +37,15 @@ public class MySqlDdl extends PlatformDdl {
|
||||
return "drop index " + maxConstraintName(indexName) + " on " + tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void alterTableDropColumn(final DdlBuffer buffer, final String tableName, final String columnName) throws IOException {
|
||||
if (this.useMigrationStoredProcedures) {
|
||||
buffer.append("CALL usp_ebean_drop_column('").append(tableName).append("', '").append(columnName).append("')").endOfStatement();
|
||||
} else {
|
||||
super.alterTableDropColumn(buffer, tableName, columnName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the drop foreign key clause.
|
||||
*/
|
||||
|
||||
+3
-2
@@ -1,14 +1,15 @@
|
||||
package io.ebeaninternal.dbmigration.migrationreader;
|
||||
|
||||
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebeaninternal.dbmigration.migration.Migration;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Simple writer for output of the Migration/ChangeSet as an XML document.
|
||||
@@ -26,7 +27,7 @@ public class MigrationXmlWriter {
|
||||
*/
|
||||
public void write(Migration migration, File file) {
|
||||
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
try (Writer writer = IOUtils.newWriter(file)) {
|
||||
|
||||
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
|
||||
if (comment != null) {
|
||||
|
||||
+4
-4
@@ -2,6 +2,7 @@ package io.ebeaninternal.dbmigration.model;
|
||||
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
@@ -14,7 +15,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
@@ -70,16 +70,16 @@ public class PlatformDdlWriter {
|
||||
*/
|
||||
protected void writePlatformDdl(DdlWrite write, File resourcePath, String fullVersion) throws IOException {
|
||||
if (!write.isApplyEmpty()) {
|
||||
try (FileWriter applyWriter = createWriter(resourcePath, fullVersion, ".sql")) {
|
||||
try (Writer applyWriter = createWriter(resourcePath, fullVersion, ".sql")) {
|
||||
writeApplyDdl(applyWriter, write);
|
||||
applyWriter.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected FileWriter createWriter(File path, String fullVersion, String suffix) throws IOException {
|
||||
protected Writer createWriter(File path, String fullVersion, String suffix) throws IOException {
|
||||
File applyFile = new File(path, fullVersion + suffix);
|
||||
return new FileWriter(applyFile);
|
||||
return IOUtils.newWriter(applyFile);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+83
@@ -112,5 +112,88 @@ BEGIN
|
||||
END
|
||||
GO
|
||||
</ddl-script>
|
||||
<ddl-script name="create procs" platforms="mysql" init="true">-- Inital script to create stored procedures etc for mysql platform
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_foreign_keys;
|
||||
|
||||
delimiter $$
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_foreign_keys TABLE, COLUMN
|
||||
-- deletes all constraints and foreign keys referring to TABLE.COLUMN
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_foreign_keys(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
DECLARE c_fk_name CHAR(255);
|
||||
DECLARE curs CURSOR FOR SELECT CONSTRAINT_NAME from information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = DATABASE() and TABLE_NAME = p_table_name and COLUMN_NAME = p_column_name
|
||||
AND REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
OPEN curs;
|
||||
|
||||
read_loop: LOOP
|
||||
FETCH curs INTO c_fk_name;
|
||||
IF done THEN
|
||||
LEAVE read_loop;
|
||||
END IF;
|
||||
SET @sql = CONCAT('ALTER TABLE ', p_table_name, ' DROP FOREIGN KEY ', c_fk_name);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
END LOOP;
|
||||
|
||||
CLOSE curs;
|
||||
END
|
||||
$$
|
||||
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_column;
|
||||
|
||||
delimiter $$
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column and ensures that all indices and constraints are dropped first
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_column(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
CALL usp_ebean_drop_foreign_keys(p_table_name, p_column_name);
|
||||
SET @sql = CONCAT('ALTER TABLE ', p_table_name, ' DROP COLUMN ', p_column_name);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
END
|
||||
$$
|
||||
</ddl-script>
|
||||
|
||||
<ddl-script name="create procs" platforms="hana" init="true">-- Inital script to create stored procedures etc for the hana platform
|
||||
delimiter $$
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_foreign_keys TABLE, COLUMN
|
||||
-- deletes all constraints and foreign keys referring to TABLE.COLUMN
|
||||
--
|
||||
CREATE OR REPLACE PROCEDURE usp_ebean_drop_foreign_keys(IN table_name NVARCHAR(256), IN column_name NVARCHAR(256))
|
||||
AS
|
||||
BEGIN
|
||||
DECLARE foreign_key_names TABLE(CONSTRAINT_NAME NVARCHAR(256), TABLE_NAME NVARCHAR(256));
|
||||
DECLARE i INT;
|
||||
|
||||
foreign_key_names = SELECT CONSTRAINT_NAME, TABLE_NAME FROM SYS.REFERENTIAL_CONSTRAINTS WHERE SCHEMA_NAME=CURRENT_SCHEMA AND TABLE_NAME=UPPER(:table_name) AND COLUMN_NAME=UPPER(:column_name);
|
||||
|
||||
FOR I IN 1 .. RECORD_COUNT(:foreign_key_names) DO
|
||||
EXEC 'ALTER TABLE "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.TABLE_NAME[i]) || '" DROP CONSTRAINT "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.CONSTRAINT_NAME[i]) || '"';
|
||||
END FOR;
|
||||
|
||||
END;
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column and ensures that all indices and constraints are dropped first
|
||||
--
|
||||
CREATE OR REPLACE PROCEDURE usp_ebean_drop_column(IN table_name NVARCHAR(256), IN column_name NVARCHAR(256))
|
||||
AS
|
||||
BEGIN
|
||||
CALL usp_ebean_drop_foreign_keys(table_name, column_name);
|
||||
EXEC 'ALTER TABLE "' || UPPER(ESCAPE_DOUBLE_QUOTES(table_name)) || '" DROP ("' || UPPER(ESCAPE_DOUBLE_QUOTES(column_name)) || '")';
|
||||
END;
|
||||
$$
|
||||
</ddl-script>
|
||||
</extra-ddl>
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.File;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class MChecksumTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void calculate() {
|
||||
File file = new File("src/test/resources/dbmigration/index/1.0__hello.sql");
|
||||
@@ -15,4 +15,12 @@ public class MChecksumTest {
|
||||
|
||||
assertThat(MChecksum.calculate(file)).isEqualTo(907060870);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateWithSpecialChars() {
|
||||
File file = new File("src/test/resources/dbmigration/index-special-chars/1.0__hello.sql");
|
||||
assertThat(file).exists();
|
||||
|
||||
assertThat(MChecksum.calculate(file)).isEqualTo(1859426839);
|
||||
}
|
||||
}
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Class to test the alternative drop behaviour using stored procedures for MySql databases .
|
||||
*
|
||||
* @author Jonas Pöhler, FOCONIS AG
|
||||
*/
|
||||
public class MysqlGenerateMigrationTest {
|
||||
|
||||
@AfterEach
|
||||
public void resetPendingDropsProperty() {
|
||||
System.clearProperty("ddl.migration.pendingDropsFor");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMysqlStoredProcedures() throws Exception {
|
||||
DefaultDbMigration migration = new DefaultDbMigration();
|
||||
migration.setIncludeIndex(true);
|
||||
// We use src/test/resources as output directory (so we see in GIT if files will change)
|
||||
migration.setPathToResources("src/test/resources");
|
||||
|
||||
migration.addPlatform(Platform.MYSQL, "mysql");
|
||||
|
||||
final PlatformConfig platformConfig = new PlatformConfig();
|
||||
platformConfig.setUseMigrationStoredProcedures(true);
|
||||
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("migrationtest");
|
||||
config.loadFromProperties();
|
||||
config.setPlatformConfig(platformConfig);
|
||||
config.setRegister(false);
|
||||
config.setDefaultServer(false);
|
||||
config.getProperties().put("ebean.migration.migrationPath", "db/migration/mysql");
|
||||
|
||||
config.setPackages(Arrays.asList("misc.migration.mysql_v1_0"));
|
||||
Database server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
migration.setMigrationPath("mysql/procedures");
|
||||
|
||||
// First, we clean up the output-directory
|
||||
assertThat(migration.migrationDirectory().getAbsolutePath()).contains("procedures");
|
||||
Files.walk(migration.migrationDirectory().toPath())
|
||||
.filter(Files::isRegularFile)
|
||||
.map(Path::toFile).forEach(File::delete);
|
||||
|
||||
// then we generate migration scripts for v1_0
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.0__initial");
|
||||
|
||||
config.setPackages(Arrays.asList("misc.migration.mysql_v1_1"));
|
||||
server.shutdown();
|
||||
server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
migration.setMigrationPath("mysql/procedures");
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.1");
|
||||
|
||||
System.setProperty("ddl.migration.pendingDropsFor", "1.1");
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.2__dropsFor_1.1");
|
||||
|
||||
final Path sqlFile = migration.migrationDirectory().toPath()
|
||||
.resolve("mysql/1.2__dropsFor_1.1.sql");
|
||||
|
||||
assertThat(sqlFile).isNotEmptyFile();
|
||||
assertThat(Files.readAllLines(sqlFile, StandardCharsets.UTF_8))
|
||||
.contains("CALL usp_ebean_drop_column('migtest_e_basic', 'status2');")
|
||||
.contains("CALL usp_ebean_drop_column('migtest_e_basic', 'description');");
|
||||
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration;
|
||||
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebeaninternal.dbmigration.migration.AddColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.ChangeSet;
|
||||
import io.ebeaninternal.dbmigration.migration.CreateTable;
|
||||
@@ -9,8 +10,8 @@ import io.ebeaninternal.dbmigration.migrationreader.MigrationXmlReader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -89,8 +90,7 @@ public class Helper {
|
||||
|
||||
public static String asText(InputStream in) throws IOException {
|
||||
|
||||
try {
|
||||
InputStreamReader reader = new InputStreamReader(in);
|
||||
try (Reader reader = IOUtils.newReader(in)) {
|
||||
|
||||
LineNumberReader lineNumberReader = new LineNumberReader(reader);
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package misc.migration.mysql_v1_0;
|
||||
|
||||
import io.ebean.annotation.DbDefault;
|
||||
import io.ebean.annotation.EnumValue;
|
||||
import io.ebean.annotation.NotNull;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Entity
|
||||
@Table(name = "migtest_e_basic")
|
||||
public class EBasic {
|
||||
|
||||
public enum Status {
|
||||
@EnumValue("N")
|
||||
NEW,
|
||||
|
||||
@EnumValue("A")
|
||||
ACTIVE,
|
||||
|
||||
@EnumValue("I")
|
||||
INACTIVE,
|
||||
}
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
Status status;
|
||||
|
||||
@DbDefault("N")
|
||||
@NotNull
|
||||
Status status2;
|
||||
|
||||
@Size(max=127)
|
||||
String name;
|
||||
|
||||
@Size(max=127)
|
||||
String description;
|
||||
|
||||
public EBasic() {
|
||||
|
||||
}
|
||||
|
||||
public EBasic(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Status getStatus2() {
|
||||
return status2;
|
||||
}
|
||||
|
||||
public void setStatus2(final Status status2) {
|
||||
this.status2 = status2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package misc.migration.mysql_v1_1;
|
||||
|
||||
import io.ebean.annotation.EnumValue;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Entity
|
||||
@Table(name = "migtest_e_basic")
|
||||
public class EBasic {
|
||||
|
||||
public enum Status {
|
||||
@EnumValue("N")
|
||||
NEW,
|
||||
|
||||
@EnumValue("A")
|
||||
ACTIVE,
|
||||
|
||||
@EnumValue("I")
|
||||
INACTIVE,
|
||||
}
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
Status status;
|
||||
|
||||
@Size(max=127)
|
||||
String name;
|
||||
|
||||
public EBasic() {
|
||||
|
||||
}
|
||||
|
||||
public EBasic(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
helloäüü
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
<createTable name="migtest_e_basic" pkName="pk_migtest_e_basic">
|
||||
<column name="id" type="integer" primaryKey="true"/>
|
||||
<column name="status" type="varchar(1)" checkConstraint="check ( status in ('N','A','I'))" checkConstraintName="ck_migtest_e_basic_status"/>
|
||||
<column name="status2" type="varchar(1)" defaultValue="'N'" notnull="true" checkConstraint="check ( status2 in ('N','A','I'))" checkConstraintName="ck_migtest_e_basic_status2"/>
|
||||
<column name="name" type="varchar(127)"/>
|
||||
<column name="description" type="varchar(127)"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="pendingDrops">
|
||||
<dropColumn columnName="status2" tableName="migtest_e_basic"/>
|
||||
<dropColumn columnName="description" tableName="migtest_e_basic"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply" dropsFor="1.1">
|
||||
<dropColumn columnName="status2" tableName="migtest_e_basic"/>
|
||||
<dropColumn columnName="description" tableName="migtest_e_basic"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Migrationscripts for ebean unittest
|
||||
-- apply changes
|
||||
create table migtest_e_basic (
|
||||
id integer auto_increment not null,
|
||||
status varchar(1),
|
||||
status2 varchar(1) default 'N' not null,
|
||||
name varchar(127),
|
||||
description varchar(127),
|
||||
constraint pk_migtest_e_basic primary key (id)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Migrationscripts for ebean unittest
|
||||
-- apply changes
|
||||
CALL usp_ebean_drop_column('migtest_e_basic', 'status2');
|
||||
|
||||
CALL usp_ebean_drop_column('migtest_e_basic', 'description');
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
-- Inital script to create stored procedures etc for mysql platform
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_foreign_keys;
|
||||
|
||||
delimiter $$
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_foreign_keys TABLE, COLUMN
|
||||
-- deletes all constraints and foreign keys referring to TABLE.COLUMN
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_foreign_keys(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
DECLARE c_fk_name CHAR(255);
|
||||
DECLARE curs CURSOR FOR SELECT CONSTRAINT_NAME from information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = DATABASE() and TABLE_NAME = p_table_name and COLUMN_NAME = p_column_name
|
||||
AND REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
OPEN curs;
|
||||
|
||||
read_loop: LOOP
|
||||
FETCH curs INTO c_fk_name;
|
||||
IF done THEN
|
||||
LEAVE read_loop;
|
||||
END IF;
|
||||
SET @sql = CONCAT('ALTER TABLE ', p_table_name, ' DROP FOREIGN KEY ', c_fk_name);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
END LOOP;
|
||||
|
||||
CLOSE curs;
|
||||
END
|
||||
$$
|
||||
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_column;
|
||||
|
||||
delimiter $$
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column and ensures that all indices and constraints are dropped first
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_column(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
CALL usp_ebean_drop_foreign_keys(p_table_name, p_column_name);
|
||||
SET @sql = CONCAT('ALTER TABLE ', p_table_name, ' DROP COLUMN ', p_column_name);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
END
|
||||
$$
|
||||
@@ -0,0 +1,4 @@
|
||||
1835064798, I__create_procs.sql
|
||||
1968521526, 1.0__initial.sql
|
||||
-728933533, 1.2__dropsFor_1.1.sql
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean external mapping api</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
@@ -33,7 +33,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -59,14 +59,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean postgis</name>
|
||||
@@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean querybean</name>
|
||||
@@ -17,7 +17,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -56,21 +56,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+7
-7
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
@@ -16,41 +16,41 @@
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>3.6.3</version>
|
||||
<version>3.8.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+6
-6
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean test</name>
|
||||
@@ -29,14 +29,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.13.3-SNAPSHOT</version>
|
||||
<version>12.14.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -56,7 +56,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test-docker</artifactId>
|
||||
<version>4.3</version>
|
||||
<version>4.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -91,7 +91,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>12.12.1</version>
|
||||
<version>12.13.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
<version>1.2.9</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class ClickHouseSetup implements PlatformSetup {
|
||||
config.setDefaultPort(8123);
|
||||
config.setUsername("default");
|
||||
config.setPassword("");
|
||||
config.setUrl("jdbc:clickhouse://localhost:${port}/${databaseName}");
|
||||
config.setUrl("jdbc:clickhouse://${host}:${port}/${databaseName}");
|
||||
config.setDriver("ru.yandex.clickhouse.ClickHouseDriver");
|
||||
config.datasourceDefaults();
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class CockroachSetup implements PlatformSetup {
|
||||
config.setDefaultPort(26257);
|
||||
config.setUsername("root");
|
||||
config.setPassword("");
|
||||
config.setUrl("jdbc:postgresql://localhost:${port}/${databaseName}?sslmode=disable");
|
||||
config.setUrl("jdbc:postgresql://${host}:${port}/${databaseName}?sslmode=disable");
|
||||
config.setDriver("org.postgresql.Driver");
|
||||
config.datasourceDefaults();
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -26,11 +26,9 @@ class Config {
|
||||
private final String db;
|
||||
private final String platform;
|
||||
private String dockerPlatform;
|
||||
|
||||
private String databaseName;
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
private int port;
|
||||
|
||||
private String url;
|
||||
@@ -38,12 +36,10 @@ class Config {
|
||||
private String schema;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
private final DatabaseConfig config;
|
||||
|
||||
private boolean containerDropCreate;
|
||||
|
||||
private final Properties dockerProperties = new Properties();
|
||||
private final DockerHost dockerHost = new DockerHost();
|
||||
|
||||
Config(String db, String platform, String databaseName, DatabaseConfig config) {
|
||||
this.db = db;
|
||||
@@ -231,11 +227,17 @@ class Config {
|
||||
|
||||
void setUrl(String urlPattern) {
|
||||
String val = getPlatformKey("url", urlPattern);
|
||||
val = val.replace("${host}", host());
|
||||
val = val.replace("${port}", String.valueOf(port));
|
||||
val = val.replace("${databaseName}", databaseName);
|
||||
this.url = val;
|
||||
}
|
||||
|
||||
String host() {
|
||||
String explicitDockerHost = getKey("dockerHost", null);
|
||||
return getKey("host", dockerHost.dockerHost(explicitDockerHost));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append to the connection URL.
|
||||
*/
|
||||
@@ -322,7 +324,6 @@ class Config {
|
||||
void setDockerVersion(String version) {
|
||||
String val = getPlatformKey("version", version);
|
||||
dockerProperties.setProperty(dockerKey("version"), val);
|
||||
|
||||
if (containerDropCreate) {
|
||||
dockerProperties.setProperty(dockerKey("startMode"), "dropCreate");
|
||||
}
|
||||
@@ -369,7 +370,10 @@ class Config {
|
||||
}
|
||||
|
||||
private void initDockerProperties() {
|
||||
|
||||
if (dockerHost.runningInDocker()) {
|
||||
// tell ebean-docker-test we are not using localhost (for jdbc DB setup commands)
|
||||
dockerProperties.setProperty(dockerKey("host"), dockerHost.dockerHost());
|
||||
}
|
||||
dockerProperties.setProperty(dockerKey("port"), String.valueOf(port));
|
||||
dockerProperties.setProperty(dockerKey("dbName"), databaseName);
|
||||
if (schema != null) {
|
||||
|
||||
@@ -11,7 +11,7 @@ class Db2Setup implements PlatformSetup {
|
||||
config.setDefaultPort(50000);
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setUrl("jdbc:db2://localhost:${port}/${databaseName}");
|
||||
config.setUrl("jdbc:db2://${host}:${port}/${databaseName}");
|
||||
config.setDriver("com.ibm.db2.jcc.DB2Driver");
|
||||
config.datasourceDefaults();
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.ebean.test.config.platform;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Helper to detect if running inside docker and determine host name for that case.
|
||||
*/
|
||||
class DockerHost {
|
||||
|
||||
private final boolean runningInDocker;
|
||||
private String dockerHost;
|
||||
|
||||
DockerHost() {
|
||||
runningInDocker = initInDocker();
|
||||
}
|
||||
|
||||
boolean runningInDocker() {
|
||||
return runningInDocker;
|
||||
}
|
||||
|
||||
String dockerHost() {
|
||||
return dockerHost;
|
||||
}
|
||||
|
||||
String dockerHost(String explicitHost) {
|
||||
if (!runningInDocker) {
|
||||
return "localhost";
|
||||
}
|
||||
dockerHost = explicitHost != null ? explicitHost : defaultDockerHost();
|
||||
return dockerHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if running inside a docker container (we are using docker in docker).
|
||||
*/
|
||||
boolean initInDocker() {
|
||||
return new File("/.dockerenv").exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default host name to use when running in docker.
|
||||
* <p>
|
||||
* Can instead be explicitly specified via <code>ebean.test.dockerHost</code>.
|
||||
*/
|
||||
String defaultDockerHost() {
|
||||
String os = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
|
||||
if (os.contains("mac") || os.contains("darwin") || os.contains("win")) {
|
||||
return "host.docker.internal";
|
||||
} else {
|
||||
return "172.17.0.1";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ class HanaSetup implements PlatformSetup {
|
||||
config.setUsername("SYSTEM");
|
||||
config.setPassword("HXEHana1");
|
||||
config.setDatabaseName("HXE");
|
||||
config.setUrl("jdbc:sap://localhost:${port}/?databaseName=${databaseName}");
|
||||
config.setUrl("jdbc:sap://${host}:${port}/?databaseName=${databaseName}");
|
||||
String schema = config.getSchema();
|
||||
if (schema != null && !schema.equals(config.getUsername())) {
|
||||
config.urlAppend("¤tSchema=" + schema);
|
||||
|
||||
@@ -13,7 +13,7 @@ class MariaDBSetup implements PlatformSetup {
|
||||
config.setDefaultPort(defaultPort);
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setUrl("jdbc:mariadb://localhost:${port}/${databaseName}?useLegacyDatetimeCode=false");
|
||||
config.setUrl("jdbc:mariadb://${host}:${port}/${databaseName}?useLegacyDatetimeCode=false");
|
||||
config.datasourceDefaults();
|
||||
|
||||
return dockerProperties(config);
|
||||
|
||||
@@ -13,7 +13,7 @@ class MySqlSetup implements PlatformSetup {
|
||||
config.setDefaultPort(defaultPort);
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setUrl("jdbc:mysql://localhost:${port}/${databaseName}");
|
||||
config.setUrl("jdbc:mysql://${host}:${port}/${databaseName}");
|
||||
config.setDriver(defaultDriver());
|
||||
config.datasourceDefaults();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class PostgisSetup implements PlatformSetup {
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setDriver("org.postgis.DriverWrapperLW");
|
||||
config.setUrl("jdbc:postgresql_lwgis://localhost:${port}/${databaseName}");
|
||||
config.setUrl("jdbc:postgresql_lwgis://${host}:${port}/${databaseName}");
|
||||
|
||||
String schema = config.getSchema();
|
||||
if (schema != null && !schema.equals(config.getUsername())) {
|
||||
|
||||
@@ -13,7 +13,7 @@ class PostgresSetup implements PlatformSetup {
|
||||
config.setDefaultPort(defaultPort);
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setUrl("jdbc:postgresql://localhost:${port}/${databaseName}");
|
||||
config.setUrl("jdbc:postgresql://${host}:${port}/${databaseName}");
|
||||
|
||||
String schema = config.getSchema();
|
||||
if (schema != null && !schema.equals(config.getUsername())) {
|
||||
@@ -44,7 +44,7 @@ class PostgresSetup implements PlatformSetup {
|
||||
config.setDefaultPort(defaultPort);
|
||||
config.setExtraUsernameDefault();
|
||||
config.setExtraDbPasswordDefault();
|
||||
config.setUrl("jdbc:postgresql://localhost:${port}/${databaseName}");
|
||||
config.setUrl("jdbc:postgresql://${host}:${port}/${databaseName}");
|
||||
config.setDriver("org.postgresql.Driver");
|
||||
config.extraDatasourceDefaults();
|
||||
}
|
||||
|
||||
@@ -8,10 +8,14 @@ import java.util.Properties;
|
||||
class RedisSetup {
|
||||
|
||||
static void run(Properties properties) {
|
||||
|
||||
String version = properties.getProperty("ebean.test.redis");
|
||||
version = properties.getProperty("ebean.test.redis.version", version);
|
||||
if (version != null) {
|
||||
DockerHost dockerHost = new DockerHost();
|
||||
if (dockerHost.runningInDocker()) {
|
||||
String host = dockerHost.dockerHost(properties.getProperty("ebean.test.dockerHost"));
|
||||
properties.setProperty("redis.host", host);
|
||||
}
|
||||
RedisConfig redisConfig = new RedisConfig(version, properties);
|
||||
RedisContainer container = new RedisContainer(redisConfig);
|
||||
container.start();
|
||||
|
||||
@@ -13,7 +13,7 @@ class SqlServerSetup implements PlatformSetup {
|
||||
config.setDefaultPort(1433);
|
||||
config.setUsernameDefault();
|
||||
config.setPassword("SqlS3rv#r");
|
||||
config.setUrl("jdbc:sqlserver://localhost:${port};databaseName=${databaseName}");
|
||||
config.setUrl("jdbc:sqlserver://${host}:${port};databaseName=${databaseName};sendTimeAsDateTime=false");
|
||||
config.setDriver("com.microsoft.sqlserver.jdbc.SQLServerDriver");
|
||||
config.datasourceDefaults();
|
||||
|
||||
|
||||
@@ -27,16 +27,17 @@ public class DatabaseConfigTest {
|
||||
@Test
|
||||
public void evalPropertiesInput() {
|
||||
|
||||
String home = System.getenv("HOME");
|
||||
String home = System.getProperty("user.home");
|
||||
String fileSeparator = System.getProperty("file.separator");
|
||||
|
||||
Properties props = new Properties();
|
||||
props.setProperty("ddl.initSql", "${HOME}/initSql");
|
||||
props.setProperty("ddl.initSql", "${user.home}" + fileSeparator + "initSql");
|
||||
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.loadFromProperties(props);
|
||||
|
||||
String ddlInitSql = config.getDdlInitSql();
|
||||
assertThat(ddlInitSql).isEqualTo(home+"/initSql");
|
||||
assertThat(ddlInitSql).isEqualTo(home + fileSeparator + "initSql");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -50,30 +50,31 @@ public class PropertiesWrapperTest {
|
||||
@Test
|
||||
public void testGetProperties() {
|
||||
|
||||
String home = System.getenv("HOME");
|
||||
String home = System.getProperty("user.home");
|
||||
String tmpDir = System.getProperty("java.io.tmpdir");
|
||||
String fileSeparator = System.getProperty("file.separator");
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.put("someBasic", "hello");
|
||||
properties.put("someInt", "42");
|
||||
properties.put("someDouble", "5.5");
|
||||
properties.put("somePath", "${HOME}/hello");
|
||||
properties.put("someSystemProp", "/aaa/${java.io.tmpdir}/bbb");
|
||||
properties.put("somePath", "${user.home}" + fileSeparator + "hello");
|
||||
properties.put("someSystemProp", fileSeparator + "aaa" + fileSeparator + "${java.io.tmpdir}" + fileSeparator + "bbb");
|
||||
|
||||
Properties evalCopy = Config.asConfiguration().eval(properties);
|
||||
PropertiesWrapper pw = new PropertiesWrapper("pref", "myserver", evalCopy, null);
|
||||
|
||||
assertEquals(42, pw.getInt("someInt", 99));
|
||||
assertEquals(Double.valueOf(5.5D), (Double.valueOf(pw.getDouble("someDouble", 99.9D))));
|
||||
assertEquals(home + "/hello", pw.get("somePath", null));
|
||||
assertEquals("/aaa/" + tmpDir + "/bbb", pw.get("someSystemProp"));
|
||||
assertEquals(home + fileSeparator + "hello", pw.get("somePath", null));
|
||||
assertEquals(fileSeparator + "aaa" + fileSeparator + tmpDir + fileSeparator + "bbb", pw.get("someSystemProp"));
|
||||
|
||||
pw = new PropertiesWrapper(evalCopy, null);
|
||||
|
||||
assertEquals(42, pw.getInt("someInt", 99));
|
||||
assertEquals(Double.valueOf(5.5D), (Double.valueOf(pw.getDouble("someDouble", 99.9D))));
|
||||
assertEquals(home + "/hello", pw.get("somePath", null));
|
||||
assertEquals("/aaa/" + tmpDir + "/bbb", pw.get("someSystemProp"));
|
||||
assertEquals(home + fileSeparator + "hello", pw.get("somePath", null));
|
||||
assertEquals(fileSeparator + "aaa" + fileSeparator + tmpDir + fileSeparator + "bbb", pw.get("someSystemProp"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,28 +2,34 @@ package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.config.PlatformConfig;
|
||||
import io.ebean.config.dbplatform.oracle.Oracle11Platform;
|
||||
import io.ebean.config.dbplatform.oracle.Oracle12Platform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class OraclePlatformTest {
|
||||
class OraclePlatformTest {
|
||||
|
||||
@Test
|
||||
public void columnAliasPrefix_Oracle11Platform() {
|
||||
void columnAliasPrefix_Oracle11Platform() {
|
||||
Oracle11Platform platform11 = new Oracle11Platform();
|
||||
assertThat(platform11.columnAliasPrefix).isEqualTo("c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void columnAliasPrefix_OraclePlatform() {
|
||||
OraclePlatform platform = new OraclePlatform();
|
||||
assertThat(platform.columnAliasPrefix).isEqualTo("c");
|
||||
void columnAliasPrefix_Oracle12Platform() {
|
||||
Oracle12Platform platform12 = new Oracle12Platform();
|
||||
assertThat(platform12.columnAliasPrefix).isEqualTo("c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uuid_default() {
|
||||
void columnAliasPrefix_OraclePlatform() {
|
||||
OraclePlatform platform = new OraclePlatform();
|
||||
assertThat(platform.columnAliasPrefix).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void uuid_default() {
|
||||
OraclePlatform platform = new OraclePlatform();
|
||||
platform.configure(new PlatformConfig(), false);
|
||||
DbPlatformType dbType = platform.getDbTypeMap().get(DbPlatformType.UUID);
|
||||
@@ -31,8 +37,7 @@ public class OraclePlatformTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uuid_as_binary() {
|
||||
|
||||
void uuid_as_binary() {
|
||||
OraclePlatform platform = new OraclePlatform();
|
||||
PlatformConfig config = new PlatformConfig();
|
||||
config.setDbUuid(PlatformConfig.DbUuid.AUTO_BINARY);
|
||||
|
||||
@@ -4,24 +4,22 @@ import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebean.ModifyAwareType;
|
||||
import io.ebean.text.json.EJson;
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebeaninternal.json.ModifyAwareMap;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class EJsonTests {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EJsonTests.class);
|
||||
|
||||
@Test
|
||||
public void test_map_simple() throws IOException {
|
||||
|
||||
@@ -46,15 +44,13 @@ public class EJsonTests {
|
||||
public void write_withWriter_expect_writerNotClosed() throws IOException {
|
||||
|
||||
File temp = Files.createTempFile("some", ".json").toFile();
|
||||
FileWriter writer = new FileWriter(temp);
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
map.put("foo", "bar");
|
||||
EJson.write(map, writer);
|
||||
writer.write("The end.");
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
log.info("write to file {}", temp.getAbsolutePath());
|
||||
try (Writer writer = IOUtils.newWriter(temp)) {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("foo", "bar");
|
||||
EJson.write(map, writer);
|
||||
writer.write("The end.");
|
||||
}
|
||||
assertThat(temp).hasContent("{\"foo\":\"bar\"}The end.");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package io.ebean.test.config.platform;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class DockerHostTest {
|
||||
|
||||
@Test
|
||||
void runningInDocker_when_false_alwaysUseLocalhost() {
|
||||
DockerHost dockerHost = new DockerHost();
|
||||
assertFalse(dockerHost.runningInDocker());
|
||||
assertEquals("localhost", dockerHost.dockerHost("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runningInDocker_when_true_useExplicit() {
|
||||
TDDockerHost dockerHost = new TDDockerHost();
|
||||
assertTrue(dockerHost.runningInDocker());
|
||||
|
||||
assertEquals("my-host", dockerHost.dockerHost("my-host"));
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
void runningInDocker_when_trueAndLinux_useDefault() {
|
||||
TDDockerHost dockerHost = new TDDockerHost();
|
||||
assertTrue(dockerHost.runningInDocker());
|
||||
|
||||
assertEquals("172.17.0.1", dockerHost.dockerHost(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runningInDocker_when_windowsDefault() {
|
||||
TDDockerHost dockerHost = new TDDockerHost();
|
||||
assertTrue(dockerHost.runningInDocker());
|
||||
|
||||
String origName = System.getProperty("os.name");
|
||||
System.setProperty("os.name", "win");
|
||||
try {
|
||||
assertEquals("host.docker.internal",dockerHost.defaultDockerHost());
|
||||
assertEquals("host.docker.internal", dockerHost.dockerHost(null));
|
||||
} finally {
|
||||
System.setProperty("os.name", origName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void runningInDocker_when_macDefault() {
|
||||
TDDockerHost dockerHost = new TDDockerHost();
|
||||
assertTrue(dockerHost.runningInDocker());
|
||||
|
||||
String origName = System.getProperty("os.name");
|
||||
System.setProperty("os.name", "mac");
|
||||
try {
|
||||
assertEquals("host.docker.internal",dockerHost.defaultDockerHost());
|
||||
assertEquals("host.docker.internal", dockerHost.dockerHost(null));
|
||||
} finally {
|
||||
System.setProperty("os.name", origName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void runningInDocker_when_linuxDefault() {
|
||||
TDDockerHost dockerHost = new TDDockerHost();
|
||||
assertTrue(dockerHost.runningInDocker());
|
||||
|
||||
String origName = System.getProperty("os.name");
|
||||
System.setProperty("os.name", "linux");
|
||||
try {
|
||||
assertEquals("172.17.0.1",dockerHost.defaultDockerHost());
|
||||
assertEquals("172.17.0.1", dockerHost.dockerHost(null));
|
||||
} finally {
|
||||
System.setProperty("os.name", origName);
|
||||
}
|
||||
}
|
||||
|
||||
static class TDDockerHost extends DockerHost {
|
||||
|
||||
@Override
|
||||
boolean initInDocker() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -11,6 +11,7 @@ import org.tests.model.basic.ResetBasicData;
|
||||
import org.tests.model.basic.TBytesOnly;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -94,7 +95,7 @@ public class CachedBeanDataSerializeTest extends BaseTestCase {
|
||||
|
||||
TBytesOnly bean = new TBytesOnly();
|
||||
bean.setId(42);
|
||||
bean.setContent(stringContent.getBytes("UTF-8"));
|
||||
bean.setContent(stringContent.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
BeanDescriptor<TBytesOnly> desc = getBeanDescriptor(TBytesOnly.class);
|
||||
CachedBeanData extract = CachedBeanDataFromBean.extract(desc, (EntityBean) bean);
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.config.EncryptKey;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.basic.encrypt.BasicEncryptKey;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -19,7 +20,7 @@ public class TestSimpleEncryptor extends BaseTestCase {
|
||||
|
||||
EncryptKey key = new BasicEncryptKey("hello");
|
||||
|
||||
byte[] data = "test123".getBytes();
|
||||
byte[] data = "test123".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
byte[] ecData = e.encrypt(data, key);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.tests.model.ivo.converter.MoneyTypeConverter;
|
||||
import javax.persistence.EnumType;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
@@ -29,7 +31,6 @@ public class TestTypeManager extends BaseTestCase {
|
||||
DefaultTypeManager typeManager = createTypeManager();
|
||||
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(MyEnum.class, null);
|
||||
typeManager.addEnumType(type, MyEnum.class);
|
||||
|
||||
Object val = type.read(new DummyDataReader("A"));
|
||||
assertThat(val).isEqualTo(MyEnum.Aval);
|
||||
@@ -131,6 +132,13 @@ public class TestTypeManager extends BaseTestCase {
|
||||
return new DefaultTypeManager(config, bootupClasses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalendar() throws SQLException {
|
||||
|
||||
DefaultTypeManager typeManager = createTypeManager();
|
||||
ScalarType<?> typeB = typeManager.getScalarType(GregorianCalendar.class);
|
||||
assertThat(typeB).isInstanceOf(ScalarTypeCalendar.class);
|
||||
}
|
||||
/**
|
||||
* Test double DataReader implementation.
|
||||
*/
|
||||
|
||||
@@ -8,12 +8,14 @@ import org.tests.model.basic.PFileContent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class TestDeleteImportedPartial extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
PFile persistentFile = new PFile("test.txt", new PFileContent("test".getBytes()));
|
||||
PFile persistentFile = new PFile("test.txt", new PFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
DB.save(persistentFile);
|
||||
Integer id = persistentFile.getId();
|
||||
|
||||
@@ -8,13 +8,15 @@ import org.tests.model.basic.PersistentFileContent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class TestDeleteOneToOne extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testCreateDeletePersistentFile() {
|
||||
|
||||
PersistentFile persistentFile = new PersistentFile("test.txt", new PersistentFileContent(
|
||||
"test".getBytes()));
|
||||
"test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
DB.save(persistentFile);
|
||||
Integer id = persistentFile.getId();
|
||||
|
||||
@@ -8,16 +8,18 @@ import org.tests.model.basic.PFileContent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class TestDeleteOneToOneMultiple extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testCreateDeletePersistentFile() {
|
||||
|
||||
PFile persistentFile = new PFile("test.txt", new PFileContent("test".getBytes()));
|
||||
PFile persistentFile = new PFile("test.txt", new PFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
// PFile persistentFile = new PFile();
|
||||
// persistentFile.setName("test.txt");
|
||||
// PFileContent content = new PFileContent();
|
||||
// content.setContent("test".getBytes());
|
||||
// content.setContent("test".getBytes(StandardCharsets.UTF_8));
|
||||
// persistentFile.setFileContent(content);
|
||||
|
||||
DB.save(persistentFile);
|
||||
|
||||
@@ -8,12 +8,14 @@ import org.tests.model.basic.PersistentFileContent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class TestSaveDeleteOneToOne extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testCreateDeletePersistentFile() {
|
||||
PersistentFile persistentFile = new PersistentFile("test.txt",
|
||||
new PersistentFileContent("test".getBytes()));
|
||||
new PersistentFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
DB.save(persistentFile);
|
||||
DB.delete(persistentFile);
|
||||
@@ -22,7 +24,7 @@ public class TestSaveDeleteOneToOne extends BaseTestCase {
|
||||
@Test
|
||||
public void testCreateLoadDeletePersistentFile() {
|
||||
PersistentFile persistentFile = new PersistentFile("test.txt",
|
||||
new PersistentFileContent("test".getBytes()));
|
||||
new PersistentFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
DB.save(persistentFile);
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@ import org.tests.model.basic.PFileContent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class TestSaveDeleteOneToOneMultiple extends BaseTestCase {
|
||||
|
||||
// public void testCreateDeletePFile() {
|
||||
// PFile persistentFile = new PFile("test.txt",
|
||||
// new PFileContent("test".getBytes()));
|
||||
// new PFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
//
|
||||
// DB.save(persistentFile);
|
||||
// DB.delete(persistentFile);
|
||||
@@ -21,7 +23,7 @@ public class TestSaveDeleteOneToOneMultiple extends BaseTestCase {
|
||||
@Test
|
||||
public void testCreateLoadDeletePFile() {
|
||||
PFile persistentFile = new PFile("test.txt",
|
||||
new PFileContent("test".getBytes()));
|
||||
new PFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
DB.save(persistentFile);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.ebean.DB;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.TWithPreInsert;
|
||||
import org.tests.model.basic.TWithPreInsertChild;
|
||||
import org.tests.model.basic.event.TWithPreInsertPersistAdapter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@@ -27,6 +28,7 @@ class TestPreInsertValidation extends BaseTestCase {
|
||||
assertThat(e.requestCascadeState()).isEqualTo(2);
|
||||
|
||||
TWithPreInsert e1 = DB.find(TWithPreInsert.class, e.getId());
|
||||
assert e1 != null;
|
||||
|
||||
e1.setTitle("Missus");
|
||||
DB.save(e1);
|
||||
@@ -54,11 +56,21 @@ class TestPreInsertValidation extends BaseTestCase {
|
||||
assert e1 != null;
|
||||
|
||||
e1.setTitle("ParentCascading-changed");
|
||||
e1.children().get(0).setName("Child0-changed");
|
||||
TWithPreInsertChild childBean = e1.children().get(0);
|
||||
childBean.setName("Child0-changed");
|
||||
DB.save(e1);
|
||||
|
||||
assertThat(e1.requestCascadeState()).isEqualTo(12);
|
||||
assertThat(e1.children().get(0).requestCascadeState()).isEqualTo(11);
|
||||
assertThat(childBean.requestCascadeState()).isEqualTo(11);
|
||||
|
||||
DB.delete(e1);
|
||||
|
||||
assertThat(e1.requestCascadeState()).isEqualTo(22);
|
||||
|
||||
// assert that isCascade() was true for the child bean
|
||||
assertThat(TWithPreInsertPersistAdapter.cascadeDelete).hasSize(1);
|
||||
String deleteCascade = TWithPreInsertPersistAdapter.cascadeDelete.get(0);
|
||||
assertThat(deleteCascade).isEqualTo("class org.tests.model.basic.TWithPreInsertChild:1");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,7 +26,7 @@ public class TestDefaults extends BaseTestCase {
|
||||
final List<String> current = LoggedSql.collect();
|
||||
|
||||
assertThat(current).isNotEmpty();
|
||||
if (isMySql() || isMariaDB()) {
|
||||
if (isMySql() || isMariaDB() || isOracle()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft values (default);");
|
||||
} else if (isSqlServer()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft (id) values (?)");
|
||||
|
||||
+3
-1
@@ -9,12 +9,14 @@ import org.tests.model.basic.PFileContent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class TestConstructorPutfieldReplacement extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
PFile persistentFile = new PFile("test.txt", new PFileContent("test".getBytes()));
|
||||
PFile persistentFile = new PFile("test.txt", new PFileContent("test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
EntityBean eb = (EntityBean) persistentFile;
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
|
||||
@@ -14,6 +14,8 @@ import org.tests.idkeys.db.GenKeySeqB;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
@@ -24,6 +26,7 @@ public class TestGeneratedKeys extends BaseTestCase {
|
||||
@ForPlatform(Platform.H2) // readSequenceValue is H2 specific
|
||||
public void testGenKeySeqA() throws SQLException {
|
||||
assumeTrue(idType() == IdType.SEQUENCE);
|
||||
|
||||
SpiEbeanServer server = spiEbeanServer();
|
||||
|
||||
try (Transaction tx = server.beginTransaction()) {
|
||||
@@ -69,20 +72,34 @@ public class TestGeneratedKeys extends BaseTestCase {
|
||||
}
|
||||
|
||||
private long readSequenceValue(Transaction tx, String sequence) throws SQLException {
|
||||
Statement stm = null;
|
||||
try {
|
||||
stm = tx.connection().createStatement();
|
||||
ResultSet rs = stm.executeQuery("select currval('" + sequence + "')");
|
||||
rs.next();
|
||||
String sql;
|
||||
switch (spiEbeanServer().databasePlatform().getPlatform().base()) {
|
||||
case H2 :
|
||||
sql = "select currval('" + sequence + "')";
|
||||
break;
|
||||
|
||||
case DB2 :
|
||||
sql = "values previous value for " + sequence;
|
||||
|
||||
break;
|
||||
case SQLSERVER :
|
||||
sql = "select current_value from sys.sequences where name = '" + sequence + "'";
|
||||
break;
|
||||
|
||||
case MARIADB :
|
||||
throw new UnsupportedOperationException("reading sequence value outside of the current connection is not supported. "
|
||||
+ "See https://mariadb.com/kb/en/previous-value-for-sequence_name/#description");
|
||||
|
||||
default :
|
||||
throw new UnsupportedOperationException("reading sequence value from "
|
||||
+ spiEbeanServer().databasePlatform().getPlatform()
|
||||
+ " is not supported.");
|
||||
|
||||
}
|
||||
try (Statement stm = tx.connection().createStatement()) {
|
||||
ResultSet rs = stm.executeQuery(sql);
|
||||
rs.next();
|
||||
return rs.getLong(1);
|
||||
} finally {
|
||||
if (stm != null) {
|
||||
try {
|
||||
stm.close();
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,5 +126,25 @@ public class TestGeneratedKeys extends BaseTestCase {
|
||||
assertNotNull(al.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform({Platform.H2, Platform.MARIADB, Platform.SQLSERVER, Platform.DB2})
|
||||
public void testGeneratedKeys() throws SQLException {
|
||||
assumeTrue(idType() == IdType.SEQUENCE);
|
||||
|
||||
SpiEbeanServer server = spiEbeanServer();
|
||||
List<Long> idList = new ArrayList<>(52);
|
||||
|
||||
try (Transaction tx = server.beginTransaction()) {
|
||||
// bigger than increment
|
||||
for (int i = 1; i < 52; i++) {
|
||||
GenKeySeqA gks = new GenKeySeqA();
|
||||
gks.setDescription("my description " + i);
|
||||
server.save(gks);
|
||||
assertFalse(idList.contains(gks.getId()));
|
||||
idList.add(gks.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static javax.persistence.CascadeType.PERSIST;
|
||||
import static javax.persistence.CascadeType.ALL;
|
||||
|
||||
@Entity
|
||||
public class TWithPreInsert implements TWithPreInsertCommon {
|
||||
@@ -20,7 +20,7 @@ public class TWithPreInsert implements TWithPreInsertCommon {
|
||||
|
||||
private String title;
|
||||
|
||||
@OneToMany(cascade = PERSIST)
|
||||
@OneToMany(cascade = ALL)
|
||||
private List<TWithPreInsertChild> children = new ArrayList<>();
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.tests.model.basic;
|
||||
|
||||
public interface TWithPreInsertCommon {
|
||||
|
||||
Integer getId();
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
+15
@@ -4,8 +4,13 @@ import io.ebean.event.BeanPersistAdapter;
|
||||
import io.ebean.event.BeanPersistRequest;
|
||||
import org.tests.model.basic.TWithPreInsertCommon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TWithPreInsertPersistAdapter extends BeanPersistAdapter {
|
||||
|
||||
public static List<String> cascadeDelete = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean isRegisterFor(Class<?> cls) {
|
||||
return TWithPreInsertCommon.class.isAssignableFrom(cls);
|
||||
@@ -32,4 +37,14 @@ public class TWithPreInsertPersistAdapter extends BeanPersistAdapter {
|
||||
return super.preUpdate(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preDelete(BeanPersistRequest<?> request) {
|
||||
TWithPreInsertCommon bean = (TWithPreInsertCommon) request.bean();
|
||||
if (request.isCascade()) {
|
||||
cascadeDelete.add(bean.getClass() + ":" + bean.getId());
|
||||
} else {
|
||||
bean.requestCascadeState(22);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.tests.model.elementcollection;
|
||||
|
||||
import io.ebean.annotation.Cache;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Cache
|
||||
@Entity
|
||||
public class EcblPerson2 {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(joinColumns = @JoinColumn(name = "person_id"))
|
||||
List<EcPhone> phoneNumbers = new ArrayList<>();
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "person id:" + id + " name:" + name + " phs:" + phoneNumbers;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<EcPhone> getPhoneNumbers() {
|
||||
return phoneNumbers;
|
||||
}
|
||||
|
||||
public void setPhoneNumbers(List<EcPhone> phoneNumbers) {
|
||||
this.phoneNumbers = phoneNumbers;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -9,10 +9,10 @@ import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestElementCollectionEmbeddedListCache extends BaseTestCase {
|
||||
class TestElementCollectionEmbeddedListCache extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
void test() {
|
||||
|
||||
EcblPerson person = new EcblPerson("CacheL");
|
||||
person.getPhoneNumbers().add(new EcPhone("64", "021","1234"));
|
||||
@@ -86,12 +86,10 @@ public class TestElementCollectionEmbeddedListCache extends BaseTestCase {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
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;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TestElementCollectionEmbeddedListCache2 extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
|
||||
EcblPerson2 person = new EcblPerson2();
|
||||
person.setName("CacheL");
|
||||
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)
|
||||
.setId(person.getId())
|
||||
.fetch("phoneNumbers")
|
||||
.findOne();
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
one.getPhoneNumbers().size();
|
||||
|
||||
List<String> sql = LoggedSql.collect();
|
||||
assertThat(sql).isEmpty();
|
||||
|
||||
EcblPerson2 two = DB.find(EcblPerson2.class )
|
||||
.setId(person.getId())
|
||||
.findOne();
|
||||
|
||||
two.getPhoneNumbers().size();
|
||||
assertThat(two.getPhoneNumbers().toString()).contains("64-021-1234", "64-021-4321");
|
||||
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql).isEmpty(); // cache hit
|
||||
|
||||
two.getPhoneNumbers().add(new EcPhone("61", "07", "11"));
|
||||
two.getPhoneNumbers().remove(1);
|
||||
|
||||
DB.save(two);
|
||||
|
||||
sql = LoggedSql.collect();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(5); // update of collection only
|
||||
assertSql(sql.get(0)).contains("delete from ecbl_person2_phone_numbers where person_id=?");
|
||||
assertSqlBind(sql.get(1));
|
||||
assertSql(sql.get(2)).contains("insert into ecbl_person2_phone_numbers (person_id,country_code,area,phnum) values (?,?,?,?)");
|
||||
assertSqlBind(sql, 3, 4);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3); // update of collection only
|
||||
assertSql(sql.get(0)).contains("delete from ecbl_person2_phone_numbers where person_id=?");
|
||||
assertSql(sql.get(1)).contains("insert into ecbl_person2_phone_numbers (person_id,country_code,area,phnum) values (?,?,?,?)");
|
||||
assertSql(sql.get(2)).contains("insert into ecbl_person2_phone_numbers (person_id,country_code,area,phnum) values (?,?,?,?)");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql).isEmpty(); // cache hit
|
||||
|
||||
|
||||
three.setName("mod-3");
|
||||
three.getPhoneNumbers().remove(0);
|
||||
|
||||
DB.save(three);
|
||||
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql).hasSize(5);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.tests.model.embedded;
|
||||
|
||||
import io.ebean.annotation.DbArray;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class EmbArrayMaster {
|
||||
|
||||
@Embeddable
|
||||
public static class EmbArrayDetail {
|
||||
@DbArray
|
||||
List<String> vals;
|
||||
|
||||
public EmbArrayDetail(List<String> vals) {
|
||||
this.vals = vals;
|
||||
}
|
||||
}
|
||||
|
||||
@Id
|
||||
int id;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "test_array_detail", joinColumns = {@JoinColumn(name = "master_id")})
|
||||
List<EmbArrayDetail> details;
|
||||
|
||||
public EmbArrayMaster(List<EmbArrayDetail> details) {
|
||||
this.details = details;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.tests.model.embedded;
|
||||
|
||||
import io.ebean.DB;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
class TestEmbeddedDbArray {
|
||||
|
||||
/**
|
||||
* Failing test case for #2477
|
||||
*/
|
||||
@Disabled
|
||||
@Test
|
||||
void testArrayInsert() {
|
||||
EmbArrayMaster t = new EmbArrayMaster(singletonList(new EmbArrayMaster.EmbArrayDetail(emptyList())));
|
||||
DB.insert(t);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user