66import java .util .List ;
77import java .util .Map ;
88import java .util .Objects ;
9- import java .util .stream .Collectors ;
109import org .seasar .doma .internal .jdbc .sql .PreparedSqlBuilder ;
1110import org .seasar .doma .jdbc .Config ;
12- import org .seasar .doma .jdbc .InParameter ;
1311import org .seasar .doma .jdbc .PreparedSql ;
1412import org .seasar .doma .jdbc .SqlKind ;
1513import org .seasar .doma .jdbc .command .Command ;
2018import org .seasar .doma .jdbc .criteria .declaration .InsertDeclaration ;
2119import org .seasar .doma .jdbc .criteria .metamodel .PropertyMetamodel ;
2220import org .seasar .doma .jdbc .criteria .query .CriteriaQuery ;
23- import org .seasar .doma .jdbc .criteria .tuple .Tuple2 ;
2421import org .seasar .doma .jdbc .entity .EntityPropertyType ;
22+ import org .seasar .doma .jdbc .query .QueryOperand ;
23+ import org .seasar .doma .jdbc .query .QueryOperandPair ;
2524import org .seasar .doma .jdbc .query .UpsertAssembler ;
2625import org .seasar .doma .jdbc .query .UpsertAssemblerContext ;
27- import org .seasar .doma .jdbc .query .UpsertSetValue ;
26+ import org .seasar .doma .jdbc .query .UpsertAssemblerContextBuilder ;
2827
2928public class NativeSqlUpsertTerminal extends AbstractStatement <NativeSqlUpsertTerminal , Integer > {
3029
@@ -52,85 +51,65 @@ public Integer execute() {
5251 protected Command <Integer > createCommand () {
5352 InsertContext context = declaration .getContext ();
5453 InsertSettings settings = context .getSettings ();
55- List <PropertyMetamodel <?>> upsertKeys = setUpsertKeysIfEmpty (context .onDuplicateContext );
56- setUpsertSetValuesIfEmpty (context , upsertKeys );
57- PreparedSql sql = getPreparedSql (settings , context );
54+ PreparedSql sql = createPreparedSql (settings , context );
5855 CriteriaQuery query = new CriteriaQuery (config , sql , getClass ().getName (), EXECUTE_METHOD_NAME );
5956 query .setQueryTimeout (settings .getQueryTimeout ());
6057 return new InsertCommand (query );
6158 }
6259
63- private List <PropertyMetamodel <?>> setUpsertKeysIfEmpty (
64- InsertContext .OnDuplicateContext context ) {
65- if (context .keys .isEmpty ()) {
66- context .keys =
67- this .declaration .getContext ().entityMetamodel .allPropertyMetamodels ().stream ()
68- .filter (propertyMetamodel -> propertyMetamodel .asType ().isId ())
69- .collect (Collectors .toList ());
70- }
71- return context .keys ;
72- }
60+ private PreparedSql createPreparedSql (InsertSettings settings , InsertContext context ) {
61+ List <EntityPropertyType <?, ?>> keys = prepareKeys (context .onDuplicateContext .keys );
62+ List <QueryOperandPair > insertValues = prepareInsertValues (context .values );
63+ List <QueryOperandPair > setValues = prepareSetValues (context .onDuplicateContext .setValues );
7364
74- private void setUpsertSetValuesIfEmpty (
75- InsertContext context , List <PropertyMetamodel <?>> upsertKeys ) {
76- if (context .onDuplicateContext .setValues .isEmpty ()) {
77- for (Operand .Prop prop : context .values .keySet ()) {
78- if (!upsertKeys .contains (prop .value )) {
79- context .onDuplicateContext .setValues .put (prop , prop );
80- }
81- }
82- }
65+ PreparedSqlBuilder sqlBuilder = assembleQuery (settings , context , keys , insertValues , setValues );
66+ return sqlBuilder .build (createCommenter (settings .getComment ()));
8367 }
8468
85- private PreparedSql getPreparedSql (InsertSettings settings , InsertContext context ) {
86- List <EntityPropertyType <?, ?>> keys = toEntityPropertyTypes (context .onDuplicateContext .keys );
87- List <Tuple2 <EntityPropertyType <?, ?>, InParameter <?>>> insertValues =
88- insertValues (context .values );
89- List <Tuple2 <EntityPropertyType <?, ?>, UpsertSetValue >> setValues =
90- setValues (context .onDuplicateContext .setValues );
91-
92- PreparedSqlBuilder sql = assembleQuery (settings , context , keys , insertValues , setValues );
93- return sql .build (createCommenter (settings .getComment ()));
69+ private List <EntityPropertyType <?, ?>> prepareKeys (
70+ List <PropertyMetamodel <?>> propertyMetamodels ) {
71+ return propertyMetamodels .stream ().map (PropertyMetamodel ::asType ).collect (toList ());
9472 }
9573
96- private List <Tuple2 < EntityPropertyType <?, ?>, InParameter <?>>> insertValues (
74+ private List <QueryOperandPair > prepareInsertValues (
9775 Map <Operand .Prop , Operand .Param > insertContextValue ) {
98- List <Tuple2 < EntityPropertyType <?, ?>, InParameter <?>>> list = new ArrayList <>();
76+ List <QueryOperandPair > list = new ArrayList <>(insertContextValue . size () );
9977 for (Map .Entry <Operand .Prop , Operand .Param > entry : insertContextValue .entrySet ()) {
10078 Operand .Prop prop = entry .getKey ();
10179 Operand .Param param = entry .getValue ();
102- list .add (new Tuple2 <>(prop .value .asType (), param .createInParameter (config )));
80+ QueryOperand left = new QueryOperand .Prop (prop .getPropertyMetamodel ().asType ());
81+ QueryOperand right =
82+ new QueryOperand .Param (
83+ param .getPropertyMetamodel ().asType (), param .createInParameter (config ));
84+ QueryOperandPair pair = new QueryOperandPair (left , right );
85+ list .add (pair );
10386 }
10487 return list ;
10588 }
10689
107- private List <Tuple2 <EntityPropertyType <?, ?>, UpsertSetValue >> setValues (
108- Map <Operand .Prop , Operand > upsertSetValues ) {
109- List <Tuple2 <EntityPropertyType <?, ?>, UpsertSetValue >> list = new ArrayList <>();
90+ private List <QueryOperandPair > prepareSetValues (Map <Operand .Prop , Operand > upsertSetValues ) {
91+ List <QueryOperandPair > list = new ArrayList <>(upsertSetValues .size ());
11092 for (Map .Entry <Operand .Prop , Operand > upsertSetValue : upsertSetValues .entrySet ()) {
11193 Operand .Prop prop = upsertSetValue .getKey ();
11294 Operand operand = upsertSetValue .getValue ();
113- UpsertSetValue jdbcQueryUpsertSetValue = operand .accept (new OperandVisitor ());
114- list .add (new Tuple2 <>(prop .value .asType (), jdbcQueryUpsertSetValue ));
95+ QueryOperand left = new QueryOperand .Prop (prop .getPropertyMetamodel ().asType ());
96+ QueryOperand right = operand .accept (new OperandVisitor ());
97+ QueryOperandPair pair = new QueryOperandPair (left , right );
98+ list .add (pair );
11599 }
116100 return list ;
117101 }
118102
119- private static List <EntityPropertyType <?, ?>> toEntityPropertyTypes (
120- List <PropertyMetamodel <?>> propertyMetamodels ) {
121- return propertyMetamodels .stream ().map (PropertyMetamodel ::asType ).collect (toList ());
122- }
123-
124103 private PreparedSqlBuilder assembleQuery (
125104 InsertSettings settings ,
126105 InsertContext context ,
127106 List <EntityPropertyType <?, ?>> keys ,
128- List <Tuple2 < EntityPropertyType <?, ?>, InParameter <?>> > insertValues ,
129- List <Tuple2 < EntityPropertyType <?, ?>, UpsertSetValue > > setValues ) {
107+ List <QueryOperandPair > insertValues ,
108+ List <QueryOperandPair > setValues ) {
130109 PreparedSqlBuilder sql =
131110 new PreparedSqlBuilder (config , SqlKind .INSERT , settings .getSqlLogType ());
132111 UpsertAssemblerContext upsertAssemblerContext =
133- new UpsertAssemblerContext (
112+ UpsertAssemblerContextBuilder . build (
134113 sql ,
135114 context .entityMetamodel .asType (),
136115 context .onDuplicateContext .duplicateKeyType ,
@@ -144,16 +123,17 @@ private PreparedSqlBuilder assembleQuery(
144123 return sql ;
145124 }
146125
147- /** A visitor for converting {@link Operand} to {@link UpsertSetValue }. */
148- private class OperandVisitor implements Operand .Visitor <UpsertSetValue > {
126+ /** A visitor for converting {@link Operand} to {@link QueryOperand }. */
127+ private class OperandVisitor implements Operand .Visitor <QueryOperand > {
149128 @ Override
150- public UpsertSetValue visit (Operand .Param param ) {
151- return new UpsertSetValue .Param (param .createInParameter (config ));
129+ public QueryOperand visit (Operand .Param param ) {
130+ return new QueryOperand .Param (
131+ param .getPropertyMetamodel ().asType (), param .createInParameter (config ));
152132 }
153133
154134 @ Override
155- public UpsertSetValue visit (Operand .Prop prop ) {
156- return new UpsertSetValue .Prop (prop .value .asType ());
135+ public QueryOperand visit (Operand .Prop prop ) {
136+ return new QueryOperand .Prop (prop .value .asType ());
157137 }
158138 }
159139}
0 commit comments