Skip to content

Commit 04b5fc1

Browse files
committed
Support the INSERT SELECT sytax
1 parent b64aca1 commit 04b5fc1

File tree

14 files changed

+287
-65
lines changed

14 files changed

+287
-65
lines changed

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/context/InsertContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class InsertContext implements Context {
1212
public final List<EntityMetamodel<?>> entityMetamodels;
1313
public final Map<Operand.Prop, Operand.Param> values = new LinkedHashMap<>();
1414
public final InsertSettings settings = new InsertSettings();
15+
public SelectContext selectContext;
1516

1617
public InsertContext(EntityMetamodel<?> entityMetamodel) {
1718
this.entityMetamodel = Objects.requireNonNull(entityMetamodel);

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/InsertDeclaration.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import java.util.Objects;
44
import java.util.function.Consumer;
5+
import java.util.function.Function;
56
import org.seasar.doma.jdbc.criteria.context.InsertContext;
7+
import org.seasar.doma.jdbc.criteria.context.SubSelectContext;
68

79
public class InsertDeclaration {
810

@@ -21,4 +23,10 @@ public void values(Consumer<ValuesDeclaration> block) {
2123
ValuesDeclaration declaration = new ValuesDeclaration(context);
2224
block.accept(declaration);
2325
}
26+
27+
public void select(Function<InsertSelectDeclaration, SubSelectContext<?>> block) {
28+
InsertSelectDeclaration declaration = new InsertSelectDeclaration();
29+
SubSelectContext<?> subSelectContext = block.apply(declaration);
30+
context.selectContext = subSelectContext.context;
31+
}
2432
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.seasar.doma.jdbc.criteria.declaration;
2+
3+
import org.seasar.doma.jdbc.criteria.metamodel.EntityMetamodel;
4+
5+
public class InsertSelectDeclaration {
6+
7+
public SubSelectFromDeclaration from(EntityMetamodel<?> entityMetamodel) {
8+
return new SubSelectFromDeclaration(entityMetamodel);
9+
}
10+
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/SubSelectFromDeclaration.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.seasar.doma.jdbc.criteria.declaration;
22

3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
36
import java.util.Objects;
47
import java.util.function.Consumer;
58
import org.seasar.doma.jdbc.criteria.context.Projection;
@@ -41,6 +44,17 @@ public SubSelectFromDeclaration orderBy(Consumer<OrderByNameDeclaration> block)
4144
return this;
4245
}
4346

47+
public <PROPERTY> SubSelectContext<PROPERTY> select() {
48+
SelectContext context = declaration.getContext();
49+
return new SubSelectContext<>(context);
50+
}
51+
52+
public <PROPERTY> SubSelectContext<PROPERTY> select(EntityMetamodel<?> entityMetamodel) {
53+
SelectContext context = declaration.getContext();
54+
context.projection = new Projection.List(entityMetamodel.allPropertyMetamodels());
55+
return new SubSelectContext<>(context);
56+
}
57+
4458
public <PROPERTY> SubSelectContext<PROPERTY> select(
4559
PropertyMetamodel<PROPERTY> propertyMetamodel) {
4660
SelectContext context = declaration.getContext();
@@ -54,4 +68,17 @@ public <PROPERTY1, PROPERTY2> SubSelectContext<Tuple2<PROPERTY1, PROPERTY2>> sel
5468
context.projection = new Projection.List(first, second);
5569
return new SubSelectContext<>(context);
5670
}
71+
72+
public SubSelectContext<List<?>> select(
73+
PropertyMetamodel<?> propertyMetamodel1,
74+
PropertyMetamodel<?> propertyMetamodel2,
75+
PropertyMetamodel<?>... propertyMetamodels) {
76+
SelectContext context = declaration.getContext();
77+
List<PropertyMetamodel<?>> list = new ArrayList<>(2 + propertyMetamodels.length);
78+
list.add(propertyMetamodel1);
79+
list.add(propertyMetamodel2);
80+
list.addAll(Arrays.asList(propertyMetamodels));
81+
context.projection = new Projection.List(list);
82+
return new SubSelectContext<>(context);
83+
}
5784
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/expression/AggregateFunction.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.seasar.doma.jdbc.criteria.expression;
22

3+
import java.util.Objects;
4+
import java.util.Optional;
5+
import java.util.function.BiFunction;
6+
import java.util.function.Function;
37
import org.seasar.doma.internal.jdbc.scalar.BasicScalar;
48
import org.seasar.doma.internal.jdbc.scalar.Scalar;
59
import org.seasar.doma.internal.jdbc.sql.ScalarInParameter;
@@ -11,11 +15,6 @@
1115
import org.seasar.doma.wrapper.LongWrapper;
1216
import org.seasar.doma.wrapper.Wrapper;
1317

14-
import java.util.Objects;
15-
import java.util.Optional;
16-
import java.util.function.BiFunction;
17-
import java.util.function.Function;
18-
1918
public interface AggregateFunction<PROPERTY> extends PropertyMetamodel<PROPERTY> {
2019
Asterisk Asterisk = new Asterisk();
2120

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.seasar.doma.jdbc.criteria.query;
22

3+
import java.util.List;
4+
import java.util.Objects;
5+
import java.util.function.BiFunction;
6+
import java.util.function.Function;
37
import org.seasar.doma.DomaException;
48
import org.seasar.doma.expr.ExpressionFunctions;
59
import org.seasar.doma.internal.jdbc.sql.BasicInParameter;
@@ -22,11 +26,6 @@
2226
import org.seasar.doma.message.Message;
2327
import org.seasar.doma.wrapper.StringWrapper;
2428

25-
import java.util.List;
26-
import java.util.Objects;
27-
import java.util.function.BiFunction;
28-
import java.util.function.Function;
29-
3029
public class BuilderSupport {
3130
private final Config config;
3231
private final Function<String, String> commenter;

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

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.seasar.doma.jdbc.criteria.context.InsertContext;
1212
import org.seasar.doma.jdbc.criteria.context.Operand;
1313
import org.seasar.doma.jdbc.criteria.metamodel.EntityMetamodel;
14+
import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
1415
import org.seasar.doma.jdbc.entity.EntityPropertyType;
1516
import org.seasar.doma.jdbc.entity.EntityType;
1617

@@ -43,31 +44,57 @@ public PreparedSql build() {
4344
buf.appendSql("insert into ");
4445
table(context.entityMetamodel);
4546
if (!context.values.isEmpty()) {
46-
buf.appendSql(" (");
47-
context
48-
.values
49-
.keySet()
50-
.forEach(
51-
key -> {
52-
column(key);
53-
buf.appendSql(", ");
54-
});
55-
buf.cutBackSql(2);
56-
buf.appendSql(") values (");
57-
context
58-
.values
59-
.values()
60-
.forEach(
61-
value -> {
62-
param(value);
63-
buf.appendSql(", ");
64-
});
65-
buf.cutBackSql(2);
66-
buf.appendSql(")");
47+
values();
48+
} else {
49+
if (context.selectContext != null) {
50+
select();
51+
}
6752
}
6853
return buf.build(commenter);
6954
}
7055

56+
private void values() {
57+
buf.appendSql(" (");
58+
context
59+
.values
60+
.keySet()
61+
.forEach(
62+
key -> {
63+
column(key);
64+
buf.appendSql(", ");
65+
});
66+
buf.cutBackSql(2);
67+
buf.appendSql(") values (");
68+
context
69+
.values
70+
.values()
71+
.forEach(
72+
value -> {
73+
param(value);
74+
buf.appendSql(", ");
75+
});
76+
buf.cutBackSql(2);
77+
buf.appendSql(")");
78+
}
79+
80+
private void select() {
81+
buf.appendSql(" (");
82+
context
83+
.entityMetamodel
84+
.allPropertyMetamodels()
85+
.forEach(
86+
p -> {
87+
column(p);
88+
buf.appendSql(", ");
89+
});
90+
buf.cutBackSql(2);
91+
buf.appendSql(") ");
92+
AliasManager aliasManager = new AliasManager(context.selectContext);
93+
SelectBuilder builder =
94+
new SelectBuilder(config, context.selectContext, Function.identity(), buf, aliasManager);
95+
builder.interpret();
96+
}
97+
7198
private void table(EntityMetamodel<?> entityMetamodel) {
7299
EntityType<?> entityType = entityMetamodel.asType();
73100
buf.appendSql(
@@ -76,7 +103,11 @@ private void table(EntityMetamodel<?> entityMetamodel) {
76103
}
77104

78105
private void column(Operand.Prop prop) {
79-
EntityPropertyType<?, ?> propertyType = prop.value.asType();
106+
column(prop.value);
107+
}
108+
109+
private void column(PropertyMetamodel<?> propertyMetamodel) {
110+
EntityPropertyType<?, ?> propertyType = propertyMetamodel.asType();
80111
buf.appendSql(
81112
propertyType.getColumnName(config.getNaming()::apply, config.getDialect()::applyQuote));
82113
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/statement/NativeSqlInsertStarting.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
import java.util.Objects;
44
import java.util.function.Consumer;
5+
import java.util.function.Function;
56
import org.seasar.doma.jdbc.Config;
7+
import org.seasar.doma.jdbc.criteria.context.SubSelectContext;
68
import org.seasar.doma.jdbc.criteria.declaration.InsertDeclaration;
9+
import org.seasar.doma.jdbc.criteria.declaration.InsertSelectDeclaration;
710
import org.seasar.doma.jdbc.criteria.declaration.ValuesDeclaration;
811

912
public class NativeSqlInsertStarting {
@@ -23,4 +26,11 @@ public NativeSqlInsertTerminal values(Consumer<ValuesDeclaration> block) {
2326
declaration.values(block);
2427
return new NativeSqlInsertTerminal(config, declaration);
2528
}
29+
30+
public NativeSqlInsertTerminal select(
31+
Function<InsertSelectDeclaration, SubSelectContext<?>> block) {
32+
Objects.requireNonNull(block);
33+
declaration.select(block);
34+
return new NativeSqlInsertTerminal(config, declaration);
35+
}
2636
}

doma-core/src/test/java/org/seasar/doma/jdbc/criteria/NativeSqlInsertTest.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class NativeSqlInsertTest {
1313
private final NativeSql nativeSql = new NativeSql(new MockConfig());
1414

1515
@Test
16-
void insertInto() {
16+
void insert() {
1717
Emp_ e = new Emp_();
1818
Statement<Integer> stmt =
1919
nativeSql
@@ -31,4 +31,27 @@ void insertInto() {
3131
"insert into EMP (ID, NAME, SALARY, VERSION) values (99, 'aaa', null, 1)",
3232
sql.getFormattedSql());
3333
}
34+
35+
@Test
36+
void insert_select_entity() {
37+
Emp_ e = new Emp_();
38+
Statement<Integer> stmt = nativeSql.insert(e).select(c -> c.from(e).select());
39+
40+
Sql<?> sql = stmt.asSql();
41+
assertEquals(
42+
"insert into EMP (ID, NAME, SALARY, VERSION) select t0_.ID, t0_.NAME, t0_.SALARY, t0_.VERSION from EMP t0_",
43+
sql.getFormattedSql());
44+
}
45+
46+
@Test
47+
void insert_select_properties() {
48+
Emp_ e = new Emp_();
49+
Statement<Integer> stmt =
50+
nativeSql.insert(e).select(c -> c.from(e).select(e.id, e.name, e.salary, e.version));
51+
52+
Sql<?> sql = stmt.asSql();
53+
assertEquals(
54+
"insert into EMP (ID, NAME, SALARY, VERSION) select t0_.ID, t0_.NAME, t0_.SALARY, t0_.VERSION from EMP t0_",
55+
sql.getFormattedSql());
56+
}
3457
}

doma-core/src/test/java/org/seasar/doma/jdbc/criteria/NativeSqlSelectTest.java

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
package org.seasar.doma.jdbc.criteria;
22

3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.avg;
5+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.concat;
6+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.count;
7+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.countDistinct;
8+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.literal;
9+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.max;
10+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.min;
11+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.sum;
12+
13+
import java.math.BigDecimal;
14+
import java.util.Arrays;
15+
import java.util.List;
316
import org.junit.jupiter.api.Test;
417
import org.seasar.doma.internal.jdbc.mock.MockConfig;
518
import org.seasar.doma.jdbc.CommentContext;
@@ -24,20 +37,6 @@
2437
import org.seasar.doma.jdbc.dialect.OracleDialect;
2538
import org.seasar.doma.jdbc.dialect.PostgresDialect;
2639

27-
import java.math.BigDecimal;
28-
import java.util.Arrays;
29-
import java.util.List;
30-
31-
import static org.junit.jupiter.api.Assertions.assertEquals;
32-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.avg;
33-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.concat;
34-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.count;
35-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.countDistinct;
36-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.literal;
37-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.max;
38-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.min;
39-
import static org.seasar.doma.jdbc.criteria.expression.Expressions.sum;
40-
4140
class NativeSqlSelectTest {
4241

4342
private final NativeSql nativeSql = new NativeSql(new MockConfig());
@@ -941,8 +940,7 @@ void aggregateFunction_countDistinct() {
941940
Buildable<?> stmt = nativeSql.from(e).select(countDistinct(e.id));
942941

943942
Sql<?> sql = stmt.asSql();
944-
assertEquals(
945-
"select count(distinct t0_.ID) from EMP t0_", sql.getFormattedSql());
943+
assertEquals("select count(distinct t0_.ID) from EMP t0_", sql.getFormattedSql());
946944
}
947945

948946
@Test

0 commit comments

Comments
 (0)