Skip to content

Commit f4ef6d3

Browse files
committed
Make embeddable diggable
1 parent a3d9711 commit f4ef6d3

File tree

8 files changed

+66
-72
lines changed

8 files changed

+66
-72
lines changed

ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,6 +2362,12 @@ ElPropertyValue buildElGetValue(String propName, ElPropertyChainBuilder chain, b
23622362
if (assocProp == null) {
23632363
return null;
23642364
}
2365+
// this method is an entry-point, although it introduces recursive calls via
2366+
// buildElPropertyValue -> createElPropertyValue -> buildElGetValue (back to here)
2367+
// it seams we can initialize ElPropertyChainBuilder at this point and skip further checks.
2368+
if (chain == null) {
2369+
chain = new ElPropertyChainBuilder(propName);
2370+
}
23652371
String remainder = propName.substring(basePos + 1);
23662372
return assocProp.buildElPropertyValue(propName, remainder, chain, propertyDeploy);
23672373
}
@@ -2373,9 +2379,7 @@ ElPropertyValue buildElGetValue(String propName, ElPropertyChainBuilder chain, b
23732379
if (property == null) {
23742380
throw new PersistenceException("No property found for [" + propName + "] in expression " + chain.expression());
23752381
}
2376-
if (property.containsMany()) {
2377-
chain.setContainsMany();
2378-
}
2382+
23792383
return chain.add(property).build();
23802384
}
23812385

ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssoc.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,7 @@ public boolean hasForeignKeyIndex() {
161161
ElPropertyValue createElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
162162
// associated or embedded bean
163163
BeanDescriptor<?> embDesc = targetDescriptor();
164-
if (chain == null) {
165-
chain = new ElPropertyChainBuilder(isEmbedded(), propName);
166-
}
167164
chain.add(this);
168-
if (containsMany()) {
169-
chain.setContainsMany();
170-
}
171165
return embDesc.buildElGetValue(remainder, chain, propertyDeploy);
172166
}
173167

ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocOne.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,17 @@ Object naturalKeyVal(Map<String, Object> values) {
210210
@Override
211211
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
212212
if (embedded) {
213-
BeanProperty embProp = embeddedPropsMap.get(remainder);
213+
String embName = remainder;
214+
int basePos = remainder.indexOf('.');
215+
if (basePos > -1) {
216+
embName = remainder.substring(0, basePos);
217+
}
218+
BeanProperty embProp = embeddedPropsMap.get(embName);
219+
214220
if (embProp == null) {
215-
String msg = "Embedded Property " + remainder + " not found in " + fullName();
221+
String msg = "Embedded Property " + embName + " not found in " + fullName();
216222
throw new PersistenceException(msg);
217223
}
218-
if (chain == null) {
219-
chain = new ElPropertyChainBuilder(true, propName);
220-
}
221-
chain.add(this);
222-
chain.setEmbedded(true);
223-
return chain.add(embProp).build();
224224
}
225225
return createElPropertyValue(propName, remainder, chain, propertyDeploy);
226226
}

