mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
72
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db25cb7bfb | ||
|
|
55a9ba7170 | ||
|
|
2df2224286 | ||
|
|
e1e8092144 | ||
|
|
4d4886d808 | ||
|
|
d11bb2c4e5 | ||
|
|
663b1bb4aa | ||
|
|
f3d26e32ec | ||
|
|
5f83584315 | ||
|
|
d28e3ee456 | ||
|
|
e1b7161b22 | ||
|
|
f63a3cb926 | ||
|
|
29c5a17202 | ||
|
|
340b100a1a | ||
|
|
80975acfbf | ||
|
|
95dab97b1b | ||
|
|
ce10dd79f9 | ||
|
|
3f12739e71 | ||
|
|
cd1ae20015 | ||
|
|
6d1e3a08e1 | ||
|
|
94e6fe90e5 | ||
|
|
9bbe99657a | ||
|
|
0faf9f54ea | ||
|
|
046a9b30b0 | ||
|
|
afb7679302 | ||
|
|
db35f0f5ed | ||
|
|
19756421ad | ||
|
|
1d678576f7 | ||
|
|
ded7d44974 | ||
|
|
c9497fd654 | ||
|
|
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 | ||
|
|
11586fb635 | ||
|
|
d555122067 | ||
|
|
b6d3dc3516 | ||
|
|
bbf54d6196 | ||
|
|
74c88ce511 | ||
|
|
309bf6a11a | ||
|
|
02b6ab0f74 | ||
|
|
0c41993ce7 | ||
|
|
d949c48245 | ||
|
|
93e603ca25 | ||
|
|
117d22fd67 | ||
|
|
f13de2c8a6 | ||
|
|
5b8ef8154a | ||
|
|
df892f4509 | ||
|
|
2755e6d1ec |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.18.4</version>
|
||||
<version>11.22.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.4</tag>
|
||||
<tag>ebean-11.22.3</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -117,7 +117,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>4.1</version>
|
||||
<version>4.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -135,7 +135,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>11.7.1</version>
|
||||
<version>11.9.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ public class DbMigrationConfig {
|
||||
*/
|
||||
protected String dbSchema;
|
||||
|
||||
/**
|
||||
* Set to true if we consider this the 'default schema' (Postgres schema that matches DB username)
|
||||
*/
|
||||
protected boolean defaultDbSchema;
|
||||
|
||||
/**
|
||||
* DB user used to run the DB migration.
|
||||
*/
|
||||
@@ -400,9 +405,15 @@ public class DbMigrationConfig {
|
||||
* Set the Db schema if it hasn't already been defined.
|
||||
*/
|
||||
public void setDefaultDbSchema(String dbSchema) {
|
||||
if (this.dbSchema == null) {
|
||||
this.dbSchema = dbSchema;
|
||||
}
|
||||
this.defaultDbSchema = true;
|
||||
this.dbSchema = dbSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is considered the default DB schema (Postgres schema matching DB username).
|
||||
*/
|
||||
public boolean isDefaultDbSchema() {
|
||||
return defaultDbSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -591,6 +602,9 @@ public class DbMigrationConfig {
|
||||
runnerConfig.setDbUsername(getDbUsername());
|
||||
runnerConfig.setDbPassword(getDbPassword());
|
||||
runnerConfig.setDbSchema(getDbSchema());
|
||||
if (defaultDbSchema) {
|
||||
runnerConfig.setSetCurrentSchema(false);
|
||||
}
|
||||
runnerConfig.setClassLoader(classLoader);
|
||||
if (patchInsertOn != null) {
|
||||
runnerConfig.setPatchInsertOn(patchInsertOn);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.CustomDbTypeMapping;
|
||||
@@ -51,7 +52,7 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* The behaviour used when ending a read only transaction at read committed isolation level.
|
||||
*/
|
||||
protected OnQueryOnly onQueryOnly = OnQueryOnly.ROLLBACK;
|
||||
protected OnQueryOnly onQueryOnly = OnQueryOnly.COMMIT;
|
||||
|
||||
/**
|
||||
* The open quote used by quoted identifiers.
|
||||
@@ -706,6 +707,20 @@ public class DatabasePlatform {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if partitions exist for the given table.
|
||||
*/
|
||||
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL to create an initial partition for the given table.
|
||||
*/
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String singlePrimaryKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the like string for this DB-Platform
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.config.dbplatform.postgres;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
@@ -11,6 +12,10 @@ import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.config.dbplatform.SqlErrorCodes;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
@@ -116,4 +121,31 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
return sql + " for update";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("select count(*) from pg_inherits i WHERE i.inhparent = ?::regclass")) {
|
||||
statement.setString(1, table);
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
return resultSet.next() && resultSet.getInt(1) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return SQL using built in partition helper functions to create some initial partitions.
|
||||
*
|
||||
* Only use this if extra-dll doesn't have some initial partitions defined (which it should).
|
||||
*/
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String pkey) {
|
||||
if (property == null) {
|
||||
property = "";
|
||||
}
|
||||
if (pkey == null) {
|
||||
pkey = "";
|
||||
}
|
||||
return "select partition('" + mode.name().toLowerCase() + "','" + tableName + "','" + pkey + "','" + property + "',1);";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -98,6 +98,11 @@ public interface DbMigration {
|
||||
*/
|
||||
void setIncludeGeneratedFileComment(boolean includeGeneratedFileComment);
|
||||
|
||||
/**
|
||||
* Set this to false to exclude the builtin support for table partitioning (with @DbPartition).
|
||||
*/
|
||||
void setIncludeBuiltInPartitioning(boolean includeBuiltInPartitioning);
|
||||
|
||||
/**
|
||||
* Set the header that is included in the generated DDL script.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.migration.ddl.DdlRunner;
|
||||
import io.ebean.util.JdbcClose;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.model.CurrentModel;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import io.ebeaninternal.extraddl.model.ExtraDdlXmlReader;
|
||||
import io.ebeaninternal.server.deploy.PartitionMeta;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -180,10 +183,50 @@ public class DdlGenerator {
|
||||
|
||||
String ignoreExtraDdl = System.getProperty("ebean.ignoreExtraDdl");
|
||||
if (!"true".equalsIgnoreCase(ignoreExtraDdl) && jaxbPresent) {
|
||||
if (currentModel.isTablePartitioning()) {
|
||||
String extraPartitioning = ExtraDdlXmlReader.buildPartitioning(server.getDatabasePlatform().getName());
|
||||
if (extraPartitioning != null && !extraPartitioning.isEmpty()) {
|
||||
runScript(connection, false, extraPartitioning, "builtin-partitioning-dll");
|
||||
}
|
||||
}
|
||||
|
||||
String extraApply = ExtraDdlXmlReader.buildExtra(server.getDatabasePlatform().getName(), false);
|
||||
if (extraApply != null) {
|
||||
runScript(connection, false, extraApply, "extra-dll");
|
||||
}
|
||||
|
||||
if (currentModel.isTablePartitioning()) {
|
||||
checkInitialTablePartitions(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if table partitions exist and if not create some. The expectation is that
|
||||
* extra-dll.xml should have some partition initialisation but this helps people get going.
|
||||
*/
|
||||
private void checkInitialTablePartitions(Connection connection) {
|
||||
|
||||
DatabasePlatform databasePlatform = server.getDatabasePlatform();
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (MTable table : currentModel.getPartitionedTables()) {
|
||||
String tableName = table.getName();
|
||||
if (!databasePlatform.tablePartitionsExist(connection, tableName)) {
|
||||
log.info("No table partitions for table {}", tableName);
|
||||
PartitionMeta meta = table.getPartitionMeta();
|
||||
String initPart = databasePlatform.tablePartitionInit(tableName, meta.getMode(), meta.getProperty(), table.singlePrimaryKey());
|
||||
sb.append(initPart).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
String initialPartitionSql = sb.toString();
|
||||
if (!initialPartitionSql.isEmpty()) {
|
||||
runScript(connection, false, initialPartitionSql, "initial table partitions");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error("Error checking initial table partitions", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
protected DatabasePlatform databasePlatform;
|
||||
|
||||
private boolean vanillaPlatform;
|
||||
|
||||
protected List<Pair> platforms = new ArrayList<>();
|
||||
|
||||
protected ServerConfig serverConfig;
|
||||
@@ -98,6 +100,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
protected String name;
|
||||
protected String generatePendingDrop;
|
||||
|
||||
protected boolean includeBuiltInPartitioning = true;
|
||||
|
||||
/**
|
||||
* Create for offline migration generation.
|
||||
*/
|
||||
@@ -179,6 +183,11 @@ public class DefaultDbMigration implements DbMigration {
|
||||
this.includeGeneratedFileComment = includeGeneratedFileComment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIncludeBuiltInPartitioning(boolean includeBuiltInPartitioning) {
|
||||
this.includeBuiltInPartitioning = includeBuiltInPartitioning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String header) {
|
||||
this.header = header;
|
||||
@@ -192,6 +201,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
*/
|
||||
@Override
|
||||
public void setPlatform(Platform platform) {
|
||||
vanillaPlatform = true;
|
||||
setPlatform(getPlatform(platform));
|
||||
}
|
||||
|
||||
@@ -276,7 +286,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
try {
|
||||
Request request = createRequest();
|
||||
if (platforms.isEmpty()) {
|
||||
generateExtraDdl(request.migrationDir, databasePlatform);
|
||||
generateExtraDdl(request.migrationDir, databasePlatform, request.isTablePartitioning());
|
||||
}
|
||||
|
||||
String pendingVersion = generatePendingDrop();
|
||||
@@ -311,16 +321,23 @@ public class DefaultDbMigration implements DbMigration {
|
||||
* migration runner.
|
||||
* </p>
|
||||
*/
|
||||
private void generateExtraDdl(File migrationDir, DatabasePlatform dbPlatform) throws IOException {
|
||||
private void generateExtraDdl(File migrationDir, DatabasePlatform dbPlatform, boolean tablePartitioning) 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())) {
|
||||
writeExtraDdl(migrationDir, script);
|
||||
}
|
||||
if (tablePartitioning && includeBuiltInPartitioning) {
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltinTablePartitioning());
|
||||
}
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.readBuiltin());
|
||||
generateExtraDdlFor(migrationDir, dbPlatform, ExtraDdlXmlReader.read());
|
||||
}
|
||||
}
|
||||
|
||||
private void generateExtraDdlFor(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -331,7 +348,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
*/
|
||||
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 +359,16 @@ 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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,6 +429,10 @@ public class DefaultDbMigration implements DbMigration {
|
||||
this.current = currentModel.read();
|
||||
}
|
||||
|
||||
boolean isTablePartitioning() {
|
||||
return current.isTablePartitioning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the migration for the pending drops for a given version.
|
||||
*/
|
||||
@@ -511,7 +540,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
File subPath = platformWriter.subPath(writePath, pair.prefix);
|
||||
platformWriter.processMigration(dbMigration, platformBuffer, subPath, fullVersion);
|
||||
|
||||
generateExtraDdl(subPath, pair.platform);
|
||||
generateExtraDdl(subPath, pair.platform, currentModel.isTablePartitioning());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,11 +571,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) {
|
||||
|
||||
@@ -257,6 +257,8 @@ public class BaseTableDdl implements TableDdl {
|
||||
useSequence = (IdType.SEQUENCE == useDbIdentityType);
|
||||
}
|
||||
|
||||
String partitionMode = createTable.getPartitionMode();
|
||||
|
||||
DdlBuffer apply = writer.apply();
|
||||
apply.append("create table ").append(tableName).append(" (");
|
||||
writeTableColumns(apply, columns, useIdentity);
|
||||
@@ -265,7 +267,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
writeCompoundUniqueConstraints(apply, createTable);
|
||||
if (!pk.isEmpty()) {
|
||||
// defined on the columns
|
||||
writePrimaryKeyConstraint(apply, createTable.getPkName(), toColumnNames(pk));
|
||||
if (partitionMode == null || !platformDdl.suppressPrimaryKeyOnPartition()) {
|
||||
writePrimaryKeyConstraint(apply, createTable.getPkName(), toColumnNames(pk));
|
||||
}
|
||||
}
|
||||
if (platformDdl.isInlineForeignKeys()) {
|
||||
writeInlineForeignKeys(writer, createTable);
|
||||
@@ -273,6 +277,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
apply.newLine().append(")");
|
||||
addTableCommentInline(apply, createTable);
|
||||
if (partitionMode != null) {
|
||||
platformDdl.addTablePartition(apply, partitionMode, createTable.getPartitionColumn());
|
||||
}
|
||||
apply.endOfStatement();
|
||||
|
||||
addComments(apply, createTable);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -659,4 +662,12 @@ public class PlatformDdl {
|
||||
public void unlockTables(DdlBuffer buffer, Collection<String> tables) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public boolean suppressPrimaryKeyOnPartition() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addTablePartition(DdlBuffer apply, String partitionMode, String partitionColumn) throws IOException {
|
||||
// only supported by postgres initially
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Postgres specific DDL.
|
||||
@@ -16,6 +19,11 @@ public class PostgresDdl extends PlatformDdl {
|
||||
this.columnSetNull = "drop not null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suppressPrimaryKeyOnPartition() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String convertArrayType(String logicalArrayType) {
|
||||
return NativeDbArray.logicalToNative(logicalArrayType);
|
||||
@@ -38,4 +46,9 @@ public class PostgresDdl extends PlatformDdl {
|
||||
}
|
||||
return columnDefn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTablePartition(DdlBuffer apply, String partitionMode, String partitionColumn) throws IOException {
|
||||
apply.append(" partition by range (").append(partitionColumn).append(")");
|
||||
}
|
||||
}
|
||||
|
||||
+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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
@@ -45,20 +45,20 @@ public class AddColumn {
|
||||
|
||||
/**
|
||||
* Gets the value of the column property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the column property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getColumn().add(newItem);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link Column }
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,11 +9,21 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* TODO
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <attribute name="constraintName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="tableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="columnNames" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="oneToOne" type="{http://www.w3.org/2001/XMLSchema}boolean" />
|
||||
* <attribute name="nullableColumns" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@@ -23,18 +33,14 @@ public class AddUniqueConstraint {
|
||||
|
||||
@XmlAttribute(name = "constraintName", required = true)
|
||||
protected String constraintName;
|
||||
|
||||
@XmlAttribute(name = "tableName", required = true)
|
||||
protected String tableName;
|
||||
|
||||
@XmlAttribute(name = "columnNames", required = true)
|
||||
protected String columnNames;
|
||||
|
||||
@XmlAttribute(name = "nullableColumns", required = true)
|
||||
protected String nullableColumns;
|
||||
|
||||
@XmlAttribute(name = "oneToOne", required = false)
|
||||
@XmlAttribute(name = "oneToOne")
|
||||
protected Boolean oneToOne;
|
||||
@XmlAttribute(name = "nullableColumns")
|
||||
protected String nullableColumns;
|
||||
|
||||
/**
|
||||
* Gets the value of the constraintName property.
|
||||
@@ -55,7 +61,7 @@ public class AddUniqueConstraint {
|
||||
public void setConstraintName(String value) {
|
||||
this.constraintName = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the tableName property.
|
||||
*
|
||||
@@ -65,15 +71,15 @@ public class AddUniqueConstraint {
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of the tableName property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
public void setTableName(String value) {
|
||||
this.tableName = value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,6 +102,26 @@ public class AddUniqueConstraint {
|
||||
this.columnNames = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the oneToOne property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link Boolean }
|
||||
*/
|
||||
public Boolean isOneToOne() {
|
||||
return oneToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the oneToOne property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link Boolean }
|
||||
*/
|
||||
public void setOneToOne(Boolean value) {
|
||||
this.oneToOne = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the nullableColumns property.
|
||||
*
|
||||
@@ -115,23 +141,5 @@ public class AddUniqueConstraint {
|
||||
public void setNullableColumns(String value) {
|
||||
this.nullableColumns = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the oneToOne property.
|
||||
*
|
||||
* @return true if oneToOne was set
|
||||
*/
|
||||
public boolean isOneToOne() {
|
||||
return Boolean.TRUE.equals(oneToOne);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the oneToOne property.
|
||||
*
|
||||
* @param value boolean
|
||||
*/
|
||||
public void setOneToOne(boolean oneToOne) {
|
||||
this.oneToOne = oneToOne;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.ebeaninternal.dbmigration.migration;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import java.util.ArrayList;
|
||||
@@ -12,13 +11,17 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="before" type="{http://ebean-orm.github.io/xml/ns/dbmigration}ddl-script" maxOccurs="unbounded" minOccurs="0"/>
|
||||
* <element name="after" type="{http://ebean-orm.github.io/xml/ns/dbmigration}ddl-script" maxOccurs="unbounded" minOccurs="0"/>
|
||||
* </sequence>
|
||||
* <attribute name="columnName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="tableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="withHistory" type="{http://www.w3.org/2001/XMLSchema}boolean" />
|
||||
@@ -50,16 +53,14 @@ import java.util.List;
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"before", "after"
|
||||
"before",
|
||||
"after"
|
||||
})
|
||||
@XmlRootElement(name = "alterColumn")
|
||||
public class AlterColumn {
|
||||
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> before;
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> after;
|
||||
|
||||
@XmlAttribute(name = "columnName", required = true)
|
||||
protected String columnName;
|
||||
@XmlAttribute(name = "tableName", required = true)
|
||||
@@ -109,6 +110,60 @@ public class AlterColumn {
|
||||
@XmlAttribute(name = "dropForeignKeyIndex")
|
||||
protected String dropForeignKeyIndex;
|
||||
|
||||
/**
|
||||
* Gets the value of the before property.
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the before property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getBefore().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link DdlScript }
|
||||
*/
|
||||
public List<DdlScript> getBefore() {
|
||||
if (before == null) {
|
||||
before = new ArrayList<>();
|
||||
}
|
||||
return this.before;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the after property.
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the after property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getAfter().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link DdlScript }
|
||||
*/
|
||||
public List<DdlScript> getAfter() {
|
||||
if (after == null) {
|
||||
after = new ArrayList<>();
|
||||
}
|
||||
return this.after;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the columnName property.
|
||||
*
|
||||
@@ -589,17 +644,4 @@ public class AlterColumn {
|
||||
this.dropForeignKeyIndex = value;
|
||||
}
|
||||
|
||||
public List<DdlScript> getBefore() {
|
||||
if (before == null) {
|
||||
before = new ArrayList<>();
|
||||
}
|
||||
return before;
|
||||
}
|
||||
|
||||
public List<DdlScript> getAfter() {
|
||||
if (after == null) {
|
||||
after = new ArrayList<>();
|
||||
}
|
||||
return after;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,21 +9,34 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* TODO
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="columnNames" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="refColumnNames" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="refTableName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="indexName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="tableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="onDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="onUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "")
|
||||
@XmlRootElement(name = "foreignKey")
|
||||
@XmlRootElement(name = "alterForeignKey")
|
||||
public class AlterForeignKey {
|
||||
|
||||
@XmlAttribute(name = "name", required = true)
|
||||
protected String name;
|
||||
@XmlAttribute(name = "columnNames", required = true)
|
||||
@XmlAttribute(name = "columnNames")
|
||||
protected String columnNames;
|
||||
@XmlAttribute(name = "refColumnNames")
|
||||
protected String refColumnNames;
|
||||
@@ -37,6 +50,7 @@ public class AlterForeignKey {
|
||||
protected String onDelete;
|
||||
@XmlAttribute(name = "onUpdate")
|
||||
protected String onUpdate;
|
||||
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
@@ -196,4 +210,5 @@ public class AlterForeignKey {
|
||||
public void setOnUpdate(String value) {
|
||||
this.onUpdate = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <simpleContent>
|
||||
|
||||
@@ -13,9 +13,9 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
@@ -50,16 +50,16 @@ public class ChangeSet {
|
||||
@XmlElement(name = "dropTable", type = DropTable.class),
|
||||
@XmlElement(name = "renameTable", type = RenameTable.class),
|
||||
@XmlElement(name = "addTableComment", type = AddTableComment.class),
|
||||
@XmlElement(name = "addUniqueConstraint", type = AddUniqueConstraint.class),
|
||||
@XmlElement(name = "addHistoryTable", type = AddHistoryTable.class),
|
||||
@XmlElement(name = "dropHistoryTable", type = DropHistoryTable.class),
|
||||
@XmlElement(name = "alterForeignKey", type = AlterForeignKey.class),
|
||||
@XmlElement(name = "addColumn", type = AddColumn.class),
|
||||
@XmlElement(name = "dropColumn", type = DropColumn.class),
|
||||
@XmlElement(name = "alterColumn", type = AlterColumn.class),
|
||||
@XmlElement(name = "renameColumn", type = RenameColumn.class),
|
||||
@XmlElement(name = "createIndex", type = CreateIndex.class),
|
||||
@XmlElement(name = "dropIndex", type = DropIndex.class),
|
||||
@XmlElement(name = "addUniqueConstraint", type = AddUniqueConstraint.class),
|
||||
@XmlElement(name = "alterForeignKey", type = AlterForeignKey.class),
|
||||
@XmlElement(name = "dropIndex", type = DropIndex.class)
|
||||
})
|
||||
protected List<Object> changeSetChildren;
|
||||
@XmlAttribute(name = "type", required = true)
|
||||
@@ -77,20 +77,20 @@ public class ChangeSet {
|
||||
|
||||
/**
|
||||
* Gets the value of the changeSetChildren property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the changeSetChildren property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getChangeSetChildren().add(newItem);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link Configuration }
|
||||
@@ -99,8 +99,10 @@ public class ChangeSet {
|
||||
* {@link DropTable }
|
||||
* {@link RenameTable }
|
||||
* {@link AddTableComment }
|
||||
* {@link AddUniqueConstraint }
|
||||
* {@link AddHistoryTable }
|
||||
* {@link DropHistoryTable }
|
||||
* {@link AlterForeignKey }
|
||||
* {@link AddColumn }
|
||||
* {@link DropColumn }
|
||||
* {@link AlterColumn }
|
||||
|
||||
@@ -7,7 +7,7 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for changeSetType.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
* <pre>
|
||||
@@ -16,6 +16,7 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* <enumeration value="apply"/>
|
||||
* <enumeration value="pendingDrops"/>
|
||||
* <enumeration value="baseline"/>
|
||||
* <enumeration value="drop"/>
|
||||
* </restriction>
|
||||
* </simpleType>
|
||||
* </pre>
|
||||
@@ -29,7 +30,9 @@ public enum ChangeSetType {
|
||||
@XmlEnumValue("pendingDrops")
|
||||
PENDING_DROPS("pendingDrops"),
|
||||
@XmlEnumValue("baseline")
|
||||
BASELINE("baseline");
|
||||
BASELINE("baseline"),
|
||||
@XmlEnumValue("drop")
|
||||
DROP("drop");
|
||||
private final String value;
|
||||
|
||||
ChangeSetType(String v) {
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.ebeaninternal.dbmigration.migration;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import java.util.ArrayList;
|
||||
@@ -12,13 +11,17 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="before" type="{http://ebean-orm.github.io/xml/ns/dbmigration}ddl-script" maxOccurs="unbounded" minOccurs="0"/>
|
||||
* <element name="after" type="{http://ebean-orm.github.io/xml/ns/dbmigration}ddl-script" maxOccurs="unbounded" minOccurs="0"/>
|
||||
* </sequence>
|
||||
* <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="defaultValue" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
@@ -43,16 +46,14 @@ import java.util.List;
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"before", "after"
|
||||
"before",
|
||||
"after"
|
||||
})
|
||||
@XmlRootElement(name = "column")
|
||||
public class Column {
|
||||
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> before;
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> after;
|
||||
|
||||
@XmlAttribute(name = "name", required = true)
|
||||
protected String name;
|
||||
@XmlAttribute(name = "type", required = true)
|
||||
@@ -88,19 +89,58 @@ public class Column {
|
||||
@XmlAttribute(name = "comment")
|
||||
protected String comment;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the before property.
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the before property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getBefore().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link DdlScript }
|
||||
*/
|
||||
public List<DdlScript> getBefore() {
|
||||
if (before == null) {
|
||||
before = new ArrayList<>();
|
||||
}
|
||||
return before;
|
||||
return this.before;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the after property.
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the after property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getAfter().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link DdlScript }
|
||||
*/
|
||||
public List<DdlScript> getAfter() {
|
||||
if (after == null) {
|
||||
after = new ArrayList<>();
|
||||
}
|
||||
return after;
|
||||
return this.after;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,7 +424,7 @@ public class Column {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignOnDelete property.
|
||||
* Gets the value of the foreignKeyOnDelete property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
@@ -404,7 +444,7 @@ public class Column {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignOnUpdate property.
|
||||
* Gets the value of the foreignKeyOnUpdate property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -14,9 +14,9 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
@@ -28,6 +28,8 @@ import java.util.List;
|
||||
* </sequence>
|
||||
* <attGroup ref="{http://ebean-orm.github.io/xml/ns/dbmigration}tablespaceAttributes"/>
|
||||
* <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="partitionMode" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="partitionColumn" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="withHistory" type="{http://www.w3.org/2001/XMLSchema}boolean" />
|
||||
* <attribute name="draft" type="{http://www.w3.org/2001/XMLSchema}boolean" />
|
||||
* <attribute name="identityType" type="{http://ebean-orm.github.io/xml/ns/dbmigration}identityType" />
|
||||
@@ -55,6 +57,10 @@ public class CreateTable {
|
||||
protected List<ForeignKey> foreignKey;
|
||||
@XmlAttribute(name = "name", required = true)
|
||||
protected String name;
|
||||
@XmlAttribute(name = "partitionMode")
|
||||
protected String partitionMode;
|
||||
@XmlAttribute(name = "partitionColumn")
|
||||
protected String partitionColumn;
|
||||
@XmlAttribute(name = "withHistory")
|
||||
protected Boolean withHistory;
|
||||
@XmlAttribute(name = "draft")
|
||||
@@ -80,20 +86,20 @@ public class CreateTable {
|
||||
|
||||
/**
|
||||
* Gets the value of the column property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the column property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getColumn().add(newItem);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link Column }
|
||||
@@ -107,20 +113,20 @@ public class CreateTable {
|
||||
|
||||
/**
|
||||
* Gets the value of the uniqueConstraint property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the uniqueConstraint property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getUniqueConstraint().add(newItem);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link UniqueConstraint }
|
||||
@@ -134,20 +140,20 @@ public class CreateTable {
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignKey property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the foreignKey property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getForeignKey().add(newItem);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link ForeignKey }
|
||||
@@ -179,6 +185,46 @@ public class CreateTable {
|
||||
this.name = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the partitionMode property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getPartitionMode() {
|
||||
return partitionMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the partitionMode property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setPartitionMode(String value) {
|
||||
this.partitionMode = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the partitionColumn property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getPartitionColumn() {
|
||||
return partitionColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the partitionColumn property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setPartitionColumn(String value) {
|
||||
this.partitionColumn = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the withHistory property.
|
||||
*
|
||||
|
||||
@@ -1,42 +1,61 @@
|
||||
package io.ebeaninternal.dbmigration.migration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
* <p>Java class for ddl-script complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* TODO @Rob: Can this generated automatically?
|
||||
* <complexType name="ddl-script">
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="ddl" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
|
||||
* </sequence>
|
||||
* <attribute name="platforms" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
@XmlType(name = "ddl-script", propOrder = {
|
||||
"ddl"
|
||||
})
|
||||
@XmlRootElement(name = "ddl-script")
|
||||
public class DdlScript {
|
||||
|
||||
@XmlValue
|
||||
@XmlElement(required = true)
|
||||
protected List<String> ddl;
|
||||
|
||||
@XmlAttribute(name = "platforms")
|
||||
protected String platforms;
|
||||
|
||||
/**
|
||||
* Gets the value of the value property.
|
||||
* Gets the value of the ddl property.
|
||||
*
|
||||
* @return possible object is
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the ddl property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getDdl().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link String }
|
||||
*/
|
||||
public List<String> getDdl() {
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,14 +9,16 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="sequenceCol" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="sequenceName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
@@ -64,16 +66,6 @@ public class DropTable {
|
||||
return sequenceCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the sequenceName property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getSequenceName() {
|
||||
return sequenceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the sequenceCol property.
|
||||
*
|
||||
@@ -84,6 +76,16 @@ public class DropTable {
|
||||
this.sequenceCol = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the sequenceName property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getSequenceName() {
|
||||
return sequenceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the sequenceName property.
|
||||
*
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
@@ -47,6 +47,7 @@ public class ForeignKey {
|
||||
protected String onDelete;
|
||||
@XmlAttribute(name = "onUpdate")
|
||||
protected String onUpdate;
|
||||
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
|
||||
@@ -7,7 +7,7 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for identityType.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
* <pre>
|
||||
|
||||
@@ -11,9 +11,9 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
@@ -38,20 +38,20 @@ public class Migration {
|
||||
|
||||
/**
|
||||
* Gets the value of the changeSet property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* This accessor method returns a reference to the live list,
|
||||
* not a snapshot. Therefore any modification you make to the
|
||||
* returned list will be present inside the JAXB object.
|
||||
* This is why there is not a <CODE>set</CODE> method for the changeSet property.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getChangeSet().add(newItem);
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link ChangeSet }
|
||||
|
||||
@@ -6,7 +6,7 @@ import javax.xml.bind.annotation.XmlRegistry;
|
||||
/**
|
||||
* This object contains factory methods for each
|
||||
* Java content interface and Java element interface
|
||||
* generated in the io.ebean.dbmigration.migration package.
|
||||
* generated in the io.ebeaninternal.dbmigration.migration package.
|
||||
* <p>An ObjectFactory allows you to programatically
|
||||
* construct new instances of the Java representation
|
||||
* for XML content. The Java representation of XML
|
||||
@@ -21,23 +21,23 @@ public class ObjectFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: io.ebean.dbmigration.migration
|
||||
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: io.ebeaninternal.dbmigration.migration
|
||||
*/
|
||||
public ObjectFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Rollback }
|
||||
* Create an instance of {@link AddUniqueConstraint }
|
||||
*/
|
||||
public Rollback createRollback() {
|
||||
return new Rollback();
|
||||
public AddUniqueConstraint createAddUniqueConstraint() {
|
||||
return new AddUniqueConstraint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddColumn }
|
||||
* Create an instance of {@link CreateTable }
|
||||
*/
|
||||
public AddColumn createAddColumn() {
|
||||
return new AddColumn();
|
||||
public CreateTable createCreateTable() {
|
||||
return new CreateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,10 +48,10 @@ public class ObjectFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link CreateTable }
|
||||
* Create an instance of {@link DdlScript }
|
||||
*/
|
||||
public CreateTable createCreateTable() {
|
||||
return new CreateTable();
|
||||
public DdlScript createDdlScript() {
|
||||
return new DdlScript();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,13 +68,6 @@ public class ObjectFactory {
|
||||
return new ForeignKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Apply }
|
||||
*/
|
||||
public Apply createApply() {
|
||||
return new Apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Configuration }
|
||||
*/
|
||||
@@ -89,13 +82,6 @@ public class ObjectFactory {
|
||||
return new DefaultTablespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddTableComment }
|
||||
*/
|
||||
public AddTableComment createAddTableComment() {
|
||||
return new AddTableComment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link RenameTable }
|
||||
*/
|
||||
@@ -111,10 +97,10 @@ public class ObjectFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AlterColumn }
|
||||
* Create an instance of {@link AlterForeignKey }
|
||||
*/
|
||||
public AlterColumn createAlterColumn() {
|
||||
return new AlterColumn();
|
||||
public AlterForeignKey createAlterForeignKey() {
|
||||
return new AlterForeignKey();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,6 +110,69 @@ public class ObjectFactory {
|
||||
return new DropColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Sql }
|
||||
*/
|
||||
public Sql createSql() {
|
||||
return new Sql();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Apply }
|
||||
*/
|
||||
public Apply createApply() {
|
||||
return new Apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Rollback }
|
||||
*/
|
||||
public Rollback createRollback() {
|
||||
return new Rollback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link DropIndex }
|
||||
*/
|
||||
public DropIndex createDropIndex() {
|
||||
return new DropIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link RenameColumn }
|
||||
*/
|
||||
public RenameColumn createRenameColumn() {
|
||||
return new RenameColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link DropTable }
|
||||
*/
|
||||
public DropTable createDropTable() {
|
||||
return new DropTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddColumn }
|
||||
*/
|
||||
public AddColumn createAddColumn() {
|
||||
return new AddColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddTableComment }
|
||||
*/
|
||||
public AddTableComment createAddTableComment() {
|
||||
return new AddTableComment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AlterColumn }
|
||||
*/
|
||||
public AlterColumn createAlterColumn() {
|
||||
return new AlterColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link CreateIndex }
|
||||
*/
|
||||
@@ -138,20 +187,6 @@ public class ObjectFactory {
|
||||
return new ChangeSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Sql }
|
||||
*/
|
||||
public Sql createSql() {
|
||||
return new Sql();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link DropTable }
|
||||
*/
|
||||
public DropTable createDropTable() {
|
||||
return new DropTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddHistoryTable }
|
||||
*/
|
||||
@@ -159,20 +194,6 @@ public class ObjectFactory {
|
||||
return new AddHistoryTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link RenameColumn }
|
||||
*/
|
||||
public RenameColumn createRenameColumn() {
|
||||
return new RenameColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link DropIndex }
|
||||
*/
|
||||
public DropIndex createDropIndex() {
|
||||
return new DropIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AlterHistoryTable }
|
||||
*/
|
||||
@@ -187,24 +208,4 @@ public class ObjectFactory {
|
||||
return new Migration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link DdlScript }
|
||||
*/
|
||||
public DdlScript createDdlScript() {
|
||||
return new DdlScript();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddUniqueConstraint }
|
||||
*/
|
||||
public AddUniqueConstraint createAddUniqueConstraint() {
|
||||
return new AddUniqueConstraint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link AddUniqueConstraint }
|
||||
*/
|
||||
public AlterForeignKey createAlterForeignKey() {
|
||||
return new AlterForeignKey();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlValue;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <simpleContent>
|
||||
|
||||
@@ -9,9 +9,9 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
|
||||
@@ -9,15 +9,17 @@ import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="columnNames" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="oneToOne" type="{http://www.w3.org/2001/XMLSchema}boolean" />
|
||||
* <attribute name="nullableColumns" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
@@ -30,16 +32,13 @@ public class UniqueConstraint {
|
||||
|
||||
@XmlAttribute(name = "name", required = true)
|
||||
protected String name;
|
||||
|
||||
@XmlAttribute(name = "columnNames", required = true)
|
||||
protected String columnNames;
|
||||
|
||||
@XmlAttribute(name = "oneToOne", required = false)
|
||||
@XmlAttribute(name = "oneToOne")
|
||||
protected Boolean oneToOne;
|
||||
|
||||
@XmlAttribute(name = "nullableColumns", required = true)
|
||||
@XmlAttribute(name = "nullableColumns")
|
||||
protected String nullableColumns;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
@@ -79,23 +78,25 @@ public class UniqueConstraint {
|
||||
public void setColumnNames(String value) {
|
||||
this.columnNames = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the oneToOne property.
|
||||
*
|
||||
* @return true if oneToOne was set
|
||||
* @return possible object is
|
||||
* {@link Boolean }
|
||||
*/
|
||||
public boolean isOneToOne() {
|
||||
return Boolean.TRUE.equals(oneToOne);
|
||||
public Boolean isOneToOne() {
|
||||
return oneToOne;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of the oneToOne property.
|
||||
*
|
||||
* @param value boolean
|
||||
* @param value allowed object is
|
||||
* {@link Boolean }
|
||||
*/
|
||||
public void setOneToOne(boolean oneToOne) {
|
||||
this.oneToOne = oneToOne;
|
||||
public void setOneToOne(Boolean value) {
|
||||
this.oneToOne = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
@@ -56,6 +60,20 @@ public class CurrentModel {
|
||||
this.platformTypes = platformTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the model contains tables that are partitioned.
|
||||
*/
|
||||
public boolean isTablePartitioning() {
|
||||
return model.isTablePartitioning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tables that have partitioning.
|
||||
*/
|
||||
public List<MTable> getPartitionedTables() {
|
||||
return model.getPartitionedTables();
|
||||
}
|
||||
|
||||
private static DbConstraintNaming.MaxLength maxLength(SpiEbeanServer server, DbConstraintNaming naming) {
|
||||
|
||||
if (naming.getMaxLength() != null) {
|
||||
@@ -111,6 +129,9 @@ public class CurrentModel {
|
||||
if (header != null && !header.isEmpty()) {
|
||||
ddl.append(header).append('\n');
|
||||
}
|
||||
|
||||
addExtraDdl(ddl, ExtraDdlXmlReader.readBuiltin(), "-- init script ");
|
||||
|
||||
ddl.append(write.apply().getBuffer());
|
||||
ddl.append(write.applyForeignKeys().getBuffer());
|
||||
ddl.append(write.applyHistoryView().getBuffer());
|
||||
@@ -119,6 +140,18 @@ public class CurrentModel {
|
||||
return ddl.toString();
|
||||
}
|
||||
|
||||
private void addExtraDdl(StringBuilder ddl, ExtraDdl extraDdl, String prefix) {
|
||||
if (extraDdl != null) {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (script.isInit() && ExtraDdlXmlReader.matchPlatform(server.getDatabasePlatform().getName(), script.getPlatforms())) {
|
||||
ddl.append(prefix + script.getName()).append('\n');
|
||||
ddl.append(script.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'Drop' DDL.
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package io.ebeaninternal.dbmigration.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp;
|
||||
import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint;
|
||||
import io.ebeaninternal.dbmigration.migration.UniqueConstraint;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A unique constraint for multiple columns.
|
||||
* <p>
|
||||
@@ -26,13 +27,13 @@ public class MCompoundUniqueConstraint {
|
||||
* The columns combined to be unique.
|
||||
*/
|
||||
private final String[] columns;
|
||||
|
||||
|
||||
private String[] nullableColumns;
|
||||
|
||||
public MCompoundUniqueConstraint(String[] columns, boolean oneToOne, String name) {
|
||||
public MCompoundUniqueConstraint(String[] columns, Boolean oneToOne, String name) {
|
||||
this.name = name;
|
||||
this.columns = columns;
|
||||
this.oneToOne = oneToOne;
|
||||
this.oneToOne = Boolean.TRUE.equals(oneToOne);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +56,7 @@ public class MCompoundUniqueConstraint {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public UniqueConstraint getUniqueConstraint() {
|
||||
UniqueConstraint uq = new UniqueConstraint();
|
||||
uq.setName(getName());
|
||||
@@ -63,6 +65,7 @@ public class MCompoundUniqueConstraint {
|
||||
uq.setOneToOne(isOneToOne());
|
||||
return uq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a AddUniqueConstraint migration for this constraint.
|
||||
*/
|
||||
@@ -87,7 +90,7 @@ public class MCompoundUniqueConstraint {
|
||||
dropUniqueConstraint.setNullableColumns(join(nullableColumns));
|
||||
return dropUniqueConstraint;
|
||||
}
|
||||
|
||||
|
||||
public void setNullableColumns(String[] nullableColumns) {
|
||||
if (nullableColumns != null && nullableColumns.length == 0) {
|
||||
this.nullableColumns = null;
|
||||
@@ -109,12 +112,12 @@ public class MCompoundUniqueConstraint {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(columns) + 31 * Objects.hash(name, oneToOne);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
@@ -125,8 +128,8 @@ public class MCompoundUniqueConstraint {
|
||||
}
|
||||
MCompoundUniqueConstraint other = (MCompoundUniqueConstraint) obj;
|
||||
return Arrays.equals(columns, other.columns)
|
||||
&& Arrays.equals(nullableColumns, other.nullableColumns)
|
||||
&& Objects.equals(name, other.name)
|
||||
&& oneToOne == other.oneToOne;
|
||||
&& Arrays.equals(nullableColumns, other.nullableColumns)
|
||||
&& Objects.equals(name, other.name)
|
||||
&& oneToOne == other.oneToOne;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.dbmigration.model;
|
||||
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.SplitColumns;
|
||||
import io.ebeaninternal.dbmigration.migration.AddColumn;
|
||||
@@ -14,6 +15,7 @@ import io.ebeaninternal.dbmigration.migration.DropTable;
|
||||
import io.ebeaninternal.dbmigration.migration.ForeignKey;
|
||||
import io.ebeaninternal.dbmigration.migration.IdentityType;
|
||||
import io.ebeaninternal.dbmigration.migration.UniqueConstraint;
|
||||
import io.ebeaninternal.server.deploy.PartitionMeta;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -61,6 +63,8 @@ public class MTable {
|
||||
*/
|
||||
private boolean draft;
|
||||
|
||||
private PartitionMeta partitionMeta;
|
||||
|
||||
/**
|
||||
* Primary key name.
|
||||
*/
|
||||
@@ -237,6 +241,10 @@ public class MTable {
|
||||
createTable.setName(name);
|
||||
createTable.setPkName(pkName);
|
||||
createTable.setComment(comment);
|
||||
if (partitionMeta != null) {
|
||||
createTable.setPartitionMode(partitionMeta.getMode().name());
|
||||
createTable.setPartitionColumn(partitionMeta.getProperty());
|
||||
}
|
||||
createTable.setTablespace(tablespace);
|
||||
createTable.setIndexTablespace(indexTablespace);
|
||||
createTable.setSequenceName(sequenceName);
|
||||
@@ -419,6 +427,20 @@ public class MTable {
|
||||
return draft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this table is partitioned.
|
||||
*/
|
||||
public boolean isPartitioned() {
|
||||
return partitionMeta != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the partition meta for this table.
|
||||
*/
|
||||
public PartitionMeta getPartitionMeta() {
|
||||
return partitionMeta;
|
||||
}
|
||||
|
||||
public void setPkName(String pkName) {
|
||||
this.pkName = pkName;
|
||||
}
|
||||
@@ -531,6 +553,17 @@ public class MTable {
|
||||
return pk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary key column if it is a simple primary key.
|
||||
*/
|
||||
public String singlePrimaryKey() {
|
||||
List<MColumn> columns = primaryKeyColumns();
|
||||
if (columns.size() == 1) {
|
||||
return columns.get(0).getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkTableName(String tableName) {
|
||||
if (!name.equals(tableName)) {
|
||||
throw new IllegalArgumentException("addColumn tableName [" + tableName + "] does not match [" + name + "]");
|
||||
@@ -745,4 +778,8 @@ public class MTable {
|
||||
compoundKey.setIndexName(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPartitionMeta(PartitionMeta partitionMeta) {
|
||||
this.partitionMeta = partitionMeta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import io.ebeaninternal.dbmigration.migration.DropTable;
|
||||
import io.ebeaninternal.dbmigration.migration.Migration;
|
||||
import io.ebeaninternal.dbmigration.migration.Sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -43,9 +44,25 @@ public class ModelContainer {
|
||||
|
||||
private final PendingDrops pendingDrops = new PendingDrops();
|
||||
|
||||
private final List<MTable> partitionedTables = new ArrayList<>();
|
||||
|
||||
public ModelContainer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the model contains tables that are partitioned.
|
||||
*/
|
||||
public boolean isTablePartitioning() {
|
||||
return !partitionedTables.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of partitioned tables.
|
||||
*/
|
||||
public List<MTable> getPartitionedTables() {
|
||||
return partitionedTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the FK references on all the draft tables.
|
||||
*/
|
||||
@@ -167,13 +184,12 @@ public class ModelContainer {
|
||||
/**
|
||||
* Unset the withHistory flag on the associated base table.
|
||||
*/
|
||||
private void applyChange(DropHistoryTable change) {
|
||||
protected void applyChange(DropHistoryTable change) {
|
||||
|
||||
MTable table = tables.get(change.getBaseTable());
|
||||
if (table == null) {
|
||||
throw new IllegalStateException("Table [" + change.getBaseTable() + "] does not exist in model?");
|
||||
if (table != null) {
|
||||
table.setWithHistory(false);
|
||||
}
|
||||
table.setWithHistory(false);
|
||||
}
|
||||
|
||||
private void applyChange(AddUniqueConstraint change) {
|
||||
@@ -224,19 +240,14 @@ public class ModelContainer {
|
||||
if (tables.containsKey(tableName)) {
|
||||
throw new IllegalStateException("Table [" + tableName + "] already exists in model?");
|
||||
}
|
||||
MTable table = new MTable(createTable);
|
||||
tables.put(tableName, table);
|
||||
tables.put(tableName, new MTable(createTable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a DropTable change to the model.
|
||||
*/
|
||||
protected void applyChange(DropTable dropTable) {
|
||||
String tableName = dropTable.getName();
|
||||
if (!tables.containsKey(tableName)) {
|
||||
throw new IllegalStateException("Table [" + tableName + "] does not exists in model?");
|
||||
}
|
||||
tables.remove(tableName);
|
||||
tables.remove(dropTable.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,22 +258,16 @@ public class ModelContainer {
|
||||
if (indexes.containsKey(indexName)) {
|
||||
throw new IllegalStateException("Index [" + indexName + "] already exists in model?");
|
||||
}
|
||||
MIndex index = new MIndex(createIndex);
|
||||
indexes.put(createIndex.getIndexName(), index);
|
||||
indexes.put(createIndex.getIndexName(), new MIndex(createIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a DropTable change to the model.
|
||||
*/
|
||||
protected void applyChange(DropIndex dropIndex) {
|
||||
String name = dropIndex.getIndexName();
|
||||
if (!indexes.containsKey(name)) {
|
||||
throw new IllegalStateException("Index [" + name + "] does not exist in model?");
|
||||
}
|
||||
indexes.remove(name);
|
||||
indexes.remove(dropIndex.getIndexName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply a AddColumn change to the model.
|
||||
*/
|
||||
@@ -300,6 +305,9 @@ public class ModelContainer {
|
||||
* Add a table (typically from reading EbeanServer meta data).
|
||||
*/
|
||||
public MTable addTable(MTable table) {
|
||||
if (table.isPartitioned()) {
|
||||
partitionedTables.add(table);
|
||||
}
|
||||
return tables.put(table.getName(), table);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
|
||||
}
|
||||
|
||||
MTable table = new MTable(descriptor.getBaseTable());
|
||||
table.setPartitionMeta(descriptor.getPartitionMeta());
|
||||
table.setComment(descriptor.getDbComment());
|
||||
if (descriptor.isHistorySupport()) {
|
||||
table.setWithHistory(true);
|
||||
|
||||
+4
-3
@@ -192,7 +192,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
col.setDbMigrationInfos(p.getDbMigrationInfos());
|
||||
col.setDefaultValue(p.getDbColumnDefault());
|
||||
if (columns.length == 1) {
|
||||
if (p.hasForeignKey()) {
|
||||
if (p.hasForeignKey() && !importedProperty.getBeanDescriptor().suppressForeignKey()) {
|
||||
// single references column (put it on the column)
|
||||
String refTable = importedProperty.getBeanDescriptor().getBaseTable();
|
||||
if (refTable == null) {
|
||||
@@ -251,19 +251,20 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
col.setIdentity(true);
|
||||
}
|
||||
TableJoin primaryKeyJoin = p.getBeanDescriptor().getPrimaryKeyJoin();
|
||||
if (primaryKeyJoin != null) {
|
||||
if (primaryKeyJoin != null && !table.isPartitioned()) {
|
||||
TableJoinColumn[] columns = primaryKeyJoin.columns();
|
||||
col.setReferences(primaryKeyJoin.getTable() + "." + columns[0].getForeignDbColumn());
|
||||
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
|
||||
}
|
||||
} 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());
|
||||
|
||||
@@ -133,8 +133,7 @@ public class VisitAllUsing {
|
||||
InheritInfo inheritInfo = descriptor.getInheritInfo();
|
||||
if (inheritInfo != null && inheritInfo.isRoot()) {
|
||||
// add all properties on the children objects
|
||||
InheritChildVisitor childVisitor = new InheritChildVisitor(this, pv);
|
||||
inheritInfo.visitChildren(childVisitor);
|
||||
inheritInfo.visitChildren(new InheritChildVisitor(this, pv));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +154,10 @@ public class VisitAllUsing {
|
||||
|
||||
@Override
|
||||
public void visit(InheritInfo inheritInfo) {
|
||||
BeanProperty[] propertiesLocal = inheritInfo.desc().propertiesLocal();
|
||||
for (BeanProperty aPropertiesLocal : propertiesLocal) {
|
||||
owner.visit(pv, aPropertiesLocal);
|
||||
for (BeanProperty beanProperty : inheritInfo.desc().propertiesLocal()) {
|
||||
if (beanProperty.isDDLColumn()) {
|
||||
owner.visit(pv, beanProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,22 @@ public class ExtraDdlXmlReader {
|
||||
public static String buildExtra(String platformName, boolean drops) {
|
||||
|
||||
ExtraDdl read = ExtraDdlXmlReader.read("/extra-ddl.xml");
|
||||
return buildExtra(platformName, drops, read);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return any extra DDL for supporting partitioning given the database platform.
|
||||
*/
|
||||
public static String buildPartitioning(String platformName) {
|
||||
return buildExtra(platformName, false, readBuiltinTablePartitioning());
|
||||
}
|
||||
|
||||
private static String buildExtra(String platformName, boolean drops, ExtraDdl read) {
|
||||
|
||||
if (read == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(300);
|
||||
for (DdlScript script : read.getDdlScript()) {
|
||||
if (script.isDrop() == drops && matchPlatform(platformName, script.getPlatforms())) {
|
||||
@@ -83,10 +96,31 @@ 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 builtin extra ddl to support table partitioning.
|
||||
*/
|
||||
public static ExtraDdl readBuiltinTablePartitioning() {
|
||||
return read("/io/ebeaninternal/dbmigration/builtin-extra-ddl-partitioning.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) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import io.ebeanservice.docstore.api.DocStoreUpdate;
|
||||
import io.ebeanservice.docstore.api.DocStoreUpdateContext;
|
||||
import io.ebeanservice.docstore.api.DocStoreUpdates;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.IOException;
|
||||
@@ -356,7 +357,15 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
private boolean flushBatchOnGetter(int propertyIndex) {
|
||||
// propertyIndex of -1 the Id property, no flush for get Id on UPDATE
|
||||
return propertyIndex == -1 ? type == Type.INSERT : beanDescriptor.isGeneratedProperty(propertyIndex);
|
||||
if (propertyIndex == -1) {
|
||||
if (beanDescriptor.isIdLoaded(intercept)) {
|
||||
return false;
|
||||
} else {
|
||||
return type == Type.INSERT;
|
||||
}
|
||||
} else {
|
||||
return beanDescriptor.isGeneratedProperty(propertyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSkipBatchForTopLevel() {
|
||||
@@ -846,12 +855,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
@Override
|
||||
public final void checkRowCount(int rowCount) {
|
||||
if (ConcurrencyMode.VERSION == concurrencyMode && rowCount != 1) {
|
||||
// fix for oracle.
|
||||
// see: https://stackoverflow.com/questions/19022175/executebatch-method-return-array-of-value-2-in-java
|
||||
if (rowCount != Statement.SUCCESS_NO_INFO) {
|
||||
String m = Message.msg("persist.conc2", String.valueOf(rowCount));
|
||||
throw new OptimisticLockException(m, null, bean);
|
||||
if (rowCount != 1 && rowCount != Statement.SUCCESS_NO_INFO) {
|
||||
if (ConcurrencyMode.VERSION == concurrencyMode) {
|
||||
throw new OptimisticLockException(Message.msg("persist.conc2", String.valueOf(rowCount)), null, bean);
|
||||
} else if (rowCount == 0 && type == Type.UPDATE) {
|
||||
throw new EntityNotFoundException("No rows updated");
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
@@ -1194,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);
|
||||
}
|
||||
|
||||
@@ -1299,14 +1307,22 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Set the request flags indicating this is an insert.
|
||||
*/
|
||||
public void flagInsert() {
|
||||
flags = Flags.setInsert(flags);
|
||||
if (intercept.isNew()) {
|
||||
flags = Flags.setInsertNormal(flags);
|
||||
} else {
|
||||
flags = Flags.setInsert(flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the request insert flag indicating this is an update.
|
||||
*/
|
||||
public void flagUpdate() {
|
||||
flags = Flags.unsetInsert(flags);
|
||||
if (intercept.isLoaded()) {
|
||||
flags = Flags.setUpdateNormal(flags);
|
||||
} else {
|
||||
flags = Flags.setUpdate(flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,8 +7,14 @@ import io.ebeaninternal.server.query.SqlJoinType;
|
||||
*/
|
||||
class AssocOneHelpRefExported extends AssocOneHelp {
|
||||
|
||||
public AssocOneHelpRefExported(BeanPropertyAssocOne<?> property) {
|
||||
private final boolean softDelete;
|
||||
|
||||
private final String softDeletePredicate;
|
||||
|
||||
AssocOneHelpRefExported(BeanPropertyAssocOne<?> property) {
|
||||
super(property);
|
||||
this.softDelete = property.targetDescriptor.isSoftDelete();
|
||||
this.softDeletePredicate = (softDelete) ? property.targetDescriptor.getSoftDeletePredicate("") : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,6 +34,10 @@ class AssocOneHelpRefExported extends AssocOneHelp {
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
String relativePrefix = ctx.getRelativePrefix(property.getName());
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
if (softDelete && !ctx.isIncludeSoftDelete()) {
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx, softDeletePredicate);
|
||||
} else {
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -204,6 +205,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
private final String draftTable;
|
||||
|
||||
private final PartitionMeta partitionMeta;
|
||||
|
||||
/**
|
||||
* DB table comment.
|
||||
*/
|
||||
@@ -482,6 +485,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.baseTableVersionsBetween = deploy.getBaseTableVersionsBetween();
|
||||
this.dependentTables = deploy.getDependentTables();
|
||||
this.dbComment = deploy.getDbComment();
|
||||
this.partitionMeta = deploy.getPartitionMeta();
|
||||
this.autoTunable = EntityType.ORM == entityType && (beanFinder == null);
|
||||
|
||||
// helper object used to derive lists of properties
|
||||
@@ -2816,6 +2820,20 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
return dbComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if foreign keys to the base table should be suppressed.
|
||||
*/
|
||||
public boolean suppressForeignKey() {
|
||||
return partitionMeta != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the partition details of the bean.
|
||||
*/
|
||||
public PartitionMeta getPartitionMeta() {
|
||||
return partitionMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dependent tables for a view based entity.
|
||||
* <p>
|
||||
@@ -3161,6 +3179,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
return ebi.hasIdOnly(idPropertyIndex);
|
||||
}
|
||||
|
||||
public boolean isIdLoaded(EntityBeanIntercept ebi) {
|
||||
return ebi.isLoadedProperty(idPropertyIndex);
|
||||
}
|
||||
|
||||
public boolean hasIdValue(EntityBean bean) {
|
||||
return (idProperty != null && !DmlUtil.isNullOrZero(idProperty.getValue(bean)));
|
||||
}
|
||||
|
||||
@@ -739,6 +739,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
if (invalidateQueryCache) {
|
||||
changeSet.addInvalidate(desc);
|
||||
} else {
|
||||
queryCacheClear(changeSet);
|
||||
if (beanCache != null) {
|
||||
changeSet.addBeanRemoveMany(desc, ids);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -12,8 +12,6 @@ public interface DbSqlContext {
|
||||
*/
|
||||
void addJoin(String type, String table, TableJoinColumn[] cols, String a1, String a2, String inheritance);
|
||||
|
||||
void pushSecondaryTableAlias(String alias);
|
||||
|
||||
/**
|
||||
* Push the current table alias onto the stack.
|
||||
*/
|
||||
@@ -91,11 +89,6 @@ public interface DbSqlContext {
|
||||
*/
|
||||
String getContent();
|
||||
|
||||
/**
|
||||
* Return the current join node.
|
||||
*/
|
||||
String peekJoin();
|
||||
|
||||
/**
|
||||
* Push a join node onto the stack.
|
||||
*/
|
||||
@@ -125,6 +118,11 @@ public interface DbSqlContext {
|
||||
*/
|
||||
void appendHistorySysPeriod();
|
||||
|
||||
/**
|
||||
* Return true if the query includes soft deleted rows.
|
||||
*/
|
||||
boolean isIncludeSoftDelete();
|
||||
|
||||
/**
|
||||
* Return true if the query is a 'asDraft' query.
|
||||
*/
|
||||
@@ -139,4 +137,5 @@ public interface DbSqlContext {
|
||||
* Append 'for update' lock hints on FROM clause (sql server only).
|
||||
*/
|
||||
void appendFromForUpdate();
|
||||
|
||||
}
|
||||
|
||||
@@ -187,6 +187,6 @@ public abstract class DeployParser {
|
||||
}
|
||||
|
||||
private boolean isWordStart(char ch) {
|
||||
return Character.isLetter(ch);
|
||||
return Character.isLetter(ch) || ch == UNDERSCORE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
|
||||
public class PartitionMeta {
|
||||
|
||||
private final PartitionMode mode;
|
||||
|
||||
private String property;
|
||||
|
||||
public PartitionMeta(PartitionMode mode, String property) {
|
||||
this.mode = mode;
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public PartitionMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String dbColumn) {
|
||||
this.property = dbColumn;
|
||||
}
|
||||
}
|
||||
@@ -126,6 +126,16 @@ public final class TableJoin {
|
||||
return type;
|
||||
}
|
||||
|
||||
public SqlJoinType addJoin(SqlJoinType joinType, String prefix, DbSqlContext ctx, String predicate) {
|
||||
String[] names = SplitName.split(prefix);
|
||||
String a1 = ctx.getTableAlias(names[0]);
|
||||
String a2 = ctx.getTableAlias(prefix);
|
||||
|
||||
SqlJoinType returnJoinType = addJoin(joinType, a1, a2, ctx);
|
||||
ctx.append("and ").append(a2).append(predicate);
|
||||
return returnJoinType;
|
||||
}
|
||||
|
||||
public SqlJoinType addJoin(SqlJoinType joinType, String prefix, DbSqlContext ctx) {
|
||||
|
||||
String[] names = SplitName.split(prefix);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy.meta;
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.DocStore;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.TableName;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
@@ -27,6 +28,7 @@ import io.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
|
||||
import io.ebeaninternal.server.deploy.DeployPropertyParserMap;
|
||||
import io.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.deploy.PartitionMeta;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
|
||||
@@ -193,6 +195,8 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private String dbComment;
|
||||
|
||||
private PartitionMeta partitionMeta;
|
||||
|
||||
/**
|
||||
* One of NONE, INDEX or EMBEDDED.
|
||||
*/
|
||||
@@ -305,6 +309,20 @@ public class DeployBeanDescriptor<T> {
|
||||
return dbComment;
|
||||
}
|
||||
|
||||
public void setPartitionMeta(PartitionMeta partitionMeta) {
|
||||
this.partitionMeta = partitionMeta;
|
||||
}
|
||||
|
||||
public PartitionMeta getPartitionMeta() {
|
||||
if (partitionMeta != null) {
|
||||
DeployBeanProperty beanProperty = getBeanProperty(partitionMeta.getProperty());
|
||||
if (beanProperty != null) {
|
||||
partitionMeta.setProperty(beanProperty.getDbColumn());
|
||||
}
|
||||
}
|
||||
return partitionMeta;
|
||||
}
|
||||
|
||||
public void setDraftable() {
|
||||
draftable = true;
|
||||
}
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.DbComment;
|
||||
import io.ebean.annotation.DbPartition;
|
||||
import io.ebean.annotation.DocStore;
|
||||
import io.ebean.annotation.Draftable;
|
||||
import io.ebean.annotation.DraftableElement;
|
||||
@@ -16,6 +17,7 @@ import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import io.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.deploy.PartitionMeta;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -152,6 +154,11 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
DbPartition partition = AnnotationUtil.findAnnotationRecursive(cls, DbPartition.class);
|
||||
if (partition != null) {
|
||||
descriptor.setPartitionMeta(new PartitionMeta(partition.mode(), partition.property()));
|
||||
}
|
||||
|
||||
Draftable draftable = AnnotationUtil.findAnnotationRecursive(cls, Draftable.class);
|
||||
if (draftable != null) {
|
||||
descriptor.setDraftable();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -456,8 +456,7 @@ public final class DefaultPersister implements Persister {
|
||||
void saveRecurse(EntityBean bean, Transaction t, Object parentBean, int flags) {
|
||||
|
||||
// determine insert or update taking into account stateless updates
|
||||
PersistRequestBean<?> request = createRequestRecurse(bean, t, parentBean, flags);
|
||||
saveRecurse(request);
|
||||
saveRecurse(createRequestRecurse(bean, t, parentBean, flags));
|
||||
}
|
||||
|
||||
private void saveRecurse(PersistRequestBean<?> request) {
|
||||
@@ -1229,8 +1228,8 @@ public final class DefaultPersister implements Persister {
|
||||
BeanDescriptor<T> desc = mgr.getBeanDescriptor();
|
||||
EntityBean entityBean = (EntityBean) bean;
|
||||
PersistRequest.Type type;
|
||||
if (Flags.isPublishOrMerge(flags)) {
|
||||
// insert if it is a new bean (as publish created it)
|
||||
if (Flags.isPublishMergeOrNormal(flags)) {
|
||||
// just use bean state to determine insert or update
|
||||
type = entityBean._ebean_getIntercept().isUpdate() ? Type.UPDATE : Type.INSERT;
|
||||
} else {
|
||||
// determine Insert or Update based on bean state and insert flag
|
||||
|
||||
@@ -5,7 +5,7 @@ package io.ebeaninternal.server.persist;
|
||||
* <p>
|
||||
* Allows passing of flag state when recursively persisting.
|
||||
*/
|
||||
public class Flags {
|
||||
public final class Flags {
|
||||
|
||||
/**
|
||||
* Indicates the bean is being inserted.
|
||||
@@ -27,6 +27,11 @@ public class Flags {
|
||||
*/
|
||||
public static final int MERGE = 0x00000008;
|
||||
|
||||
/**
|
||||
* Indicates Normal insert or update (not forced).
|
||||
*/
|
||||
public static final int NORMAL = 0x00000010;
|
||||
|
||||
/**
|
||||
* No flags set.
|
||||
*/
|
||||
@@ -34,7 +39,9 @@ public class Flags {
|
||||
|
||||
public static final int PUBLISH_RECURSE = PUBLISH + RECURSE;
|
||||
|
||||
private static final int PUBLISH_MERGE = PUBLISH + MERGE;
|
||||
private static final int PUBLISH_MERGE_NORMAL = PUBLISH + MERGE + NORMAL;
|
||||
|
||||
private static final int INSERT_NORMAL = INSERT + NORMAL;
|
||||
|
||||
/**
|
||||
* Return true if the bean is being inserted.
|
||||
@@ -65,10 +72,10 @@ public class Flags {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if part of a Merge or Publish.
|
||||
* Return true if part of a Merge or Publish or Normal (bean state matches persist).
|
||||
*/
|
||||
public static boolean isPublishOrMerge(long state) {
|
||||
return (state & PUBLISH_MERGE) != 0;
|
||||
public static boolean isPublishMergeOrNormal(int state) {
|
||||
return (state & PUBLISH_MERGE_NORMAL) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,54 +89,70 @@ public class Flags {
|
||||
* Set Insert flag.
|
||||
*/
|
||||
public static int setInsert(int state) {
|
||||
return set(state, INSERT, true);
|
||||
return set(state, INSERT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert flag and normal in that bean is in NEW state (for insert).
|
||||
*/
|
||||
public static int setInsertNormal(int state) {
|
||||
return set(state, INSERT_NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent was not inserted.
|
||||
*/
|
||||
public static int unsetInsert(int state) {
|
||||
return set(state, INSERT, false);
|
||||
public static int setUpdate(int state) {
|
||||
return unset(state, INSERT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Insert and normal in that bean is in LOADED state (for update).
|
||||
*/
|
||||
public static int setUpdateNormal(int state) {
|
||||
state &= ~INSERT;
|
||||
state |= NORMAL;
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Recurse flag.
|
||||
*/
|
||||
public static int setRecurse(int state) {
|
||||
return set(state, RECURSE, true);
|
||||
return set(state, RECURSE);
|
||||
}
|
||||
|
||||
public static int unsetRecuse(int state) {
|
||||
return set(state, RECURSE, false);
|
||||
return unset(state, RECURSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Publish flag.
|
||||
*/
|
||||
public static int setPublish(int state) {
|
||||
return set(state, PUBLISH, true);
|
||||
return set(state, PUBLISH);
|
||||
}
|
||||
|
||||
public static int unsetPublish(int state) {
|
||||
return set(state, PUBLISH, false);
|
||||
return unset(state, PUBLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Merge flag.
|
||||
*/
|
||||
public static int setMerge(int state) {
|
||||
return set(state, MERGE, true);
|
||||
return set(state, MERGE);
|
||||
}
|
||||
|
||||
public static int unsetMerge(int state) {
|
||||
return set(state, MERGE, false);
|
||||
return unset(state, MERGE);
|
||||
}
|
||||
|
||||
private static int set(int state, int flag, boolean setFlag) {
|
||||
if (setFlag) {
|
||||
return (state |= flag);
|
||||
} else {
|
||||
return state &= ~flag;
|
||||
}
|
||||
private static int set(int state, int flag) {
|
||||
return (state |= flag);
|
||||
}
|
||||
|
||||
private static int unset(int state, int flag) {
|
||||
return state &= ~flag;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,6 @@ import io.ebeaninternal.server.lib.util.Str;
|
||||
import io.ebeaninternal.server.persist.BatchedPstmt;
|
||||
import io.ebeaninternal.server.persist.BatchedPstmtHolder;
|
||||
import io.ebeaninternal.server.persist.dmlbind.BindableRequest;
|
||||
import io.ebeaninternal.server.transaction.TransactionManager;
|
||||
import io.ebeaninternal.server.type.DataBind;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -50,11 +49,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 +225,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:
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.OrderBy;
|
||||
import io.ebean.OrderBy.Property;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
@@ -18,27 +17,22 @@ class CQueryOrderBy {
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final SpiQuery<?> query;
|
||||
private final OrderBy<?> orderBy;
|
||||
|
||||
/**
|
||||
* Create the logical order by clause.
|
||||
*/
|
||||
public static String parse(BeanDescriptor<?> desc, SpiQuery<?> query) {
|
||||
return new CQueryOrderBy(desc, query).parseInternal();
|
||||
public static String parse(BeanDescriptor<?> desc, OrderBy<?> orderBy) {
|
||||
return new CQueryOrderBy(desc, orderBy).parseInternal();
|
||||
}
|
||||
|
||||
private CQueryOrderBy(BeanDescriptor<?> desc, SpiQuery<?> query) {
|
||||
private CQueryOrderBy(BeanDescriptor<?> desc, OrderBy<?> orderBy) {
|
||||
this.desc = desc;
|
||||
this.query = query;
|
||||
this.orderBy = orderBy;
|
||||
}
|
||||
|
||||
private String parseInternal() {
|
||||
|
||||
OrderBy<?> orderBy = query.getOrderBy();
|
||||
if (orderBy == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
List<Property> properties = orderBy.getProperties();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.OrderBy;
|
||||
import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.SpiExpressionList;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
@@ -329,7 +330,11 @@ public class CQueryPredicates {
|
||||
|
||||
private String parseOrderBy() {
|
||||
|
||||
return CQueryOrderBy.parse(request.getBeanDescriptor(), query);
|
||||
OrderBy<?> orderBy = query.getOrderBy();
|
||||
if (orderBy == null) {
|
||||
return null;
|
||||
}
|
||||
return CQueryOrderBy.parse(request.getBeanDescriptor(), orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,11 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
this.fromForUpdate = fromForUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeSoftDelete() {
|
||||
return alias.isIncludeSoftDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendFromForUpdate() {
|
||||
if (fromForUpdate != null) {
|
||||
@@ -99,11 +104,6 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
return encryptedProps.toArray(new BeanProperty[encryptedProps.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String peekJoin() {
|
||||
return joinStack.peek();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popJoin() {
|
||||
joinStack.pop();
|
||||
@@ -206,11 +206,6 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
return alias.getTableAliasManyWhere(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushSecondaryTableAlias(String alias) {
|
||||
tableAliasStack.push(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePrefix(String propName) {
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -17,6 +18,8 @@ class SqlTreeAlias {
|
||||
|
||||
private static final Pattern TABLE_ALIAS_REPLACE = Pattern.compile("${}", Pattern.LITERAL);
|
||||
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
|
||||
private int counter;
|
||||
|
||||
private int manyWhereCounter;
|
||||
@@ -33,8 +36,9 @@ class SqlTreeAlias {
|
||||
|
||||
private final String rootTableAlias;
|
||||
|
||||
SqlTreeAlias(String rootTableAlias) {
|
||||
SqlTreeAlias(String rootTableAlias, SpiQuery.TemporalMode temporalMode) {
|
||||
this.rootTableAlias = rootTableAlias;
|
||||
this.temporalMode = temporalMode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,4 +215,8 @@ class SqlTreeAlias {
|
||||
boolean isIncludeJoins() {
|
||||
return !aliasMap.isEmpty() || !manyWhereAliasMap.isEmpty();
|
||||
}
|
||||
|
||||
boolean isIncludeSoftDelete() {
|
||||
return temporalMode == SpiQuery.TemporalMode.SOFT_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public final class SqlTreeBuilder {
|
||||
this.queryDetail = query.getDetail();
|
||||
|
||||
this.predicates = predicates;
|
||||
this.alias = new SqlTreeAlias(request.getBaseTableAlias());
|
||||
this.alias = new SqlTreeAlias(request.getBaseTableAlias(), temporalMode);
|
||||
this.distinctOnPlatform = builder.isPlatformDistinctOn();
|
||||
|
||||
String fromForUpdate = builder.fromForUpdate(query);
|
||||
@@ -412,7 +412,13 @@ public final class SqlTreeBuilder {
|
||||
if (!selectProps.containsProperty(baseName)) {
|
||||
STreeProperty p = desc.findPropertyWithDynamic(baseName);
|
||||
if (p == null) {
|
||||
logger.error("property [" + propName + "] not found on " + desc + " for query - excluding it.");
|
||||
// maybe dynamic formula with schema prefix
|
||||
p = desc.findPropertyWithDynamic(propName);
|
||||
if (p != null) {
|
||||
selectProps.add(p);
|
||||
} else {
|
||||
logger.error("property [" + propName + "] not found on " + desc + " for query - excluding it.");
|
||||
}
|
||||
|
||||
} else if (p.isEmbedded()) {
|
||||
// add the embedded bean (and effectively
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -301,7 +301,7 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
}
|
||||
|
||||
// default to rollback if not defined on the platform
|
||||
return dbPlatformOnQueryOnly == null ? OnQueryOnly.ROLLBACK : dbPlatformOnQueryOnly;
|
||||
return dbPlatformOnQueryOnly == null ? OnQueryOnly.COMMIT : dbPlatformOnQueryOnly;
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
|
||||
@@ -112,14 +112,14 @@ interface ArrayElementConverter<T> {
|
||||
|
||||
@Override
|
||||
public Object toElement(Object rawValue) {
|
||||
return scalarType.parse(rawValue.toString());
|
||||
return scalarType.toBeanType(rawValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toDbArray(Object[] objects) {
|
||||
Object[] dbArray = new Object[objects.length];
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
dbArray[i] = scalarType.format(objects[i]);
|
||||
dbArray[i] = scalarType.toJdbcType(objects[i]);
|
||||
}
|
||||
return dbArray;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user