#513 - Column Constraint for Enum types should cover all Enum values in an inheritance hierachy

This commit is contained in:
Robin Bygrave
2016-05-19 20:55:16 +12:00
parent 4606c7c99f
commit db8dd48e53
9 changed files with 133 additions and 70 deletions
@@ -11,12 +11,13 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Used as part of ModelBuildBeanVisitor and generally adds the MColumn to the associated
@@ -249,9 +250,13 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
col.setUnique(determineUniqueConstraintName(col.getName()));
indexSetAdd(col.getName());
}
String checkConstraint = p.getDbConstraintExpression();
if (checkConstraint != null) {
col.setCheckConstraint(checkConstraint);
Set<String> checkConstraintValues = p.getDbCheckConstraintValues();
if (checkConstraintValues != null) {
if (beanDescriptor.hasInheritance()) {
InheritInfo inheritInfo = beanDescriptor.getInheritInfo();
inheritInfo.appendCheckConstraintValues(p.getName(), checkConstraintValues);
}
col.setCheckConstraint(buildCheckConstraint(p.getDbColumn(), checkConstraintValues));
col.setCheckConstraintName(determineCheckConstraintName(col.getName()));
}
@@ -268,6 +273,22 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
table.addColumn(col);
}
/**
* Build the check constraint clause given the db column and values.
*/
private String buildCheckConstraint(String dbColumn, Set<String> checkConstraintValues) {
StringBuilder sb = new StringBuilder();
sb.append("check ( ").append(dbColumn).append(" in (");
int count = 0;
for (String value : checkConstraintValues) {
if (count++ > 0) {
sb.append(",");
}
sb.append(value);
}
sb.append("))");
return sb.toString();
}
private void indexSetAdd(String column) {
indexSet.add(column);
@@ -6,11 +6,9 @@ import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebean.config.EncryptKey;
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
import com.avaje.ebean.config.dbplatform.DbType;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeanservice.docstore.api.mapping.DocMappingBuilder;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyMapping;
import com.avaje.ebean.plugin.Property;
import com.avaje.ebean.text.StringParser;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedWhenCreated;
@@ -28,7 +26,10 @@ import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypeBoolean;
import com.avaje.ebeaninternal.server.type.ScalarTypeEnum;
import com.avaje.ebeaninternal.util.ValueUtil;
import com.avaje.ebeanservice.docstore.api.mapping.DocMappingBuilder;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyMapping;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyOptions;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
import com.avaje.ebeanservice.docstore.api.support.DocStructure;
@@ -45,6 +46,7 @@ import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Description of a property of a bean. Includes its deployment information such
@@ -231,11 +233,6 @@ public class BeanProperty implements ElPropertyValue, Property {
*/
final String dbComment;
/**
* DB Constraint (typically check constraint on enum)
*/
final String dbConstraintExpression;
final DbEncryptFunction dbEncryptFunction;
int deployOrder;
@@ -304,7 +301,6 @@ public class BeanProperty implements ElPropertyValue, Property {
this.dbLength = deploy.getDbLength();
this.dbScale = deploy.getDbScale();
this.dbColumnDefn = InternString.intern(deploy.getDbColumnDefn());
this.dbConstraintExpression = InternString.intern(deploy.getDbConstraintExpression());
this.dbColumnDefault = deploy.getDbColumnDefault();
this.inherited = false;// deploy.isInherited();
@@ -414,7 +410,6 @@ public class BeanProperty implements ElPropertyValue, Property {
this.dbLength = source.getDbLength();
this.dbScale = source.getDbScale();
this.dbColumnDefn = InternString.intern(source.getDbColumnDefn());
this.dbConstraintExpression = InternString.intern(source.getDbConstraintExpression());
this.dbColumnDefault = source.dbColumnDefault;
this.inherited = source.isInherited();
@@ -977,8 +972,11 @@ public class BeanProperty implements ElPropertyValue, Property {
* For an Enum returns IN expression for the set of Enum values.
* </p>
*/
public String getDbConstraintExpression() {
return dbConstraintExpression;
public Set<String> getDbCheckConstraintValues() {
if (scalarType instanceof ScalarTypeEnum) {
return ((ScalarTypeEnum) scalarType).getDbCheckConstraintValues();
}
return null;
}
/**
@@ -3,6 +3,7 @@ package com.avaje.ebeaninternal.server.deploy;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import javax.persistence.PersistenceException;
@@ -88,6 +89,25 @@ public class InheritInfo {
}
}
/**
* Append check constraint values for the entire inheritance hierarchy.
*/
public void appendCheckConstraintValues(final String propertyName, final Set<String> checkConstraintValues) {
visitChildren(new InheritInfoVisitor() {
@Override
public void visit(InheritInfo inheritInfo) {
BeanProperty prop = inheritInfo.desc().getBeanProperty(propertyName);
if (prop != null) {
Set<String> values = prop.getDbCheckConstraintValues();
if (values != null) {
checkConstraintValues.addAll(values);
}
}
}
});
}
/**
* return true if anything in the inheritance hierarchy has a relationship with a save cascade on
* it.
@@ -393,17 +393,6 @@ public class DeployBeanProperty {
}
}
public String getDbConstraintExpression() {
if (scalarType instanceof ScalarTypeEnum) {
// create a check constraint for the enum
ScalarTypeEnum etype = (ScalarTypeEnum) scalarType;
// check dbColName IN ('A', 'I', 'D')
return "check (" + dbColumn + " in " + etype.getConstraintInValues() + ")";
}
return null;
}
/**
* Return the scalarType. This returns null for native JDBC types, otherwise
* it is used to convert between logical types and jdbc types.
@@ -1,5 +1,7 @@
package com.avaje.ebeaninternal.server.type;
import java.util.Set;
/**
* Marker interface for the Enum scalar types.
*/
@@ -8,6 +10,6 @@ public interface ScalarTypeEnum {
/**
* Return the IN values for DB constraint construction.
*/
String getConstraintInValues();
Set<String> getDbCheckConstraintValues();
}
@@ -11,6 +11,8 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* JPA standard based Enum scalar type.
@@ -41,22 +43,17 @@ public class ScalarTypeEnumStandard {
/**
* Return the IN values for DB constraint construction.
*/
public String getConstraintInValues() {
@Override
public Set<String> getDbCheckConstraintValues() {
StringBuilder sb = new StringBuilder();
LinkedHashSet<String> values = new LinkedHashSet<String>();
sb.append("(");
Object[] ea = enumType.getEnumConstants();
for (int i = 0; i < ea.length; i++) {
Enum<?> e = (Enum<?>) ea[i];
if (i > 0) {
sb.append(",");
}
sb.append("'").append(e.name()).append("'");
values.add("'" + e.name() + "'");
}
sb.append(")");
return sb.toString();
return values;
}
private int maxValueLength(Class<?> enumType) {
@@ -129,21 +126,15 @@ public class ScalarTypeEnumStandard {
/**
* Return the IN values for DB constraint construction.
*/
public String getConstraintInValues() {
@Override
public Set<String> getDbCheckConstraintValues() {
StringBuilder sb = new StringBuilder();
sb.append("(");
LinkedHashSet<String> values = new LinkedHashSet<String>();
for (int i = 0; i < enumArray.length; i++) {
Enum<?> e = (Enum<?>) enumArray[i];
if (i > 0) {
sb.append(",");
}
sb.append(e.ordinal());
values.add(Integer.toString(e.ordinal()));
}
sb.append(")");
return sb.toString();
return values;
}
public void bind(DataBind b, Object value) throws SQLException {
@@ -2,6 +2,8 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Additional control over mapping to DB values.
@@ -35,32 +37,21 @@ public class ScalarTypeEnumWithMapping extends ScalarTypeEnumStandard.EnumBase i
/**
* Return the IN values for DB constraint construction.
*/
public String getConstraintInValues() {
@Override
public Set<String> getDbCheckConstraintValues() {
StringBuilder sb = new StringBuilder();
int i = 0;
sb.append("(");
LinkedHashSet values = new LinkedHashSet();
Iterator<?> it = beanDbMap.dbValues();
while (it.hasNext()) {
Object dbValue = it.next();
if (i++ > 0) {
sb.append(",");
}
if (!beanDbMap.isIntegerType()) {
sb.append("'");
}
sb.append(dbValue.toString());
if (!beanDbMap.isIntegerType()) {
sb.append("'");
if (beanDbMap.isIntegerType()) {
values.add(dbValue.toString());
} else {
values.add("'" + dbValue.toString() + "'");
}
}
sb.append(")");
return sb.toString();
return values;
}
/**