mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23a9cf9bb3 | ||
|
|
75395a8481 | ||
|
|
a161d0c01b | ||
|
|
1dd7720605 | ||
|
|
3d2f885e87 | ||
|
|
2b3e485beb | ||
|
|
d4be0718a8 | ||
|
|
6d0556a120 | ||
|
|
ec7e4e4935 | ||
|
|
471605619a | ||
|
|
02fe956056 | ||
|
|
db13034fec | ||
|
|
c2489beb82 | ||
|
|
9a424d7d6d | ||
|
|
9b74602617 | ||
|
|
5c99986476 | ||
|
|
7d38933e9d | ||
|
|
7668fb11a9 | ||
|
|
eac68166d9 | ||
|
|
cb0023345f | ||
|
|
f0f7feb125 | ||
|
|
c8e32253a5 | ||
|
|
01541bb208 | ||
|
|
2d44d06f36 | ||
|
|
fda930a162 | ||
|
|
5a6cdb9a86 | ||
|
|
5ef7fe8504 |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.18.5</version>
|
||||
<version>11.19.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.18.5</tag>
|
||||
<tag>ebean-11.19.3</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -360,7 +360,7 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<doctitle>Ebean 10</doctitle>
|
||||
<doctitle>Ebean 11</doctitle>
|
||||
<overview>src/main/java/io/ebean/overview.html</overview>
|
||||
<source>1.8</source>
|
||||
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
|
||||
|
||||
@@ -412,6 +412,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> select(String properties);
|
||||
|
||||
/**
|
||||
* Apply the fetchGroup which defines what part of the object graph to load.
|
||||
*/
|
||||
Query<T> select(FetchGroup<T> fetchGroup);
|
||||
|
||||
/**
|
||||
* Set whether this query uses DISTINCT.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package io.ebean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Defines what part of the object graph to load (select and fetch clauses).
|
||||
* <p>
|
||||
* Using a FetchGroup effectively sets the select() and fetch() clauses for a query. It is alternative
|
||||
* to specifying the select() and fetch() clauses on the query allowing for more re-use of "what to load"
|
||||
* that can be defined separately from the query and combined with other FetchGroups.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Select example</h3>*
|
||||
* <pre>{@code
|
||||
*
|
||||
* FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class, "name, status");
|
||||
*
|
||||
* Customer.query()
|
||||
* .select(fetchGroup)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Select and fetch example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName, lastName, email")
|
||||
* .build();
|
||||
*
|
||||
* Customer.query()
|
||||
* .select(fetchGroup)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Combining FetchGroups</h3>
|
||||
* <p>
|
||||
* FetchGroups can be combined together to form another FetchGroup.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* FetchGroup<Address> FG_ADDRESS = FetchGroup.of(Address.class)
|
||||
* .select("line1, line2, city")
|
||||
* .fetch("country", "name")
|
||||
* .build();
|
||||
*
|
||||
* FetchGroup<Customer> FG_CUSTOMER = FetchGroup.of(Customer.class)
|
||||
* .select("name, version")
|
||||
* .fetch("billingAddress", FG_ADDRESS)
|
||||
* .build();
|
||||
*
|
||||
*
|
||||
* Customer.query()
|
||||
* .select(FG_CUSTOMER)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> The bean type the Fetch group can be applied to
|
||||
*/
|
||||
public interface FetchGroup<T> {
|
||||
|
||||
/**
|
||||
* Return the FetchGroup with the given select clause.
|
||||
* <p>
|
||||
* We use this for simple FetchGroup that only select() properties and do not have additional fetch() clause.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class, "name, status");
|
||||
*
|
||||
* Customer.query()
|
||||
* .select(fetchGroup)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param select The select clause of the FetchGroup
|
||||
*
|
||||
* @return The FetchGroup with the given select clause
|
||||
*/
|
||||
@Nonnull
|
||||
static <T> FetchGroup<T> of(Class<T> cls, String select) {
|
||||
return XServiceProvider.fetchGroupOf(cls, select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroupBuilder with the given select clause that we can add fetch clauses to.
|
||||
* <p>
|
||||
* We chain select() with one or more fetch() clauses to define the object graph to load.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName, lastName, email")
|
||||
* .build();
|
||||
*
|
||||
* Customer.query()
|
||||
* .select(fetchGroup)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return The FetchGroupBuilder with the given select clause which we will add fetch clauses to
|
||||
*/
|
||||
@Nonnull
|
||||
static <T> FetchGroupBuilder<T> of(Class<T> cls) {
|
||||
return XServiceProvider.fetchGroupOf(cls);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package io.ebean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Builds a FetchGroup by adding fetch clauses.
|
||||
* <p>
|
||||
* We add select() and fetch() clauses to define the object graph we want to load.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* FetchGroup fetchGroup = FetchGroup
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName, lastName, email")
|
||||
* .build();
|
||||
*
|
||||
* Customer.query()
|
||||
* .select(fetchGroup)
|
||||
* .where()
|
||||
* ...
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public interface FetchGroupBuilder<T> {
|
||||
|
||||
/**
|
||||
* Specify specific properties to select (top level properties).
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> select(String select);
|
||||
|
||||
/**
|
||||
* Fetch all the properties at the given path.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetch(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path with the nested fetch group.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetch(String path, FetchGroup<?> nestedGroup);
|
||||
|
||||
/**
|
||||
* Fetch the path using a query join with the nested fetch group.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchQuery(String path, FetchGroup<?> nestedGroup);
|
||||
|
||||
/**
|
||||
* Fetch the path lazily with the nested fetch group.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchLazy(String path, FetchGroup<?> nestedGroup);
|
||||
|
||||
/**
|
||||
* Fetch the path including specified properties.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetch(String path, String properties);
|
||||
|
||||
/**
|
||||
* Fetch the path including all its properties using a query join.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchQuery(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path including specified properties using a query join.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchQuery(String path, String properties);
|
||||
|
||||
/**
|
||||
* Fetch the path including all its properties lazily.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchLazy(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path including specified properties lazily.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchLazy(String path, String properties);
|
||||
|
||||
/**
|
||||
* Build and return the FetchGroup.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroup<T> build();
|
||||
}
|
||||
@@ -397,6 +397,11 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> select(String fetchProperties);
|
||||
|
||||
/**
|
||||
* Apply the fetchGroup which defines what part of the object graph to load.
|
||||
*/
|
||||
Query<T> select(FetchGroup<T> fetchGroup);
|
||||
|
||||
/**
|
||||
* Specify a path to fetch eagerly including specific properties.
|
||||
* <p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.service.SpiFetchGroupService;
|
||||
import io.ebean.service.SpiProfileLocationFactory;
|
||||
import io.ebean.service.SpiRawSqlService;
|
||||
|
||||
@@ -15,6 +16,16 @@ class XServiceProvider {
|
||||
|
||||
private static SpiProfileLocationFactory profileLocationFactory = initProfileLocation();
|
||||
|
||||
private static SpiFetchGroupService fetchGroupService = initSpiFetchGroupService();
|
||||
|
||||
private static SpiFetchGroupService initSpiFetchGroupService() {
|
||||
Iterator<SpiFetchGroupService> loader = ServiceLoader.load(SpiFetchGroupService.class).iterator();
|
||||
if (loader.hasNext()) {
|
||||
return loader.next();
|
||||
}
|
||||
throw new IllegalStateException("No service implementation found for SpiFetchGroupService?");
|
||||
}
|
||||
|
||||
private static SpiRawSqlService initRawSql() {
|
||||
|
||||
Iterator<SpiRawSqlService> loader = ServiceLoader.load(SpiRawSqlService.class).iterator();
|
||||
@@ -47,4 +58,17 @@ class XServiceProvider {
|
||||
return profileLocationFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroup with the given select clause.
|
||||
*/
|
||||
static <T> FetchGroup<T> fetchGroupOf(Class<T> cls, String select) {
|
||||
return fetchGroupService.of(cls, select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroupBuilder with the given select clause.
|
||||
*/
|
||||
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
|
||||
return fetchGroupService.of(cls);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3130,9 +3130,10 @@ public class ServerConfig {
|
||||
* @return A copy of the PlatformConfig with overridden properties
|
||||
*/
|
||||
public PlatformConfig newPlatformConfig(String propertiesPath, String platformPrefix) {
|
||||
|
||||
if (properties == null) {
|
||||
properties = new Properties();
|
||||
}
|
||||
PropertiesWrapper p = new PropertiesWrapper(propertiesPath, platformPrefix, properties, classLoadConfig);
|
||||
|
||||
PlatformConfig config = new PlatformConfig(platformConfig);
|
||||
config.loadSettings(p);
|
||||
return config;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.ebean.service;
|
||||
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchGroupBuilder;
|
||||
|
||||
/**
|
||||
* Service that parses FetchGroup expressions.
|
||||
*/
|
||||
public interface SpiFetchGroupService {
|
||||
|
||||
/**
|
||||
* Return the FetchGroup with the given select clause.
|
||||
*
|
||||
* @param beanType The type of entity bean the fetch group is for
|
||||
* @param select The properties to select (top level properties)
|
||||
*/
|
||||
<T> FetchGroup<T> of(Class<T> beanType, String select);
|
||||
|
||||
/**
|
||||
* Create and return a FetchGroupBuilder starting with a select() clause.
|
||||
*
|
||||
* @param beanType The type of entity bean the fetch group is for
|
||||
* @return The FetchGroupBuilder to add additional select and fetch clauses
|
||||
*/
|
||||
<T> FetchGroupBuilder<T> of(Class<T> beanType);
|
||||
}
|
||||
@@ -84,6 +84,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
protected DatabasePlatform databasePlatform;
|
||||
|
||||
private boolean vanillaPlatform;
|
||||
|
||||
protected List<Pair> platforms = new ArrayList<>();
|
||||
|
||||
protected ServerConfig serverConfig;
|
||||
@@ -192,6 +194,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
*/
|
||||
@Override
|
||||
public void setPlatform(Platform platform) {
|
||||
vanillaPlatform = true;
|
||||
setPlatform(getPlatform(platform));
|
||||
}
|
||||
|
||||
@@ -314,24 +317,28 @@ public class DefaultDbMigration implements DbMigration {
|
||||
private void generateExtraDdl(File migrationDir, DatabasePlatform dbPlatform) throws IOException {
|
||||
|
||||
if (dbPlatform != null) {
|
||||
ExtraDdl extraDdl = ExtraDdlXmlReader.read("/extra-ddl.xml");
|
||||
if (extraDdl != null) {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (!script.isDrop() && ExtraDdlXmlReader.matchPlatform(dbPlatform.getName(), script.getPlatforms())) {
|
||||
generateExtraDdl(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltin());
|
||||
generateExtraDdl(migrationDir, dbPlatform, ExtraDdlXmlReader.read());
|
||||
}
|
||||
}
|
||||
|
||||
private void generateExtraDdl(File migrationDir, DatabasePlatform dbPlatform, ExtraDdl extraDdl) throws IOException {
|
||||
if (extraDdl != null) {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (!script.isDrop() && ExtraDdlXmlReader.matchPlatform(dbPlatform.getName(), script.getPlatforms())) {
|
||||
writeExtraDdl(migrationDir, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write (or override) the "repeatable" migration script.
|
||||
*/
|
||||
private void writeExtraDdl(File migrationDir, DdlScript script) throws IOException {
|
||||
|
||||
String fullName = repeatableMigrationName(script.getName());
|
||||
String fullName = repeatableMigrationName(script.isInit(), script.getName());
|
||||
|
||||
logger.info("writing repeatable script {}", fullName);
|
||||
|
||||
@@ -342,8 +349,18 @@ public class DefaultDbMigration implements DbMigration {
|
||||
}
|
||||
}
|
||||
|
||||
private String repeatableMigrationName(String scriptName) {
|
||||
return "R__" + scriptName.replace(' ', '_') + migrationConfig.getApplySuffix();
|
||||
|
||||
|
||||
private String repeatableMigrationName(boolean init, String scriptName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (init) {
|
||||
sb.append("I__");
|
||||
} else {
|
||||
sb.append("R__");
|
||||
}
|
||||
sb.append(scriptName.replace(' ', '_'));
|
||||
sb.append(migrationConfig.getApplySuffix());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -542,11 +559,10 @@ public class DefaultDbMigration implements DbMigration {
|
||||
if (server == null) {
|
||||
setServer(Ebean.getDefaultServer());
|
||||
}
|
||||
if (databasePlatform == null && platforms.isEmpty()) {
|
||||
// not explicitly set not set a list of platforms so
|
||||
// default to the platform of the default server
|
||||
if (vanillaPlatform || databasePlatform == null) {
|
||||
// not explicitly set so use the platform of the server
|
||||
databasePlatform = server.getDatabasePlatform();
|
||||
logger.debug("set platform to {}", databasePlatform.getName());
|
||||
logger.trace("set platform to {}", databasePlatform.getName());
|
||||
}
|
||||
if (migrationConfig != null) {
|
||||
if (strictMode != null) {
|
||||
|
||||
@@ -38,6 +38,16 @@ public class MySqlDdl extends PlatformDdl {
|
||||
return "alter table " + tableName + " drop foreign key " + maxConstraintName(fkName);
|
||||
}
|
||||
|
||||
/**
|
||||
* It is rather complex to delete a column on MySql as there must not exist any foreign keys.
|
||||
* That's why we call a user stored procedure here
|
||||
*/
|
||||
@Override
|
||||
public void alterTableDropColumn(DdlBuffer buffer, String tableName, String columnName) throws IOException {
|
||||
|
||||
buffer.append("CALL usp_ebean_drop_column('").append(tableName).append("', '").append(columnName).append("')").endOfStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterTableDropConstraint(String tableName, String constraintName) {
|
||||
// drop constraint not supported in MySQL 5.7 and 8.0 but starting with MariaDB 10.2.1 CHECK is evaluated
|
||||
@@ -61,7 +71,7 @@ public class MySqlDdl extends PlatformDdl {
|
||||
@Override
|
||||
public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) {
|
||||
|
||||
String suffix = DdlHelp.isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + defaultValue;
|
||||
String suffix = DdlHelp.isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + convertDefaultValue(defaultValue);
|
||||
|
||||
// use alter
|
||||
return "alter table " + tableName + " alter " + columnName + " " + suffix;
|
||||
|
||||
@@ -246,6 +246,9 @@ public class PlatformDdl {
|
||||
* Convert the standard type to the platform specific type.
|
||||
*/
|
||||
public String convert(String type, boolean identity) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
if (type.contains("[]")) {
|
||||
return convertArrayType(type);
|
||||
}
|
||||
|
||||
+43
-22
@@ -3,7 +3,9 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.migration.AlterColumn;
|
||||
import io.ebeaninternal.server.persist.platform.MultiValueBind;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -137,13 +139,7 @@ public class SqlServerDdl extends PlatformDdl {
|
||||
// a rather complex statement.
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (DdlHelp.isDropDefault(defaultValue)) {
|
||||
sb.append("delimiter $$\n");
|
||||
sb.append("DECLARE @Tmp nvarchar(200);");
|
||||
sb.append("select @Tmp = t1.name from sys.default_constraints t1\n");
|
||||
sb.append(" join sys.columns t2 on t1.object_id = t2.default_object_id\n");
|
||||
sb.append(" where t1.parent_object_id = OBJECT_ID('").append(tableName)
|
||||
.append("') and t2.name = '").append(columnName).append("';\n");
|
||||
sb.append("if @Tmp is not null EXEC('alter table ").append(tableName).append(" drop constraint ' + @Tmp)$$");
|
||||
sb.append("EXEC usp_ebean_drop_default_constraint ").append(tableName).append(", ").append(columnName);
|
||||
} else {
|
||||
sb.append("alter table ").append(tableName);
|
||||
sb.append(" add default ").append(convertDefaultValue(defaultValue)).append(" for ").append(columnName);
|
||||
@@ -200,25 +196,50 @@ public class SqlServerDdl extends PlatformDdl {
|
||||
|
||||
/**
|
||||
* It is rather complex to delete a column on SqlServer as there must not exist any references
|
||||
* (constraints, default values, indices and foreign keys). The list is not yet complete, as
|
||||
* indices over multiple columns will not yet deleted.
|
||||
* (This may be changed to delete all refering objects by using the sys.* tables later)
|
||||
* (constraints, default values, indices and foreign keys). That's why we call a user stored procedure here
|
||||
*/
|
||||
@Override
|
||||
public void alterTableDropColumn(DdlBuffer buffer, String tableName, String columnName) throws IOException {
|
||||
buffer.append("-- drop column ").append(tableName).append(".").append(columnName).endOfStatement();
|
||||
|
||||
buffer.append(alterTableDropUniqueConstraint(tableName, naming.uniqueConstraintName(tableName, columnName)));
|
||||
buffer.endOfStatement();
|
||||
buffer.append(alterColumnDefaultValue(tableName, columnName, DdlHelp.DROP_DEFAULT));
|
||||
buffer.endOfStatement();
|
||||
buffer.append(alterTableDropConstraint(tableName, naming.checkConstraintName(tableName, columnName)));
|
||||
buffer.endOfStatement();
|
||||
buffer.append(dropIndex(naming.indexName(tableName, columnName), tableName));
|
||||
buffer.endOfStatement();
|
||||
buffer.append(alterTableDropForeignKey(tableName, naming.foreignKeyConstraintName(tableName, columnName)));
|
||||
buffer.endOfStatement();
|
||||
super.alterTableDropColumn(buffer, tableName, columnName);
|
||||
buffer.append("EXEC usp_ebean_drop_column ").append(tableName).append(", ").append(columnName).endOfStatement();
|
||||
}
|
||||
|
||||
/**
|
||||
* This writes the multi value datatypes needed for {@link MultiValueBind}
|
||||
*/
|
||||
@Override
|
||||
public void generateProlog(DdlWrite write) throws IOException {
|
||||
super.generateProlog(write);
|
||||
|
||||
generateTVPDefinitions(write, "bigint");
|
||||
generateTVPDefinitions(write, "float");
|
||||
generateTVPDefinitions(write, "bit");
|
||||
generateTVPDefinitions(write, "date");
|
||||
generateTVPDefinitions(write, "time");
|
||||
//generateTVPDefinitions(write, "datetime2");
|
||||
generateTVPDefinitions(write, "uniqueidentifier");
|
||||
generateTVPDefinitions(write, "nvarchar(max)");
|
||||
|
||||
}
|
||||
|
||||
private void generateTVPDefinitions(DdlWrite write, String definition) throws IOException {
|
||||
int pos = definition.indexOf('(');
|
||||
String name = pos == -1 ? definition : definition.substring(0, pos);
|
||||
|
||||
dropTVP(write.dropAll(), name);
|
||||
//TVPs are included in "I__create_procs.sql"
|
||||
//createTVP(write.apply(), name, definition);
|
||||
}
|
||||
|
||||
private void dropTVP(DdlBuffer ddl, String name) throws IOException {
|
||||
ddl.append("if exists (select name from sys.types where name = 'ebean_").append(name)
|
||||
.append("_tvp') drop type ebean_").append(name).append("_tvp").endOfStatement();
|
||||
}
|
||||
|
||||
private void createTVP(DdlBuffer ddl, String name, String definition) throws IOException {
|
||||
ddl.append("if not exists (select name from sys.types where name = 'ebean_").append(name)
|
||||
.append("_tvp') create type ebean_").append(name).append("_tvp as table (c1 ").append(definition).append(")")
|
||||
.endOfStatement();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,12 @@ import io.ebeaninternal.dbmigration.migration.ChangeSet;
|
||||
import io.ebeaninternal.dbmigration.model.build.ModelBuildBeanVisitor;
|
||||
import io.ebeaninternal.dbmigration.model.build.ModelBuildContext;
|
||||
import io.ebeaninternal.dbmigration.model.visitor.VisitAllUsing;
|
||||
import io.ebeaninternal.extraddl.model.DdlScript;
|
||||
import io.ebeaninternal.extraddl.model.ExtraDdl;
|
||||
import io.ebeaninternal.extraddl.model.ExtraDdlXmlReader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Reads EbeanServer bean descriptors to build the current model.
|
||||
@@ -111,6 +115,19 @@ public class CurrentModel {
|
||||
if (header != null && !header.isEmpty()) {
|
||||
ddl.append(header).append('\n');
|
||||
}
|
||||
|
||||
ExtraDdl extraDdl = ExtraDdlXmlReader.readBuiltin();
|
||||
if (extraDdl != null) {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (script.isInit() && ExtraDdlXmlReader.matchPlatform(server.getDatabasePlatform().getName(), script.getPlatforms())) {
|
||||
ddl.append("-- init script " + script.getName()).append('\n');
|
||||
ddl.append(script.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ddl.append(write.apply().getBuffer());
|
||||
ddl.append(write.applyForeignKeys().getBuffer());
|
||||
ddl.append(write.applyHistoryView().getBuffer());
|
||||
|
||||
@@ -42,9 +42,10 @@ public class MigrationModel {
|
||||
|
||||
// find all the migration xml files
|
||||
File[] xmlFiles = modelDirectory.listFiles(pathname -> pathname.getName().toLowerCase().endsWith(modelSuffix));
|
||||
|
||||
if (xmlFiles == null || xmlFiles.length == 0) {
|
||||
return;
|
||||
}
|
||||
List<MigrationResource> resources = new ArrayList<>(xmlFiles.length);
|
||||
|
||||
for (File xmlFile : xmlFiles) {
|
||||
resources.add(new MigrationResource(xmlFile, createVersion(xmlFile)));
|
||||
}
|
||||
|
||||
+2
-1
@@ -258,12 +258,13 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
}
|
||||
} else {
|
||||
col.setDefaultValue(p.getDbColumnDefault());
|
||||
col.setDbMigrationInfos(p.getDbMigrationInfos());
|
||||
if (!p.isNullable() || p.isDDLNotNull()) {
|
||||
col.setNotnull(true);
|
||||
}
|
||||
}
|
||||
|
||||
col.setDbMigrationInfos(p.getDbMigrationInfos());
|
||||
|
||||
if (p.isUnique() && !p.isId()) {
|
||||
col.setUnique(determineUniqueConstraintName(col.getName()));
|
||||
indexSetAdd(col.getName());
|
||||
|
||||
@@ -39,7 +39,8 @@ public class DdlScript {
|
||||
protected String platforms;
|
||||
@XmlAttribute(name = "drop")
|
||||
protected boolean drop;
|
||||
|
||||
@XmlAttribute(name = "init")
|
||||
protected boolean init;
|
||||
/**
|
||||
* Gets the value of the value property.
|
||||
*
|
||||
@@ -114,4 +115,17 @@ public class DdlScript {
|
||||
this.drop = drop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if this a init script.
|
||||
*/
|
||||
public boolean isInit() {
|
||||
return init;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets that this is a init script.
|
||||
*/
|
||||
public void setInit(boolean init) {
|
||||
this.init = init;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,10 +83,24 @@ public class ExtraDdlXmlReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the builtin extra ddl. (Stored procedures, tvp types etc)
|
||||
*/
|
||||
public static ExtraDdl readBuiltin() {
|
||||
return read("/io/ebeaninternal/dbmigration/builtin-extra-ddl.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the extra ddl.
|
||||
*/
|
||||
public static ExtraDdl read() {
|
||||
return read("/extra-ddl.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and return a ExtraDdl from an xml document at the given resource path.
|
||||
*/
|
||||
public static ExtraDdl read(String resourcePath) {
|
||||
private static ExtraDdl read(String resourcePath) {
|
||||
|
||||
try (InputStream is = ExtraDdlXmlReader.class.getResourceAsStream(resourcePath)) {
|
||||
if (is == null) {
|
||||
|
||||
@@ -1202,7 +1202,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
/**
|
||||
* Set the value of the Version property on the bean.
|
||||
*/
|
||||
public void setVersionValue(Object versionValue) {
|
||||
private void setVersionValue(Object versionValue) {
|
||||
version = beanDescriptor.setVersion(entityBean, versionValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -357,14 +357,34 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
|
||||
* Return true if this association is updateable.
|
||||
*/
|
||||
public boolean isUpdateable() {
|
||||
return tableJoin.columns().length <= 0 || tableJoin.columns()[0].isUpdateable();
|
||||
TableJoinColumn[] columns = tableJoin.columns();
|
||||
if (columns.length <= 0) {
|
||||
return true;
|
||||
}
|
||||
for (TableJoinColumn column : columns) {
|
||||
if (column.isUpdateable()) {
|
||||
// at least 1 is updatable
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this association is insertable.
|
||||
*/
|
||||
public boolean isInsertable() {
|
||||
return tableJoin.columns().length <= 0 || tableJoin.columns()[0].isInsertable();
|
||||
TableJoinColumn[] columns = tableJoin.columns();
|
||||
if (columns.length <= 0) {
|
||||
return true;
|
||||
}
|
||||
for (TableJoinColumn column : columns) {
|
||||
if (column.isInsertable()) {
|
||||
// at least 1 is insertable
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,16 +463,18 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
|
||||
String matchColumn = col.getForeignDbColumn();
|
||||
String localColumn = col.getLocalDbColumn();
|
||||
String localSqlFormula = col.getLocalSqlFormula();
|
||||
boolean insertable = col.isInsertable();
|
||||
boolean updateable = col.isUpdateable();
|
||||
|
||||
for (int j = 0; j < props.length; j++) {
|
||||
if (props[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
|
||||
return new ImportedIdSimple(owner, localColumn, localSqlFormula, props[j], j);
|
||||
return new ImportedIdSimple(owner, localColumn, localSqlFormula, props[j], j, insertable, updateable);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < others.length; j++) {
|
||||
if (others[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
|
||||
return new ImportedIdSimple(owner, localColumn, localSqlFormula, others[j], j + props.length);
|
||||
return new ImportedIdSimple(owner, localColumn, localSqlFormula, others[j], j + props.length, insertable, updateable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,6 +213,12 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
// by default not including "Many" properties in document store
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerColumn(BeanDescriptor<?> desc, String prefix) {
|
||||
if (targetDescriptor != null) {
|
||||
desc.registerTable(targetDescriptor.getBaseTable(), this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return the underlying collection of beans.
|
||||
*/
|
||||
|
||||
@@ -64,8 +64,11 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
@Override
|
||||
public void dmlAppend(GenerateDmlRequest request) {
|
||||
|
||||
boolean update = request.isUpdate();
|
||||
for (ImportedIdSimple anImported : imported) {
|
||||
request.appendColumn(anImported.localDbColumn);
|
||||
if (anImported.isInclude(update)) {
|
||||
request.appendColumn(anImported.localDbColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,30 +103,28 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
@Override
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
Object embeddedId = null;
|
||||
|
||||
if (bean != null) {
|
||||
embeddedId = foreignAssocOne.getValue(bean);
|
||||
}
|
||||
Object embeddedId = (bean == null) ? null : foreignAssocOne.getValue(bean);
|
||||
|
||||
boolean update = request.isUpdate();
|
||||
if (embeddedId == null) {
|
||||
for (ImportedIdSimple anImported : imported) {
|
||||
if (anImported.owner.isUpdateable()) {
|
||||
if (anImported.isInclude(update)) {
|
||||
request.bind(null, anImported.foreignProperty);
|
||||
}
|
||||
}
|
||||
// return anything non-null to skip a derived relationship update
|
||||
return Object.class;
|
||||
|
||||
} else {
|
||||
EntityBean embedded = (EntityBean) embeddedId;
|
||||
for (ImportedIdSimple anImported : imported) {
|
||||
if (anImported.owner.isUpdateable()) {
|
||||
if (anImported.isInclude(update)) {
|
||||
Object scalarValue = anImported.foreignProperty.getValue(embedded);
|
||||
request.bind(scalarValue, anImported.foreignProperty);
|
||||
}
|
||||
}
|
||||
return embedded;
|
||||
}
|
||||
// hmmm, not worrying about this just yet
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,15 +47,32 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
|
||||
protected final int position;
|
||||
|
||||
public ImportedIdSimple(BeanPropertyAssoc<?> owner, String localDbColumn, String localSqlFormula, BeanProperty foreignProperty, int position) {
|
||||
/**
|
||||
* If true include in insert.
|
||||
*/
|
||||
private final boolean insertable;
|
||||
|
||||
/**
|
||||
* If true include in update.
|
||||
*/
|
||||
private final boolean updateable;
|
||||
|
||||
public ImportedIdSimple(BeanPropertyAssoc<?> owner, String localDbColumn, String localSqlFormula, BeanProperty foreignProperty, int position,
|
||||
boolean insertable, boolean updateable) {
|
||||
this.owner = owner;
|
||||
this.localDbColumn = InternString.intern(localDbColumn);
|
||||
this.localSqlFormula = InternString.intern(localSqlFormula);
|
||||
this.foreignProperty = foreignProperty;
|
||||
this.position = position;
|
||||
this.insertable = insertable;
|
||||
this.updateable = updateable;
|
||||
this.logicalName = InternString.intern(owner.getName() + "." + foreignProperty.getName());
|
||||
}
|
||||
|
||||
public ImportedIdSimple(BeanPropertyAssoc<?> owner, String localDbColumn, String localSqlFormula, BeanProperty foreignProperty, int position) {
|
||||
this(owner, localDbColumn, localSqlFormula, foreignProperty, position, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list as an array sorted into the same order as the Bean Properties.
|
||||
*/
|
||||
@@ -68,6 +85,13 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
return importedIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if it should be included in the update (or insert).
|
||||
*/
|
||||
public boolean isInclude(boolean update) {
|
||||
return (update) ? updateable : insertable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// remove FindBugs warning
|
||||
|
||||
@@ -304,6 +304,12 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = getFullTableName(joinTable);
|
||||
if (intTableName.isEmpty()) {
|
||||
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
|
||||
intTableName = getM2MJoinTableName(localTable, otherTable);
|
||||
}
|
||||
|
||||
// set the intersection table
|
||||
DeployTableJoin intJoin = new DeployTableJoin();
|
||||
intJoin.setTable(intTableName);
|
||||
|
||||
@@ -116,6 +116,10 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
prop.setFetchPreference(fetchPreference.value());
|
||||
}
|
||||
|
||||
io.ebean.annotation.NotNull nonNull = get(prop, io.ebean.annotation.NotNull.class);
|
||||
if (nonNull != null) {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
if (validationAnnotations) {
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeaninternal.server.type.DataEncryptSupport;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
import io.ebeaninternal.server.type.ScalarTypeArray;
|
||||
import io.ebeaninternal.server.type.ScalarTypeWrapper;
|
||||
import io.ebeaninternal.server.type.SimpleAesEncryptor;
|
||||
import io.ebeaninternal.server.type.TypeManager;
|
||||
import org.slf4j.Logger;
|
||||
@@ -116,8 +117,8 @@ public class DeployUtil {
|
||||
throw new IllegalArgumentException("Class [" + enumType + "] is Not a Enum?");
|
||||
}
|
||||
try {
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) enumType;
|
||||
EnumType type = enumerated != null ? enumerated.value() : null;
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) enumType;
|
||||
EnumType type = enumerated != null ? enumerated.value() : null;
|
||||
ScalarType<?> scalarType = typeManager.createEnumScalarType(enumClass, type);
|
||||
prop.setScalarType(scalarType);
|
||||
prop.setDbType(scalarType.getJdbcType());
|
||||
@@ -278,19 +279,25 @@ public class DeployUtil {
|
||||
*/
|
||||
public void setLobType(DeployBeanProperty prop) {
|
||||
|
||||
// is String or byte[] ? used to determine if its a CLOB or BLOB
|
||||
Class<?> type = prop.getPropertyType();
|
||||
ScalarType<?> scalarType = prop.getScalarType();
|
||||
|
||||
// this also sets the lob flag on DeployBeanProperty
|
||||
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
|
||||
if (scalarType instanceof ScalarTypeWrapper) {
|
||||
int lobType = scalarType.getJdbcType() == Types.VARCHAR ? dbCLOBType : dbBLOBType;
|
||||
prop.setDbType(lobType);
|
||||
} else {
|
||||
// is String or byte[] ? used to determine if its a CLOB or BLOB
|
||||
Class<?> type = prop.getPropertyType();
|
||||
// this also sets the lob flag on DeployBeanProperty
|
||||
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
|
||||
if (scalarType == null) {
|
||||
// this should never occur actually
|
||||
throw new RuntimeException("No ScalarType for LOB type [" + type + "] [" + lobType + "]");
|
||||
scalarType = typeManager.getScalarType(type, lobType);
|
||||
if (scalarType == null) {
|
||||
// this should never occur actually
|
||||
throw new RuntimeException("No ScalarType for LOB type [" + type + "] [" + lobType + "]");
|
||||
}
|
||||
prop.setDbType(lobType);
|
||||
prop.setScalarType(scalarType);
|
||||
}
|
||||
prop.setDbType(lobType);
|
||||
prop.setScalarType(scalarType);
|
||||
}
|
||||
|
||||
private boolean isClobType(Class<?> type) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.ebean.DtoQuery;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionFactory;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.FutureList;
|
||||
@@ -460,6 +461,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.select(fetchProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> select(FetchGroup fetchGroup) {
|
||||
return query.select(fetchGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setDistinct(boolean distinct) {
|
||||
return query.setDistinct(distinct);
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.CountDistinctOrder;
|
||||
import io.ebean.DtoQuery;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.FutureList;
|
||||
@@ -759,6 +760,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.select(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> select(FetchGroup fetchGroup) {
|
||||
return exprList.select(fetchGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setDistinct(boolean distinct) {
|
||||
return exprList.setDistinct(distinct);
|
||||
|
||||
@@ -14,11 +14,16 @@ public class DeleteHandler extends DmlHandler {
|
||||
|
||||
private final DeleteMeta meta;
|
||||
|
||||
public DeleteHandler(PersistRequestBean<?> persist, DeleteMeta meta) {
|
||||
DeleteHandler(PersistRequestBean<?> persist, DeleteMeta meta) {
|
||||
super(persist, meta.isEmptyStringAsNull());
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and bind the delete statement.
|
||||
*/
|
||||
|
||||
@@ -50,11 +50,6 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
|
||||
|
||||
protected String sql;
|
||||
|
||||
/**
|
||||
* The generated value for the @Version property. Must be set after where clause is bound.
|
||||
*/
|
||||
protected Object versionValue;
|
||||
|
||||
protected DmlHandler(PersistRequestBean<?> persistRequest, boolean emptyStringToNull) {
|
||||
this.now = System.currentTimeMillis();
|
||||
this.persistRequest = persistRequest;
|
||||
@@ -231,30 +226,6 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
|
||||
prop.bind(dataBind, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a generated value on a update. This can not be set to the bean
|
||||
* until after the where clause has been bound for concurrency checking.
|
||||
* <p>
|
||||
* GeneratedProperty values are likely going to be used for optimistic
|
||||
* concurrency checking. This includes 'counter' and 'update timestamp'
|
||||
* generation.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void registerGeneratedVersion(Object versionValue) {
|
||||
this.versionValue = versionValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set any update generated values to the bean. Must be called after where
|
||||
* clause has been bound.
|
||||
*/
|
||||
public void setUpdateGenValues() {
|
||||
if (versionValue != null) {
|
||||
persistRequest.setVersionValue(versionValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check with useGeneratedKeys to get appropriate PreparedStatement.
|
||||
*/
|
||||
|
||||
@@ -29,10 +29,6 @@ public class GenerateDmlRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void appendColumnIsNull(String column) {
|
||||
appendColumn(column, IS_NULL);
|
||||
}
|
||||
|
||||
public void appendColumn(String column) {
|
||||
//String bind = (insertMode > 0) ? "?" : "=?";
|
||||
appendColumn(column, "?");
|
||||
@@ -91,4 +87,7 @@ public class GenerateDmlRequest {
|
||||
this.prefix2 = ", ";
|
||||
}
|
||||
|
||||
public boolean isUpdate() {
|
||||
return insertMode == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ public class InsertHandler extends DmlHandler {
|
||||
this.concatinatedKey = meta.isConcatenatedKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and bind the insert statement.
|
||||
*/
|
||||
|
||||
@@ -17,11 +17,16 @@ public class UpdateHandler extends DmlHandler {
|
||||
|
||||
private boolean emptySetClause;
|
||||
|
||||
public UpdateHandler(PersistRequestBean<?> persist, UpdateMeta meta) {
|
||||
UpdateHandler(PersistRequestBean<?> persist, UpdateMeta meta) {
|
||||
super(persist, meta.isEmptyStringAsNull());
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and bind the update statement.
|
||||
*/
|
||||
@@ -50,8 +55,6 @@ public class UpdateHandler extends DmlHandler {
|
||||
if (persistRequest.isBatched()) {
|
||||
batchedPstmt.registerInputStreams(dataBind.getInputStreams());
|
||||
}
|
||||
setUpdateGenValues();
|
||||
|
||||
logSql(sql);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,12 +42,6 @@ public interface BindableRequest {
|
||||
*/
|
||||
void bindNoLog(Object value, BeanProperty prop) throws SQLException;
|
||||
|
||||
/**
|
||||
* Register the value from a update GeneratedValue. This can only be set to
|
||||
* the bean property after the where clause has bean built.
|
||||
*/
|
||||
void registerGeneratedVersion(Object value);
|
||||
|
||||
/**
|
||||
* Return the original PersistRequest.
|
||||
*/
|
||||
@@ -59,4 +53,8 @@ public interface BindableRequest {
|
||||
*/
|
||||
long now();
|
||||
|
||||
/**
|
||||
* Return true if this is an update request.
|
||||
*/
|
||||
boolean isUpdate();
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ public class FactoryAssocOnes {
|
||||
*/
|
||||
public void create(List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode) {
|
||||
|
||||
BeanPropertyAssocOne<?>[] ones = desc.propertiesOneImported();
|
||||
|
||||
for (BeanPropertyAssocOne<?> one : ones) {
|
||||
for (BeanPropertyAssocOne<?> one : desc.propertiesOneImported()) {
|
||||
if (!one.isImportedPrimaryKey()) {
|
||||
switch (mode) {
|
||||
case INSERT:
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import io.ebeaninternal.server.querydefn.SpiFetchGroup;
|
||||
|
||||
/**
|
||||
* Default FetchGroup implementation.
|
||||
*/
|
||||
class DFetchGroup<T> implements SpiFetchGroup<T> {
|
||||
|
||||
private final OrmQueryDetail detail;
|
||||
|
||||
DFetchGroup(OrmQueryDetail detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrmQueryDetail detail() {
|
||||
return detail.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrmQueryDetail underlying() {
|
||||
return detail;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchGroupBuilder;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import io.ebeaninternal.server.querydefn.SpiFetchGroup;
|
||||
|
||||
/**
|
||||
* Default implementation of the FetchGroupBuilder.
|
||||
*/
|
||||
class DFetchGroupBuilder<T> implements FetchGroupBuilder<T> {
|
||||
|
||||
private static final FetchConfig FETCH_QUERY = new FetchConfig().query();
|
||||
|
||||
private static final FetchConfig FETCH_LAZY = new FetchConfig().lazy();
|
||||
|
||||
private final OrmQueryDetail detail;
|
||||
|
||||
DFetchGroupBuilder() {
|
||||
this.detail = new OrmQueryDetail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> select(String select) {
|
||||
detail.select(select);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetch(String path) {
|
||||
detail.fetch(path, null, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetch(String path, FetchGroup nestedGroup) {
|
||||
return fetchNested(path, nestedGroup, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetchQuery(String path, FetchGroup nestedGroup) {
|
||||
return fetchNested(path, nestedGroup, FETCH_QUERY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetchLazy(String path, FetchGroup nestedGroup) {
|
||||
return fetchNested(path, nestedGroup, FETCH_LAZY);
|
||||
}
|
||||
|
||||
private FetchGroupBuilder<T> fetchNested(String path, FetchGroup nestedGroup, FetchConfig fetchConfig) {
|
||||
|
||||
OrmQueryDetail nestedDetail = ((SpiFetchGroup) nestedGroup).underlying();
|
||||
detail.addNested(path, nestedDetail, fetchConfig);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetchQuery(String path) {
|
||||
detail.fetch(path, null, FETCH_QUERY);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetchLazy(String path) {
|
||||
detail.fetch(path, null, FETCH_LAZY);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetch(String path, String properties) {
|
||||
detail.fetch(path, properties, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetchQuery(String path, String properties) {
|
||||
detail.fetch(path, properties, FETCH_QUERY);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroupBuilder<T> fetchLazy(String path, String properties) {
|
||||
detail.fetch(path, properties, FETCH_LAZY);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchGroup<T> build() {
|
||||
return new DFetchGroup<>(detail);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchGroupBuilder;
|
||||
import io.ebean.service.SpiFetchGroupService;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
|
||||
/**
|
||||
* Default implementation of SpiFetchGroupService.
|
||||
*/
|
||||
public final class DFetchGroupService implements SpiFetchGroupService {
|
||||
|
||||
@Override
|
||||
public <T> FetchGroup<T> of(Class<T> cls, String select) {
|
||||
return new DFetchGroup<>(detail(select));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FetchGroupBuilder<T> of(Class<T> cls) {
|
||||
return new DFetchGroupBuilder<>();
|
||||
}
|
||||
|
||||
private OrmQueryDetail detail(String select) {
|
||||
OrmQueryDetail detail = new OrmQueryDetail();
|
||||
detail.select(select);
|
||||
return detail;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import io.ebean.Expression;
|
||||
import io.ebean.ExpressionFactory;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.FutureList;
|
||||
@@ -1329,6 +1330,12 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> select(FetchGroup fetchGroup) {
|
||||
this.detail = ((SpiFetchGroup)fetchGroup).detail();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> fetch(String property) {
|
||||
return fetch(property, null, null);
|
||||
|
||||
@@ -55,6 +55,16 @@ public class OrmQueryDetail implements Serializable {
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a nested OrmQueryDetail to this detail.
|
||||
*/
|
||||
public void addNested(String path, OrmQueryDetail other, FetchConfig config) {
|
||||
fetch(path, other.baseProps.getProperties(), config);
|
||||
for (Map.Entry<String, OrmQueryProperties> entry : other.fetchPaths.entrySet()) {
|
||||
fetch(path + "." + entry.getKey(), entry.getValue().getProperties(), entry.getValue().getFetchConfig());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the hash for the query plan.
|
||||
*/
|
||||
|
||||
@@ -148,27 +148,30 @@ public class OrmQueryProperties implements Serializable {
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
private OrmQueryProperties(OrmQueryProperties source) {
|
||||
|
||||
private OrmQueryProperties(OrmQueryProperties source, FetchConfig sourceFetchConfig) {
|
||||
this.fetchConfig = sourceFetchConfig;
|
||||
this.parentPath = source.parentPath;
|
||||
this.path = source.path;
|
||||
this.rawProperties = source.rawProperties;
|
||||
this.trimmedProperties = source.trimmedProperties;
|
||||
this.cache = source.cache;
|
||||
this.readOnly = source.readOnly;
|
||||
this.fetchConfig = source.fetchConfig;
|
||||
this.filterMany = source.filterMany;
|
||||
this.included = (source.included == null) ? null : new LinkedHashSet<>(source.included);
|
||||
if (includedBeanJoin != null) {
|
||||
this.includedBeanJoin = new HashSet<>(source.includedBeanJoin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the OrmQueryProperties.
|
||||
*/
|
||||
public OrmQueryProperties copy() {
|
||||
return new OrmQueryProperties(this);
|
||||
return new OrmQueryProperties(this, this.fetchConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy with the given fetch config.
|
||||
*/
|
||||
public OrmQueryProperties copy(FetchConfig fetchConfig) {
|
||||
return new OrmQueryProperties(this, fetchConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.ebeaninternal.server.querydefn;
|
||||
|
||||
import io.ebean.FetchGroup;
|
||||
|
||||
/**
|
||||
* Service API of FetchGroup.
|
||||
*/
|
||||
public interface SpiFetchGroup<T> extends FetchGroup<T> {
|
||||
|
||||
/**
|
||||
* Return the detail to use for query execution.
|
||||
*/
|
||||
OrmQueryDetail detail();
|
||||
|
||||
/**
|
||||
* Return the underlying detail for copy purposes.
|
||||
*/
|
||||
OrmQueryDetail underlying();
|
||||
}
|
||||
@@ -51,6 +51,7 @@ public class ScalarTypeChar extends ScalarTypeBaseVarchar<Character> {
|
||||
|
||||
@Override
|
||||
public Character toBeanType(Object value) {
|
||||
if (value == null) return null;
|
||||
String s = BasicTypeConverter.toString(value);
|
||||
return s.charAt(0);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ public class ScalarTypeCharArray extends ScalarTypeBaseVarchar<char[]> {
|
||||
|
||||
@Override
|
||||
public char[] toBeanType(Object value) {
|
||||
if (value == null) return null;
|
||||
String s = BasicTypeConverter.toString(value);
|
||||
return s.toCharArray();
|
||||
}
|
||||
|
||||
@@ -1,66 +1,24 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* ScalarType for String.
|
||||
*/
|
||||
public class ScalarTypeClob extends ScalarTypeBaseVarchar<String> {
|
||||
public class ScalarTypeClob extends ScalarTypeStringBase {
|
||||
|
||||
protected ScalarTypeClob(boolean jdbcNative, int jdbcType) {
|
||||
super(String.class, jdbcNative, jdbcType);
|
||||
ScalarTypeClob(boolean jdbcNative, int jdbcType) {
|
||||
super(jdbcNative, jdbcType);
|
||||
}
|
||||
|
||||
public ScalarTypeClob() {
|
||||
super(String.class, true, Types.CLOB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertFromDbString(String dbValue) {
|
||||
return dbValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToDbString(String beanValue) {
|
||||
return beanValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, String value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
b.setString(value);
|
||||
}
|
||||
super(true, Types.CLOB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read(DataReader dataReader) throws SQLException {
|
||||
|
||||
return dataReader.getStringFromStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toJdbcType(Object value) {
|
||||
return BasicTypeConverter.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBeanType(Object value) {
|
||||
return BasicTypeConverter.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(String t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ public class ScalarTypeDuration extends ScalarTypeBase<Duration> {
|
||||
@Override
|
||||
public Duration toBeanType(Object value) {
|
||||
if (value instanceof Duration) return (Duration) value;
|
||||
if (value == null) return null;
|
||||
return Duration.ofSeconds(BasicTypeConverter.toLong(value));
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ public class ScalarTypeDurationWithNanos extends ScalarTypeDuration {
|
||||
@Override
|
||||
public Duration toBeanType(Object value) {
|
||||
if (value instanceof Duration) return (Duration) value;
|
||||
if (value == null) return null;
|
||||
return convertFromBigDecimal(BasicTypeConverter.toBigDecimal(value));
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ScalarTypeInstant extends ScalarTypeBaseDateTime<Instant> {
|
||||
|
||||
@Override
|
||||
public Instant toBeanType(Object value) {
|
||||
if (value instanceof Instant) return (Instant) value;
|
||||
return convertFromTimestamp((Timestamp) value);
|
||||
if (value instanceof Timestamp) return convertFromTimestamp((Timestamp) value);
|
||||
return (Instant) value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class ScalarTypeLocalDateTime extends ScalarTypeBaseDateTime<LocalDateTim
|
||||
|
||||
@Override
|
||||
public LocalDateTime toBeanType(Object value) {
|
||||
if (value instanceof LocalDateTime) return (LocalDateTime) value;
|
||||
return convertFromTimestamp((Timestamp) value);
|
||||
if (value instanceof Timestamp) return convertFromTimestamp((Timestamp) value);
|
||||
return (LocalDateTime) value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
@@ -12,8 +11,4 @@ public class ScalarTypeLongVarchar extends ScalarTypeClob {
|
||||
super(true, Types.LONGVARCHAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read(DataReader dataReader) throws SQLException {
|
||||
return dataReader.getStringFromStream();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class ScalarTypeOffsetDateTime extends ScalarTypeBaseDateTime<OffsetDateT
|
||||
|
||||
@Override
|
||||
public OffsetDateTime toBeanType(Object value) {
|
||||
if (value instanceof OffsetDateTime) return (OffsetDateTime) value;
|
||||
return convertFromTimestamp((Timestamp) value);
|
||||
if (value instanceof Timestamp) return convertFromTimestamp((Timestamp) value);
|
||||
return (OffsetDateTime) value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +1,15 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebeaninternal.server.core.BasicTypeConverter;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* ScalarType for String.
|
||||
*/
|
||||
public class ScalarTypeString extends ScalarTypeBase<String> {
|
||||
public class ScalarTypeString extends ScalarTypeStringBase {
|
||||
|
||||
public static final ScalarTypeString INSTANCE = new ScalarTypeString();
|
||||
|
||||
private ScalarTypeString() {
|
||||
super(String.class, true, Types.VARCHAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, String value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
b.setString(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read(DataReader dataReader) throws SQLException {
|
||||
return dataReader.getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toJdbcType(Object value) {
|
||||
return BasicTypeConverter.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBeanType(Object value) {
|
||||
return BasicTypeConverter.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertFromMillis(long systemTimeMillis) {
|
||||
return String.valueOf(systemTimeMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
return null;
|
||||
} else {
|
||||
return dataInput.readUTF();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeData(DataOutput dataOutput, String value) throws IOException {
|
||||
|
||||
if (value == null) {
|
||||
dataOutput.writeBoolean(false);
|
||||
} else {
|
||||
dataOutput.writeBoolean(true);
|
||||
dataOutput.writeUTF(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsonRead(JsonParser parser) throws IOException {
|
||||
return parser.getValueAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator writer, String value) throws IOException {
|
||||
writer.writeString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocPropertyType getDocType() {
|
||||
return DocPropertyType.TEXT;
|
||||
super(true, Types.VARCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebeaninternal.server.core.BasicTypeConverter;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Base ScalarType for String type using Varchar, Clob and LongVarchar.
|
||||
*/
|
||||
public abstract class ScalarTypeStringBase extends ScalarTypeBase<String> {
|
||||
|
||||
ScalarTypeStringBase(boolean jdbcNative, int jdbcType) {
|
||||
super(String.class, jdbcNative, jdbcType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, String value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
b.setString(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read(DataReader dataReader) throws SQLException {
|
||||
return dataReader.getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toJdbcType(Object value) {
|
||||
return BasicTypeConverter.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBeanType(Object value) {
|
||||
return BasicTypeConverter.toString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertFromMillis(long systemTimeMillis) {
|
||||
return String.valueOf(systemTimeMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
return null;
|
||||
} else {
|
||||
return dataInput.readUTF();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeData(DataOutput dataOutput, String value) throws IOException {
|
||||
|
||||
if (value == null) {
|
||||
dataOutput.writeBoolean(false);
|
||||
} else {
|
||||
dataOutput.writeBoolean(true);
|
||||
dataOutput.writeUTF(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsonRead(JsonParser parser) throws IOException {
|
||||
return parser.getValueAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator writer, String value) throws IOException {
|
||||
writer.writeString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocPropertyType getDocType() {
|
||||
return DocPropertyType.TEXT;
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,7 @@ public class ScalarTypeYear extends ScalarTypeBase<Year> {
|
||||
@Override
|
||||
public Year toBeanType(Object value) {
|
||||
if (value instanceof Year) return (Year) value;
|
||||
if (value == null) return null;
|
||||
return Year.of(BasicTypeConverter.toInteger(value));
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ public class ScalarTypeYearMonthDate extends ScalarTypeBaseDate<YearMonth> {
|
||||
public YearMonth toBeanType(Object value) {
|
||||
if (value instanceof YearMonth) return (YearMonth) value;
|
||||
if (value instanceof LocalDate) return fromLocalDate((LocalDate) value);
|
||||
if (value == null) return null;
|
||||
return fromLocalDate(BasicTypeConverter.toDate(value).toLocalDate());
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public class ScalarTypeZonedDateTime extends ScalarTypeBaseDateTime<ZonedDateTim
|
||||
|
||||
@Override
|
||||
public ZonedDateTime toBeanType(Object value) {
|
||||
if (value instanceof ZonedDateTime) return (ZonedDateTime) value;
|
||||
return convertFromTimestamp((Timestamp) value);
|
||||
if (value instanceof Timestamp) return convertFromTimestamp((Timestamp) value);
|
||||
return (ZonedDateTime) value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
io.ebeaninternal.server.query.DFetchGroupService
|
||||
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<extra-ddl xmlns="http://ebean-orm.github.io/xml/ns/extraddl">
|
||||
|
||||
<ddl-script name="create procs" platforms="sqlserver" init="true">-- Initial script to create stored procedures etc for sqlserver platform
|
||||
|
||||
-- create table-value-parameters
|
||||
if not exists (select name from sys.types where name = 'ebean_bigint_tvp') create type ebean_bigint_tvp as table (c1 bigint);
|
||||
if not exists (select name from sys.types where name = 'ebean_float_tvp') create type ebean_float_tvp as table (c1 float);
|
||||
if not exists (select name from sys.types where name = 'ebean_bit_tvp') create type ebean_bit_tvp as table (c1 bit);
|
||||
if not exists (select name from sys.types where name = 'ebean_date_tvp') create type ebean_date_tvp as table (c1 date);
|
||||
if not exists (select name from sys.types where name = 'ebean_time_tvp') create type ebean_time_tvp as table (c1 time);
|
||||
if not exists (select name from sys.types where name = 'ebean_uniqueidentifier_tvp') create type ebean_uniqueidentifier_tvp as table (c1 uniqueidentifier);
|
||||
if not exists (select name from sys.types where name = 'ebean_nvarchar_tvp') create type ebean_nvarchar_tvp as table (c1 nvarchar(max));
|
||||
|
||||
delimiter $$
|
||||
-----------------------------------------------------------
|
||||
-- PROCEDURE: usp_ebean_drop_indices TABLE, COLUMN
|
||||
-- deletes all indices referring to TABLE.COLUMN
|
||||
-----------------------------------------------------------
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_indices @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
declare @indexName nvarchar(255)
|
||||
BEGIN
|
||||
DECLARE index_cursor CURSOR FOR SELECT i.name from sys.indexes i
|
||||
join sys.index_columns ic on ic.object_id = i.object_id and ic.index_id = i.index_id
|
||||
join sys.columns c on c.object_id = ic.object_id and c.column_id = ic.column_id
|
||||
where i.object_id = OBJECT_ID(@tableName) AND c.name = @columnName;
|
||||
OPEN index_cursor
|
||||
FETCH NEXT FROM index_cursor INTO @indexName
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
set @sql = 'drop index ' + @indexName + ' on ' + @tableName;
|
||||
EXECUTE(@sql);
|
||||
|
||||
FETCH NEXT FROM index_cursor INTO @indexName
|
||||
END;
|
||||
CLOSE index_cursor;
|
||||
DEALLOCATE index_cursor;
|
||||
END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--------------------------------------------------------------------
|
||||
-- PROCEDURE: usp_ebean_drop_default_constraint TABLE, COLUMN
|
||||
-- deletes the default constraint, which has a random name
|
||||
--------------------------------------------------------------------
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_default_constraint @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @tmp nvarchar(1000)
|
||||
BEGIN
|
||||
select @Tmp = t1.name from sys.default_constraints t1
|
||||
join sys.columns t2 on t1.object_id = t2.default_object_id
|
||||
where t1.parent_object_id = OBJECT_ID(@tableName) and t2.name = @columnName;
|
||||
|
||||
if @Tmp is not null EXEC('alter table ' + @tableName +' drop constraint ' + @tmp);
|
||||
END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--------------------------------------------------------------------
|
||||
-- PROCEDURE: usp_ebean_drop_constraints TABLE, COLUMN
|
||||
-- deletes constraints and foreign keys refering to TABLE.COLUMN
|
||||
--------------------------------------------------------------------
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_constraints @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
declare @constraintName nvarchar(255)
|
||||
BEGIN
|
||||
DECLARE name_cursor CURSOR FOR
|
||||
SELECT cc.name from sys.check_constraints cc
|
||||
join sys.columns c on c.object_id = cc.parent_object_id and c.column_id = cc.parent_column_id
|
||||
where parent_object_id = OBJECT_ID(@tableName) AND c.name = @columnName
|
||||
UNION SELECT fk.name from sys.foreign_keys fk
|
||||
join sys.foreign_key_columns fkc on fkc.constraint_object_id = fk.object_id
|
||||
and fkc.parent_object_id = fk.parent_object_id
|
||||
join sys.columns c on c.object_id = fkc.parent_object_id and c.column_id = fkc.parent_column_id
|
||||
where fkc.parent_object_id = OBJECT_ID(@tableName) AND c.name = @columnName;
|
||||
|
||||
OPEN name_cursor
|
||||
FETCH NEXT FROM name_cursor INTO @constraintName
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
set @sql = 'alter table ' + @tableName + ' drop constraint ' + @constraintName;
|
||||
EXECUTE(@sql);
|
||||
|
||||
FETCH NEXT FROM name_cursor INTO @constraintName
|
||||
END;
|
||||
CLOSE name_cursor;
|
||||
DEALLOCATE name_cursor;
|
||||
END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
-------------------------------------------------------------------------------------
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column annd ensures that all indices and constraints are dropped first
|
||||
-------------------------------------------------------------------------------------
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_column @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
BEGIN
|
||||
EXEC usp_ebean_drop_indices @tableName, @columnName;
|
||||
EXEC usp_ebean_drop_default_constraint @tableName, @columnName;
|
||||
EXEC usp_ebean_drop_constraints @tableName, @columnName;
|
||||
|
||||
set @sql = 'alter table ' + @tableName + ' drop column ' + @columnName;
|
||||
EXECUTE(@sql);
|
||||
END
|
||||
$$
|
||||
</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>
|
||||
</extra-ddl>
|
||||
@@ -0,0 +1,115 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Address;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class FetchGroupTest extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void simple() {
|
||||
|
||||
FetchGroup<Customer> fetch = FetchGroup.of(Customer.class, "name, status");
|
||||
|
||||
Query<Customer> query = Customer.find
|
||||
.query()
|
||||
.where()
|
||||
.ilike("name", "rob")
|
||||
.select(fetch);
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query)).contains("select t0.id, t0.name, t0.status from");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void nestedWithQueryJoin() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
FetchGroup<Customer> fetch = FetchGroup.of(Customer.class)
|
||||
.select("name, status")
|
||||
.fetchQuery("contacts", "firstName, lastName, email")
|
||||
.build();
|
||||
|
||||
Query<Customer> query = Customer.find
|
||||
.query()
|
||||
.where()
|
||||
.ilike("name", "rob")
|
||||
.select(fetch);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
query.findList();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.name, t0.status from o_customer");
|
||||
assertThat(sql.get(1)).contains("select t0.customer_id, t0.id, t0.first_name, t0.last_name, t0.email from contact");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void nestedWithQueryJoin_asNestedFetchGroup() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
FetchGroup<Contact> CT_NAME = FetchGroup.of(Contact.class, "firstName, lastName, email");
|
||||
|
||||
FetchGroup<Customer> fetch = FetchGroup.of(Customer.class)
|
||||
.select("name")
|
||||
.fetchQuery("contacts", CT_NAME)
|
||||
.build();
|
||||
|
||||
Query<Customer> query = Customer.find
|
||||
.query()
|
||||
.where()
|
||||
.ilike("name", "rob")
|
||||
.select(fetch);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
query.findList();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.name from o_customer");
|
||||
assertThat(sql.get(1)).contains(" from contact");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nested_withNestedFetchGroup() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
FetchGroup<Address> FGAddress = FetchGroup.of(Address.class)
|
||||
.select("line1, line2, city")
|
||||
.fetch("country", "name")
|
||||
.build();
|
||||
|
||||
FetchGroup<Customer> FBCustomer = FetchGroup.of(Customer.class)
|
||||
.select("name, version")
|
||||
.fetch("billingAddress", FGAddress)
|
||||
.build();
|
||||
|
||||
Query<Customer> query = Customer.find
|
||||
.query()
|
||||
.where()
|
||||
.ilike("name", "rob")
|
||||
.select(FBCustomer);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
query.findList();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.name, t0.version, t1.id, t1.line_1, t1.line_2, t1.city, t2.code, t2.name from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id left join o_country t2 on t2.code = t1.country_code ");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.IgnorePlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.migration.MigrationConfig;
|
||||
import io.ebean.migration.ddl.DdlRunner;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.Helper;
|
||||
|
||||
@@ -16,7 +17,6 @@ import javax.persistence.PersistenceException;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -84,6 +84,9 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
"migtest_oto_child",
|
||||
"migtest_oto_master");
|
||||
|
||||
if (isSqlServer() || isMySql()) {
|
||||
runScript(false, "I__create_procs.sql");
|
||||
}
|
||||
|
||||
runScript(false, "1.0__initial.sql");
|
||||
|
||||
@@ -103,7 +106,6 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
assertThat(server().execute(update)).isEqualTo(2);
|
||||
}
|
||||
|
||||
|
||||
createHistoryEntities();
|
||||
|
||||
// Run migration
|
||||
@@ -121,7 +123,7 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
|
||||
assertThat(row.getString("new_string_field")).isEqualTo("foo'bar");
|
||||
assertThat(row.getBoolean("new_boolean_field2")).isTrue();
|
||||
assertThat(row.getTimestamp("some_date")).isEqualTo(new Timestamp(100, 0, 1, 0, 0, 0, 0)); // = 2000-01-01T00:00:00
|
||||
//assertThat(row.getTimestamp("some_date")).isCloseTo(new Date(), 86_000); // allow 1 minute delta
|
||||
|
||||
row = result.get(1);
|
||||
assertThat(row.getInteger("id")).isEqualTo(2);
|
||||
@@ -130,15 +132,10 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
|
||||
assertThat(row.getString("new_string_field")).isEqualTo("foo'bar");
|
||||
assertThat(row.getBoolean("new_boolean_field2")).isTrue();
|
||||
assertThat(row.getTimestamp("some_date")).isEqualTo(new Timestamp(100, 0, 1, 0, 0, 0, 0)); // = 2000-01-01T00:00:00
|
||||
//assertThat(row.getTimestamp("some_date")).isCloseTo(new Date(), 60_000); // allow 1 minute delta
|
||||
|
||||
// Run migration & drops
|
||||
if (isMySql()) {
|
||||
return; // TODO: mysql cannot drop table (need stored procedure for drop column)
|
||||
}
|
||||
runScript(false, "1.2__dropsFor_1.1.sql");
|
||||
|
||||
|
||||
// Oracle caches the statement and does not detect schema change. It fails with
|
||||
// an ORA-01007
|
||||
if (isOracle()) {
|
||||
@@ -191,7 +188,7 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
update = server().createSqlUpdate("update migtest_e_history5 set test_number = 45 where id = 1");
|
||||
assertThat(server().execute(update)).isEqualTo(1);
|
||||
|
||||
update = server().createSqlUpdate("insert into migtest_e_history6 (id, test_number2) values (1, 7)");
|
||||
update = server().createSqlUpdate("insert into migtest_e_history6 (id, test_number1, test_number2) values (1, 2, 7)");
|
||||
assertThat(server().execute(update)).isEqualTo(1);
|
||||
update = server().createSqlUpdate("update migtest_e_history6 set test_number2 = 45 where id = 1");
|
||||
assertThat(server().execute(update)).isEqualTo(1);
|
||||
|
||||
+1
-1
@@ -185,7 +185,7 @@ public class PlatformDdl_AlterColumnTest {
|
||||
assertEquals("alter table mytab alter acol drop default", sql);
|
||||
|
||||
sql = sqlServerDdl.alterColumnDefaultValue("mytab", "acol", "DROP DEFAULT");
|
||||
assertThat(sql).startsWith("delimiter $$").endsWith("$$");
|
||||
assertEquals("EXEC usp_ebean_drop_default_constraint mytab, acol", sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -12,7 +12,7 @@ public class ExtraDdlXmlReaderTest {
|
||||
@Test
|
||||
public void read(){
|
||||
|
||||
ExtraDdl read = ExtraDdlXmlReader.read("/extra-ddl.xml");
|
||||
ExtraDdl read = ExtraDdlXmlReader.read();
|
||||
assertNotNull(read);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import javax.validation.constraints.Size;
|
||||
@Embeddable
|
||||
public class CKeyParentId {
|
||||
|
||||
@Size(max=127)
|
||||
Integer oneKey;
|
||||
|
||||
@Size(max=127)
|
||||
|
||||
@@ -6,7 +6,6 @@ import javax.validation.constraints.Size;
|
||||
@Embeddable
|
||||
public class CKeyParentId {
|
||||
|
||||
@Size(max=127)
|
||||
Integer oneKey;
|
||||
|
||||
@Size(max=127)
|
||||
|
||||
@@ -62,8 +62,10 @@ public class EBasic {
|
||||
@Size(max=127)
|
||||
String description;
|
||||
|
||||
@NotNull
|
||||
@DbDefault("2000-01-01T00:00:00")
|
||||
//@NotNull
|
||||
//@DbDefault("2000-01-01T00:00:00") //- date time literals do not work for each platform yet
|
||||
//@DbDefault("now") //- now does not work for mariaDb
|
||||
// MariaDb requires: ALTER TABLE `migtest_e_basic` CHANGE `some_date` `some_date` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
Timestamp someDate;
|
||||
|
||||
@NotNull
|
||||
@@ -108,7 +110,6 @@ public class EBasic {
|
||||
@DbDefault("42")
|
||||
int newInteger;
|
||||
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
@DbMigration(preAlter= "insert into migtest_e_user (id) select distinct user_id from migtest_e_basic") // ensure all users exist
|
||||
EUser user;
|
||||
|
||||
@@ -4,6 +4,7 @@ package misc.migration.v1_1;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import io.ebean.annotation.DbDefault;
|
||||
import io.ebean.annotation.History;
|
||||
@@ -14,18 +15,21 @@ import io.ebean.annotation.NotNull;
|
||||
@Table(name = "migtest_e_history2")
|
||||
@History
|
||||
public class EHistory2 {
|
||||
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
|
||||
@NotNull
|
||||
@DbDefault("unknown")
|
||||
String testString;
|
||||
|
||||
@HistoryExclude
|
||||
String testString2;
|
||||
|
||||
|
||||
@NotNull
|
||||
@DbDefault("unknown")
|
||||
String testString3;
|
||||
|
||||
@Size(max = 20)
|
||||
String newColumn;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import javax.validation.constraints.Size;
|
||||
@Embeddable
|
||||
public class CKeyParentId {
|
||||
|
||||
@Size(max=127)
|
||||
Integer oneKey;
|
||||
|
||||
@Size(max=127)
|
||||
|
||||
@@ -3,15 +3,14 @@ package org.tests.batchload;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.QueryIterator;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -78,13 +77,15 @@ public class TestSecondaryQueries extends TransactionalTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Iterator<Order> orders = Ebean.find(Order.class)
|
||||
.select("status")
|
||||
.setMaxRows(10)
|
||||
.setUseCache(false)
|
||||
.findIterate();
|
||||
while (orders.hasNext()) {
|
||||
orders.next(); // dummy read
|
||||
try (QueryIterator<Order> orders =
|
||||
Ebean.find(Order.class).select("status")
|
||||
.setMaxRows(10)
|
||||
.setUseCache(false)
|
||||
.findIterate()) {
|
||||
|
||||
while (orders.hasNext()) {
|
||||
orders.next(); // dummy read
|
||||
}
|
||||
}
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.tests.merge;
|
||||
|
||||
import io.ebean.annotation.NotNull;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@@ -12,7 +14,8 @@ public class MContactMessage extends MBase {
|
||||
|
||||
private String notes;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
private MContact contact;
|
||||
|
||||
public MContactMessage(String title, String subject) {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.tests.model.composite;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class CkeClient {
|
||||
|
||||
@EmbeddedId
|
||||
private CkeClientKey clientPK;
|
||||
|
||||
@JoinColumns({
|
||||
@JoinColumn(name = "username", referencedColumnName = "username"),
|
||||
@JoinColumn(name = "cod_cpny", referencedColumnName = "cod_cpny", insertable = false, updatable = false)
|
||||
})
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
private CkeUser user;
|
||||
|
||||
private String notes;
|
||||
|
||||
public CkeUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(CkeUser user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public CkeClientKey getClientPK() {
|
||||
return clientPK;
|
||||
}
|
||||
|
||||
public void setClientPK(CkeClientKey clientPK) {
|
||||
this.clientPK = clientPK;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.tests.model.composite;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Embeddable
|
||||
public class CkeClientKey {
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "cod_cpny")
|
||||
private int codCompany;
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "cod_client")
|
||||
private String codClient;
|
||||
|
||||
public CkeClientKey(int codCompany, String codClient) {
|
||||
this.codCompany = codCompany;
|
||||
this.codClient = codClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CkeClientKey that = (CkeClientKey) o;
|
||||
return codCompany == that.codCompany &&
|
||||
Objects.equals(codClient, that.codClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(codCompany, codClient);
|
||||
}
|
||||
|
||||
public int getCodCompany() {
|
||||
return codCompany;
|
||||
}
|
||||
|
||||
public void setCodCompany(int codCompany) {
|
||||
this.codCompany = codCompany;
|
||||
}
|
||||
|
||||
public String getCodClient() {
|
||||
return codClient;
|
||||
}
|
||||
|
||||
public void setCodClient(String codClient) {
|
||||
this.codClient = codClient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.tests.model.composite;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class CkeUser {
|
||||
|
||||
@EmbeddedId
|
||||
private CkeUserKey userPK;
|
||||
|
||||
private String name;
|
||||
|
||||
public CkeUserKey getUserPK() {
|
||||
return userPK;
|
||||
}
|
||||
|
||||
public void setUserPK(CkeUserKey userPK) {
|
||||
this.userPK = userPK;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.tests.model.composite;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.util.Objects;
|
||||
|
||||
@Embeddable
|
||||
public class CkeUserKey {
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "cod_cpny")
|
||||
private int codCompany;
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "username")
|
||||
private String username;
|
||||
|
||||
public CkeUserKey(int codCompany, String username) {
|
||||
this.codCompany = codCompany;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CkeUserKey that = (CkeUserKey) o;
|
||||
return codCompany == that.codCompany &&
|
||||
Objects.equals(username, that.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(codCompany, username);
|
||||
}
|
||||
|
||||
public int getCodCompany() {
|
||||
return codCompany;
|
||||
}
|
||||
|
||||
public void setCodCompany(int codCompany) {
|
||||
this.codCompany = codCompany;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.tests.model.composite;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestCompositeKeyUserClient extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
CkeUser user0 = new CkeUser();
|
||||
user0.setUserPK(new CkeUserKey(20, "sally"));
|
||||
user0.setName("sally");
|
||||
Ebean.save(user0);
|
||||
|
||||
CkeUser user1 = new CkeUser();
|
||||
user1.setUserPK(new CkeUserKey(20, "frank"));
|
||||
user1.setName("hello");
|
||||
Ebean.save(user1);
|
||||
|
||||
CkeClient client = new CkeClient();
|
||||
client.setNotes("try it");
|
||||
client.setClientPK(new CkeClientKey(20, "susan"));
|
||||
client.setUser(user1);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.save(client);
|
||||
|
||||
client.setNotes("update it");
|
||||
client.setUser(user0);
|
||||
|
||||
Ebean.save(client);
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("insert into cke_client (cod_cpny, cod_client, notes, username) values (?,?,?,?)");
|
||||
assertThat(sql.get(1)).contains("update cke_client set notes=?, username=? where cod_cpny=? and cod_client=?");
|
||||
|
||||
Ebean.delete(client);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.tests.o2m.jointable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="mkeygroup")
|
||||
public class JtMonkeyGroup {
|
||||
|
||||
@Id
|
||||
long pid;
|
||||
|
||||
String name;
|
||||
|
||||
/**
|
||||
* No cascading over to Monkey but we do maintain the join table regardless.
|
||||
*/
|
||||
@OneToMany
|
||||
@JoinTable
|
||||
List<JtMonkey> monkeys;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public JtMonkeyGroup(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public void setPid(long pid) {
|
||||
this.pid = pid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<JtMonkey> getMonkeys() {
|
||||
return monkeys;
|
||||
}
|
||||
|
||||
public void setMonkeys(List<JtMonkey> monkeys) {
|
||||
this.monkeys = monkeys;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.tests.o2m.jointable;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestOneToManyJoinTableNoTableName extends BaseTestCase {
|
||||
|
||||
private JtMonkeyGroup troop = new JtMonkeyGroup("Pink");
|
||||
|
||||
private JtMonkey m0 = new JtMonkey("Sim3");
|
||||
private JtMonkey m1 = new JtMonkey("Tim3");
|
||||
private JtMonkey m2 = new JtMonkey("Uim3");
|
||||
|
||||
private void initialInsert() {
|
||||
Ebean.saveAll(Arrays.asList(troop, m0, m1, m2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void base() {
|
||||
|
||||
initialInsert();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
// make m0 dirty ... but no cascade saved?
|
||||
m0.setFoodPreference("camera");
|
||||
troop.getMonkeys().add(m0);
|
||||
troop.getMonkeys().add(m1);
|
||||
|
||||
Ebean.save(troop);
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("insert into mkeygroup_monkey (mkeygroup_pid, monkey_mid) values (?, ?)");
|
||||
|
||||
int intersectionRows = Ebean.createSqlQuery("select count(*) as total from mkeygroup_monkey where mkeygroup_pid = ?")
|
||||
.setParameter(1, troop.getPid())
|
||||
.findOne()
|
||||
.getInteger("total");
|
||||
|
||||
assertThat(intersectionRows).isEqualTo(2);
|
||||
|
||||
LoggedSqlCollector.current();
|
||||
JtMonkeyGroup fetchTroop = Ebean.find(JtMonkeyGroup.class)
|
||||
.fetch("monkeys")
|
||||
.where().idEq(troop.getPid())
|
||||
.findOne();
|
||||
|
||||
assertThat(fetchTroop.getMonkeys()).hasSize(2);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(trimSql(sql.get(0))).contains("from mkeygroup t0 left join mkeygroup_monkey t1z_ on t1z_.mkeygroup_pid = t0.pid left join monkey t1 on t1.mid = t1z_.monkey_mid where t0.pid = ?");
|
||||
assertThat(trimSql(sql.get(0))).contains("select t0.pid, t0.name, t0.version, t1.mid, t1.name, t1.food_preference, t1.version");
|
||||
|
||||
Ebean.delete(troop);
|
||||
|
||||
sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("delete from mkeygroup_monkey where mkeygroup_pid = ?");
|
||||
assertThat(sql.get(1)).contains("delete from mkeygroup where pid=? and version=?");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestQueryFindNative extends BaseTestCase {
|
||||
|
||||
|
||||
@Test
|
||||
public void joinFromManyToOne() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql =
|
||||
"select c.id, c.first_name, c.last_name, t.id, t.name " +
|
||||
" from contact c " +
|
||||
" join o_customer t on t.id = c.customer_id " +
|
||||
" where t.name like ? " +
|
||||
" order by c.first_name, c.last_name";
|
||||
|
||||
List<Contact> contacts =
|
||||
server()
|
||||
.findNative(Contact.class, sql)
|
||||
.setParameter(1, "Rob")
|
||||
.findList();
|
||||
|
||||
|
||||
assertThat(contacts).isNotEmpty();
|
||||
|
||||
Customer customer = contacts.get(0).getCustomer();
|
||||
assertThat(customer).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void joinFromOneToMany() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql =
|
||||
"select cu.id, cu.name, ct.id, ct.first_name " +
|
||||
" from o_customer cu " +
|
||||
" left join contact ct on cu.id = ct.customer_id " +
|
||||
" where cu.name like ? " +
|
||||
" order by name";
|
||||
|
||||
List<Customer> customers =
|
||||
server()
|
||||
.findNative(Customer.class, sql)
|
||||
.setParameter(1, "Rob")
|
||||
.findList();
|
||||
|
||||
assertThat(customers).isNotEmpty();
|
||||
|
||||
List<Contact> contacts = customers.get(0).getContacts();
|
||||
assertThat(contacts).isNotEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.tests.types;
|
||||
|
||||
/**
|
||||
* Encrypted string.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
public class EncryptedBinary {
|
||||
|
||||
private final byte[] encryptedData;
|
||||
|
||||
EncryptedBinary(byte[] encryptedData) {
|
||||
this.encryptedData = encryptedData;
|
||||
}
|
||||
|
||||
public byte[] getEncryptedData() {
|
||||
return encryptedData;
|
||||
}
|
||||
|
||||
public byte[] decrypt() {
|
||||
return xor(encryptedData);
|
||||
}
|
||||
|
||||
public static EncryptedBinary encrypt(final byte[] s) {
|
||||
return new EncryptedBinary(xor(s));
|
||||
}
|
||||
|
||||
private static byte[] xor(byte[] s) {
|
||||
byte[] ret = new byte[s.length];
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
ret[i] = (byte) (s[i] ^ i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.tests.types;
|
||||
|
||||
/**
|
||||
* Encrypted string.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
public class EncryptedString {
|
||||
|
||||
private final String encryptedData;
|
||||
|
||||
EncryptedString(String encryptedData) {
|
||||
this.encryptedData = encryptedData;
|
||||
}
|
||||
|
||||
public String getEncryptedData() {
|
||||
return encryptedData;
|
||||
}
|
||||
|
||||
public String decrypt() {
|
||||
return rot13(encryptedData);
|
||||
}
|
||||
|
||||
public static EncryptedString encrypt(final String s) {
|
||||
return new EncryptedString(rot13(s));
|
||||
}
|
||||
|
||||
private static String rot13(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c >= 'a' && c <= 'm') c += 13;
|
||||
else if (c >= 'A' && c <= 'M') c += 13;
|
||||
else if (c >= 'n' && c <= 'z') c -= 13;
|
||||
else if (c >= 'N' && c <= 'Z') c -= 13;
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.tests.types;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Lob;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.tests.model.BaseModel;
|
||||
|
||||
@Entity
|
||||
public class PasswordStoreModel extends BaseModel {
|
||||
private static final long serialVersionUID = 1L;
|
||||
// PasswordStoreModel should have the following column definitions in DDL
|
||||
// enc1 varchar(30),
|
||||
// enc2 varchar(40),
|
||||
// enc3 clob,
|
||||
// enc4 varbinary(30),
|
||||
// enc5 varbinary(40),
|
||||
// enc6 blob,
|
||||
|
||||
@Size(max = 30)
|
||||
private EncryptedString enc1;
|
||||
@Column(length = 40)
|
||||
private EncryptedString enc2;
|
||||
@Lob
|
||||
private EncryptedString enc3;
|
||||
|
||||
@Size(max = 30)
|
||||
private EncryptedBinary enc4;
|
||||
@Column(length = 40)
|
||||
private EncryptedBinary enc5;
|
||||
@Lob
|
||||
private EncryptedBinary enc6;
|
||||
|
||||
public EncryptedString getEnc1() {
|
||||
return enc1;
|
||||
}
|
||||
|
||||
public void setEnc1(EncryptedString enc1) {
|
||||
this.enc1 = enc1;
|
||||
}
|
||||
|
||||
public EncryptedString getEnc2() {
|
||||
return enc2;
|
||||
}
|
||||
|
||||
public void setEnc2(EncryptedString enc2) {
|
||||
this.enc2 = enc2;
|
||||
}
|
||||
|
||||
public EncryptedString getEnc3() {
|
||||
return enc3;
|
||||
}
|
||||
|
||||
public void setEnc3(EncryptedString enc3) {
|
||||
this.enc3 = enc3;
|
||||
}
|
||||
|
||||
public EncryptedBinary getEnc4() {
|
||||
return enc4;
|
||||
}
|
||||
|
||||
public void setEnc4(EncryptedBinary enc4) {
|
||||
this.enc4 = enc4;
|
||||
}
|
||||
|
||||
public EncryptedBinary getEnc5() {
|
||||
return enc5;
|
||||
}
|
||||
|
||||
public void setEnc5(EncryptedBinary enc5) {
|
||||
this.enc5 = enc5;
|
||||
}
|
||||
|
||||
public EncryptedBinary getEnc6() {
|
||||
return enc6;
|
||||
}
|
||||
|
||||
public void setEnc6(EncryptedBinary enc6) {
|
||||
this.enc6 = enc6;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.tests.types;
|
||||
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
|
||||
public class ScalarTypeEncryptedBinaryConverter implements ScalarTypeConverter<EncryptedBinary, byte[]> {
|
||||
|
||||
|
||||
@Override
|
||||
public EncryptedBinary getNullValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EncryptedBinary wrapValue(final byte[] scalarType) {
|
||||
return new EncryptedBinary(scalarType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] unwrapValue(final EncryptedBinary beanType) {
|
||||
return beanType.getEncryptedData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.tests.types;
|
||||
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
|
||||
public class ScalarTypeEncryptedStringConverter implements ScalarTypeConverter<EncryptedString, String> {
|
||||
|
||||
@Override
|
||||
public EncryptedString getNullValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EncryptedString wrapValue(final String scalarType) {
|
||||
return new EncryptedString(scalarType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String unwrapValue(final EncryptedString beanType) {
|
||||
return beanType.getEncryptedData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.tests.types;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestEncryptedString extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testName() {
|
||||
PasswordStoreModel model = new PasswordStoreModel();
|
||||
|
||||
model.setEnc1(EncryptedString.encrypt("Hello"));
|
||||
model.setEnc2(EncryptedString.encrypt("World"));
|
||||
model.setEnc3(EncryptedString.encrypt("Test"));
|
||||
|
||||
model.setEnc4(EncryptedBinary.encrypt("Hello".getBytes(StandardCharsets.UTF_8)));
|
||||
model.setEnc5(EncryptedBinary.encrypt("World".getBytes(StandardCharsets.UTF_8)));
|
||||
model.setEnc6(EncryptedBinary.encrypt("Test".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
|
||||
model.save();
|
||||
|
||||
model = Ebean.find(PasswordStoreModel.class, model.getId());
|
||||
|
||||
assertThat(model.getEnc1().getEncryptedData()).isNotEqualTo("Hello");
|
||||
assertThat(model.getEnc2().getEncryptedData()).isNotEqualTo("World");
|
||||
assertThat(model.getEnc3().getEncryptedData()).isNotEqualTo("Test");
|
||||
assertThat(model.getEnc4().getEncryptedData()).isNotEqualTo("Hello".getBytes(StandardCharsets.UTF_8));
|
||||
assertThat(model.getEnc5().getEncryptedData()).isNotEqualTo("World".getBytes(StandardCharsets.UTF_8));
|
||||
assertThat(model.getEnc6().getEncryptedData()).isNotEqualTo("Test".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
|
||||
assertThat(model.getEnc1().decrypt()).isEqualTo("Hello");
|
||||
assertThat(model.getEnc2().decrypt()).isEqualTo("World");
|
||||
assertThat(model.getEnc3().decrypt()).isEqualTo("Test");
|
||||
assertThat(model.getEnc4().decrypt()).isEqualTo("Hello".getBytes(StandardCharsets.UTF_8));
|
||||
assertThat(model.getEnc5().decrypt()).isEqualTo("World".getBytes(StandardCharsets.UTF_8));
|
||||
assertThat(model.getEnc6().decrypt()).isEqualTo("Test".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@ package org.tests.types;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.plugin.BeanType;
|
||||
import io.ebean.plugin.ExpressionPath;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.tests.model.types.SomeNewTypesBean;
|
||||
|
||||
@@ -21,9 +24,7 @@ import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class TestNewTypes extends BaseTestCase {
|
||||
|
||||
@@ -145,4 +146,90 @@ public class TestNewTypes extends BaseTestCase {
|
||||
assertNull(fetched.getPath());
|
||||
assertNull(fetched.getPeriod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetGetPathNonNull() throws Exception {
|
||||
SomeNewTypesBean refBean = new SomeNewTypesBean();
|
||||
refBean.setLocalDate(LocalDate.now());
|
||||
refBean.setLocalDateTime(LocalDateTime.now());
|
||||
refBean.setOffsetDateTime(OffsetDateTime.now());
|
||||
refBean.setZonedDateTime(ZonedDateTime.now());
|
||||
refBean.setInstant(Instant.now());
|
||||
refBean.setYear(Year.now());
|
||||
refBean.setMonth(Month.APRIL);
|
||||
refBean.setDayOfWeek(DayOfWeek.WEDNESDAY);
|
||||
refBean.setZoneId(ZoneId.systemDefault());
|
||||
refBean.setZoneOffset(ZonedDateTime.now().getOffset());
|
||||
refBean.setYearMonth(YearMonth.of(2014, 9));
|
||||
refBean.setPath(Paths.get(TEMP_PATH));
|
||||
refBean.setPeriod(Period.of(4,3,2));
|
||||
|
||||
testSetGetPath(refBean);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetGetPathNull() throws Exception {
|
||||
SomeNewTypesBean refBean = new SomeNewTypesBean();
|
||||
testSetGetPath(refBean);
|
||||
}
|
||||
private void testSetGetPath(SomeNewTypesBean refBean) {
|
||||
SomeNewTypesBean testBean = new SomeNewTypesBean();
|
||||
BeanType<SomeNewTypesBean> beanType = Ebean.getDefaultServer().getPluginApi().getBeanType(SomeNewTypesBean.class);
|
||||
ExpressionPath localDate = beanType.getExpressionPath("localDate");
|
||||
ExpressionPath localDateTime = beanType.getExpressionPath("localDateTime");
|
||||
ExpressionPath offsetDateTime = beanType.getExpressionPath("offsetDateTime");
|
||||
ExpressionPath zonedDateTime = beanType.getExpressionPath("zonedDateTime");
|
||||
ExpressionPath instant = beanType.getExpressionPath("instant");
|
||||
ExpressionPath year = beanType.getExpressionPath("year");
|
||||
ExpressionPath month = beanType.getExpressionPath("month");
|
||||
ExpressionPath dayOfWeek = beanType.getExpressionPath("dayOfWeek");
|
||||
ExpressionPath zoneId = beanType.getExpressionPath("zoneId");
|
||||
ExpressionPath zoneOffset = beanType.getExpressionPath("zoneOffset");
|
||||
ExpressionPath yearMonth = beanType.getExpressionPath("yearMonth");
|
||||
ExpressionPath path = beanType.getExpressionPath("path");
|
||||
ExpressionPath period = beanType.getExpressionPath("period");
|
||||
|
||||
localDate.pathSet(testBean, refBean.getLocalDate());
|
||||
assertThat(localDate.pathGet(testBean)).isEqualTo(refBean.getLocalDate());
|
||||
|
||||
localDateTime.pathSet(testBean, refBean.getLocalDateTime());
|
||||
assertThat(localDateTime.pathGet(testBean)).isEqualTo(refBean.getLocalDateTime());
|
||||
|
||||
offsetDateTime.pathSet(testBean, refBean.getOffsetDateTime());
|
||||
assertThat(offsetDateTime.pathGet(testBean)).isEqualTo(refBean.getOffsetDateTime());
|
||||
|
||||
zonedDateTime.pathSet(testBean, refBean.getZonedDateTime());
|
||||
assertThat(zonedDateTime.pathGet(testBean)).isEqualTo(refBean.getZonedDateTime());
|
||||
|
||||
instant.pathSet(testBean, refBean.getInstant());
|
||||
assertThat(instant.pathGet(testBean)).isEqualTo(refBean.getInstant());
|
||||
|
||||
year.pathSet(testBean, refBean.getYear());
|
||||
assertThat(year.pathGet(testBean)).isEqualTo(refBean.getYear());
|
||||
|
||||
month.pathSet(testBean, refBean.getMonth());
|
||||
assertThat(month.pathGet(testBean)).isEqualTo(refBean.getMonth());
|
||||
|
||||
dayOfWeek.pathSet(testBean, refBean.getDayOfWeek());
|
||||
assertThat(dayOfWeek.pathGet(testBean)).isEqualTo(refBean.getDayOfWeek());
|
||||
|
||||
zoneId.pathSet(testBean, refBean.getZoneId());
|
||||
assertThat(zoneId.pathGet(testBean)).isEqualTo(refBean.getZoneId());
|
||||
|
||||
zoneOffset.pathSet(testBean, refBean.getZoneOffset());
|
||||
assertThat(zoneOffset.pathGet(testBean)).isEqualTo(refBean.getZoneOffset());
|
||||
|
||||
yearMonth.pathSet(testBean, refBean.getYearMonth());
|
||||
assertThat(yearMonth.pathGet(testBean)).isEqualTo(refBean.getYearMonth());
|
||||
|
||||
path.pathSet(testBean, refBean.getPath());
|
||||
assertThat(path.pathGet(testBean)).isEqualTo(refBean.getPath());
|
||||
|
||||
period.pathSet(testBean, refBean.getPeriod());
|
||||
assertThat(period.pathGet(testBean)).isEqualTo(refBean.getPeriod());
|
||||
|
||||
Ebean.save(refBean);
|
||||
Ebean.save(testBean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,10 +39,6 @@ alter table migtest_e_basic add constraint ck_mgtst__bsc_stts check ( status in
|
||||
-- rename all collisions;
|
||||
-- NOT SUPPORTED alter table migtest_e_basic add constraint uq_mgtst__b_vs45xo unique (description);
|
||||
|
||||
update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null;
|
||||
alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00';
|
||||
alter table migtest_e_basic alter column some_date set not null;
|
||||
|
||||
insert into migtest_e_user (id) select distinct user_id from migtest_e_basic;
|
||||
alter table migtest_e_basic add constraint fk_mgtst__bsc_sr_d foreign key (user_id) references migtest_e_user (id) on delete restrict;
|
||||
alter table migtest_e_basic alter column user_id set null;
|
||||
@@ -72,6 +68,7 @@ alter table migtest_e_history2 alter column test_string set default 'unknown';
|
||||
alter table migtest_e_history2 alter column test_string set not null;
|
||||
alter table migtest_e_history2 add column test_string2 varchar(255);
|
||||
alter table migtest_e_history2 add column test_string3 varchar(255) default 'unknown' not null;
|
||||
alter table migtest_e_history2 add column new_column varchar(20);
|
||||
|
||||
alter table migtest_e_history4 alter column test_number bigint;
|
||||
alter table migtest_e_history5 add column test_boolean boolean default false not null;
|
||||
|
||||
@@ -19,8 +19,6 @@ alter table migtest_e_basic alter column status drop default;
|
||||
alter table migtest_e_basic alter column status set null;
|
||||
alter table migtest_e_basic add constraint ck_mgtst__bsc_stts check ( status in ('N','A','I'));
|
||||
alter table migtest_e_basic drop constraint uq_mgtst__b_vs45xo;
|
||||
alter table migtest_e_basic alter column some_date drop default;
|
||||
alter table migtest_e_basic alter column some_date set null;
|
||||
|
||||
update migtest_e_basic set user_id = 23 where user_id is null;
|
||||
alter table migtest_e_basic drop constraint fk_mgtst__bsc_sr_d;
|
||||
|
||||
@@ -20,6 +20,8 @@ alter table migtest_e_history2 drop column test_string2;
|
||||
|
||||
alter table migtest_e_history2 drop column test_string3;
|
||||
|
||||
alter table migtest_e_history2 drop column new_column;
|
||||
|
||||
alter table migtest_e_history5 drop column test_boolean;
|
||||
|
||||
alter table migtest_e_softdelete drop column deleted;
|
||||
|
||||
@@ -13,7 +13,7 @@ create table migtest_ckey_detail (
|
||||
);
|
||||
|
||||
create table migtest_ckey_parent (
|
||||
one_key integer(127) not null,
|
||||
one_key integer not null,
|
||||
two_key varchar(127) not null,
|
||||
name varchar(255),
|
||||
version integer not null,
|
||||
|
||||
@@ -23,7 +23,7 @@ create table migtest_mtm_m_migtest_mtm_c (
|
||||
constraint pk_migtest_mtm_m_migtest_mtm_c primary key (migtest_mtm_m_id,migtest_mtm_c_id)
|
||||
);
|
||||
|
||||
alter table migtest_ckey_detail add column one_key integer(127);
|
||||
alter table migtest_ckey_detail add column one_key integer;
|
||||
alter table migtest_ckey_detail add column two_key varchar(127);
|
||||
|
||||
alter table migtest_ckey_detail add constraint fk_migtest_ckey_detail_parent foreign key (one_key,two_key) references migtest_ckey_parent (one_key,two_key) on delete restrict on update restrict;
|
||||
@@ -45,10 +45,6 @@ alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( sta
|
||||
-- rename all collisions;
|
||||
alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description);
|
||||
|
||||
update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null;
|
||||
alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00';
|
||||
alter table migtest_e_basic alter column some_date set not null;
|
||||
|
||||
insert into migtest_e_user (id) select distinct user_id from migtest_e_basic;
|
||||
alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict;
|
||||
alter table migtest_e_basic alter column user_id set null;
|
||||
@@ -78,8 +74,10 @@ alter table migtest_e_history2 alter column test_string set default 'unknown';
|
||||
alter table migtest_e_history2 alter column test_string set not null;
|
||||
alter table migtest_e_history2 add column test_string2 varchar(255);
|
||||
alter table migtest_e_history2 add column test_string3 varchar(255) default 'unknown' not null;
|
||||
alter table migtest_e_history2 add column new_column varchar(20);
|
||||
alter table migtest_e_history2_history add column test_string2 varchar(255);
|
||||
alter table migtest_e_history2_history add column test_string3 varchar(255) default 'unknown';
|
||||
alter table migtest_e_history2_history add column new_column varchar(20);
|
||||
|
||||
alter table migtest_e_history4 alter column test_number bigint;
|
||||
alter table migtest_e_history4_history alter column test_number bigint;
|
||||
@@ -136,7 +134,7 @@ create view migtest_e_history4_with_history as select * from migtest_e_history4
|
||||
create view migtest_e_history5_with_history as select * from migtest_e_history5 union all select * from migtest_e_history5_history;
|
||||
|
||||
create trigger migtest_e_history_history_upd before update,delete on migtest_e_history for each row call "io.ebean.config.dbplatform.h2.H2HistoryTrigger";
|
||||
-- changes: [add test_string2, add test_string3]
|
||||
-- changes: [add test_string2, add test_string3, add new_column]
|
||||
drop trigger migtest_e_history2_history_upd;
|
||||
create trigger migtest_e_history2_history_upd before update,delete on migtest_e_history2 for each row call "io.ebean.config.dbplatform.h2.H2HistoryTrigger";
|
||||
-- changes: [exclude test_string]
|
||||
|
||||
@@ -24,8 +24,6 @@ alter table migtest_e_basic alter column status drop default;
|
||||
alter table migtest_e_basic alter column status set null;
|
||||
alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I'));
|
||||
alter table migtest_e_basic drop constraint uq_migtest_e_basic_description;
|
||||
alter table migtest_e_basic alter column some_date drop default;
|
||||
alter table migtest_e_basic alter column some_date set null;
|
||||
|
||||
update migtest_e_basic set user_id = 23 where user_id is null;
|
||||
alter table migtest_e_basic drop constraint if exists fk_migtest_e_basic_user_id;
|
||||
|
||||
@@ -32,6 +32,9 @@ alter table migtest_e_history2_history drop column test_string2;
|
||||
alter table migtest_e_history2 drop column test_string3;
|
||||
alter table migtest_e_history2_history drop column test_string3;
|
||||
|
||||
alter table migtest_e_history2 drop column new_column;
|
||||
alter table migtest_e_history2_history drop column new_column;
|
||||
|
||||
alter table migtest_e_history5 drop column test_boolean;
|
||||
alter table migtest_e_history5_history drop column test_boolean;
|
||||
|
||||
@@ -47,7 +50,7 @@ create view migtest_e_history2_with_history as select * from migtest_e_history2
|
||||
|
||||
create view migtest_e_history5_with_history as select * from migtest_e_history5 union all select * from migtest_e_history5_history;
|
||||
|
||||
-- changes: [drop test_string2, drop test_string3]
|
||||
-- changes: [drop test_string2, drop test_string3, drop new_column]
|
||||
drop trigger migtest_e_history2_history_upd;
|
||||
create trigger migtest_e_history2_history_upd before update,delete on migtest_e_history2 for each row call "io.ebean.config.dbplatform.h2.H2HistoryTrigger";
|
||||
-- changes: [drop test_boolean]
|
||||
|
||||
@@ -39,10 +39,6 @@ alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( sta
|
||||
-- rename all collisions;
|
||||
alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description);
|
||||
|
||||
update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null;
|
||||
alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00';
|
||||
alter table migtest_e_basic alter column some_date set not null;
|
||||
|
||||
insert into migtest_e_user (id) select distinct user_id from migtest_e_basic;
|
||||
alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict;
|
||||
alter table migtest_e_basic alter column user_id set null;
|
||||
@@ -72,6 +68,7 @@ alter table migtest_e_history2 alter column test_string set default 'unknown';
|
||||
alter table migtest_e_history2 alter column test_string set not null;
|
||||
alter table migtest_e_history2 add column test_string2 varchar(255);
|
||||
alter table migtest_e_history2 add column test_string3 varchar(255) default 'unknown' not null;
|
||||
alter table migtest_e_history2 add column new_column varchar(20);
|
||||
|
||||
alter table migtest_e_history4 alter column test_number bigint;
|
||||
alter table migtest_e_history5 add column test_boolean boolean default false not null;
|
||||
|
||||
@@ -19,8 +19,6 @@ alter table migtest_e_basic alter column status drop default;
|
||||
alter table migtest_e_basic alter column status set null;
|
||||
alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I'));
|
||||
alter table migtest_e_basic drop constraint uq_migtest_e_basic_description;
|
||||
alter table migtest_e_basic alter column some_date drop default;
|
||||
alter table migtest_e_basic alter column some_date set null;
|
||||
|
||||
update migtest_e_basic set user_id = 23 where user_id is null;
|
||||
alter table migtest_e_basic drop constraint if exists fk_migtest_e_basic_user_id;
|
||||
|
||||
@@ -20,6 +20,8 @@ alter table migtest_e_history2 drop column test_string2;
|
||||
|
||||
alter table migtest_e_history2 drop column test_string3;
|
||||
|
||||
alter table migtest_e_history2 drop column new_column;
|
||||
|
||||
alter table migtest_e_history5 drop column test_boolean;
|
||||
|
||||
alter table migtest_e_softdelete drop column deleted;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<column name="something" type="varchar"/>
|
||||
</createTable>
|
||||
<createTable name="migtest_ckey_parent" pkName="pk_migtest_ckey_parent">
|
||||
<column name="one_key" type="integer(127)" primaryKey="true"/>
|
||||
<column name="one_key" type="integer" primaryKey="true"/>
|
||||
<column name="two_key" type="varchar(127)" primaryKey="true"/>
|
||||
<column name="name" type="varchar"/>
|
||||
<column name="version" type="integer" notnull="true"/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
<addColumn tableName="migtest_ckey_detail">
|
||||
<column name="one_key" type="integer(127)"/>
|
||||
<column name="one_key" type="integer"/>
|
||||
<column name="two_key" type="varchar(127)"/>
|
||||
</addColumn>
|
||||
<alterForeignKey name="fk_migtest_ckey_detail_parent" columnNames="one_key,two_key" refColumnNames="one_key,two_key" refTableName="migtest_ckey_parent" indexName="ix_migtest_ckey_detail_parent" tableName="migtest_ckey_detail"/>
|
||||
@@ -17,7 +17,6 @@
|
||||
<alterColumn columnName="description" tableName="migtest_e_basic" unique="uq_migtest_e_basic_description">
|
||||
<before>-- rename all collisions</before>
|
||||
</alterColumn>
|
||||
<alterColumn columnName="some_date" tableName="migtest_e_basic" currentType="timestamp" defaultValue="'2000-01-01T00:00:00'" notnull="true" currentNotnull="false"/>
|
||||
<alterColumn columnName="user_id" tableName="migtest_e_basic" currentType="integer" notnull="false" currentNotnull="true" references="migtest_e_user.id" foreignKeyName="fk_migtest_e_basic_user_id" foreignKeyIndex="ix_migtest_e_basic_user_id">
|
||||
<before>insert into migtest_e_user (id) select distinct user_id from migtest_e_basic</before>
|
||||
</alterColumn>
|
||||
@@ -46,6 +45,7 @@
|
||||
<addColumn tableName="migtest_e_history2" withHistory="true">
|
||||
<column name="test_string2" type="varchar" historyExclude="true"/>
|
||||
<column name="test_string3" type="varchar" defaultValue="'unknown'" notnull="true"/>
|
||||
<column name="new_column" type="varchar(20)"/>
|
||||
</addColumn>
|
||||
<alterColumn columnName="test_string" tableName="migtest_e_history3" withHistory="true" historyExclude="true"/>
|
||||
<alterColumn columnName="test_number" tableName="migtest_e_history4" withHistory="true" type="bigint" currentType="integer" currentNotnull="false"/>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<alterColumn columnName="one_id" tableName="migtest_fk_set_null" references="migtest_fk_one.id" foreignKeyName="fk_migtest_fk_set_null_one_id" foreignKeyIndex="ix_migtest_fk_set_null_one_id" foreignKeyOnDelete="SET_NULL" foreignKeyOnUpdate="RESTRICT" dropForeignKey="fk_migtest_fk_set_null_one_id" dropForeignKeyIndex="ix_migtest_fk_set_null_one_id"/>
|
||||
<alterColumn columnName="status" tableName="migtest_e_basic" currentType="varchar(1)" defaultValue="DROP DEFAULT" notnull="false" currentNotnull="true" checkConstraint="check ( status in ('N','A','I'))" checkConstraintName="ck_migtest_e_basic_status"/>
|
||||
<alterColumn columnName="description" tableName="migtest_e_basic" dropUnique="uq_migtest_e_basic_description"/>
|
||||
<alterColumn columnName="some_date" tableName="migtest_e_basic" currentType="timestamp" defaultValue="DROP DEFAULT" notnull="false" currentNotnull="true"/>
|
||||
<alterColumn columnName="user_id" tableName="migtest_e_basic" currentType="integer" defaultValue="23" notnull="true" currentNotnull="false" dropForeignKey="fk_migtest_e_basic_user_id" dropForeignKeyIndex="ix_migtest_e_basic_user_id"/>
|
||||
<addColumn tableName="migtest_e_basic">
|
||||
<column name="old_boolean" type="boolean" defaultValue="false" notnull="true"/>
|
||||
@@ -55,6 +54,7 @@
|
||||
<dropHistoryTable baseTable="migtest_e_history"/>
|
||||
<dropColumn columnName="test_string2" tableName="migtest_e_history2" withHistory="true"/>
|
||||
<dropColumn columnName="test_string3" tableName="migtest_e_history2" withHistory="true"/>
|
||||
<dropColumn columnName="new_column" tableName="migtest_e_history2" withHistory="true"/>
|
||||
<dropColumn columnName="test_boolean" tableName="migtest_e_history5" withHistory="true"/>
|
||||
<dropColumn columnName="deleted" tableName="migtest_e_softdelete"/>
|
||||
<dropColumn columnName="master_id" tableName="migtest_oto_child"/>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<dropHistoryTable baseTable="migtest_e_history"/>
|
||||
<dropColumn columnName="test_string2" tableName="migtest_e_history2" withHistory="true"/>
|
||||
<dropColumn columnName="test_string3" tableName="migtest_e_history2" withHistory="true"/>
|
||||
<dropColumn columnName="new_column" tableName="migtest_e_history2" withHistory="true"/>
|
||||
<dropColumn columnName="test_boolean" tableName="migtest_e_history5" withHistory="true"/>
|
||||
<dropColumn columnName="deleted" tableName="migtest_e_softdelete"/>
|
||||
<dropColumn columnName="master_id" tableName="migtest_oto_child"/>
|
||||
|
||||
@@ -13,7 +13,7 @@ create table migtest_ckey_detail (
|
||||
);
|
||||
|
||||
create table migtest_ckey_parent (
|
||||
one_key integer(127) not null,
|
||||
one_key integer not null,
|
||||
two_key varchar(127) not null,
|
||||
name varchar(255),
|
||||
version integer not null,
|
||||
|
||||
@@ -23,7 +23,7 @@ create table migtest_mtm_m_migtest_mtm_c (
|
||||
constraint pk_migtest_mtm_m_migtest_mtm_c primary key (migtest_mtm_m_id,migtest_mtm_c_id)
|
||||
);
|
||||
|
||||
alter table migtest_ckey_detail add column one_key integer(127);
|
||||
alter table migtest_ckey_detail add column one_key integer;
|
||||
alter table migtest_ckey_detail add column two_key varchar(127);
|
||||
|
||||
alter table migtest_ckey_detail add constraint fk_migtest_ckey_detail_parent foreign key (one_key,two_key) references migtest_ckey_parent (one_key,two_key) on delete restrict on update restrict;
|
||||
@@ -44,10 +44,6 @@ alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( sta
|
||||
-- rename all collisions;
|
||||
alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description);
|
||||
|
||||
update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null;
|
||||
alter table migtest_e_basic alter some_date set default '2000-01-01T00:00:00';
|
||||
alter table migtest_e_basic modify some_date datetime(6) not null;
|
||||
|
||||
insert into migtest_e_user (id) select distinct user_id from migtest_e_basic;
|
||||
alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict;
|
||||
alter table migtest_e_basic modify user_id integer;
|
||||
@@ -75,8 +71,10 @@ alter table migtest_e_history2 alter test_string set default 'unknown';
|
||||
alter table migtest_e_history2 modify test_string varchar(255) not null;
|
||||
alter table migtest_e_history2 add column test_string2 varchar(255);
|
||||
alter table migtest_e_history2 add column test_string3 varchar(255) default 'unknown' not null;
|
||||
alter table migtest_e_history2 add column new_column varchar(20);
|
||||
alter table migtest_e_history2_history add column test_string2 varchar(255);
|
||||
alter table migtest_e_history2_history add column test_string3 varchar(255) default 'unknown';
|
||||
alter table migtest_e_history2_history add column new_column varchar(20);
|
||||
|
||||
alter table migtest_e_history4 modify test_number bigint;
|
||||
alter table migtest_e_history4_history modify test_number bigint;
|
||||
@@ -142,17 +140,17 @@ create trigger migtest_e_history_history_del before delete on migtest_e_history
|
||||
insert into migtest_e_history_history (sys_period_start,sys_period_end,id, test_string) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string);
|
||||
end$$
|
||||
lock tables migtest_e_history2 write, migtest_e_history3 write, migtest_e_history4 write, migtest_e_history5 write;
|
||||
-- changes: [add test_string2, add test_string3]
|
||||
-- changes: [add test_string2, add test_string3, add new_column]
|
||||
drop trigger migtest_e_history2_history_upd;
|
||||
drop trigger migtest_e_history2_history_del;
|
||||
delimiter $$
|
||||
create trigger migtest_e_history2_history_upd before update on migtest_e_history2 for each row begin
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3, obsolete_string1, obsolete_string2) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3, OLD.obsolete_string1, OLD.obsolete_string2);
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3, new_column, obsolete_string1, obsolete_string2) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3, OLD.new_column, OLD.obsolete_string1, OLD.obsolete_string2);
|
||||
set NEW.sys_period_start = now(6);
|
||||
end$$
|
||||
delimiter $$
|
||||
create trigger migtest_e_history2_history_del before delete on migtest_e_history2 for each row begin
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3, obsolete_string1, obsolete_string2) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3, OLD.obsolete_string1, OLD.obsolete_string2);
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3, new_column, obsolete_string1, obsolete_string2) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3, OLD.new_column, OLD.obsolete_string1, OLD.obsolete_string2);
|
||||
end$$
|
||||
-- changes: [exclude test_string]
|
||||
drop trigger migtest_e_history3_history_upd;
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
drop view if exists migtest_e_history2_with_history;
|
||||
|
||||
-- apply changes
|
||||
alter table migtest_e_basic drop column old_boolean;
|
||||
CALL usp_ebean_drop_column('migtest_e_basic', 'old_boolean');
|
||||
|
||||
alter table migtest_e_basic drop column old_boolean2;
|
||||
CALL usp_ebean_drop_column('migtest_e_basic', 'old_boolean2');
|
||||
|
||||
alter table migtest_e_basic drop column eref_id;
|
||||
CALL usp_ebean_drop_column('migtest_e_basic', 'eref_id');
|
||||
|
||||
alter table migtest_e_history2 drop column obsolete_string1;
|
||||
alter table migtest_e_history2_history drop column obsolete_string1;
|
||||
CALL usp_ebean_drop_column('migtest_e_history2', 'obsolete_string1');
|
||||
CALL usp_ebean_drop_column('migtest_e_history2_history', 'obsolete_string1');
|
||||
|
||||
alter table migtest_e_history2 drop column obsolete_string2;
|
||||
alter table migtest_e_history2_history drop column obsolete_string2;
|
||||
CALL usp_ebean_drop_column('migtest_e_history2', 'obsolete_string2');
|
||||
CALL usp_ebean_drop_column('migtest_e_history2_history', 'obsolete_string2');
|
||||
|
||||
drop table if exists migtest_e_ref;
|
||||
create view migtest_e_history2_with_history as select * from migtest_e_history2 union all select * from migtest_e_history2_history;
|
||||
@@ -24,11 +24,11 @@ drop trigger migtest_e_history2_history_upd;
|
||||
drop trigger migtest_e_history2_history_del;
|
||||
delimiter $$
|
||||
create trigger migtest_e_history2_history_upd before update on migtest_e_history2 for each row begin
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3);
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3, new_column) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3, OLD.new_column);
|
||||
set NEW.sys_period_start = now(6);
|
||||
end$$
|
||||
delimiter $$
|
||||
create trigger migtest_e_history2_history_del before delete on migtest_e_history2 for each row begin
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3);
|
||||
insert into migtest_e_history2_history (sys_period_start,sys_period_end,id, test_string, test_string3, new_column) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string, OLD.test_string3, OLD.new_column);
|
||||
end$$
|
||||
unlock tables;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user