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-core/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java index d9386ed9b..065884b54 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java @@ -452,7 +452,7 @@ public final class SqlTreeBuilder { // Also note that this can include transient properties. // This makes sense for transient properties used to // hold sum() count() type values (with SqlSelect) - final Set selectInclude = queryProps.getSelectInclude(); + final Set selectInclude = queryProps.getIncluded(); for (String propName : selectInclude) { if (!propName.isEmpty()) { addProperty(selectProps, desc, queryProps, propName); 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 2f73bceb7..364f6ab93 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 1310b709a..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,25 +106,20 @@ 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.append("select ", sb); + baseProps.asStringDebug("select ", sb); } if (fetchPaths != null) { for (OrmQueryProperties join : fetchPaths.values()) { if (sb.length() > 0) { sb.append(" "); } - join.append("fetch ", sb); + join.asStringDebug("fetch ", sb); } } return sb.toString(); @@ -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/OrmQueryProperties.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java index 805c3bf68..bbbc425de 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/OrmQueryProperties.java @@ -30,12 +30,8 @@ public class OrmQueryProperties implements Serializable { private final String parentPath; private final String path; - - private final String rawProperties; - private final String trimmedProperties; - - private final LinkedHashSet included; - + private final String properties; + private final Set included; private final FetchConfig fetchConfig; /** @@ -84,8 +80,7 @@ public class OrmQueryProperties implements Serializable { public OrmQueryProperties(String path) { this.path = path; this.parentPath = SplitName.parent(path); - this.rawProperties = null; - this.trimmedProperties = null; + this.properties = null; this.included = null; this.fetchConfig = DEFAULT_FETCH; } @@ -100,8 +95,7 @@ public class OrmQueryProperties implements Serializable { this.path = path; this.parentPath = SplitName.parent(path); - this.rawProperties = rawProperties; - this.trimmedProperties = response.properties; + this.properties = response.properties; this.included = response.included; this.cache = response.cache; this.readOnly = response.readOnly; @@ -115,39 +109,17 @@ public class OrmQueryProperties implements Serializable { } } - public OrmQueryProperties(String path, LinkedHashSet parsedProperties) { - if (parsedProperties == null) { - throw new IllegalArgumentException("parsedProperties is null"); - } - + public OrmQueryProperties(String path, Set included) { this.path = path; this.parentPath = SplitName.parent(path); // for rawSql parsedProperties can be empty (when only fetching Id property) - this.included = parsedProperties; - this.rawProperties = join(parsedProperties); - this.trimmedProperties = rawProperties; + this.included = included; + this.properties = String.join(",", included); this.cache = false; this.readOnly = false; this.fetchConfig = DEFAULT_FETCH; } - /** - * Join the set of properties into a comma delimited string. - */ - private String join(LinkedHashSet parsedProperties) { - StringBuilder sb = new StringBuilder(50); - boolean first = true; - for (String property : parsedProperties) { - if (first) { - first = false; - } else { - sb.append(","); - } - sb.append(property); - } - return sb.toString(); - } - /** * Copy constructor. */ @@ -155,8 +127,7 @@ public class OrmQueryProperties implements Serializable { this.fetchConfig = sourceFetchConfig; this.parentPath = source.parentPath; this.path = source.path; - this.rawProperties = source.rawProperties; - this.trimmedProperties = source.trimmedProperties; + this.properties = source.properties; this.cache = source.cache; this.readOnly = source.readOnly; this.filterMany = source.filterMany; @@ -240,8 +211,8 @@ public class OrmQueryProperties implements Serializable { @SuppressWarnings("unchecked") public void configureBeanQuery(SpiQuery query) { - if (trimmedProperties != null && !trimmedProperties.isEmpty()) { - query.select(trimmedProperties); + if (properties != null && !properties.isEmpty()) { + query.select(properties); } if (filterMany != null) { @@ -268,7 +239,7 @@ public class OrmQueryProperties implements Serializable { } public boolean hasSelectClause() { - if ("*".equals(trimmedProperties)) { + if ("*".equals(properties)) { // explicitly selected all properties return true; } @@ -280,25 +251,17 @@ public class OrmQueryProperties implements Serializable { * Return true if the properties and configuration are empty. */ public boolean isEmpty() { - return rawProperties == null || rawProperties.isEmpty(); + return properties == null || properties.isEmpty(); } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(40); - append("", sb); - return sb.toString(); - } - - public String append(String prefix, StringBuilder sb) { + public void asStringDebug(String prefix, StringBuilder sb) { sb.append(prefix); if (path != null) { sb.append(path).append(" "); } if (!isEmpty()) { - sb.append("(").append(rawProperties).append(")"); + sb.append("(").append(properties).append(")"); } - return sb.toString(); } boolean isChild(OrmQueryProperties possibleChild) { @@ -319,7 +282,7 @@ public class OrmQueryProperties implements Serializable { * Return the raw properties. */ public String getProperties() { - return rawProperties; + return properties; } /** @@ -350,10 +313,6 @@ public class OrmQueryProperties implements Serializable { includedBeanJoin.add(propertyName); } - public Set getSelectInclude() { - return included; - } - public Set getSelectQueryJoin() { return secondaryQueryJoins; } @@ -373,7 +332,6 @@ public class OrmQueryProperties implements Serializable { } boolean isIncluded(String propName) { - if (includedBeanJoin != null && includedBeanJoin.contains(propName)) { return false; } @@ -474,24 +432,21 @@ public class OrmQueryProperties implements Serializable { * Calculate the query plan hash. */ public void queryPlanHash(StringBuilder builder) { - - builder.append("qpp["); + builder.append("p["); builder.append(path); if (included != null){ - builder.append(" included:").append(included); + builder.append("/i").append(included); } if (secondaryQueryJoins != null) { - builder.append(" secondary:").append(secondaryQueryJoins); + builder.append("/s").append(secondaryQueryJoins); } - if (filterMany != null) { - builder.append(" filterMany["); + builder.append("/f["); filterMany.queryPlanHash(builder); builder.append("]"); } - if (fetchConfig != null) { - builder.append(" config:").append(fetchConfig.hashCode()); + builder.append("/c:").append(fetchConfig.hashCode()); } builder.append("]"); } 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 5c03e0a33..9350baf2b 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; @@ -53,9 +53,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; @@ -70,124 +68,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/ebean/plugin/BeanTypeTest.java b/ebean-core/src/test/java/io/ebean/plugin/BeanTypeTest.java index 2b880805a..820e89408 100644 --- a/ebean-core/src/test/java/io/ebean/plugin/BeanTypeTest.java +++ b/ebean-core/src/test/java/io/ebean/plugin/BeanTypeTest.java @@ -177,7 +177,7 @@ public class BeanTypeTest { beanType(Order.class).docStore().applyPath(orderQuery); OrmQueryDetail detail = orderQuery.getDetail(); - assertThat(detail.getChunk("customer", false).getSelectInclude()).containsExactly("id", "name"); + assertThat(detail.getChunk("customer", false).getIncluded()).containsExactly("id", "name"); } @Test(expected = IllegalStateException.class) diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java index f15cffc38..cc715509d 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java @@ -15,7 +15,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_empty() throws Exception { + public void when_empty() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse(""); assertAllDefaults(res); @@ -23,7 +23,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasStar() throws Exception { + public void when_hasStar() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("*"); assertAllDefaults(res); @@ -31,7 +31,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasCache() throws Exception { + public void when_hasCache() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+cache"); assertThat(res.cache).isTrue(); @@ -39,7 +39,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasCache_first() throws Exception { + public void when_hasCache_first() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+cache,id"); assertThat(res.cache).isTrue(); @@ -47,7 +47,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasCache_last() throws Exception { + public void when_hasCache_last() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+cache"); assertThat(res.cache).isTrue(); @@ -55,7 +55,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasCache_middle() throws Exception { + public void when_hasCache_middle() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+cache, id"); assertThat(res.cache).isTrue(); @@ -63,7 +63,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasReadOnly() throws Exception { + public void when_hasReadOnly() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+readonly"); assertThat(res.readOnly).isTrue(); @@ -71,7 +71,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasLazy() throws Exception { + public void when_hasLazy() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy"); assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(0); @@ -79,7 +79,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasLazyValue() throws Exception { + public void when_hasLazyValue() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy(20)"); assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); @@ -87,7 +87,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasLazyValue_last() throws Exception { + public void when_hasLazyValue_last() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+lazy(20)"); assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); @@ -95,7 +95,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_hasLazyValue_first() throws Exception { + public void when_hasLazyValue_first() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy(20),id,name"); assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); @@ -103,7 +103,7 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_allProperties() throws Exception { + public void when_allProperties() { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+query(4),+lazy(5)"); assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(5); @@ -111,14 +111,21 @@ public class OrmQueryPropertiesParserTest { } @Test - public void when_everything_set() throws Exception { + public void when_everything_set() { - OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("id, name +readonly +lazy(20) +query(30) +cache"); + OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("id, name, +readonly ,+lazy(20), +query(30) ,+cache"); + assertThat(res.included).containsExactly("id", "name"); assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); assertThat(res.fetchConfig.getQueryBatchSize()).isEqualTo(30); assertThat(res.readOnly).isTrue(); assertThat(res.cache).isTrue(); - assertThat(res.included).containsExactly("id", "name"); + } + + @Test + public void when_formula() { + + OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("a,MD5(id::text) as b,c"); + assertThat(res.included).containsExactly("a", "MD5(id::text) as b", "c"); } private void assertAllDefaults(OrmQueryPropertiesParser.Response res) { diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesTest.java index 547ea5966..196eb09a5 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/querydefn/OrmQueryPropertiesTest.java @@ -10,11 +10,11 @@ public class OrmQueryPropertiesTest { String append(String prefix, OrmQueryProperties p1) { StringBuilder sb = new StringBuilder(); - p1.append(prefix, sb); + p1.asStringDebug(prefix, sb); return sb.toString(); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = NullPointerException.class) public void construct_with_propertySet_when_null() { new OrmQueryProperties(null, (LinkedHashSet) null); } 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();