Skip to content

Commit

Permalink
Fix/Provide #471, #473
Browse files Browse the repository at this point in the history
  • Loading branch information
babyfish-ct committed Mar 22, 2024
1 parent 6a3885c commit 00f2b60
Show file tree
Hide file tree
Showing 18 changed files with 476 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ interface AbstractPropBuilder {

String getAlias();

AliasPattern getAliasPattern();

AbstractProp build(DtoType<?, ?> type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import org.antlr.v4.runtime.Token;

class AliasPattern {
public class AliasPattern {

private final CompilerContext<?, ?> ctx;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI

private final DtoTypeBuilder<T, P> parent;

private final AliasPattern aliasPattern;

private final Map<String, P> basePropMap;

private final int baseLine;
Expand Down Expand Up @@ -43,6 +45,7 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI

DtoPropBuilder(
DtoTypeBuilder<T, P> parent,
AliasPattern aliasPattern,
P baseProp,
int line,
int col,
Expand All @@ -58,6 +61,7 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI
name = name + "Id";
}
this.parent = Objects.requireNonNull(parent, "parent cannot be null");
this.aliasPattern = aliasPattern;
this.basePropMap = Collections.singletonMap(
Objects.requireNonNull(baseProp, "basePropMap cannot be null").getName(),
baseProp
Expand Down Expand Up @@ -85,6 +89,7 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI

DtoPropBuilder(
DtoTypeBuilder<T, P> parent,
AliasPattern aliasPattern,
DtoParser.PositivePropContext prop
) {
CompilerContext<T, P> ctx = parent.ctx;
Expand Down Expand Up @@ -115,6 +120,7 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI
}
}
this.parent = Objects.requireNonNull(parent, "parent cannot be null");
this.aliasPattern = aliasPattern;
this.baseLine = prop.props.get(0).getLine();
this.baseCol = prop.props.get(0).getCharPositionInLine();
this.aliasLine = prop.alias != null ? prop.alias.getLine() : prop.props.get(prop.props.size() - 1).getLine();
Expand Down Expand Up @@ -234,13 +240,13 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI
funcName = "id";
break;
case "flat":
if (!baseProp.isAssociation(true)) {
if (!baseProp.isAssociation(true) && !baseProp.isEmbedded()) {
throw ctx.exception(
prop.func.getLine(),
prop.func.getCharPositionInLine(),
"Cannot call the function \"flat\" because the current prop \"" +
baseProp +
"\" is not association"
"\" is neither association nor embedded"
);
}
if (baseProp.isList() && !parent.modifiers.contains(DtoTypeModifier.SPECIFICATION)) {
Expand Down Expand Up @@ -611,6 +617,15 @@ class DtoPropBuilder<T extends BaseType, P extends BaseProp> implements DtoPropI
}
}
}
if (!prop.bodySuperInterfaces.isEmpty() && funcName != null) {
throw ctx.exception(
prop.bodySuperInterfaces.get(0).start.getLine(),
prop.bodySuperInterfaces.get(0).start.getCharPositionInLine(),
"Illegal property \"" +
baseProp.getName() +
"\", cannot invoke any function when the target dto implements some interfaces"
);
}
targetTypeBuilder = new DtoTypeBuilder<>(
this,
ctx.getTargetType(baseProp),
Expand Down Expand Up @@ -821,6 +836,11 @@ private DtoPropBuilder<T, P> getNullableFlatParent() {
return null;
}

@Override
public AliasPattern getAliasPattern() {
return aliasPattern;
}

@SuppressWarnings("unchecked")
@Override
public DtoProp<T, P> build(DtoType<?, ?> type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ class DtoPropImpl<T extends BaseType, P extends BaseProp> implements DtoProp<T,
this.tail = this;
}

DtoPropImpl(DtoProp<T, P> head, DtoProp<T, P> next) {
DtoPropImpl(DtoProp<T, P> head, DtoProp<T, P> next, AliasPattern aliasPattern) {
this.basePropMap = head.getBasePropMap();
this.nextProp = next;
this.baseLine = next.getBaseLine();
this.baseCol = next.getBaseColumn();
this.alias = next.getAlias();
this.alias = aliasPattern != null ?
aliasPattern.alias(next.getName(), next.getAliasLine(), next.getAliasColumn()) :
next.getAlias();
this.aliasLine = next.getAliasLine();
this.aliasCol = next.getAliasColumn();
this.annotations = next.getAnnotations();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ private void handleMicro(DtoParser.MicroContext micro) {
DtoPropBuilder<T, P> propBuilder =
new DtoPropBuilder<>(
this,
currentAliasGroup,
baseProp,
micro.start.getLine(),
micro.start.getCharPositionInLine(),
Expand Down Expand Up @@ -287,6 +288,7 @@ private void handleMicro(DtoParser.MicroContext micro) {
DtoPropBuilder<T, P> propBuilder =
new DtoPropBuilder<>(
this,
currentAliasGroup,
baseProp,
qnCtx.stop.getLine(),
qnCtx.stop.getCharPositionInLine(),
Expand All @@ -306,7 +308,7 @@ public AliasPattern currentAliasGroup() {
}

private void handlePositiveProp(DtoParser.PositivePropContext prop) {
DtoPropBuilder<T, P> builder = new DtoPropBuilder<>(this, prop);
DtoPropBuilder<T, P> builder = new DtoPropBuilder<>(this, currentAliasGroup, prop);
for (P baseProp : builder.getBasePropMap().values()) {
handlePositiveProp0(builder, baseProp);
}
Expand Down Expand Up @@ -483,24 +485,6 @@ DtoType<T, P> build() {
return dtoType;
}

@SuppressWarnings("unchecked")
public DtoTypeBuilder<T, P> toRecursionBody(DtoPropBuilder<T, P> recursivePropBuilder) {
IdentityHashMap<DtoPropBuilder<T, P>, Object> removedMap = new IdentityHashMap<>();
for (AbstractPropBuilder builder : aliasPositivePropMap.values()) {
if (isExcluded(builder.getAlias()) || builder == recursivePropBuilder || !(builder instanceof DtoPropBuilder<?, ?>)) {
continue;
}
DtoPropBuilder<T, P> otherBuilder = (DtoPropBuilder<T, P>) builder;
if (otherBuilder.isRecursive()) {
removedMap.put(otherBuilder, null);
}
}
if (removedMap.isEmpty()) {
return this;
}
return new DtoTypeBuilder<>(this, removedMap.keySet());
}

@SuppressWarnings("unchecked")
private Map<String, AbstractProp> resolveDeclaredProps() {
if (this.declaredProps != null) {
Expand All @@ -511,38 +495,38 @@ private Map<String, AbstractProp> resolveDeclaredProps() {
if (isExcluded(builder.getAlias()) || positivePropMap.containsKey(builder.getBaseProp())) {
continue;
}
DtoProp<T, P> dtoProp = builder.build(dtoType);
declaredPropMap.put(dtoProp.getAlias(), dtoProp);
addProps(builder, declaredPropMap);
}
for (AbstractPropBuilder builder : aliasPositivePropMap.values()) {
if (isExcluded(builder.getAlias()) || declaredPropMap.containsKey(builder.getAlias())) {
continue;
}
AbstractProp abstractProp = builder.build(dtoType);
if (declaredPropMap.put(abstractProp.getAlias(), abstractProp) != null) {
throw ctx.exception(
abstractProp.getAliasLine(),
abstractProp.getAliasColumn(),
"Duplicated property alias \"" +
builder.getAlias() +
"\""
);
}
addProps(builder, declaredPropMap);
}
for (DtoPropBuilder<T, P> builder : flatPositiveProps) {
DtoProp<T, P> head = builder.build(dtoType);
Map<String, AbstractProp> deeperProps = builder.getTargetBuilder().resolveDeclaredProps();
for (AbstractProp deeperProp : deeperProps.values()) {
DtoProp<T, P> dtoProp = new DtoPropImpl<>(head, (DtoProp<T, P>) deeperProp);
if (isExcluded(dtoProp.getAlias())) {
List<AbstractProp> deeperProps = builder.getTargetBuilder().build().getProps();
for (AbstractProp deeperProp : deeperProps) {
if (deeperProp instanceof UserProp) {
UserProp userProp = (UserProp)deeperProp;
throw ctx.exception(
userProp.getAliasLine(),
userProp.getAliasColumn(),
"User defined property cannot be declared under flat type"
);
}
DtoProp<T, P> deeperDtoProp = (DtoProp<T, P>) deeperProp;
String alias = deeperDtoProp.getAlias();
DtoProp<T, P> dtoProp = new DtoPropImpl<>(head, deeperDtoProp, null);
if (isExcluded(alias)) {
continue;
}
if (declaredPropMap.put(dtoProp.getAlias(), dtoProp) != null) {
if (declaredPropMap.put(alias, dtoProp) != null) {
throw ctx.exception(
dtoProp.getAliasLine(),
dtoProp.getAliasColumn(),
"Duplicated property alias \"" +
dtoProp.getAlias() +
alias +
"\""
);
}
Expand All @@ -551,6 +535,32 @@ private Map<String, AbstractProp> resolveDeclaredProps() {
return this.declaredProps = Collections.unmodifiableMap(declaredPropMap);
}

private void addProps(AbstractPropBuilder propBuilder, Map<String, AbstractProp> outMap) {
AbstractProp prop = propBuilder.build(dtoType);
if (prop instanceof DtoProp<?, ?> && ((DtoProp<?, ?>)prop).isFlat()) {
for (AbstractProp deeperProp : ((DtoProp<?, ?>)prop).getTargetType().getProps()) {
DtoProp<T, P> flattedProp = new DtoPropImpl<>((DtoPropImpl<T, P>) prop, (DtoPropImpl<T, P>)deeperProp, propBuilder.getAliasPattern());
if (outMap.put(flattedProp.getAlias(), flattedProp) != null) {
throw ctx.exception(
flattedProp.getAliasLine(),
flattedProp.getAliasColumn(),
"Duplicated property alias \"" +
flattedProp.getAlias() +
"\""
);
}
}
} else if (outMap.put(prop.getAlias(), prop) != null) {
throw ctx.exception(
prop.getAliasLine(),
prop.getAliasColumn(),
"Duplicated property alias \"" +
propBuilder.getAlias() +
"\""
);
}
}

private boolean isExcluded(String alias) {
if (!negativePropAliasMap.containsKey(alias)) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ public String getDoc() {
return doc;
}

@Override
public AliasPattern getAliasPattern() {
return null;
}

public UserProp build(DtoType<?, ?> type) {
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,36 @@ public void testFlat6() {
Assertions.assertEquals("valueIn", prop.getFuncName());
}

@Test
public void testFlat7() {
List<DtoType<BaseType, BaseProp>> dtoTypes = MyDtoCompiler.treeNode(
"TreeFlatView {\n" +
" #allScalars(this)\n" +
" flat(parent) {\n" +
" as(^ -> parent) {\n" +
" #allScalars(this)\n" +
" flat(parent) {\n" +
" as(^ -> parent) {\n" +
" #allScalars(this)\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}\n"
);
assertContentEquals(
"TreeFlatView {" +
"--->id, " +
"--->name, " +
"--->@optional parent.id as parentId, " +
"--->@optional parent.name as parentName, " +
"--->@optional parent.parent.id.id as parentParentId, " +
"--->@optional parent.parent.name.name as parentParentName" +
"}",
dtoTypes.get(0).toString()
);
}

@Test
public void testUserProp() {
List<DtoType<BaseType, BaseProp>> dtoTypes = MyDtoCompiler.book(
Expand Down
41 changes: 41 additions & 0 deletions project/jimmer-sql-kotlin/src/test/dto/Transform.dto
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,45 @@ TransformView2 {
y
}
}
}

TransformFlatView {
id
flat(source) {
as(^ -> source) {
flat(leftTop) {
x as x1
y as y1
}
flat(rightBottom) {
x as x2
y as y2
}
}
}
flat(target) {
as(^ -> target) {
flat(leftTop) {
x as x1
y as y1
}
flat(rightBottom) {
x as x2
y as y2
}
}
}
}

specification TransformSpecification {
flat(source) {
flat(leftTop) {
ge(x)
}
}
flat(target) {
flat(rightBottom) {
le(x)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import org.babyfish.jimmer.sql.kt.model.classic.book.id
import org.babyfish.jimmer.sql.kt.model.classic.store.BookStore
import org.babyfish.jimmer.sql.kt.model.classic.store.name
import org.babyfish.jimmer.sql.kt.model.classic.store.website
import org.babyfish.jimmer.sql.kt.model.hr.Employee
import org.babyfish.jimmer.sql.kt.model.hr.departmentId
import org.babyfish.jimmer.sql.kt.model.inheritance.Administrator
import org.babyfish.jimmer.sql.kt.model.inheritance.name
import org.junit.Test
Expand Down Expand Up @@ -171,4 +173,22 @@ class DMLTest : AbstractMutationTest() {
rowCount(4)
}
}

@Test
fun testDeleteByAssociatedId() {
executeAndExpectRowCount(
sqlClient.createDelete(Employee::class) {
where(table.departmentId eq 1L)
}
) {
statement {
sql(
"""delete from EMPLOYEE tb_1_
|where tb_1_.DEPARTMENT_ID = ?
|and tb_1_.DELETED_UUID is null""".trimMargin()
)
}
rowCount(2)
}
}
}
Loading

0 comments on commit 00f2b60

Please sign in to comment.