Let enum arrays be saved as integers or strings (#1467)

* Let enums be saved as integers or strings as needed

* Add tests for int and varchar @DbArray enums
This commit is contained in:
Snōwball
2018-08-13 21:26:14 +12:00
committed by Rob Bygrave
parent 0faf9f54ea
commit 9bbe99657a
7 changed files with 106 additions and 13 deletions
@@ -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;
}
@@ -60,7 +60,19 @@ public class ScalarTypeArrayList extends ScalarTypeJsonCollection<List> implemen
@Override
public ScalarTypeArrayList typeForEnum(ScalarType<?> scalarType) {
return new ScalarTypeArrayList("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
final String arrayType;
switch (scalarType.getJdbcType()) {
case Types.INTEGER:
arrayType = "integer";
break;
case Types.VARCHAR:
arrayType = "varchar";
break;
default:
throw new IllegalArgumentException("JdbcType [" + scalarType.getJdbcType() + "] not supported for @DbArray mapping on set.");
}
return new ScalarTypeArrayList(arrayType, scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType));
}
}
@@ -54,13 +54,24 @@ public class ScalarTypeArraySet<T> extends ScalarTypeJsonCollection<Set<T>> impl
if (valueType.equals(String.class)) {
return STRING;
}
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping on set");
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping on list");
}
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public ScalarTypeArraySet typeForEnum(ScalarType<?> scalarType) {
return new ScalarTypeArraySet("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
final String arrayType;
switch (scalarType.getJdbcType()) {
case Types.INTEGER:
arrayType = "integer";
break;
case Types.VARCHAR:
arrayType = "varchar";
break;
default:
throw new IllegalArgumentException("JdbcType [" + scalarType.getJdbcType() + "] not supported for @DbArray mapping on set.");
}
return new ScalarTypeArraySet(arrayType, scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType));
}
}
@@ -38,6 +38,12 @@ public class EArrayBean {
@DbArray
List<Status> statuses;
@DbArray
List<VarcharEnum> vcEnums = new ArrayList<>();
@DbArray
List<IntEnum> intEnums = new ArrayList<>();
@DbArray
Set<Status> status2;
@@ -100,6 +106,21 @@ public class EArrayBean {
this.statuses = statuses;
}
public List<VarcharEnum> getVcEnums() {
return vcEnums;
}
public void setVcEnums(final List<VarcharEnum> vcEnums) {
this.vcEnums = vcEnums;
}
public List<IntEnum> getIntEnums() {
return intEnums;
}
public void setIntEnums(final List<IntEnum> intEnums) {
this.intEnums = intEnums;
}
public Set<Status> getStatus2() {
return status2;
@@ -0,0 +1,13 @@
package org.tests.model.array;
import io.ebean.annotation.DbEnumType;
import io.ebean.annotation.DbEnumValue;
public enum IntEnum {
ZERO, ONE, TWO;
@DbEnumValue(storage = DbEnumType.INTEGER)
public int dbValue() {
return 100 + ordinal();
}
}
@@ -1,19 +1,22 @@
package org.tests.model.array;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
import io.ebean.Query;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
import io.ebean.Query;
import io.ebean.SqlRow;
public class TestDbArray_basic extends BaseTestCase {
@@ -22,7 +25,7 @@ public class TestDbArray_basic extends BaseTestCase {
private EArrayBean found;
@Test
public void insert() {
public void insert() throws SQLException {
bean.setName("some stuff");
@@ -44,6 +47,10 @@ public class TestDbArray_basic extends BaseTestCase {
bean.setStatuses(new ArrayList<>());
bean.getStatuses().add(EArrayBean.Status.ONE);
bean.getStatuses().add(EArrayBean.Status.THREE);
bean.getVcEnums().add(VarcharEnum.ONE);
bean.getVcEnums().add(VarcharEnum.TWO);
bean.getIntEnums().add(IntEnum.ZERO);
bean.getIntEnums().add(IntEnum.TWO);
bean.setStatus2(new LinkedHashSet<>());
bean.getStatus2().add(EArrayBean.Status.TWO);
@@ -64,16 +71,23 @@ public class TestDbArray_basic extends BaseTestCase {
.arrayIsNotEmpty("phoneNumbers")
.arrayContains("statuses", EArrayBean.Status.ONE)
.arrayContains("status2", EArrayBean.Status.TWO)
.arrayContains("vcEnums", VarcharEnum.TWO)
.arrayContains("intEnums", IntEnum.ZERO)
.query();
List<EArrayBean> list = query.findList();
List<EArrayBean.Status> statuses = list.get(0).getStatuses();
Set<EArrayBean.Status> status2 = list.get(0).getStatus2();
List<IntEnum> intEnums = list.get(0).getIntEnums();
List<VarcharEnum> varcharEnums = list.get(0).getVcEnums();
assertThat(statuses).contains(EArrayBean.Status.ONE, EArrayBean.Status.THREE);
assertThat(status2).contains(EArrayBean.Status.ONE, EArrayBean.Status.TWO);
assertThat(intEnums).containsExactly(IntEnum.ZERO, IntEnum.TWO);
assertThat(varcharEnums).containsExactly(VarcharEnum.ONE, VarcharEnum.TWO);
assertThat(query.getGeneratedSql()).contains(" t0.other_ids @> array[?,?]::bigint[] ");
assertThat(query.getGeneratedSql()).contains(" t0.uids @> array[?] ");
assertThat(query.getGeneratedSql()).contains(" t0.phone_numbers @> array[?] ");
@@ -87,6 +101,15 @@ public class TestDbArray_basic extends BaseTestCase {
.query();
query.findList();
final SqlRow row = Ebean.createSqlQuery("select * from earray_bean").findOne();
final String[] vcs = (String[]) ((java.sql.Array) row.get("vc_enums")).getArray();
assertThat(vcs).containsExactly("xXxONE", "xXxTWO");
final Integer[] ints = (Integer[]) ((java.sql.Array) row.get("int_enums")).getArray();
assertThat(ints).containsExactly(100, 102);
assertThat(query.getGeneratedSql()).contains(" coalesce(cardinality(t0.other_ids),0) = 0");
assertThat(query.getGeneratedSql()).contains(" not (t0.uids @> array[?])");
}
@@ -0,0 +1,13 @@
package org.tests.model.array;
import io.ebean.annotation.DbEnumType;
import io.ebean.annotation.DbEnumValue;
public enum VarcharEnum {
ZERO, ONE, TWO;
@DbEnumValue(storage = DbEnumType.VARCHAR)
public String dbValue() {
return "xXx" + name();
}
}