MySql update - Internal changes for DB Migration / DDL generation #369

This commit is contained in:
Robin Bygrave
2015-08-06 11:15:31 +12:00
parent e83a6f05bc
commit 13ed298ee8
19 changed files with 205 additions and 345 deletions
@@ -129,6 +129,8 @@ public class DbIdentity {
switch (identityType) {
case GENERATOR:
return IdType.GENERATOR;
case EXTERNAL:
return IdType.EXTERNAL;
case SEQUENCE:
return supportsSequence ? IdType.SEQUENCE : idType;
case IDENTITY:
@@ -9,6 +9,10 @@ import java.util.Map;
*/
public class DbTypeMap {
private static final DbType JSON_CLOB_PLACEHOLDER = new DbType("jsonClobPlaceholder");
private static final DbType JSON_BLOB_PLACEHOLDER = new DbType("jsonBlobPlaceholder");
private static final DbType JSON_VARCHAR_PLACEHOLDER = new DbType("jsonVarcharPlaceholder");
/**
* A map to reverse lookup the type by name.
* <p>
@@ -106,11 +110,11 @@ public class DbTypeMap {
put(DbType.JSONVarchar, new DbType("jsonvarchar", 1000));
} else {
put(DbType.JSON, new DbType("clob")); // Postgres maps this to JSON
put(DbType.JSONB, new DbType("clob")); // Postgres maps this to JSONB
put(DbType.JSONClob, new DbType("clob"));
put(DbType.JSONBlob, new DbType("blob"));
put(DbType.JSONVarchar, new DbType("varchar", 1000));
put(DbType.JSON, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSON
put(DbType.JSONB, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSONB
put(DbType.JSONClob, JSON_CLOB_PLACEHOLDER);
put(DbType.JSONBlob, JSON_BLOB_PLACEHOLDER);
put(DbType.JSONVarchar, JSON_VARCHAR_PLACEHOLDER);
}
put(Types.LONGVARBINARY, new DbType("longvarbinary"));
@@ -141,11 +145,30 @@ public class DbTypeMap {
return get(Types.CLOB);
case DbType.JSONVarchar:
return get(Types.VARCHAR);
case DbType.JSON:
return getJsonType(DbType.JSON);
case DbType.JSONB:
return getJsonType(DbType.JSONB);
default:
return get(typeKey);
}
}
private DbType getJsonType(int type) {
DbType dbType = get(type);
if (dbType == JSON_CLOB_PLACEHOLDER) {
return get(Types.CLOB);
}
if (dbType == JSON_BLOB_PLACEHOLDER) {
return get(Types.BLOB);
}
if (dbType == JSON_VARCHAR_PLACEHOLDER) {
return get(Types.VARCHAR);
}
// Postgres has specific type
return get(type);
}
/**
* Override the type for a given JDBC type.
*/
@@ -26,6 +26,15 @@ public enum IdType {
* id properties of type UUID.
* </p>
*/
GENERATOR
GENERATOR,
/**
* Expected that the identity is externally set (for example a ISO code for
* country or currency or a user defined code for lookup tables).
* <p>
* Used when the key is a compound key or lookup table code.
* </p>
*/
EXTERNAL
}
@@ -1,6 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.MySqlDdl;
import javax.sql.DataSource;
import java.sql.Types;
@@ -24,6 +25,7 @@ public class MySqlPlatform extends DatabasePlatform {
this.likeClause = "like ? escape''";
this.selectCountWithAlias = true;
this.dbEncrypt = new MySqlDbEncrypt();
this.platformDdl = new MySqlDdl(this.dbTypeMap, this.dbIdentity);
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
@@ -222,7 +222,8 @@ public class BaseTableDdl implements TableDdl {
}
write.rollbackForeignKeys()
.append("alter table ").append(tableName).append(" drop constraint ").append(fkName)
.append("alter table ").append(tableName).append(" ")
.append(platformDdl.dropForeignKeyConstraint(fkName))
.endOfStatement();
write.rollbackForeignKeys().end();
@@ -0,0 +1,20 @@
package com.avaje.ebean.dbmigration.ddlgeneration.platform;
import com.avaje.ebean.config.dbplatform.DbIdentity;
import com.avaje.ebean.config.dbplatform.DbTypeMap;
/**
* MySql specific DDL.
*/
public class MySqlDdl extends PlatformDdl {
public MySqlDdl(DbTypeMap platformTypes, DbIdentity dbIdentity) {
super(platformTypes, dbIdentity);
}
@Override
public String dropForeignKeyConstraint(String fkName) {
return "drop foreign key "+fkName;
}
}
@@ -70,6 +70,10 @@ public class PlatformDdl {
return foreignKeyRestrict;
}
public String dropForeignKeyConstraint(String fkName) {
return "drop constraint "+fkName;
}
/**
* Convert the standard type to the platform specific type.
*/
@@ -16,6 +16,7 @@ import javax.xml.bind.annotation.XmlType;
* &lt;enumeration value="IDENTITY"/>
* &lt;enumeration value="SEQUENCE"/>
* &lt;enumeration value="GENERATOR"/>
* &lt;enumeration value="EXTERNAL"/>
* &lt;enumeration value="DEFAULT"/>
* &lt;/restriction>
* &lt;/simpleType>
@@ -29,6 +30,7 @@ public enum IdentityType {
IDENTITY,
SEQUENCE,
GENERATOR,
EXTERNAL,
DEFAULT;
public String value() {
@@ -1,333 +0,0 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://ebean-orm.github.io/xml/ns/dbmigration"
targetNamespace="http://ebean-orm.github.io/xml/ns/dbmigration" elementFormDefault="qualified">
<!-- =========================================================== -->
<!-- APPLICATIONS -->
<!-- =========================================================== -->
<!-- Root level type : applications -->
<xsd:element name="applications">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="application" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="application">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="resourcePath" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- =========================================================== -->
<!-- CHANGE LOG -->
<!-- =========================================================== -->
<!-- Root level type : migration -->
<xsd:element name="migration">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="changeSet" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="changeSet">
<xsd:complexType>
<xsd:sequence>
<xsd:choice>
<xsd:group ref="changeSetChildren" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:positiveInteger" use="required"/>
<xsd:attribute name="comment" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<!-- =========================================================== -->
<!-- CHANGE SET CHILDREN -->
<!-- =========================================================== -->
<xsd:element name="sql">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="apply" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="rollback" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="apply">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="rollback">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<!-- CONFIGURATION -->
<xsd:element name="configuration">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="defaultTablespace"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="defaultTablespace">
<xsd:complexType>
<xsd:attribute name="tables" type="xsd:string"/>
<xsd:attribute name="indexes" type="xsd:string"/>
<xsd:attribute name="history" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<!-- TABLE -->
<xsd:element name="createTable">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="column" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element ref="uniqueConstraint" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="foreignKey" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="withHistory" type="xsd:boolean"/>
<xsd:attribute name="identityType" type="identityType"/>
<xsd:attribute name="sequenceName" type="xsd:string"/>
<xsd:attribute name="sequenceInitial" type="xsd:positiveInteger"/>
<xsd:attribute name="sequenceAllocate" type="xsd:positiveInteger"/>
<xsd:attributeGroup ref="tablespaceAttributes"/>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="identityType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="IDENTITY"/>
<xsd:enumeration value="SEQUENCE"/>
<xsd:enumeration value="GENERATOR"/>
<xsd:enumeration value="DEFAULT"/>
</xsd:restriction>
</xsd:simpleType>
<!-- Only expected to be used for compound unique constraint -->
<xsd:element name="uniqueConstraint">
<xsd:complexType>
<xsd:attribute name="columnNames" type="xsd:string" use="required"/>
<xsd:attribute name="constraintName" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<!-- Only expected to be used for compound foreign keys -->
<xsd:element name="foreignKey">
<xsd:complexType>
<xsd:attribute name="columnNames" type="xsd:string" use="required"/>
<xsd:attribute name="refColumnNames" type="xsd:string" use="required"/>
<xsd:attribute name="refTableName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="dropTable">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="renameTable">
<xsd:complexType>
<xsd:attribute name="oldName" type="xsd:string" use="required"/>
<xsd:attribute name="newName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- HISTORY -->
<xsd:element name="createHistoryTable">
<xsd:complexType>
<xsd:attribute name="baseTable" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="dropHistoryTable">
<xsd:complexType>
<xsd:attribute name="baseTable" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- COLUMN -->
<xsd:element name="addColumn">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="column" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="tableName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="dropColumn">
<xsd:complexType>
<xsd:attribute name="columnName" type="xsd:string" use="required"/>
<xsd:attribute name="tableName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="renameColumn">
<xsd:complexType>
<xsd:attribute name="oldName" type="xsd:string" use="required"/>
<xsd:attribute name="newName" type="xsd:string" use="required"/>
<xsd:attribute name="tableName" type="xsd:string" use="required"/>
<xsd:attribute name="dataType" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<!-- VIEW -->
<xsd:element name="createView">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="replaceIfExists" type="xsd:boolean"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="dropView">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="renameView">
<xsd:complexType>
<xsd:attribute name="oldName" type="xsd:string" use="required"/>
<xsd:attribute name="newName" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- FOREIGN KEY -->
<xsd:element name="addForeignKey">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="columns" type="xsd:string" use="required"/>
<xsd:attribute name="references" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="dropForeignKey">
<xsd:complexType mixed="true">
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- ============================================ -->
<xsd:element name="column">
<xsd:complexType mixed="true">
<xsd:attributeGroup ref="column"/>
<xsd:attributeGroup ref="columnAttributes"/>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="tablespaceAttributes">
<xsd:attribute name="tablespace" type="xsd:string"/>
<xsd:attribute name="indexTablespace" type="xsd:string"/>
<xsd:attribute name="remarks" type="xsd:string"/>
</xsd:attributeGroup>
<xsd:attributeGroup name="columnAttributes">
<xsd:attribute name="notnull" type="xsd:boolean"/>
<xsd:attribute name="checkConstraint" type="xsd:string"/>
<xsd:attribute name="unique" type="xsd:boolean"/>
<xsd:attribute name="primaryKey" type="xsd:boolean"/>
<xsd:attribute name="identity" type="xsd:boolean"/> <!-- aka autoincrement/identity -->
<xsd:attribute name="references" type="xsd:string"/>
<!--<xsd:attribute name="primaryKeyTablespace" type="xsd:string"/>-->
<!--<xsd:attribute name="deleteCascade" type="xsd:boolean"/>-->
<!--<xsd:attribute name="deferrable" type="xsd:boolean"/>-->
<!--<xsd:attribute name="initiallyDeferred" type="xsd:boolean"/>-->
</xsd:attributeGroup>
<xsd:attributeGroup name="column">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="type" type="xsd:string" use="required"/>
<xsd:attribute name="defaultValue" type="xsd:string"/>
<xsd:attribute name="remarks" type="xsd:string"/>
</xsd:attributeGroup>
<!-- Children for changeSet -->
<xsd:group name="changeSetChildren">
<xsd:choice>
<xsd:element ref="configuration" maxOccurs="1"/>
<xsd:element ref="sql" maxOccurs="unbounded"/>
<xsd:element ref="createTable" maxOccurs="unbounded"/>
<xsd:element ref="dropTable" maxOccurs="unbounded"/>
<xsd:element ref="renameTable" maxOccurs="unbounded"/>
<xsd:element ref="createHistoryTable" maxOccurs="unbounded"/>
<xsd:element ref="createView" maxOccurs="unbounded"/>
<xsd:element ref="dropView" maxOccurs="unbounded"/>
<xsd:element ref="renameView" maxOccurs="unbounded"/>
<xsd:element ref="addColumn" maxOccurs="unbounded"/>
<xsd:element ref="dropColumn" maxOccurs="unbounded"/>
<xsd:element ref="renameColumn" maxOccurs="unbounded"/>
<xsd:element ref="addForeignKey" maxOccurs="unbounded"/>
<xsd:element ref="dropForeignKey" maxOccurs="unbounded"/>
<!--<xsd:element ref="createIndex" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="dropIndex" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="createSequence" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="alterSequence" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="dropSequence" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="addNotNullConstraint" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="dropNotNullConstraint" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="addPrimaryKey" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="dropPrimaryKey" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="addUniqueConstraint" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="dropUniqueConstraint" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="addDefaultValue" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="dropDefaultValue" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="sql" maxOccurs="unbounded"/>-->
<!--<xsd:element ref="createProcedure" maxOccurs="unbounded"/>-->
</xsd:choice>
</xsd:group>
</xsd:schema>
@@ -74,6 +74,11 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
table.setIdentityType(IdentityType.GENERATOR);
return;
}
if (IdType.EXTERNAL == descriptor.getIdType()) {
// externally defined code (lookup table, ISO country code etc)
table.setIdentityType(IdentityType.EXTERNAL);
return;
}
int initialValue = descriptor.getSequenceInitialValue();
int allocationSize = descriptor.getSequenceAllocationSize();
@@ -1065,6 +1065,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
if (desc.isPrimaryKeyCompoundOrNonNumeric()) {
// assuming that this is a user supplied key like ISO country code or ISO currency code or lookup table code
logger.debug("Expecting user defined identity on " + desc.getFullName() + " - not using db sequence or autoincrement");
desc.setIdType(IdType.EXTERNAL);
return;
}
// use the default. IDENTITY or SEQUENCE.