From 009f91b9499c7c88e109461ec7fcfbf59d71c9e4 Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Tue, 4 Aug 2015 19:48:47 +1200 Subject: [PATCH] WIP Db Migration compound keys --- h2-migration.xml | 1694 +++++++++-------- .../ddlgeneration/platform/BaseTableDdl.java | 102 +- .../platform/DdlNamingConvention.java | 4 +- .../dbmigration/migration/AddColumn.java | 4 +- .../dbmigration/migration/Applications.java | 4 +- .../dbmigration/migration/ChangeSet.java | 8 +- .../ebean/dbmigration/migration/Column.java | 192 +- .../migration/CreateHistoryTable.java | 2 +- .../dbmigration/migration/CreateTable.java | 65 +- .../dbmigration/migration/Migration.java | 4 +- .../dbmigration/migration/ObjectFactory.java | 144 +- .../ebean/dbmigration/model/CurrentModel.java | 14 + .../ebean/dbmigration/model/MColumn.java | 12 +- .../model/MCompoundForeignKey.java | 27 + .../avaje/ebean/dbmigration/model/MTable.java | 20 + .../build/ModelBuildPropertyVisitor.java | 8 +- .../platform/DdlNamingConventionTest.java | 7 +- .../build/ModelBuild_compoundKeyTest.java | 43 +- .../resources/container/test-compoundkey.xml | 6 + 19 files changed, 1250 insertions(+), 1110 deletions(-) diff --git a/h2-migration.xml b/h2-migration.xml index c7c2b7139..0d29627a3 100644 --- a/h2-migration.xml +++ b/h2-migration.xml @@ -1,1273 +1,1277 @@ - + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - + - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - + + + + - + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - + + - + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - - - - - - - + + + + + + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - + - - + + - - - + + + diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java index d03923b76..fdbe744ee 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -5,6 +5,8 @@ import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; import com.avaje.ebean.dbmigration.ddlgeneration.TableDdl; import com.avaje.ebean.dbmigration.migration.Column; import com.avaje.ebean.dbmigration.migration.CreateTable; +import com.avaje.ebean.dbmigration.migration.ForeignKey; +import com.avaje.ebean.dbmigration.migration.PrimaryKey; import com.avaje.ebean.dbmigration.model.MTable; import java.io.IOException; @@ -50,7 +52,15 @@ public class BaseTableDdl implements TableDdl { writeUniqueConstraints(apply, createTable); writeCompoundUniqueConstraints(apply, createTable); if (!pk.isEmpty()) { - writePrimaryKeyConstraint(apply, tableName, pk); + // defined on the columns + writePrimaryKeyConstraint(apply, tableName, toColumnNames(pk)); + } else { + // defined on the table + if (createTable.getPrimaryKey() == null) { + System.out.print("asd"); + } else { + writePrimaryKeyConstraint(apply, tableName, createTable.getPrimaryKey()); + } } apply.newLine().append(")").endOfStatement(); @@ -75,14 +85,32 @@ public class BaseTableDdl implements TableDdl { protected void writeAddForeignKeys(DdlWrite write, CreateTable createTable) throws IOException { + String tableName = createTable.getName(); List columns = createTable.getColumn(); for (Column column : columns) { String references = column.getReferences(); if (hasValue(references)) { - writeForeignKey(write, createTable.getName(), column.getName(), references); + writeForeignKey(write, tableName, column.getName(), references); } } - //createTable. + + writeAddCompoundForeignKeys(write, createTable); + } + + protected void writeAddCompoundForeignKeys(DdlWrite write, CreateTable createTable) throws IOException { + + String tableName = createTable.getName(); + + List foreignKey = createTable.getForeignKey(); + for (ForeignKey key : foreignKey) { + + String refTableName = key.getRefTableName(); + String fkName = determineForeignKeyConstraintName(tableName, refTableName); + String[] cols = toColumnNamesSplit(key.getColumnNames()); + String[] refColumns = toColumnNamesSplit(key.getRefColumnNames()); + + writeForeignKey(write, fkName, tableName, cols, refTableName, refColumns); + } } @@ -109,10 +137,10 @@ public class BaseTableDdl implements TableDdl { fkeyBuffer .append("alter table ").append(tableName) .append(" add constraint ").append(fkName) - .append(" foreign key ("); + .append(" foreign key"); appendColumns(columns, fkeyBuffer); fkeyBuffer - .append(") references ") + .append(" references ") .append(refTable); appendColumns(refColumns, fkeyBuffer); fkeyBuffer.appendWithSpace(platformDdl.getForeignKeyRestrict()) @@ -144,7 +172,7 @@ public class BaseTableDdl implements TableDdl { if (i > 0) { buffer.append(","); } - buffer.append(columns[i]); + buffer.append(columns[i].trim()); } buffer.append(")"); } @@ -215,23 +243,23 @@ public class BaseTableDdl implements TableDdl { buffer.append(")"); } + protected void writePrimaryKeyConstraint(DdlBuffer buffer, String tableName, PrimaryKey pk) throws IOException { + + String columnNames = pk.getColumnNames(); + String[] cols = columnNames.split(","); + writePrimaryKeyConstraint(buffer, tableName, cols); + } + /** * Write the primary key constraint inline with the create table statement. */ - protected void writePrimaryKeyConstraint(DdlBuffer buffer, String tableName, List pk) throws IOException { + protected void writePrimaryKeyConstraint(DdlBuffer buffer, String tableName, String[] pkColumns) throws IOException { - String pkName = determinePrimaryKeyName(tableName, pk); + String pkName = determinePrimaryKeyName(tableName, pkColumns); buffer.append(",").newLine(); - buffer.append(" constraint ").append(pkName).append(" primary key "); - buffer.append("("); - for (int i = 0; i < pk.size(); i++) { - if (i > 0) { - buffer.append(","); - } - buffer.append(pk.get(i).getName()); - } - buffer.append(")"); + buffer.append(" constraint ").append(pkName).append(" primary key"); + appendColumns(pkColumns, buffer); } /** @@ -239,19 +267,34 @@ public class BaseTableDdl implements TableDdl { */ public void alterTableAddPrimaryKey(DdlBuffer buffer, String tableName, List pk) throws IOException { - String pkName = determinePrimaryKeyName(tableName, pk); + String[] pkColumns = toColumnNames(pk); + String pkName = determinePrimaryKeyName(tableName, pkColumns); buffer.append("alter table ").append(tableName); - buffer.append(" add primary key ").append(pkName).append(" ("); - for (int i = 0; i < pk.size(); i++) { - if (i > 0) { - buffer.append(","); - } - buffer.append(pk.get(i).getName()); - } + buffer.append(" add primary key ").append(pkName); + appendColumns(pkColumns, buffer); buffer.append(")").endOfStatement(); } + /** + * Return as an array of string column names. + */ + private String[] toColumnNames(List columns) { + + String[] cols = new String[columns.size()]; + for (int i = 0; i < cols.length; i++) { + cols[i] = columns.get(i).getName(); + } + return cols; + } + + /** + * Return as an array of string column names. + */ + private String[] toColumnNamesSplit(String columns) { + return columns.split(","); + } + /** * Write the column definition to the create table statement. */ @@ -283,14 +326,9 @@ public class BaseTableDdl implements TableDdl { /** * Return the primary key constraint name. */ - protected String determinePrimaryKeyName(String tableName, List pkColumns) { + protected String determinePrimaryKeyName(String tableName, String[] pkColumns) { - // collect the primary key column names - List pkColumnNames = new ArrayList(pkColumns.size()); - for (int i = 0; i < pkColumns.size(); i++) { - pkColumnNames.add(pkColumns.get(i).getName()); - } - return namingConvention.primaryKeyName(tableName, pkColumnNames); + return namingConvention.primaryKeyName(tableName, pkColumns); } /** diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConvention.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConvention.java index caecbb7aa..0827be799 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConvention.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConvention.java @@ -35,7 +35,7 @@ public class DdlNamingConvention { /** * Return the primary key constraint name. */ - public String primaryKeyName(String tableName, List pkColumns) { + public String primaryKeyName(String tableName, String[] pkColumns) { return pkPrefix + normalise(tableName) + pkSuffix; } @@ -62,7 +62,7 @@ public class DdlNamingConvention { StringBuilder sb = new StringBuilder(30); for (int i = 0; i < columns.length; i++) { if (i > 0) { - sb.append("-"); + sb.append("_"); } sb.append(columns[i]); } diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/AddColumn.java b/src/main/java/com/avaje/ebean/dbmigration/migration/AddColumn.java index 91d01e3cb..112f4cc0b 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/AddColumn.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/AddColumn.java @@ -1,14 +1,14 @@ package com.avaje.ebean.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.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import java.util.ArrayList; -import java.util.List; /** diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/Applications.java b/src/main/java/com/avaje/ebean/dbmigration/migration/Applications.java index 950b038dd..3c6b52774 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/Applications.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/Applications.java @@ -1,12 +1,12 @@ package com.avaje.ebean.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.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import java.util.ArrayList; -import java.util.List; /** diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/ChangeSet.java b/src/main/java/com/avaje/ebean/dbmigration/migration/ChangeSet.java index 502f7875f..586eb125e 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/ChangeSet.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/ChangeSet.java @@ -1,6 +1,9 @@ package com.avaje.ebean.dbmigration.migration; +import java.math.BigInteger; +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; @@ -9,9 +12,6 @@ import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; /** @@ -50,7 +50,7 @@ public class ChangeSet { @XmlElement(name = "createTable", type = CreateTable.class), @XmlElement(name = "dropTable", type = DropTable.class), @XmlElement(name = "renameTable", type = RenameTable.class), - @XmlElement(name = "addHistoryTable", type = CreateHistoryTable.class), + @XmlElement(name = "createHistoryTable", type = CreateHistoryTable.class), @XmlElement(name = "createView", type = CreateView.class), @XmlElement(name = "dropView", type = DropView.class), @XmlElement(name = "renameView", type = RenameView.class), diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/Column.java b/src/main/java/com/avaje/ebean/dbmigration/migration/Column.java index 5abc4568c..5bb5e7bf3 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/Column.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/Column.java @@ -18,8 +18,8 @@ import javax.xml.bind.annotation.XmlValue; * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> - * <attGroup ref="{http://ebean-orm.github.io/xml/ns/dbmigration}column"/> * <attGroup ref="{http://ebean-orm.github.io/xml/ns/dbmigration}columnAttributes"/> + * <attGroup ref="{http://ebean-orm.github.io/xml/ns/dbmigration}column"/> * </restriction> * </complexContent> * </complexType> @@ -36,14 +36,6 @@ public class Column { @XmlValue protected String content; - @XmlAttribute(name = "name", required = true) - protected String name; - @XmlAttribute(name = "type", required = true) - protected String type; - @XmlAttribute(name = "defaultValue") - protected String defaultValue; - @XmlAttribute(name = "remarks") - protected String remarks; @XmlAttribute(name = "notnull") protected Boolean notnull; @XmlAttribute(name = "checkConstraint") @@ -56,12 +48,14 @@ public class Column { protected Boolean identity; @XmlAttribute(name = "references") protected String references; - @XmlAttribute(name = "deleteCascade") - protected Boolean deleteCascade; - @XmlAttribute(name = "deferrable") - protected Boolean deferrable; - @XmlAttribute(name = "initiallyDeferred") - protected Boolean initiallyDeferred; + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "type", required = true) + protected String type; + @XmlAttribute(name = "defaultValue") + protected String defaultValue; + @XmlAttribute(name = "remarks") + protected String remarks; /** * Gets the value of the content property. @@ -87,102 +81,6 @@ public class Column { this.content = value; } - /** - * Gets the value of the name property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getName() { - return name; - } - - /** - * Sets the value of the name property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setName(String value) { - this.name = value; - } - - /** - * Gets the value of the type property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getType() { - return type; - } - - /** - * Sets the value of the type property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setType(String value) { - this.type = value; - } - - /** - * Gets the value of the defaultValue property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getDefaultValue() { - return defaultValue; - } - - /** - * Sets the value of the defaultValue property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setDefaultValue(String value) { - this.defaultValue = value; - } - - /** - * Gets the value of the remarks property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getRemarks() { - return remarks; - } - - /** - * Sets the value of the remarks property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setRemarks(String value) { - this.remarks = value; - } - /** * Gets the value of the notnull property. * @@ -328,75 +226,99 @@ public class Column { } /** - * Gets the value of the deleteCascade property. + * Gets the value of the name property. * * @return * possible object is - * {@link Boolean } + * {@link String } * */ - public Boolean isDeleteCascade() { - return deleteCascade; + public String getName() { + return name; } /** - * Sets the value of the deleteCascade property. + * Sets the value of the name property. * * @param value * allowed object is - * {@link Boolean } + * {@link String } * */ - public void setDeleteCascade(Boolean value) { - this.deleteCascade = value; + public void setName(String value) { + this.name = value; } /** - * Gets the value of the deferrable property. + * Gets the value of the type property. * * @return * possible object is - * {@link Boolean } + * {@link String } * */ - public Boolean isDeferrable() { - return deferrable; + public String getType() { + return type; } /** - * Sets the value of the deferrable property. + * Sets the value of the type property. * * @param value * allowed object is - * {@link Boolean } + * {@link String } * */ - public void setDeferrable(Boolean value) { - this.deferrable = value; + public void setType(String value) { + this.type = value; } /** - * Gets the value of the initiallyDeferred property. + * Gets the value of the defaultValue property. * * @return * possible object is - * {@link Boolean } + * {@link String } * */ - public Boolean isInitiallyDeferred() { - return initiallyDeferred; + public String getDefaultValue() { + return defaultValue; } /** - * Sets the value of the initiallyDeferred property. + * Sets the value of the defaultValue property. * * @param value * allowed object is - * {@link Boolean } + * {@link String } * */ - public void setInitiallyDeferred(Boolean value) { - this.initiallyDeferred = value; + public void setDefaultValue(String value) { + this.defaultValue = value; + } + + /** + * Gets the value of the remarks property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getRemarks() { + return remarks; + } + + /** + * Sets the value of the remarks property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setRemarks(String value) { + this.remarks = value; } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/CreateHistoryTable.java b/src/main/java/com/avaje/ebean/dbmigration/migration/CreateHistoryTable.java index f3e779cff..c495260c0 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/CreateHistoryTable.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/CreateHistoryTable.java @@ -27,7 +27,7 @@ import javax.xml.bind.annotation.XmlType; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "") -@XmlRootElement(name = "addHistoryTable") +@XmlRootElement(name = "createHistoryTable") public class CreateHistoryTable { @XmlAttribute(name = "baseTable", required = true) diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/CreateTable.java b/src/main/java/com/avaje/ebean/dbmigration/migration/CreateTable.java index 1546a9b49..5d14d95bd 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/CreateTable.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/CreateTable.java @@ -1,14 +1,14 @@ package com.avaje.ebean.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.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import java.util.ArrayList; -import java.util.List; /** @@ -23,6 +23,8 @@ import java.util.List; * <sequence> * <element ref="{http://ebean-orm.github.io/xml/ns/dbmigration}column" maxOccurs="unbounded"/> * <element ref="{http://ebean-orm.github.io/xml/ns/dbmigration}uniqueConstraint" maxOccurs="unbounded" minOccurs="0"/> + * <element ref="{http://ebean-orm.github.io/xml/ns/dbmigration}foreignKey" maxOccurs="unbounded" minOccurs="0"/> + * <element ref="{http://ebean-orm.github.io/xml/ns/dbmigration}primaryKey" minOccurs="0"/> * </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" /> @@ -37,7 +39,9 @@ import java.util.List; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "column", - "uniqueConstraint" + "uniqueConstraint", + "foreignKey", + "primaryKey" }) @XmlRootElement(name = "createTable") public class CreateTable { @@ -45,6 +49,8 @@ public class CreateTable { @XmlElement(required = true) protected List column; protected List uniqueConstraint; + protected List foreignKey; + protected PrimaryKey primaryKey; @XmlAttribute(name = "name", required = true) protected String name; @XmlAttribute(name = "withHistory") @@ -114,6 +120,59 @@ public class CreateTable { return this.uniqueConstraint; } + /** + * Gets the value of the foreignKey property. + * + *

+ * 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 set method for the foreignKey property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getForeignKey().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ForeignKey } + * + * + */ + public List getForeignKey() { + if (foreignKey == null) { + foreignKey = new ArrayList(); + } + return this.foreignKey; + } + + /** + * Gets the value of the primaryKey property. + * + * @return + * possible object is + * {@link PrimaryKey } + * + */ + public PrimaryKey getPrimaryKey() { + return primaryKey; + } + + /** + * Sets the value of the primaryKey property. + * + * @param value + * allowed object is + * {@link PrimaryKey } + * + */ + public void setPrimaryKey(PrimaryKey value) { + this.primaryKey = value; + } + /** * Gets the value of the name property. * diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/Migration.java b/src/main/java/com/avaje/ebean/dbmigration/migration/Migration.java index b4ec46043..54f97dcb7 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/Migration.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/Migration.java @@ -1,13 +1,13 @@ package com.avaje.ebean.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.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import java.util.ArrayList; -import java.util.List; /** diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/ObjectFactory.java b/src/main/java/com/avaje/ebean/dbmigration/migration/ObjectFactory.java index c0614a695..be3d2564c 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/ObjectFactory.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/ObjectFactory.java @@ -7,7 +7,7 @@ import javax.xml.bind.annotation.XmlRegistry; /** * This object contains factory methods for each * Java content interface and Java element interface - * generated in the org.avaje.ebean.dbmigration.migration package. + * generated in the com.avaje.ebean.dbmigration.migration package. *

An ObjectFactory allows you to programatically * construct new instances of the Java representation * for XML content. The Java representation of XML @@ -23,36 +23,12 @@ public class ObjectFactory { /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.avaje.ebean.dbmigration.migration + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.avaje.ebean.dbmigration.migration * */ public ObjectFactory() { } - /** - * Create an instance of {@link Rollback } - * - */ - public Rollback createRollback() { - return new Rollback(); - } - - /** - * Create an instance of {@link AddColumn } - * - */ - public AddColumn createAddColumn() { - return new AddColumn(); - } - - /** - * Create an instance of {@link Column } - * - */ - public Column createColumn() { - return new Column(); - } - /** * Create an instance of {@link CreateTable } * @@ -61,6 +37,14 @@ public class ObjectFactory { return new CreateTable(); } + /** + * Create an instance of {@link Column } + * + */ + public Column createColumn() { + return new Column(); + } + /** * Create an instance of {@link UniqueConstraint } * @@ -69,6 +53,22 @@ public class ObjectFactory { return new UniqueConstraint(); } + /** + * Create an instance of {@link ForeignKey } + * + */ + public ForeignKey createForeignKey() { + return new ForeignKey(); + } + + /** + * Create an instance of {@link PrimaryKey } + * + */ + public PrimaryKey createPrimaryKey() { + return new PrimaryKey(); + } + /** * Create an instance of {@link DropForeignKey } * @@ -77,14 +77,6 @@ public class ObjectFactory { return new DropForeignKey(); } - /** - * Create an instance of {@link Apply } - * - */ - public Apply createApply() { - return new Apply(); - } - /** * Create an instance of {@link Configuration } * @@ -117,22 +109,6 @@ public class ObjectFactory { return new DropHistoryTable(); } - /** - * Create an instance of {@link RenameView } - * - */ - public RenameView createRenameView() { - return new RenameView(); - } - - /** - * Create an instance of {@link AddForeignKey } - * - */ - public AddForeignKey createAddForeignKey() { - return new AddForeignKey(); - } - /** * Create an instance of {@link DropColumn } * @@ -149,14 +125,6 @@ public class ObjectFactory { return new DropView(); } - /** - * Create an instance of {@link ChangeSet } - * - */ - public ChangeSet createChangeSet() { - return new ChangeSet(); - } - /** * Create an instance of {@link Sql } * @@ -166,11 +134,19 @@ public class ObjectFactory { } /** - * Create an instance of {@link DropTable } + * Create an instance of {@link Apply } * */ - public DropTable createDropTable() { - return new DropTable(); + public Apply createApply() { + return new Apply(); + } + + /** + * Create an instance of {@link Rollback } + * + */ + public Rollback createRollback() { + return new Rollback(); } /** @@ -181,6 +157,14 @@ public class ObjectFactory { return new CreateHistoryTable(); } + /** + * Create an instance of {@link RenameColumn } + * + */ + public RenameColumn createRenameColumn() { + return new RenameColumn(); + } + /** * Create an instance of {@link CreateView } * @@ -190,11 +174,43 @@ public class ObjectFactory { } /** - * Create an instance of {@link RenameColumn } + * Create an instance of {@link DropTable } * */ - public RenameColumn createRenameColumn() { - return new RenameColumn(); + public DropTable createDropTable() { + return new DropTable(); + } + + /** + * Create an instance of {@link AddColumn } + * + */ + public AddColumn createAddColumn() { + return new AddColumn(); + } + + /** + * Create an instance of {@link RenameView } + * + */ + public RenameView createRenameView() { + return new RenameView(); + } + + /** + * Create an instance of {@link AddForeignKey } + * + */ + public AddForeignKey createAddForeignKey() { + return new AddForeignKey(); + } + + /** + * Create an instance of {@link ChangeSet } + * + */ + public ChangeSet createChangeSet() { + return new ChangeSet(); } /** diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java b/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java index ca78b7893..506bfcc54 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java @@ -49,6 +49,10 @@ public class CurrentModel { return model; } + public void setChangeSet(ChangeSet changeSet) { + this.changeSet = changeSet; + } + public ChangeSet getChangeSet() { read(); if (changeSet == null) { @@ -90,6 +94,16 @@ public class CurrentModel { return ddl.toString(); } + public DdlWrite generateDdl(ChangeSet changeSet) throws IOException { + + DdlWrite write = new DdlWrite(); + + BaseDdlHandler handler = handler(); + handler.generate(write, changeSet); + + return write; + } + private void createDdl() throws IOException { if (write == null) { diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/MColumn.java b/src/main/java/com/avaje/ebean/dbmigration/model/MColumn.java index f24dfd1db..39a3d15d4 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/MColumn.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/MColumn.java @@ -109,17 +109,15 @@ public class MColumn { Column c = new Column(); c.setName(name); c.setType(type); - c.setNotnull(notnull); + if (notnull) c.setNotnull(notnull); + if (unique) c.setUnique(unique); + if (primaryKey) c.setPrimaryKey(primaryKey); + if (identity) c.setIdentity(identity); + c.setCheckConstraint(checkConstraint); - c.setUnique(unique); - c.setPrimaryKey(primaryKey); - c.setIdentity(identity); c.setReferences(references); c.setDefaultValue(defaultValue); - //c.setDeleteCascade(); - //c.setDeferrable(deferrable); - return c; } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/MCompoundForeignKey.java b/src/main/java/com/avaje/ebean/dbmigration/model/MCompoundForeignKey.java index 84472f97e..4d48123ed 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/MCompoundForeignKey.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/MCompoundForeignKey.java @@ -1,5 +1,8 @@ package com.avaje.ebean.dbmigration.model; +import com.avaje.ebean.dbmigration.migration.Column; +import com.avaje.ebean.dbmigration.migration.ForeignKey; + import java.util.ArrayList; import java.util.List; @@ -24,4 +27,28 @@ public class MCompoundForeignKey { columns.add(dbCol); referenceColumns.add(refColumn); } + + public ForeignKey createForeignKey() { + ForeignKey fk = new ForeignKey(); + fk.setColumnNames(toColumnNames(columns)); + fk.setRefColumnNames(toColumnNames(referenceColumns)); + fk.setRefTableName(referenceTable); + return fk; + } + + /** + * Return as an array of string column names. + */ + private String toColumnNames(List columns) { + + StringBuilder sb = new StringBuilder(40); + for (int i = 0; i < columns.size(); i++) { + if (i > 0) { + sb.append(","); + } + sb.append(columns.get(i)); + } + return sb.toString(); + } + } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java b/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java index 753fdadb5..71510e356 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java @@ -4,6 +4,7 @@ import com.avaje.ebean.dbmigration.migration.AddColumn; import com.avaje.ebean.dbmigration.migration.Column; import com.avaje.ebean.dbmigration.migration.CreateTable; import com.avaje.ebean.dbmigration.migration.DropColumn; +import com.avaje.ebean.dbmigration.migration.ForeignKey; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -81,6 +82,11 @@ public class MTable { for (MColumn column : this.columns.values()) { createTable.getColumn().add(column.createColumn()); } + + for (MCompoundForeignKey compoundKey : compoundKeys) { + createTable.getForeignKey().add(compoundKey.createForeignKey()); + } + return createTable; } @@ -142,6 +148,19 @@ public class MTable { return compoundKeys; } + /** + * Return the list of columns that make the primary key. + */ + public List primaryKeyColumns() { + List pk = new ArrayList(3); + for (MColumn column : columns.values()) { + if (column.isPrimaryKey()) { + pk.add(column); + } + } + return pk; + } + private void checkTableName(String tableName) { if (!name.equals(tableName)) { throw new IllegalArgumentException("addColumn tableName ["+tableName+"] does not match ["+name+"]"); @@ -183,4 +202,5 @@ public class MTable { public void addForeignKey(MCompoundForeignKey compoundKey) { compoundKeys.add(compoundKey); } + } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java b/src/main/java/com/avaje/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java index 444611e29..d13d72858 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java @@ -24,6 +24,8 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { private final MTable table; + private MColumn lastColumn; + public ModelBuildPropertyVisitor(ModelBuildContext ctx, MTable table) { this.ctx = ctx; this.table = table; @@ -59,8 +61,11 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { @Override public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne embedded) { - //this.embedded = embedded; visitScalar(p); + if (embedded.isId()) { + // compound primary key + lastColumn.setPrimaryKey(true); + } } @Override @@ -141,6 +146,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { } col.setCheckConstraint(p.getDbConstraintExpression()); + lastColumn = col; table.addColumn(col); } diff --git a/src/test/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConventionTest.java b/src/test/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConventionTest.java index a9f8a7b59..1c69c8021 100644 --- a/src/test/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConventionTest.java +++ b/src/test/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/DdlNamingConventionTest.java @@ -2,9 +2,6 @@ package com.avaje.ebean.dbmigration.ddlgeneration.platform; import org.junit.Test; -import java.util.ArrayList; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; public class DdlNamingConventionTest { @@ -14,9 +11,7 @@ public class DdlNamingConventionTest { @Test public void testPrimaryKeyName() throws Exception { - List cols = new ArrayList(); - cols.add("[jim]"); - cols.add("`jack`"); + String[] cols = {"[jim]","`jack`"}; assertThat(defaultNaming.primaryKeyName("[cat].[sce].[foo_bar]", cols)).isEqualTo("pk_foo_bar"); } diff --git a/src/test/java/com/avaje/ebean/dbmigration/model/build/ModelBuild_compoundKeyTest.java b/src/test/java/com/avaje/ebean/dbmigration/model/build/ModelBuild_compoundKeyTest.java index ad63ef2bc..01bd2c458 100644 --- a/src/test/java/com/avaje/ebean/dbmigration/model/build/ModelBuild_compoundKeyTest.java +++ b/src/test/java/com/avaje/ebean/dbmigration/model/build/ModelBuild_compoundKeyTest.java @@ -2,8 +2,13 @@ package com.avaje.ebean.dbmigration.model.build; import com.avaje.ebean.BaseTestCase; +import com.avaje.ebean.Ebean; import com.avaje.ebean.EbeanServerFactory; import com.avaje.ebean.config.ServerConfig; +import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; +import com.avaje.ebean.dbmigration.ddlgeneration.Helper; +import com.avaje.ebean.dbmigration.migration.Migration; +import com.avaje.ebean.dbmigration.migrationreader.MigrationXmlReader; import com.avaje.ebean.dbmigration.model.CurrentModel; import com.avaje.ebean.dbmigration.model.MTable; import com.avaje.ebean.dbmigration.model.ModelContainer; @@ -14,13 +19,13 @@ import com.avaje.tests.model.basic.CKeyParent; import com.avaje.tests.model.basic.CKeyParentId; import org.junit.Test; +import java.io.IOException; + import static org.assertj.core.api.Assertions.assertThat; public class ModelBuild_compoundKeyTest extends BaseTestCase { - @Test - public void test() { - + private SpiEbeanServer getServer() { ServerConfig config = new ServerConfig(); config.setName("h2"); config.loadFromProperties(); @@ -36,7 +41,13 @@ public class ModelBuild_compoundKeyTest extends BaseTestCase { config.addClass(CKeyParentId.class); - SpiEbeanServer ebeanServer = (SpiEbeanServer)EbeanServerFactory.create(config); + return (SpiEbeanServer) EbeanServerFactory.create(config); + } + + @Test + public void test() throws IOException { + + SpiEbeanServer ebeanServer = getServer(); CurrentModel currentModel = new CurrentModel(ebeanServer); ModelContainer model = currentModel.read(); @@ -46,6 +57,30 @@ public class ModelBuild_compoundKeyTest extends BaseTestCase { assertThat(parent).isNotNull(); assertThat(detail).isNotNull(); + assertThat(parent.primaryKeyColumns()).hasSize(2); + assertThat(detail.getCompoundKeys()).hasSize(1); + + String apply = Helper.asText(this, "/assert/ModelBuild_compoundKeyTest/apply.sql"); + + String createDdl = currentModel.getCreateDdl(); + assertThat(createDdl).isEqualTo(apply); } + + + @Test + public void testFromMigration() throws IOException { + + + Migration migration = MigrationXmlReader.read("/container/test-compoundkey.xml"); + + SpiEbeanServer ebeanServer = getServer(); + CurrentModel currentModel = new CurrentModel(ebeanServer); + currentModel.setChangeSet(migration.getChangeSet().get(0)); + + String createDdl = currentModel.getCreateDdl(); + String apply = Helper.asText(this, "/assert/ModelBuild_compoundKeyTest/apply.sql"); + + assertThat(createDdl).isEqualTo(apply); + } } \ No newline at end of file diff --git a/src/test/resources/container/test-compoundkey.xml b/src/test/resources/container/test-compoundkey.xml index c424ba941..b9f167021 100644 --- a/src/test/resources/container/test-compoundkey.xml +++ b/src/test/resources/container/test-compoundkey.xml @@ -4,11 +4,17 @@ + + + + + +