Skip to content

Commit

Permalink
feat: EXPOSED-357 Support DELETE...RETURNING statement (#2061)
Browse files Browse the repository at this point in the history
Add deleteReturning() that uses ReturningStatement and tests.
  • Loading branch information
bog-walk authored Apr 29, 2024
1 parent 4f5b037 commit c87f446
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
2 changes: 2 additions & 0 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,8 @@ public final class org/jetbrains/exposed/sql/QueriesKt {
public static final fun deleteAll (Lorg/jetbrains/exposed/sql/Table;)I
public static final fun deleteIgnoreWhere (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;)I
public static synthetic fun deleteIgnoreWhere$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)I
public static final fun deleteReturning (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement;
public static synthetic fun deleteReturning$default (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement;
public static final fun deleteWhere (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;)I
public static synthetic fun deleteWhere$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)I
public static final fun exists (Lorg/jetbrains/exposed/sql/Table;)Z
Expand Down
17 changes: 17 additions & 0 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,23 @@ fun <T : Table> T.deleteIgnoreWhere(limit: Int? = null, offset: Long? = null, op
fun Table.deleteAll(): Int =
DeleteStatement.all(TransactionManager.current(), this@deleteAll)

/**
* Represents the SQL statement that deletes rows in a table and returns specified data from the deleted rows.
*
* @param returning Columns and expressions to include in the returned data. This defaults to all columns in the table.
* @param where Condition that determines which rows to delete. If left as `null`, all rows in the table will be deleted.
* @return A [ReturningStatement] that will be executed once iterated over, providing [ResultRow]s containing the specified
* expressions mapped to their resulting data.
* @sample org.jetbrains.exposed.sql.tests.shared.dml.ReturningTests.testDeleteReturning
*/
fun <T : Table> T.deleteReturning(
returning: List<Expression<*>> = columns,
where: (SqlExpressionBuilder.() -> Op<Boolean>)? = null
): ReturningStatement {
val delete = DeleteStatement(this, where?.let { SqlExpressionBuilder.it() }, false, null, null)
return ReturningStatement(this, returning, delete)
}

/**
* Represents the SQL statement that inserts a new row into a table.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.times
import org.jetbrains.exposed.sql.statements.ReturningStatement
import org.jetbrains.exposed.sql.tests.DatabaseTestsBase
import org.jetbrains.exposed.sql.tests.TestDB
import org.jetbrains.exposed.sql.tests.shared.assertEqualCollections
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertIs
import kotlin.test.assertTrue

class ReturningTests : DatabaseTestsBase() {
private val returningSupportedDb = TestDB.postgreSQLRelatedDB.toSet() + TestDB.SQLITE
Expand Down Expand Up @@ -93,6 +95,34 @@ class ReturningTests : DatabaseTestsBase() {
it[price] = 99.0
}
assertIs<ReturningStatement>(stmt)

assertEquals(0, Items.selectAll().count())

assertTrue { Items.deleteReturning().toList().isEmpty() }
}
}

@Test
fun testDeleteReturning() {
withTables(TestDB.enabledDialects() - returningSupportedDb, Items) {
Items.batchInsert(listOf("A" to 99.0, "B" to 100.0, "C" to 200.0)) { (n, p) ->
this[Items.name] = n
this[Items.price] = p
}

assertEquals(3, Items.selectAll().count())

// return all columns by default
val result1 = Items.deleteReturning(where = { Items.price eq 200.0 }).single()
assertEquals(3, result1[Items.id].value)
assertEquals("C", result1[Items.name])
assertEquals(200.0, result1[Items.price])

assertEquals(2, Items.selectAll().count())

val result2 = Items.deleteReturning(listOf(Items.id)).map { it[Items.id].value }
assertEqualCollections(listOf(1, 2), result2)

assertEquals(0, Items.selectAll().count())
}
}
Expand Down

0 comments on commit c87f446

Please sign in to comment.