@@ -30,7 +30,12 @@ import org.ktorm.schema.Column
3030/* *
3131 * Bulk insert expression, represents a bulk insert statement in MySQL.
3232 *
33- * For example: `insert into table (column1, column2) values (?, ?), (?, ?), (?, ?)...`.
33+ * For example:
34+ *
35+ * ```sql
36+ * insert into table (column1, column2) values (?, ?), (?, ?), (?, ?)...
37+ * on duplicate key update ...
38+ * ```
3439 *
3540 * @property table the table to be inserted.
3641 * @property assignments column assignments of the bulk insert statement.
@@ -82,21 +87,90 @@ public data class BulkInsertExpression(
8287 * @return the effected row count.
8388 * @see batchInsert
8489 */
85- public fun <T : BaseTable <* >> Database.bulkInsert (table : T , block : BulkInsertStatementBuilder <T >.() -> Unit ): Int {
90+ public fun <T : BaseTable <* >> Database.bulkInsert (
91+ table : T , block : BulkInsertStatementBuilder <T >.() -> Unit
92+ ): Int {
8693 val builder = BulkInsertStatementBuilder (table).apply (block)
8794
88- val expr = AliasRemover .visit(
95+ val expression = AliasRemover .visit(
8996 BulkInsertExpression (table.asExpression(), builder.assignments, builder.updateAssignments)
9097 )
9198
92- return executeUpdate(expr)
99+ return executeUpdate(expression)
100+ }
101+
102+ /* *
103+ * Bulk insert records to the table, determining if there is a key conflict while inserting each of them,
104+ * and automatically performs updates if any conflict exists.
105+ *
106+ * Usage:
107+ *
108+ * ```kotlin
109+ * database.bulkInsertOrUpdate(Employees) {
110+ * item {
111+ * set(it.id, 1)
112+ * set(it.name, "vince")
113+ * set(it.job, "engineer")
114+ * set(it.salary, 1000)
115+ * set(it.hireDate, LocalDate.now())
116+ * set(it.departmentId, 1)
117+ * }
118+ * item {
119+ * set(it.id, 5)
120+ * set(it.name, "vince")
121+ * set(it.job, "engineer")
122+ * set(it.salary, 1000)
123+ * set(it.hireDate, LocalDate.now())
124+ * set(it.departmentId, 1)
125+ * }
126+ * onDuplicateKey {
127+ * set(it.salary, it.salary + 900)
128+ * }
129+ * }
130+ * ```
131+ *
132+ * Generated SQL:
133+ *
134+ * ```sql
135+ * insert into t_employee (id, name, job, salary, hire_date, department_id)
136+ * values (?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?)
137+ * on duplicate key update salary = t_employee.salary + ?
138+ * ```
139+ *
140+ * @since 3.3.0
141+ * @param table the table to be inserted.
142+ * @param block the DSL block used to construct the expression.
143+ * @return the effected row count.
144+ * @see bulkInsert
145+ */
146+ public fun <T : BaseTable <* >> Database.bulkInsertOrUpdate (
147+ table : T , block : BulkInsertOrUpdateStatementBuilder <T >.() -> Unit
148+ ): Int {
149+ val builder = BulkInsertOrUpdateStatementBuilder (table).apply (block)
150+
151+ val expression = AliasRemover .visit(
152+ BulkInsertExpression (table.asExpression(), builder.assignments, builder.updateAssignments)
153+ )
154+
155+ return executeUpdate(expression)
93156}
94157
95158/* *
96159 * DSL builder for bulk insert statements.
97160 */
161+ public class BulkInsertStatementBuilder <T : BaseTable <* >>(table : T ) : BulkInsertOrUpdateStatementBuilder<T>(table) {
162+
163+ @Deprecated(" This function will be removed in the future, please use bulkInsertOrUpdate instead of bulkInsert." )
164+ override fun onDuplicateKey (block : BulkInsertOrUpdateOnDuplicateKeyClauseBuilder .(T ) -> Unit ) {
165+ super .onDuplicateKey(block)
166+ }
167+ }
168+
169+ /* *
170+ * DSL builder for bulk insert or update statements.
171+ */
98172@KtormDsl
99- public class BulkInsertStatementBuilder <T : BaseTable <* >>(internal val table : T ) {
173+ public open class BulkInsertOrUpdateStatementBuilder <T : BaseTable <* >>(internal val table : T ) {
100174 internal val assignments = ArrayList <List <ColumnAssignmentExpression <* >>>()
101175 internal val updateAssignments = ArrayList <ColumnAssignmentExpression <* >>()
102176
@@ -119,18 +193,18 @@ public class BulkInsertStatementBuilder<T : BaseTable<*>>(internal val table: T)
119193 /* *
120194 * Specify the update assignments while any key conflict exists.
121195 */
122- public fun onDuplicateKey (block : BulkInsertOnDuplicateKeyClauseBuilder .(T ) -> Unit ) {
123- val builder = BulkInsertOnDuplicateKeyClauseBuilder ()
196+ public open fun onDuplicateKey (block : BulkInsertOrUpdateOnDuplicateKeyClauseBuilder .(T ) -> Unit ) {
197+ val builder = BulkInsertOrUpdateOnDuplicateKeyClauseBuilder ()
124198 builder.block(table)
125199 updateAssignments + = builder.assignments
126200 }
127201}
128202
129203/* *
130- * DSL builder for bulk insert on duplicate key clause.
204+ * DSL builder for bulk insert or update on duplicate key clause.
131205 */
132206@KtormDsl
133- public class BulkInsertOnDuplicateKeyClauseBuilder : MySqlAssignmentsBuilder () {
207+ public class BulkInsertOrUpdateOnDuplicateKeyClauseBuilder : MySqlAssignmentsBuilder () {
134208
135209 /* *
136210 * Use VALUES() function in a ON DUPLICATE KEY UPDATE clause.
0 commit comments