ebean-core/src/main/java/io/ebeaninternal/server/el/ElPropertyChain.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,38 +37,32 @@ public final class ElPropertyChain implements ElPropertyValue {
3737
private final ScalarType<?> scalarType;
3838
private final ElPropertyValue lastElPropertyValue;
3939

40-
public ElPropertyChain(boolean containsMany, boolean embedded, String expression, ElPropertyValue[] chain) {
41-
this.containsMany = containsMany;
40+
public ElPropertyChain(String expression, boolean containsMany, ElPropertyValue chain[]) {
4241
this.chain = chain;
4342
this.expression = expression;
43+
this.containsMany = containsMany;
44+
4445
int dotPos = expression.lastIndexOf('.');
4546
if (dotPos > -1) {
4647
this.name = expression.substring(dotPos + 1);
47-
if (embedded) {
48-
int embPos = expression.lastIndexOf('.', dotPos - 1);
49-
this.prefix = embPos == -1 ? null : expression.substring(0, embPos);
50-
51-
} else {
52-
this.prefix = expression.substring(0, dotPos);
53-
}
48+
this.prefix = expression.substring(0, dotPos);
5449
} else {
5550
this.prefix = null;
5651
this.name = expression;
5752
}
5853

59-
this.assocId = chain[chain.length - 1].isAssocId();
60-
61-
this.last = chain.length - 1;
62-
this.lastBeanProperty = chain[chain.length - 1].beanProperty();
54+
this.last = this.chain.length - 1;
55+
this.lastElPropertyValue = this.chain[this.last];
56+
this.assocId = this.lastElPropertyValue.isAssocId();
57+
this.lastBeanProperty = lastElPropertyValue.beanProperty();
6358
if (lastBeanProperty != null) {
6459
this.scalarType = lastBeanProperty.scalarType();
6560
} else {
6661
// case for nested compound type (non-scalar)
6762
this.scalarType = null;
6863
}
69-
this.lastElPropertyValue = chain[chain.length - 1];
70-
this.placeHolder = placeHolder(prefix, lastElPropertyValue, false);
71-
this.placeHolderEncrypted = placeHolder(prefix, lastElPropertyValue, true);
64+
this.placeHolder = placeHolder(this.prefix, lastElPropertyValue, false);
65+
this.placeHolderEncrypted = placeHolder(this.prefix, lastElPropertyValue, true);
7266
}
7367

7468
@Override

ebean-core/src/main/java/io/ebeaninternal/server/el/ElPropertyChainBuilder.java

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,19 @@ public final class ElPropertyChainBuilder {
1717

1818
private final String expression;
1919
private final List<ElPropertyValue> chain = new ArrayList<>();
20-
private boolean embedded;
21-
private boolean containsMany;
20+
private boolean containsMany = false;
2221

2322
/**
2423
* Create with the original expression.
2524
*/
26-
public ElPropertyChainBuilder(boolean embedded, String expression) {
27-
this.embedded = embedded;
25+
public ElPropertyChainBuilder(String expression) {
2826
this.expression = expression;
2927
}
3028

3129
public boolean isContainsMany() {
3230
return containsMany;
3331
}
3432

35-
public void setContainsMany() {
36-
this.containsMany = true;
37-
}
38-
3933
public String expression() {
4034
return expression;
4135
}
@@ -48,20 +42,16 @@ public ElPropertyChainBuilder add(ElPropertyValue element) {
4842
throw new NullPointerException("element null in expression " + expression);
4943
}
5044
chain.add(element);
45+
if (element.containsMany()) {
46+
containsMany = true;
47+
}
5148
return this;
5249
}
5350

5451
/**
5552
* Build the immutable ElGetChain from the build information.
5653
*/
5754
public ElPropertyChain build() {
58-
return new ElPropertyChain(containsMany, embedded, expression, chain.toArray(new ElPropertyValue[0]));
59-
}
60-
61-
/**
62-
* Permits to set whole chain as embedded when the leaf is embedded
63-
*/
64-
public void setEmbedded(boolean embedded) {
65-
this.embedded = embedded;
55+
return new ElPropertyChain(expression, containsMany, chain.toArray(new ElPropertyValue[0]));
6656
}
6757
}

ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeAlias.java

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import io.ebeaninternal.api.SpiQuery;
55

66
import java.util.HashMap;
7-
import java.util.HashSet;
87
import java.util.Map;
98
import java.util.Set;
109
import java.util.TreeSet;
@@ -16,7 +15,8 @@ final class SqlTreeAlias {
1615

1716
private final SpiQuery.TemporalMode temporalMode;
1817
private final TreeSet<String> joinProps = new TreeSet<>();
19-
private HashSet<String> embeddedPropertyJoins;
18+
// embedded property as key, and true if many-where-property
19+
private HashMap<String, Boolean> embeddedPropertyJoins;
2020
private final TreeSet<String> manyWhereJoinProps = new TreeSet<>();
2121
private final HashMap<String, String> aliasMap = new HashMap<>();
2222
private final HashMap<String, String> manyWhereAliasMap = new HashMap<>();
@@ -32,19 +32,19 @@ final class SqlTreeAlias {
3232
/**
3333
* Add joins to support where predicates
3434
*/
35-
void addManyWhereJoins(Set<String> manyWhereJoins) {
35+
void addManyWhereJoins(Set<String> manyWhereJoins, STreeType desc) {
3636
if (manyWhereJoins != null) {
3737
for (String include : manyWhereJoins) {
38-
addPropertyJoin(include, manyWhereJoinProps);
38+
addPropertyJoin(include, manyWhereJoinProps, desc, true);
3939
}
4040
}
4141
}
4242

43-
private void addEmbeddedPropertyJoin(String embProp) {
43+
private void addEmbeddedPropertyJoin(String embProp, Boolean isManyWhere) {
4444
if (embeddedPropertyJoins == null) {
45-
embeddedPropertyJoins = new HashSet<>();
45+
embeddedPropertyJoins = new HashMap<>();
4646
}
47-
embeddedPropertyJoins.add(embProp);
47+
embeddedPropertyJoins.put(embProp, isManyWhere);
4848
}
4949

5050
/**
@@ -53,21 +53,21 @@ private void addEmbeddedPropertyJoin(String embProp) {
5353
public void addJoin(Set<String> propJoins, STreeType desc) {
5454
if (propJoins != null) {
5555
for (String propJoin : propJoins) {
56-
if (desc.isEmbeddedPath(propJoin)) {
57-
addEmbeddedPropertyJoin(propJoin);
58-
} else {
59-
addPropertyJoin(propJoin, joinProps);
60-
}
56+
addPropertyJoin(propJoin, joinProps, desc, false);
6157
}
6258
}
6359
}
6460

65-
private void addPropertyJoin(String include, TreeSet<String> set) {
66-
if (set.add(include)) {
67-
String[] split = SplitName.split(include);
68-
if (split[0] != null) {
69-
addPropertyJoin(split[0], set);
70-
}
61+
private void addPropertyJoin(String include, TreeSet<String> set, STreeType desc, Boolean isManyWhere) {
62+
if (include == null) {
63+
return;
64+
}
65+
String[] split = SplitName.split(include);
66+
if (desc.isEmbeddedPath(include)) {
67+
addEmbeddedPropertyJoin(include, isManyWhere);
68+
addPropertyJoin(split[0], set, desc, isManyWhere);
69+
} else if (set.add(include)) {
70+
addPropertyJoin(split[0], set, desc, isManyWhere);
7171
}
7272
}
7373

@@ -86,11 +86,14 @@ void buildAlias() {
8686

8787
private void mapEmbeddedPropertyAlias() {
8888
if (embeddedPropertyJoins != null) {
89-
for (String propJoin : embeddedPropertyJoins) {
90-
String[] split = SplitName.split(propJoin);
89+
for (Map.Entry<String,Boolean> propJoin : embeddedPropertyJoins.entrySet()) {
90+
String[] split = SplitName.split(propJoin.getKey());
9191
// the table alias of the parent path
92-
String alias = tableAlias(split[0]);
93-
aliasMap.put(propJoin, alias);
92+
if (Boolean.TRUE.equals(propJoin.getValue())) {
93+
manyWhereAliasMap.put(propJoin.getKey(), tableAliasManyWhere(split[0]));
94+
} else {
95+
aliasMap.put(propJoin.getKey(), tableAlias(split[0]));
96+
}
9497
}
9598
}
9699
}

ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ private SqlTreeNode buildRootNode(STreeType desc) {
220220
if (!rawSql) {
221221
alias.addJoin(queryDetail.getFetchPaths(), desc);
222222
alias.addJoin(predicates.predicateIncludes(), desc);
223-
alias.addManyWhereJoins(manyWhereJoins.propertyNames());
223+
alias.addManyWhereJoins(manyWhereJoins.propertyNames(), desc);
224224
// build set of table alias
225225
alias.buildAlias();
226226
predicates.parseTableAlias(alias);
@@ -681,6 +681,12 @@ private SqlTreeNodeExtraJoin findExtraJoinRoot(String includeProp, SqlTreeNodeEx
681681
// parent already handled by select
682682
return childJoin;
683683
}
684+
if (desc.isEmbeddedPath(parentPropertyName)) {
685+
// digging in embedded property
686+
// so we have to join parent property path
687+
includeProp = parentPropertyName;
688+
continue;
689+
}
684690

685691
SqlTreeNodeExtraJoin parentJoin = joinRegister.get(parentPropertyName);
686692
if (parentJoin == null) {

ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public void appendFrom(DbSqlContext ctx, SqlJoinType currentJoinType) {
8383
* intersection table if this is a ManyToMany node.
8484
*/
8585
private void appendFromBaseTable(DbSqlContext ctx, SqlJoinType joinType) {
86+
if (nodeBeanProp.isEmbedded()) {
87+
return;
88+
}
8689
String alias = ctx.tableAliasManyWhere(prefix);
8790
String parentAlias = ctx.tableAliasManyWhere(parentPrefix);
8891

0 commit comments

Comments
 (0)