diff --git a/ebean-api/pom.xml b/ebean-api/pom.xml index 4150e1cb3..c5f36193b 100644 --- a/ebean-api/pom.xml +++ b/ebean-api/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean api diff --git a/ebean-autotune/pom.xml b/ebean-autotune/pom.xml index 5892fda8e..b50be9b0d 100644 --- a/ebean-autotune/pom.xml +++ b/ebean-autotune/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT @@ -26,7 +26,7 @@ io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided diff --git a/ebean-autotune/src/test/java/io/ebeaninternal/server/autotune/service/ProfileOriginTest.java b/ebean-autotune/src/test/java/io/ebeaninternal/server/autotune/service/ProfileOriginTest.java index 4bc86f6b4..ec0a09596 100644 --- a/ebean-autotune/src/test/java/io/ebeaninternal/server/autotune/service/ProfileOriginTest.java +++ b/ebean-autotune/src/test/java/io/ebeaninternal/server/autotune/service/ProfileOriginTest.java @@ -30,7 +30,7 @@ public class ProfileOriginTest extends BaseTestCase { OrmQueryDetail detail = po.buildDetail(desc); - assertThat(detail.asString().trim()).isEqualTo("fetch customer (name)"); + assertThat(detail.asStringDebug().trim()).isEqualTo("fetch customer (name)"); } @Test @@ -49,7 +49,7 @@ public class ProfileOriginTest extends BaseTestCase { OrmQueryDetail detail = po.buildDetail(desc); - assertThat(detail.asString()).isEqualTo("select (orderDate) fetch customer (name)"); + assertThat(detail.asStringDebug()).isEqualTo("select (orderDate) fetch customer (name)"); } @Test @@ -67,7 +67,7 @@ public class ProfileOriginTest extends BaseTestCase { OrmQueryDetail detail = po.buildDetail(desc); - assertThat(detail.asString().trim()).isEqualTo("select (orderDate,customer)"); + assertThat(detail.asStringDebug().trim()).isEqualTo("select (orderDate,customer)"); } @Test @@ -90,7 +90,7 @@ public class ProfileOriginTest extends BaseTestCase { OrmQueryDetail detail = po.buildDetail(desc); - assertThat(detail.asString()).isEqualTo("select (orderDate) fetch customer (billingAddress)"); + assertThat(detail.asStringDebug()).isEqualTo("select (orderDate) fetch customer (billingAddress)"); } @@ -119,7 +119,7 @@ public class ProfileOriginTest extends BaseTestCase { po.collectUsageInfo(c); OrmQueryDetail detail = po.buildDetail(desc); - assertThat(detail.asString()).isEqualTo("fetch customer (name,note) fetch customer.billingAddress (line1)"); + assertThat(detail.asStringDebug()).isEqualTo("fetch customer (name,note) fetch customer.billingAddress (line1)"); } private NodeUsageCollector node(String path) { diff --git a/ebean-bom/pom.xml b/ebean-bom/pom.xml index b3b611006..6a18b3017 100644 --- a/ebean-bom/pom.xml +++ b/ebean-bom/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean bom @@ -81,88 +81,88 @@ io.ebean ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-core-type - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-ddl-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-externalmapping-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-externalmapping-xml - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-autotune - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-querybean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean querybean-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided io.ebean kotlin-querybean-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided io.ebean ebean-test - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test io.ebean ebean-postgis - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-redis - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT diff --git a/ebean-core-type/pom.xml b/ebean-core-type/pom.xml index 18e8f5bb8..50d80ce17 100644 --- a/ebean-core-type/pom.xml +++ b/ebean-core-type/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean-core-type @@ -21,7 +21,7 @@ io.ebean ebean-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT diff --git a/ebean-core/pom.xml b/ebean-core/pom.xml index 1c5a407b8..082cb17aa 100644 --- a/ebean-core/pom.xml +++ b/ebean-core/pom.xml @@ -3,7 +3,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean-core @@ -92,19 +92,19 @@ io.ebean ebean-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-core-type - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-externalmapping-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java index 91c949a0f..b3346562b 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocManys.java @@ -5,7 +5,6 @@ import io.ebean.annotation.FetchPreference; import io.ebean.annotation.HistoryExclude; import io.ebean.annotation.Where; import io.ebean.bean.BeanCollection.ModifyListenMode; -import io.ebean.config.BeanNotRegisteredException; import io.ebean.config.NamingConvention; import io.ebean.config.TableName; import io.ebean.core.type.ScalarType; @@ -140,15 +139,15 @@ class AnnotationAssocManys extends AnnotationAssoc { JoinTable joinTable = get(prop, JoinTable.class); if (joinTable != null) { if (prop.isManyToMany()) { - // expected this readJoinTable(joinTable, prop); - } else { // OneToMany with @JoinTable prop.setO2mJoinTable(); readJoinTable(joinTable, prop); manyToManyDefaultJoins(prop); } + } else if (prop.isManyToMany()) { + checkSelfManyToMany(prop); } if (prop.getMappedBy() != null) { @@ -181,6 +180,12 @@ class AnnotationAssocManys extends AnnotationAssoc { } } + private void checkSelfManyToMany(DeployBeanPropertyAssocMany prop) { + if (prop.getTargetType().equals(descriptor.getBeanType())) { + throw new IllegalStateException("@ManyToMany mapping for " + prop.getFullBeanName() + " requires explicit @JoinTable with joinColumns & inverseJoinColumns. Refer issue #2157"); + } + } + @SuppressWarnings("unchecked") private void readElementCollection(DeployBeanPropertyAssocMany prop, ElementCollection elementCollection) { @@ -430,7 +435,6 @@ class AnnotationAssocManys extends AnnotationAssoc { } private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany manyProp) { - manyProp.setMappedBy(propAnn.mappedBy()); manyProp.setFetchType(propAnn.fetch()); setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo()); @@ -442,7 +446,6 @@ class AnnotationAssocManys extends AnnotationAssoc { } private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany manyProp) { - manyProp.setMappedBy(propAnn.mappedBy()); manyProp.setFetchType(propAnn.fetch()); setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo()); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 961684be5..ef58d99f6 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -1136,81 +1136,81 @@ public class DefaultOrmQuery implements SpiQuery { private String planDescription() { StringBuilder sb = new StringBuilder(300); if (type != null) { - sb.append("t:").append(type.ordinal()); + sb.append(type.ordinal()); } if (useDocStore) { - sb.append(",ds:"); + sb.append("/ds"); } if (beanDescriptor.getDiscValue() != null) { - sb.append(",disc:").append(beanDescriptor.getDiscValue()); + sb.append("/dv").append(beanDescriptor.getDiscValue()); } if (temporalMode != SpiQuery.TemporalMode.CURRENT) { - sb.append(",temp:").append(temporalMode.ordinal()); + sb.append("/tm").append(temporalMode.ordinal()); if (versionsStart != null) { - sb.append(",vb:"); + sb.append("v"); } } if (forUpdate != null) { - sb.append(",forUpd:").append(forUpdate.ordinal()); + sb.append("/fu").append(forUpdate.ordinal()); if (lockType != null) { - sb.append(",lt:").append(lockType.ordinal()); + sb.append("t").append(lockType.ordinal()); } } if (id != null) { - sb.append(",id:"); + sb.append("/id"); } if (manualId) { - sb.append(",manId:"); + sb.append("/md"); } if (distinct) { - sb.append(",dist:"); + sb.append("/dt"); } if (allowLoadErrors) { - sb.append(",allowLoadErrors:"); + sb.append("/ae"); } if (disableLazyLoading) { - sb.append(",disLazy:"); + sb.append("/dl"); } if (baseTable != null) { - sb.append(",baseTable:").append(baseTable); + sb.append("/bt").append(baseTable); } if (rootTableAlias != null) { - sb.append(",root:").append(rootTableAlias); + sb.append("/ra").append(rootTableAlias); } if (orderBy != null) { - sb.append(",orderBy:").append(orderBy.toStringFormat()); + sb.append("/ob").append(orderBy.toStringFormat()); } if (m2mIncludeJoin != null) { - sb.append(",m2m:").append(m2mIncludeJoin.getTable()); + sb.append("/m2").append(m2mIncludeJoin.getTable()); } if (mapKey != null) { - sb.append(",mapKey:").append(mapKey); + sb.append("/mk").append(mapKey); } if (countDistinctOrder != null) { - sb.append(",countDistOrd:").append(countDistinctOrder.name()); + sb.append("/cd").append(countDistinctOrder.name()); } if (detail != null) { - sb.append(" detail["); + sb.append("/d["); detail.queryPlanHash(sb); sb.append("]"); } if (bindParams != null) { - sb.append(" bindParams["); + sb.append("/b["); bindParams.buildQueryPlanHash(sb); sb.append("]"); } if (whereExpressions != null) { - sb.append(" where["); + sb.append("/w["); whereExpressions.queryPlanHash(sb); sb.append("]"); } if (havingExpressions != null) { - sb.append(" having["); + sb.append("/h["); havingExpressions.queryPlanHash(sb); sb.append("]"); } if (updateProperties != null) { - sb.append(" update["); + sb.append("/u["); updateProperties.buildQueryPlanHash(sb); sb.append("]"); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryDetail.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryDetail.java index b36daaf58..b8837111e 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryDetail.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryDetail.java @@ -106,15 +106,10 @@ public class OrmQueryDetail implements Serializable { return p1 == null ? p2 == null : p1.isSameByAutoTune(p2); } - @Override - public String toString() { - return asString(); - } - /** * Return the detail in string form. */ - public String asString() { + public String asStringDebug() { StringBuilder sb = new StringBuilder(); if (!baseProps.isEmpty()) { baseProps.asStringDebug("select ", sb); @@ -150,7 +145,7 @@ public class OrmQueryDetail implements Serializable { * Set the base query properties to be empty. */ public void setEmptyBase() { - this.baseProps = new OrmQueryProperties(null, new LinkedHashSet<>()); + this.baseProps = new OrmQueryProperties(null, Collections.emptySet()); } /** @@ -316,7 +311,7 @@ public class OrmQueryDetail implements Serializable { if (addId) { parentProp = new OrmQueryProperties(parentPath, assocOne.getTargetIdProperty()); } else { - parentProp = new OrmQueryProperties(parentPath, new LinkedHashSet<>()); + parentProp = new OrmQueryProperties(parentPath, Collections.emptySet()); } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPlanKey.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPlanKey.java index c083eb3d5..3a9ac8e33 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPlanKey.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPlanKey.java @@ -29,7 +29,7 @@ class OrmQueryPlanKey implements CQueryPlanKey { @Override public CQueryPlanKey withDeleteByIds() { - return new OrmQueryPlanKey(description + ":deleteByIds", 0, 0, null); + return new OrmQueryPlanKey(description + "/deleteByIds", 0, 0, null); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java index e7c416390..02b3afbac 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java @@ -3,8 +3,8 @@ package io.ebeaninternal.server.querydefn; import io.ebean.FetchConfig; import io.ebeaninternal.server.util.DSelectColumnsParser; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.Iterator; +import java.util.Set; /** * Parses the path properties string. @@ -22,9 +22,9 @@ class OrmQueryPropertiesParser { final boolean cache; final FetchConfig fetchConfig; final String properties; - final LinkedHashSet included; + final Set included; - Response(boolean readOnly, boolean cache, int queryFetchBatch, int lazyFetchBatch, String properties, LinkedHashSet included) { + Response(boolean readOnly, boolean cache, int queryFetchBatch, int lazyFetchBatch, String properties, Set included) { this.readOnly = readOnly; this.cache = cache; this.properties = properties; @@ -55,9 +55,7 @@ class OrmQueryPropertiesParser { return new OrmQueryPropertiesParser(rawProperties).parse(); } - private String inputProperties; - - private String outputProperties = ""; + private final String inputProperties; private boolean allProperties; private boolean readOnly; private boolean cache; @@ -72,124 +70,61 @@ class OrmQueryPropertiesParser { * Parse the raw string properties input. */ private Response parse() { - if (inputProperties == null || inputProperties.isEmpty()) { return EMPTY; } - int pos = inputProperties.indexOf("+readonly"); - if (pos > -1) { - inputProperties = inputProperties.replace("+readonly", ""); - readOnly = true; - } - pos = inputProperties.indexOf("+cache"); - if (pos > -1) { - inputProperties = inputProperties.replace("+cache", ""); - cache = true; - } - pos = inputProperties.indexOf("+query"); - if (pos > -1) { - queryFetchBatch = parseBatchHint(pos, "+query"); - } - pos = inputProperties.indexOf("+lazy"); - if (pos > -1) { - lazyFetchBatch = parseBatchHint(pos, "+lazy"); - } - - LinkedHashSet included = parseIncluded(); - String properties = (allProperties) ? "*" : outputProperties; - return new Response(readOnly, cache, queryFetchBatch, lazyFetchBatch, properties, included); - } - - /** - * Parse the include separating by comma or semicolon. - */ - private LinkedHashSet parseIncluded() { - - inputProperties = inputProperties.trim(); - if (inputProperties.isEmpty()) { - // default properties - return null; - } if (inputProperties.equals("*")) { // explicit all properties allProperties = true; - return null; + return new Response(readOnly, cache, queryFetchBatch, lazyFetchBatch, "*", null); } - - List res = splitRawSelect(inputProperties); - - StringBuilder sb = new StringBuilder(70); - LinkedHashSet propertySet = new LinkedHashSet<>(res.size() * 2); - - int count = 0; - String temp; - for (String re : res) { - temp = re.trim(); - if (!temp.isEmpty()) { - if (count > 0) { - sb.append(","); - } - sb.append(temp); - propertySet.add(temp); - count++; + boolean hints = false; + Set fields = splitRawSelect(inputProperties); + final Iterator iterator = fields.iterator(); + while (iterator.hasNext()) { + String val = iterator.next(); + if (val.startsWith("+")) { + hints = true; + iterator.remove(); + parseHint(val); + } else if (val.equals("*")) { + allProperties = true; } } - - if (propertySet.isEmpty()) { - // default properties - return null; + String properties = allProperties ? "*" : hints ? String.join(",", fields) : inputProperties; + if (fields.isEmpty()) { + fields = null; } + return new Response(readOnly, cache, queryFetchBatch, lazyFetchBatch, properties, fields); + } - if (propertySet.contains("*")) { - // explicit all properties - allProperties = true; - return null; + private void parseHint(String val) { + if (val.equals("+readonly")) { + readOnly = true; + } else if (val.equals("+cache")) { + cache = true; + } else if (val.startsWith("+query")) { + queryFetchBatch = parseBatch(val); + } else if (val.startsWith("+lazy")) { + lazyFetchBatch = parseBatch(val); } + } - // partial properties - outputProperties = sb.toString(); - return propertySet; + private int parseBatch(String val) { + if (val.endsWith(")")) { + int start = val.lastIndexOf('('); + if (start > 0) { + return Integer.parseInt(val.substring(start + 1, val.length() - 1)); + } + } + return 0; } /** * Split allowing 'dynamic function based properties'. */ - private List splitRawSelect(String inputProperties) { + private Set splitRawSelect(String inputProperties) { return DSelectColumnsParser.parse(inputProperties); } - private int parseBatchHint(int pos, String option) { - - int startPos = pos + option.length(); - int endPos = findEndPos(startPos, inputProperties); - if (endPos == -1) { - inputProperties = inputProperties.replace(option, ""); - return 0; - - } else { - - String batchParam = inputProperties.substring(startPos + 1, endPos); - - if (endPos + 1 >= inputProperties.length()) { - inputProperties = inputProperties.substring(0, pos); - } else { - inputProperties = inputProperties.substring(0, pos) + inputProperties.substring(endPos + 1); - } - return Integer.parseInt(batchParam); - } - } - - private int findEndPos(int pos, String props) { - - if (pos < props.length()) { - if (props.charAt(pos) == '(') { - int endPara = props.indexOf(')', pos + 1); - if (endPara == -1) { - throw new RuntimeException("Error could not find ')' in " + props + " after position " + pos); - } - return endPara; - } - } - return -1; - } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSqlColumnsParser.java b/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSqlColumnsParser.java index 2ee3b354d..74c02badd 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSqlColumnsParser.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSqlColumnsParser.java @@ -6,6 +6,7 @@ import io.ebeaninternal.server.util.DSelectColumnsParser; import javax.persistence.PersistenceException; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.regex.Pattern; /** @@ -28,11 +29,8 @@ final class DRawSqlColumnsParser { } private ColumnMapping parse() { - - List columnList = DSelectColumnsParser.parse(sqlSelect); - + Set columnList = DSelectColumnsParser.parse(sqlSelect); List columns = new ArrayList<>(columnList.size()); - for (String rawColumn : columnList) { columns.add(parseColumn(rawColumn)); } @@ -40,7 +38,6 @@ final class DRawSqlColumnsParser { } private ColumnMapping.Column parseColumn(String colInfo) { - String[] split = COLINFO_SPLIT.split(colInfo); if (split.length > 1) { ArrayList tmp = new ArrayList<>(split.length); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/util/DSelectColumnsParser.java b/ebean-core/src/main/java/io/ebeaninternal/server/util/DSelectColumnsParser.java index c172f92b2..b4ec33a67 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/util/DSelectColumnsParser.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/util/DSelectColumnsParser.java @@ -1,7 +1,7 @@ package io.ebeaninternal.server.util; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedHashSet; +import java.util.Set; /** * Splits a select clause into 'logical columns' taking into account functions and quotes. @@ -14,7 +14,7 @@ public final class DSelectColumnsParser { private int pos; - public static List parse(String sqlSelect) { + public static Set parse(String sqlSelect) { return new DSelectColumnsParser(sqlSelect).parse(); } @@ -23,9 +23,8 @@ public final class DSelectColumnsParser { this.end = selectClause.length(); } - private List parse() { - - ArrayList columns = new ArrayList<>(); + private Set parse() { + LinkedHashSet columns = new LinkedHashSet<>(); while (pos <= end) { columns.add(nextColumnInfo()); } diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/util/DSelectColumnsParserTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/util/DSelectColumnsParserTest.java index 0b30e225c..cc9234925 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/util/DSelectColumnsParserTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/util/DSelectColumnsParserTest.java @@ -2,7 +2,7 @@ package io.ebeaninternal.server.util; import org.junit.Test; -import java.util.List; +import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -11,49 +11,49 @@ public class DSelectColumnsParserTest { @Test public void parse() { - List cols = DSelectColumnsParser.parse("a,MD5(id::text) as b,c"); + Set cols = DSelectColumnsParser.parse("a,MD5(id::text) as b,c"); assertThat(cols).containsExactly("a", "MD5(id::text) as b", "c"); } @Test public void whitespace_is_trimmed() { - List cols = DSelectColumnsParser.parse("a , MD5(id::text) as b , c "); + Set cols = DSelectColumnsParser.parse("a , MD5(id::text) as b , c "); assertThat(cols).containsExactly("a", "MD5(id::text) as b", "c"); } @Test public void nestedFunctions() { - List cols = DSelectColumnsParser.parse("a , concat(id,'sd',inner(foo)) as b , c "); + Set cols = DSelectColumnsParser.parse("a , concat(id,'sd',inner(foo)) as b , c "); assertThat(cols).containsExactly("a", "concat(id,'sd',inner(foo)) as b", "c"); } @Test public void basic() { - List cols = DSelectColumnsParser.parse("name , status , billingAddress "); + Set cols = DSelectColumnsParser.parse("name , status , billingAddress "); assertThat(cols).containsExactly("name", "status", "billingAddress"); } @Test public void basic_noWhitespace() { - List cols = DSelectColumnsParser.parse("a,b,c"); + Set cols = DSelectColumnsParser.parse("a,b,c"); assertThat(cols).containsExactly("a", "b", "c"); } @Test public void formula_noWhitespace() { - List cols = DSelectColumnsParser.parse("a,concat(x,y),c"); + Set cols = DSelectColumnsParser.parse("a,concat(x,y),c"); assertThat(cols).containsExactly("a", "concat(x,y)", "c"); } @Test public void with_logicalCast_andAsAlias() { - List cols = DSelectColumnsParser.parse("name , concat(status,'-end')::String as fullName , billingAddress "); + Set cols = DSelectColumnsParser.parse("name , concat(status,'-end')::String as fullName , billingAddress "); assertThat(cols).containsExactly("name", "concat(status,'-end')::String as fullName", "billingAddress"); } diff --git a/ebean-core/src/test/java/org/tests/batchload/TestQueryJoin.java b/ebean-core/src/test/java/org/tests/batchload/TestQueryJoin.java index 1cbe7fd48..81bac2193 100644 --- a/ebean-core/src/test/java/org/tests/batchload/TestQueryJoin.java +++ b/ebean-core/src/test/java/org/tests/batchload/TestQueryJoin.java @@ -28,7 +28,7 @@ public class TestQueryJoin extends BaseTestCase { Query query = Ebean.find(Order.class).select("status") // .join("details","+query(10)") - .fetch("customer", "+lazy(10) name, status").fetch("customer.contacts").order().asc("id"); + .fetch("customer", "+lazy(10), name, status").fetch("customer.contacts").order().asc("id"); // .join("customer.billingAddress"); List list = query.findList(); diff --git a/ebean-core/src/test/java/org/tests/model/interfaces/SelfManyMany.java b/ebean-core/src/test/java/org/tests/model/interfaces/SelfManyMany.java new file mode 100644 index 000000000..6cfc52193 --- /dev/null +++ b/ebean-core/src/test/java/org/tests/model/interfaces/SelfManyMany.java @@ -0,0 +1,40 @@ +package org.tests.model.interfaces; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import java.util.List; + +@Entity +public class SelfManyMany { + + @Id + private long id; + + private final String name; + + @ManyToMany + // requires explicit @JoinTable + @JoinTable(name = "self_many_bridge", + joinColumns = @JoinColumn(name = "self_1_id"), + inverseJoinColumns = @JoinColumn(name = "self_2_id")) + private List related; + + public SelfManyMany(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public List getRelated() { + return related; + } +} diff --git a/ebean-core/src/test/java/org/tests/model/interfaces/TestSelfMany.java b/ebean-core/src/test/java/org/tests/model/interfaces/TestSelfMany.java new file mode 100644 index 000000000..e12c47cfd --- /dev/null +++ b/ebean-core/src/test/java/org/tests/model/interfaces/TestSelfMany.java @@ -0,0 +1,15 @@ +package org.tests.model.interfaces; + +import io.ebean.BaseTestCase; +import io.ebean.DB; +import org.junit.Test; + +public class TestSelfMany extends BaseTestCase { + + @Test + public void self_manyToMany() { + + SelfManyMany m = new SelfManyMany("1"); + DB.save(m); + } +} diff --git a/ebean-ddl-generator/pom.xml b/ebean-ddl-generator/pom.xml index c6039a3ca..c343386bf 100644 --- a/ebean-ddl-generator/pom.xml +++ b/ebean-ddl-generator/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean ddl generation @@ -29,14 +29,14 @@ io.ebean ebean-core-type - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided diff --git a/ebean-externalmapping-api/pom.xml b/ebean-externalmapping-api/pom.xml index b7229936c..fd23c73a2 100644 --- a/ebean-externalmapping-api/pom.xml +++ b/ebean-externalmapping-api/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean external mapping api diff --git a/ebean-externalmapping-xml/pom.xml b/ebean-externalmapping-xml/pom.xml index 7364bff24..806a215df 100644 --- a/ebean-externalmapping-xml/pom.xml +++ b/ebean-externalmapping-xml/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT @@ -33,7 +33,7 @@ io.ebean ebean-externalmapping-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT @@ -59,14 +59,14 @@ io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test io.ebean ebean-ddl-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test diff --git a/ebean-postgis/pom.xml b/ebean-postgis/pom.xml index 1240f27fe..a6a88a75f 100644 --- a/ebean-postgis/pom.xml +++ b/ebean-postgis/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean postgis @@ -24,7 +24,7 @@ io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided @@ -75,7 +75,7 @@ io.ebean ebean-test - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test diff --git a/ebean-querybean/pom.xml b/ebean-querybean/pom.xml index 3cd58500d..edcd84379 100644 --- a/ebean-querybean/pom.xml +++ b/ebean-querybean/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT @@ -27,7 +27,7 @@ io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided @@ -67,14 +67,14 @@ io.ebean ebean-ddl-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test io.ebean querybean-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test diff --git a/ebean-redis/pom.xml b/ebean-redis/pom.xml index 35d45e38a..e76555b30 100644 --- a/ebean-redis/pom.xml +++ b/ebean-redis/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean-redis @@ -22,35 +22,35 @@ io.ebean ebean-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided io.ebean ebean-querybean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test io.ebean querybean-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test io.ebean ebean-test - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test diff --git a/ebean-test/pom.xml b/ebean-test/pom.xml index 0c3632dd5..6809737df 100644 --- a/ebean-test/pom.xml +++ b/ebean-test/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT @@ -43,14 +43,14 @@ io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT provided io.ebean ebean-ddl-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT diff --git a/ebean/pom.xml b/ebean/pom.xml index 5732d2910..9cc0b0a60 100644 --- a/ebean/pom.xml +++ b/ebean/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT ebean composite @@ -22,34 +22,20 @@ io.ebean ebean-api - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT io.ebean ebean-querybean - 12.6.7-SNAPSHOT - - - - - io.ebean - ebean-ddl-generator - 12.6.7-SNAPSHOT - - - - - io.ebean - ebean-autotune - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT diff --git a/kotlin-querybean-generator/pom.xml b/kotlin-querybean-generator/pom.xml index 5d6336d29..7e37844df 100644 --- a/kotlin-querybean-generator/pom.xml +++ b/kotlin-querybean-generator/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT kotlin querybean generator @@ -29,7 +29,7 @@ io.ebean ebean-querybean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test @@ -43,7 +43,7 @@ io.ebean ebean-core - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test @@ -64,7 +64,7 @@ io.ebean ebean-ddl-generator - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT test diff --git a/kotlin-querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java b/kotlin-querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java index 8524a59f9..ee21711d2 100644 --- a/kotlin-querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java +++ b/kotlin-querybean-generator/src/main/java/io/ebean/querybean/generator/SimpleQueryBeanWriter.java @@ -8,6 +8,9 @@ import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -42,6 +45,23 @@ class SimpleQueryBeanWriter { "kotlin.Char" }; + // These are special classes under Kotlin, and are auto-imported, same as + // java.lang under Java + private static final Set kotlinBlackListedImports = Collections.unmodifiableSet( + new HashSet<>( + Arrays.asList( + "java.util.ArrayList", + "java.util.HashMap", + "java.util.HashSet", + "java.util.LinkedHashMap", + "java.util.LinkedHashSet", + "java.util.List", + "java.util.Map", + "java.util.Set" + ) + ) + ); + private final Set importTypes = new TreeSet<>(); private final List properties = new ArrayList<>(); @@ -158,6 +178,7 @@ class SimpleQueryBeanWriter { importTypes.add(kotlinTypes[i]); } } + importTypes.removeAll(kotlinBlackListedImports); } private boolean isEntity() { diff --git a/pom.xml b/pom.xml index c9e885454..6222be793 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ io.ebean ebean-parent - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT pom ebean parent diff --git a/querybean-generator/pom.xml b/querybean-generator/pom.xml index 52c966bea..adee59843 100644 --- a/querybean-generator/pom.xml +++ b/querybean-generator/pom.xml @@ -4,7 +4,7 @@ ebean-parent io.ebean - 12.6.7-SNAPSHOT + 12.6.8-SNAPSHOT querybean generator