Skip to content

Commit a620ef0

Browse files
committed
Enhance aggregate strategies with alias validation
1 parent 4d9579e commit a620ef0

File tree

13 files changed

+95
-30
lines changed

13 files changed

+95
-30
lines changed

doma-core/src/main/java/org/seasar/doma/jdbc/aggregate/AbstractAggregateStrategyType.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,27 @@
2121

2222
public abstract class AbstractAggregateStrategyType implements AggregateStrategyType {
2323

24+
private final String name;
2425
private final EntityType<?> root;
2526
private final String tableAlias;
2627
private final List<AssociationLinkerType<?, ?>> associationLinkerTypes;
2728

2829
protected AbstractAggregateStrategyType(
30+
String name,
2931
EntityType<?> root,
3032
String tableAlias,
3133
List<AssociationLinkerType<?, ?>> associationLinkerTypes) {
32-
Objects.requireNonNull(tableAlias);
34+
this.name = Objects.requireNonNull(name);
3335
this.root = Objects.requireNonNull(root);
3436
this.tableAlias = Objects.requireNonNull(tableAlias);
3537
this.associationLinkerTypes = Objects.requireNonNull(associationLinkerTypes);
3638
}
3739

40+
@Override
41+
public String getName() {
42+
return name;
43+
}
44+
3845
@Override
3946
public EntityType<?> getRoot() {
4047
return root;

doma-core/src/main/java/org/seasar/doma/jdbc/aggregate/AggregateStrategyType.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.seasar.doma.jdbc.aggregate;
1717

18+
import java.util.ArrayList;
1819
import java.util.List;
1920
import org.seasar.doma.jdbc.entity.EntityType;
2021

@@ -23,9 +24,21 @@
2324
* its associated entities.
2425
*/
2526
public interface AggregateStrategyType {
27+
28+
String getName();
29+
2630
EntityType<?> getRoot();
2731

2832
String getTableAlias();
2933

3034
List<AssociationLinkerType<?, ?>> getAssociationLinkerTypes();
35+
36+
default List<String> getTableAliases() {
37+
List<String> result = new ArrayList<>();
38+
result.add(getTableAlias());
39+
for (AssociationLinkerType<?, ?> associationLinkerType : getAssociationLinkerTypes()) {
40+
result.add(associationLinkerType.getTableAlias());
41+
}
42+
return result;
43+
}
3144
}

doma-core/src/main/java/org/seasar/doma/jdbc/query/AbstractSelectQuery.java

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919

2020
import java.util.Arrays;
2121
import java.util.HashMap;
22+
import java.util.HashSet;
2223
import java.util.List;
2324
import java.util.Map;
2425
import java.util.Set;
2526
import java.util.function.BiFunction;
2627
import java.util.function.Function;
2728
import java.util.stream.Collectors;
2829
import java.util.stream.Stream;
30+
import org.seasar.doma.DomaException;
2931
import org.seasar.doma.FetchType;
3032
import org.seasar.doma.internal.expr.ExpressionEvaluator;
3133
import org.seasar.doma.internal.expr.Value;
@@ -45,7 +47,6 @@
4547
import org.seasar.doma.jdbc.aggregate.AggregateStrategyType;
4648
import org.seasar.doma.jdbc.command.SelectCommand;
4749
import org.seasar.doma.jdbc.dialect.Dialect;
48-
import org.seasar.doma.jdbc.entity.EntityPropertyType;
4950
import org.seasar.doma.jdbc.entity.EntityType;
5051
import org.seasar.doma.message.Message;
5152
import org.seasar.doma.wrapper.PrimitiveLongWrapper;
@@ -138,34 +139,38 @@ protected List<String> expandAggregateColumns(ExpandNode node, String aliasCsv)
138139
if (aggregateStrategyType == null) {
139140
return List.of();
140141
}
141-
Set<String> aliases =
142+
143+
Set<String> definedAliases = new HashSet<>(aggregateStrategyType.getTableAliases());
144+
Set<String> requiredAliases =
142145
Arrays.stream(aliasCsv.split(","))
143146
.map(String::trim)
144147
.filter(s -> !s.isEmpty())
148+
.peek(
149+
s -> {
150+
if (!definedAliases.contains(s)) {
151+
throw new DomaException(Message.DOMA2239, s, aggregateStrategyType.getName());
152+
}
153+
})
145154
.collect(Collectors.toSet());
146-
Stream<Pair<String, EntityPropertyType<?, ?>>> rootColumns =
147-
entityType.getEntityPropertyTypes().stream()
148-
.map(
149-
p -> {
150-
String tableAlias = aggregateStrategyType.getTableAlias();
151-
return new Pair<>(tableAlias, p);
152-
});
153-
Stream<Pair<String, EntityPropertyType<?, ?>>> associationColumns =
154-
aggregateStrategyType.getAssociationLinkerTypes().stream()
155-
.flatMap(
156-
linkerType -> {
157-
String tableAlias = linkerType.getTableAlias();
158-
return linkerType.getTarget().getEntityPropertyTypes().stream()
159-
.map(p -> new Pair<>(tableAlias, p));
160-
});
155+
161156
Naming naming = config.getNaming();
162157
Dialect dialect = config.getDialect();
163-
return Stream.concat(rootColumns, associationColumns)
164-
.filter(p -> aliases.isEmpty() || aliases.contains(p.fst))
158+
159+
Stream<Pair<String, EntityType<?>>> rootStream =
160+
Stream.of(
161+
new Pair<>(aggregateStrategyType.getTableAlias(), aggregateStrategyType.getRoot()));
162+
Stream<Pair<String, EntityType<?>>> associationStream =
163+
aggregateStrategyType.getAssociationLinkerTypes().stream()
164+
.map(it -> new Pair<>(it.getTableAlias(), it.getTarget()));
165+
166+
return Stream.concat(rootStream, associationStream)
167+
.filter(pair -> requiredAliases.isEmpty() || requiredAliases.contains(pair.fst))
168+
.flatMap(
169+
pair -> pair.snd.getEntityPropertyTypes().stream().map(it -> new Pair<>(pair.fst, it)))
165170
.map(
166-
p -> {
167-
String tableAlias = p.fst;
168-
String columnName = p.snd.getColumnName(naming::apply, dialect::applyQuote);
171+
pair -> {
172+
String tableAlias = pair.fst;
173+
String columnName = pair.snd.getColumnName(naming::apply, dialect::applyQuote);
169174
return String.format("%1$s.%2$s as %1$s_%2$s", tableAlias, columnName);
170175
})
171176
.toList();

doma-core/src/main/java/org/seasar/doma/message/Message.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ public enum Message implements MessageResource {
284284
{4}
285285
PATH=[{2}]
286286
SQL=[{3}]"""),
287+
DOMA2239(
288+
"The table alias \"{0}\" passed to the expansion directive is not defined in the aggregate strategy \"{1}\"."),
287289

288290
// expression
289291
DOMA3001(

doma-processor/src/main/java/org/seasar/doma/internal/apt/generator/AggregateStrategyTypeGenerator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ private void printConstructor() {
7878
iprint("private %1$s() {%n", simpleName);
7979
indent();
8080
iprint(
81-
"super(%1$s, \"%2$s\", java.util.List.of(%n",
82-
strategyMeta.root().getTypeCode(), strategyMeta.tableAlias());
81+
"super(\"%1$s\", %2$s, \"%3$s\", java.util.List.of(%n",
82+
/* 1 */ strategyMeta.typeElement().getQualifiedName(),
83+
/* 2 */ strategyMeta.root().getTypeCode(),
84+
/* 3 */ strategyMeta.tableAlias());
8385
indent();
8486
Iterator<AssociationLinkerMeta> iter = strategyMeta.associationLinkerMetas().iterator();
8587
while (iter.hasNext()) {

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/aggregate/AggregateStrategyMeta.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717

1818
import java.util.List;
1919
import java.util.Objects;
20+
import javax.lang.model.element.TypeElement;
2021
import org.seasar.doma.internal.apt.cttype.EntityCtType;
2122
import org.seasar.doma.internal.apt.meta.TypeElementMeta;
2223

2324
public record AggregateStrategyMeta(
24-
EntityCtType root, String tableAlias, List<AssociationLinkerMeta> associationLinkerMetas)
25+
TypeElement typeElement,
26+
EntityCtType root,
27+
String tableAlias,
28+
List<AssociationLinkerMeta> associationLinkerMetas)
2529
implements TypeElementMeta {
2630

2731
public AggregateStrategyMeta {

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/aggregate/AggregateStrategyMetaFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public AggregateStrategyMeta createTypeElementMeta(TypeElement typeElement) {
8282
validateAllTableAliases(aggregateStrategyAnnot.getTableAliasValue(), associationLinkerMetas);
8383
validateNavigation(root, associationLinkerMetas);
8484
return new AggregateStrategyMeta(
85-
root, aggregateStrategyAnnot.getTableAliasValue(), associationLinkerMetas);
85+
typeElement, root, aggregateStrategyAnnot.getTableAliasValue(), associationLinkerMetas);
8686
}
8787

8888
private void validateAllPropertyPaths(List<AssociationLinkerMeta> associationLinkerMetas) {

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/aggregate/AggregateStrategyProcessorTest_ChildEntityStrategy.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public final class _ChildEntityStrategy extends org.seasar.doma.jdbc.aggregate.A
1111
}
1212

1313
private _ChildEntityStrategy() {
14-
super(org.seasar.doma.internal.apt.processor.aggregate._ChildEntity.getSingletonInternal(), "c", java.util.List.of(
14+
super("org.seasar.doma.internal.apt.processor.aggregate.ChildEntityStrategy", org.seasar.doma.internal.apt.processor.aggregate._ChildEntity.getSingletonInternal(), "c", java.util.List.of(
1515
org.seasar.doma.jdbc.aggregate.AssociationLinkerType.of("", "dept", 1, "d", org.seasar.doma.internal.apt.processor.aggregate._ChildEntity.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate._Dept.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate.ChildEntityStrategy.dept),
1616
org.seasar.doma.jdbc.aggregate.AssociationLinkerType.of("", "emp", 1, "e", org.seasar.doma.internal.apt.processor.aggregate._ChildEntity.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate.ChildEntityStrategy.emp)
1717
));

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/aggregate/AggregateStrategyProcessorTest_DeptStrategy.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public final class _DeptStrategy extends org.seasar.doma.jdbc.aggregate.Abstract
1111
}
1212

1313
private _DeptStrategy() {
14-
super(org.seasar.doma.internal.apt.processor.aggregate._Dept.getSingletonInternal(), "d", java.util.List.of(
14+
super("org.seasar.doma.internal.apt.processor.aggregate.DeptStrategy", org.seasar.doma.internal.apt.processor.aggregate._Dept.getSingletonInternal(), "d", java.util.List.of(
1515
org.seasar.doma.jdbc.aggregate.AssociationLinkerType.of("employees", "employees.address", 2, "a", org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate._Address.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate.DeptStrategy.address),
1616
org.seasar.doma.jdbc.aggregate.AssociationLinkerType.of("", "employees", 1, "e", org.seasar.doma.internal.apt.processor.aggregate._Dept.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate.DeptStrategy.dept)
1717
));

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/aggregate/AggregateStrategyProcessorTest_EmpStrategy.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public final class _EmpStrategy extends org.seasar.doma.jdbc.aggregate.AbstractA
1111
}
1212

1313
private _EmpStrategy() {
14-
super(org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), "e", java.util.List.of(
14+
super("org.seasar.doma.internal.apt.processor.aggregate.EmpStrategy", org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), "e", java.util.List.of(
1515
org.seasar.doma.jdbc.aggregate.AssociationLinkerType.of("", "dept", 1, "d", org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate._Dept.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate.EmpStrategy.dept),
1616
org.seasar.doma.jdbc.aggregate.AssociationLinkerType.of("", "address", 1, "a", org.seasar.doma.internal.apt.processor.aggregate._Emp.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate._Address.getSingletonInternal(), org.seasar.doma.internal.apt.processor.aggregate.EmpStrategy.address)
1717
));

0 commit comments

Comments
 (0)