Skip to content

Commit 67a1e7e

Browse files
sqlite: check empty insert & update #457
1 parent dc5fb4d commit 67a1e7e

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

ktorm-support-sqlite/src/main/kotlin/org/ktorm/support/sqlite/BulkInsert.kt

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.ktorm.support.sqlite
1818

19-
import org.ktorm.database.CachedRowSet
2019
import org.ktorm.database.Database
2120
import org.ktorm.database.asIterable
2221
import org.ktorm.dsl.AliasRemover
@@ -97,12 +96,7 @@ public data class BulkInsertExpression(
9796
public fun <T : BaseTable<*>> Database.bulkInsert(
9897
table: T, block: BulkInsertStatementBuilder<T>.(T) -> Unit
9998
): Int {
100-
val builder = BulkInsertStatementBuilder(table).apply { block(table) }
101-
102-
val expression = dialect.createExpressionVisitor(AliasRemover).visit(
103-
BulkInsertExpression(table.asExpression(), builder.assignments)
104-
)
105-
99+
val expression = buildBulkInsertExpression(table, returning = emptyList(), block = block)
106100
return executeUpdate(expression)
107101
}
108102

@@ -149,7 +143,8 @@ public fun <T : BaseTable<*>> Database.bulkInsert(
149143
public fun <T : BaseTable<*>, C : Any> Database.bulkInsertReturning(
150144
table: T, returning: Column<C>, block: BulkInsertStatementBuilder<T>.(T) -> Unit
151145
): List<C?> {
152-
val rowSet = bulkInsertReturningRowSet(table, listOf(returning), block)
146+
val expression = buildBulkInsertExpression(table, listOf(returning), block)
147+
val rowSet = executeQuery(expression)
153148
return rowSet.asIterable().map { row -> returning.sqlType.getResult(row, 1) }
154149
}
155150

@@ -197,7 +192,8 @@ public fun <T : BaseTable<*>, C1 : Any, C2 : Any> Database.bulkInsertReturning(
197192
table: T, returning: Pair<Column<C1>, Column<C2>>, block: BulkInsertStatementBuilder<T>.(T) -> Unit
198193
): List<Pair<C1?, C2?>> {
199194
val (c1, c2) = returning
200-
val rowSet = bulkInsertReturningRowSet(table, listOf(c1, c2), block)
195+
val expression = buildBulkInsertExpression(table, listOf(c1, c2), block)
196+
val rowSet = executeQuery(expression)
201197
return rowSet.asIterable().map { row -> Pair(c1.sqlType.getResult(row, 1), c2.sqlType.getResult(row, 2)) }
202198
}
203199

@@ -245,7 +241,8 @@ public fun <T : BaseTable<*>, C1 : Any, C2 : Any, C3 : Any> Database.bulkInsertR
245241
table: T, returning: Triple<Column<C1>, Column<C2>, Column<C3>>, block: BulkInsertStatementBuilder<T>.(T) -> Unit
246242
): List<Triple<C1?, C2?, C3?>> {
247243
val (c1, c2, c3) = returning
248-
val rowSet = bulkInsertReturningRowSet(table, listOf(c1, c2, c3), block)
244+
val expression = buildBulkInsertExpression(table, listOf(c1, c2, c3), block)
245+
val rowSet = executeQuery(expression)
249246
return rowSet.asIterable().map { row ->
250247
Triple(c1.sqlType.getResult(row, 1), c2.sqlType.getResult(row, 2), c3.sqlType.getResult(row, 3))
251248
}
@@ -254,20 +251,26 @@ public fun <T : BaseTable<*>, C1 : Any, C2 : Any, C3 : Any> Database.bulkInsertR
254251
/**
255252
* Bulk insert records to the table, returning row set.
256253
*/
257-
private fun <T : BaseTable<*>> Database.bulkInsertReturningRowSet(
254+
private fun <T : BaseTable<*>> Database.buildBulkInsertExpression(
258255
table: T, returning: List<Column<*>>, block: BulkInsertStatementBuilder<T>.(T) -> Unit
259-
): CachedRowSet {
256+
): SqlExpression {
260257
val builder = BulkInsertStatementBuilder(table).apply { block(table) }
258+
if (builder.assignments.isEmpty()) {
259+
throw IllegalArgumentException("There are no items in the bulk operation.")
260+
}
261+
for (assignments in builder.assignments) {
262+
if (assignments.isEmpty()) {
263+
throw IllegalArgumentException("There are no columns to insert in the statement.")
264+
}
265+
}
261266

262-
val expression = dialect.createExpressionVisitor(AliasRemover).visit(
267+
return dialect.createExpressionVisitor(AliasRemover).visit(
263268
BulkInsertExpression(
264269
table = table.asExpression(),
265270
assignments = builder.assignments,
266271
returningColumns = returning.map { it.asExpression() }
267272
)
268273
)
269-
270-
return executeQuery(expression)
271274
}
272275

273276
/**
@@ -491,6 +494,14 @@ private fun <T : BaseTable<*>> Database.buildBulkInsertOrUpdateExpression(
491494
table: T, returning: List<Column<*>>, block: BulkInsertOrUpdateStatementBuilder<T>.(T) -> Unit
492495
): SqlExpression {
493496
val builder = BulkInsertOrUpdateStatementBuilder(table).apply { block(table) }
497+
if (builder.assignments.isEmpty()) {
498+
throw IllegalArgumentException("There are no items in the bulk operation.")
499+
}
500+
for (assignments in builder.assignments) {
501+
if (assignments.isEmpty()) {
502+
throw IllegalArgumentException("There are no columns to insert in the statement.")
503+
}
504+
}
494505

495506
val conflictColumns = builder.conflictColumns.ifEmpty { table.primaryKeys }
496507
if (conflictColumns.isEmpty()) {

ktorm-support-sqlite/src/main/kotlin/org/ktorm/support/sqlite/InsertOrUpdate.kt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,7 @@ public data class InsertOrUpdateExpression(
8383
public fun <T : BaseTable<*>> Database.insertOrUpdate(
8484
table: T, block: InsertOrUpdateStatementBuilder.(T) -> Unit
8585
): Int {
86-
val expression = dialect.createExpressionVisitor(AliasRemover).visit(
87-
buildInsertOrUpdateExpression(table, returning = emptyList(), block = block)
88-
)
89-
86+
val expression = buildInsertOrUpdateExpression(table, returning = emptyList(), block = block)
9087
return executeUpdate(expression)
9188
}
9289

@@ -237,10 +234,7 @@ public fun <T : BaseTable<*>, C1 : Any, C2 : Any, C3 : Any> Database.insertOrUpd
237234
private fun <T : BaseTable<*>> Database.insertOrUpdateReturningRow(
238235
table: T, returning: List<Column<*>>, block: InsertOrUpdateStatementBuilder.(T) -> Unit
239236
): CachedRowSet? {
240-
val expression = dialect.createExpressionVisitor(AliasRemover).visit(
241-
buildInsertOrUpdateExpression(table, returning, block)
242-
)
243-
237+
val expression = buildInsertOrUpdateExpression(table, returning, block)
244238
val rowSet = executeQuery(expression)
245239

246240
if (rowSet.size() == 0) {
@@ -260,10 +254,13 @@ private fun <T : BaseTable<*>> Database.insertOrUpdateReturningRow(
260254
/**
261255
* Build an insert or update expression.
262256
*/
263-
private fun <T : BaseTable<*>> buildInsertOrUpdateExpression(
257+
private fun <T : BaseTable<*>> Database.buildInsertOrUpdateExpression(
264258
table: T, returning: List<Column<*>>, block: InsertOrUpdateStatementBuilder.(T) -> Unit
265-
): InsertOrUpdateExpression {
259+
): SqlExpression {
266260
val builder = InsertOrUpdateStatementBuilder().apply { block(table) }
261+
if (builder.assignments.isEmpty()) {
262+
throw IllegalArgumentException("There are no columns to insert in the statement.")
263+
}
267264

268265
val conflictColumns = builder.conflictColumns.ifEmpty { table.primaryKeys }
269266
if (conflictColumns.isEmpty()) {
@@ -280,13 +277,15 @@ private fun <T : BaseTable<*>> buildInsertOrUpdateExpression(
280277
throw IllegalStateException(msg)
281278
}
282279

283-
return InsertOrUpdateExpression(
284-
table = table.asExpression(),
285-
assignments = builder.assignments,
286-
conflictColumns = conflictColumns.map { it.asExpression() },
287-
updateAssignments = if (builder.doNothing) emptyList() else builder.updateAssignments,
288-
where = builder.where?.asExpression(),
289-
returningColumns = returning.map { it.asExpression() }
280+
return dialect.createExpressionVisitor(AliasRemover).visit(
281+
InsertOrUpdateExpression(
282+
table = table.asExpression(),
283+
assignments = builder.assignments,
284+
conflictColumns = conflictColumns.map { it.asExpression() },
285+
updateAssignments = if (builder.doNothing) emptyList() else builder.updateAssignments,
286+
where = builder.where?.asExpression(),
287+
returningColumns = returning.map { it.asExpression() }
288+
)
290289
)
291290
}
292291

@@ -411,6 +410,9 @@ private fun <T : BaseTable<*>> Database.insertReturningRow(
411410
table: T, returning: List<Column<*>>, block: AssignmentsBuilder.(T) -> Unit
412411
): CachedRowSet {
413412
val builder = SQLiteAssignmentsBuilder().apply { block(table) }
413+
if (builder.assignments.isEmpty()) {
414+
throw IllegalArgumentException("There are no columns to insert in the statement.")
415+
}
414416

415417
val expression = dialect.createExpressionVisitor(AliasRemover).visit(
416418
InsertOrUpdateExpression(

0 commit comments

Comments
 (0)