From 01c34894132864ad7b0029cd8639e98fca31e299 Mon Sep 17 00:00:00 2001 From: Chantal Loncle <82039410+bog-walk@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:40:12 -0400 Subject: [PATCH 1/2] feat: EXPOSED-494 Inline DSL statement and query functions Make as many eligible statement and query functions inline where possible. Functions with nullable functional type paramaters have been marked noinline, but this may change upon review. --- .../org/jetbrains/exposed/sql/Queries.kt | 68 ++++++++++++------- .../kotlin/org/jetbrains/exposed/sql/Query.kt | 4 +- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt index 847522f08a..11f5fdc513 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt @@ -118,7 +118,7 @@ fun T.deleteWhere(limit: Int? = null, offset: Long? = null, op: T.(I * @return Count of deleted rows. * @sample org.jetbrains.exposed.sql.tests.shared.dml.DeleteTests.testDelete01 */ -fun T.deleteWhere(limit: Int? = null, op: T.(ISqlExpressionBuilder) -> Op): Int = +inline fun T.deleteWhere(limit: Int? = null, op: T.(ISqlExpressionBuilder) -> Op): Int = DeleteStatement.where(TransactionManager.current(), this@deleteWhere, op(SqlExpressionBuilder), false, limit) @Deprecated( @@ -142,7 +142,7 @@ fun T.deleteIgnoreWhere(limit: Int? = null, offset: Long? = null, op * @param op Condition that determines which rows to delete. * @return Count of deleted rows. */ -fun T.deleteIgnoreWhere(limit: Int? = null, op: T.(ISqlExpressionBuilder) -> Op): Int = +inline fun T.deleteIgnoreWhere(limit: Int? = null, op: T.(ISqlExpressionBuilder) -> Op): Int = DeleteStatement.where(TransactionManager.current(), this@deleteIgnoreWhere, op(SqlExpressionBuilder), true, limit) /** @@ -163,9 +163,9 @@ fun Table.deleteAll(): Int = * expressions mapped to their resulting data. * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReturningTests.testDeleteReturning */ -fun T.deleteReturning( +inline fun T.deleteReturning( returning: List> = columns, - where: (SqlExpressionBuilder.() -> Op)? = null + noinline where: (SqlExpressionBuilder.() -> Op)? = null ): ReturningStatement { val delete = DeleteStatement(this, where?.let { SqlExpressionBuilder.it() }, false, null) return ReturningStatement(this, returning, delete) @@ -185,12 +185,12 @@ fun T.deleteReturning( * @return The number of deleted rows. * @sample org.jetbrains.exposed.sql.tests.shared.dml.DeleteTests.testDeleteWithSingleJoin */ -fun Join.delete( +inline fun Join.delete( targetTable: Table, vararg targetTables: Table, ignore: Boolean = false, limit: Int? = null, - where: (SqlExpressionBuilder.() -> Op)? = null + noinline where: (SqlExpressionBuilder.() -> Op)? = null ): Int { val targets = listOf(targetTable) + targetTables val delete = DeleteStatement(this, where?.let { SqlExpressionBuilder.it() }, ignore, limit, targets) @@ -202,7 +202,9 @@ fun Join.delete( * * @sample org.jetbrains.exposed.sql.tests.h2.H2Tests.insertInH2 */ -fun T.insert(body: T.(InsertStatement) -> Unit): InsertStatement = InsertStatement(this).apply { +inline fun T.insert( + body: T.(InsertStatement) -> Unit +): InsertStatement = InsertStatement(this).apply { body(this) execute(TransactionManager.current()) } @@ -213,7 +215,9 @@ fun T.insert(body: T.(InsertStatement) -> Unit): InsertState * @return The generated ID for the new row. * @sample org.jetbrains.exposed.sql.tests.shared.dml.InsertTests.testGeneratedKey04 */ -fun , T : IdTable> T.insertAndGetId(body: T.(InsertStatement>) -> Unit): EntityID = +inline fun , T : IdTable> T.insertAndGetId( + body: T.(InsertStatement>) -> Unit +): EntityID = InsertStatement>(this, false).run { body(this) execute(TransactionManager.current()) @@ -366,7 +370,9 @@ private fun executeBatch( * * @sample org.jetbrains.exposed.sql.tests.shared.dml.InsertTests.testInsertIgnoreAndGetIdWithPredefinedId */ -fun T.insertIgnore(body: T.(UpdateBuilder<*>) -> Unit): InsertStatement = InsertStatement(this, isIgnore = true).apply { +inline fun T.insertIgnore( + body: T.(UpdateBuilder<*>) -> Unit +): InsertStatement = InsertStatement(this, isIgnore = true).apply { body(this) execute(TransactionManager.current()) } @@ -381,7 +387,9 @@ fun T.insertIgnore(body: T.(UpdateBuilder<*>) -> Unit): InsertStatem * @return The generated ID for the new row, or `null` if none was retrieved after statement execution. * @sample org.jetbrains.exposed.sql.tests.shared.dml.InsertTests.testInsertIgnoreAndGetId01 */ -fun , T : IdTable> T.insertIgnoreAndGetId(body: T.(UpdateBuilder<*>) -> Unit): EntityID? = +inline fun , T : IdTable> T.insertIgnoreAndGetId( + body: T.(UpdateBuilder<*>) -> Unit +): EntityID? = InsertStatement>(this, isIgnore = true).run { body(this) when (execute(TransactionManager.current())) { @@ -398,7 +406,9 @@ fun , T : IdTable> T.insertIgnoreAndGetId(body: T.(Up * * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReplaceTests.testReplaceWithExpression */ -fun T.replace(body: T.(UpdateBuilder<*>) -> Unit): ReplaceStatement = ReplaceStatement(this).apply { +inline fun T.replace( + body: T.(UpdateBuilder<*>) -> Unit +): ReplaceStatement = ReplaceStatement(this).apply { body(this) execute(TransactionManager.current()) } @@ -463,7 +473,7 @@ private fun Column<*>.isValidIfAutoIncrement(): Boolean = * expressions mapped to their resulting data. * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReturningTests.testInsertReturning */ -fun T.insertReturning( +inline fun T.insertReturning( returning: List> = columns, ignoreErrors: Boolean = false, body: T.(InsertStatement) -> Unit @@ -481,7 +491,11 @@ fun T.insertReturning( * @return The number of updated rows. * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpdateTests.testUpdate01 */ -fun T.update(where: (SqlExpressionBuilder.() -> Op)? = null, limit: Int? = null, body: T.(UpdateStatement) -> Unit): Int { +inline fun T.update( + noinline where: (SqlExpressionBuilder.() -> Op)? = null, + limit: Int? = null, + body: T.(UpdateStatement) -> Unit +): Int { val query = UpdateStatement(this, limit, where?.let { SqlExpressionBuilder.it() }) body(query) return query.execute(TransactionManager.current()) ?: 0 @@ -495,7 +509,11 @@ fun T.update(where: (SqlExpressionBuilder.() -> Op)? = null * @return The number of updated rows. * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpdateTests.testUpdateWithSingleJoin */ -fun Join.update(where: (SqlExpressionBuilder.() -> Op)? = null, limit: Int? = null, body: (UpdateStatement) -> Unit): Int { +inline fun Join.update( + noinline where: (SqlExpressionBuilder.() -> Op)? = null, + limit: Int? = null, + body: (UpdateStatement) -> Unit +): Int { val query = UpdateStatement(this, limit, where?.let { SqlExpressionBuilder.it() }) body(query) return query.execute(TransactionManager.current()) ?: 0 @@ -509,9 +527,9 @@ fun Join.update(where: (SqlExpressionBuilder.() -> Op)? = null, limit: * expressions mapped to their resulting data. * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReturningTests.testUpdateReturning */ -fun T.updateReturning( +inline fun T.updateReturning( returning: List> = columns, - where: (SqlExpressionBuilder.() -> Op)? = null, + noinline where: (SqlExpressionBuilder.() -> Op)? = null, body: T.(UpdateStatement) -> Unit ): ReturningStatement { val update = UpdateStatement(this, null, where?.let { SqlExpressionBuilder.it() }) @@ -539,11 +557,11 @@ fun T.updateReturning( * @param where Condition that determines which rows to update, if a unique violation is found. * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpsertTests.testUpsertWithUniqueIndexConflict */ -fun T.upsert( +inline fun T.upsert( vararg keys: Column<*>, - onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, + noinline onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, onUpdateExclude: List>? = null, - where: (SqlExpressionBuilder.() -> Op)? = null, + noinline where: (SqlExpressionBuilder.() -> Op)? = null, body: T.(UpsertStatement) -> Unit ) = UpsertStatement(this, keys = keys, onUpdateExclude = onUpdateExclude, where = where?.let { SqlExpressionBuilder.it() }).apply { onUpdate?.let { storeUpdateValues(it) } @@ -588,12 +606,12 @@ fun T.upsert( * expressions mapped to their resulting data. * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReturningTests.testUpsertReturning */ -fun T.upsertReturning( +inline fun T.upsertReturning( vararg keys: Column<*>, returning: List> = columns, - onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, + noinline onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, onUpdateExclude: List>? = null, - where: (SqlExpressionBuilder.() -> Op)? = null, + noinline where: (SqlExpressionBuilder.() -> Op)? = null, body: T.(UpsertStatement) -> Unit ): ReturningStatement { val upsert = UpsertStatement(this, keys = keys, onUpdateExclude, where?.let { SqlExpressionBuilder.it() }) @@ -756,9 +774,9 @@ fun Table.exists(): Boolean = currentDialect.tableExists(this) * when records are matched or not matched. * @return A [MergeTableStatement] which represents the MERGE operation with the configured actions. */ -fun D.mergeFrom( +inline fun D.mergeFrom( source: S, - on: (SqlExpressionBuilder.() -> Op)? = null, + noinline on: (SqlExpressionBuilder.() -> Op)? = null, body: MergeTableStatement.() -> Unit ): MergeTableStatement { return MergeTableStatement(this, source, on = on?.invoke(SqlExpressionBuilder)).apply { @@ -779,7 +797,7 @@ fun D.mergeFrom( * when records are matched or not matched. * @return A [MergeSelectStatement] which represents the MERGE operation with the configured actions. */ -fun T.mergeFrom( +inline fun T.mergeFrom( selectQuery: QueryAlias, on: SqlExpressionBuilder.() -> Op, body: MergeSelectStatement.() -> Unit diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Query.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Query.kt index 443f9bbfc1..d635d49cd1 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Query.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Query.kt @@ -95,7 +95,7 @@ open class Query(override var set: FieldSet, where: Op?) : AbstractQuer * property used as the receiver and the current [set] as an argument. * @sample org.jetbrains.exposed.sql.tests.shared.dml.AdjustQueryTests.testAdjustQuerySlice */ - fun adjustSelect(body: ColumnSet.(FieldSet) -> Query): Query = apply { set = set.source.body(set).set } + inline fun adjustSelect(body: ColumnSet.(FieldSet) -> Query): Query = apply { set = set.source.body(set).set } /** * Assigns a new column set, either a [Table] or a [Join], by changing the `source` property of this query's [set], @@ -104,7 +104,7 @@ open class Query(override var set: FieldSet, where: Op?) : AbstractQuer * @param body Builder for the new column set, with the previous column set value as the receiver. * @sample org.jetbrains.exposed.sql.tests.shared.dml.AdjustQueryTests.testAdjustQueryColumnSet */ - fun adjustColumnSet(body: ColumnSet.() -> ColumnSet): Query { + inline fun adjustColumnSet(body: ColumnSet.() -> ColumnSet): Query { return adjustSelect { oldSlice -> body().select(oldSlice.fields) } } From d5f1d2c2a7f59cfc3e180964036fac8837bbd857 Mon Sep 17 00:00:00 2001 From: Chantal Loncle <82039410+bog-walk@users.noreply.github.com> Date: Thu, 10 Oct 2024 21:45:59 -0400 Subject: [PATCH 2/2] feat: EXPOSED-494 Inline DSL statement and query functions - Add crossinline keyword to body parameters to prevent non-local returns - Duplicate functions with null where parameters to allow inline --- exposed-core/api/exposed-core.api | 12 +- .../org/jetbrains/exposed/sql/Queries.kt | 180 ++++++++++++++---- 2 files changed, 159 insertions(+), 33 deletions(-) diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index b21738db24..344b69288e 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -1821,14 +1821,18 @@ public final class org/jetbrains/exposed/sql/QueriesKt { public static synthetic fun batchUpsert$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;[Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function2;Ljava/util/List;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/List; public static synthetic fun batchUpsert$default (Lorg/jetbrains/exposed/sql/Table;Lkotlin/sequences/Sequence;[Lorg/jetbrains/exposed/sql/Column;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/List; public static synthetic fun batchUpsert$default (Lorg/jetbrains/exposed/sql/Table;Lkotlin/sequences/Sequence;[Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function2;Ljava/util/List;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/List; + public static final fun delete (Lorg/jetbrains/exposed/sql/Join;Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Table;ZLjava/lang/Integer;)I public static final fun delete (Lorg/jetbrains/exposed/sql/Join;Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Table;ZLjava/lang/Integer;Lkotlin/jvm/functions/Function1;)I + public static synthetic fun delete$default (Lorg/jetbrains/exposed/sql/Join;Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Table;ZLjava/lang/Integer;ILjava/lang/Object;)I public static synthetic fun delete$default (Lorg/jetbrains/exposed/sql/Join;Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Table;ZLjava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I 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 final fun deleteIgnoreWhere (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;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 synthetic fun deleteIgnoreWhere$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)I + public static final fun deleteReturning (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; 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;ILjava/lang/Object;)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 final fun deleteWhere (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;)I @@ -1846,8 +1850,8 @@ public final class org/jetbrains/exposed/sql/QueriesKt { public static final fun insertReturning (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; public static synthetic fun insertReturning$default (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; public static final fun mergeFrom (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/QueryAlias;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/statements/MergeSelectStatement; + public static final fun mergeFrom (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/statements/MergeTableStatement; public static final fun mergeFrom (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/statements/MergeTableStatement; - public static synthetic fun mergeFrom$default (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/statements/MergeTableStatement; public static final fun replace (Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/exposed/sql/statements/ReplaceStatement; public static final fun replace (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;)Ljava/lang/Integer; public static synthetic fun replace$default (Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;ILjava/lang/Object;)Ljava/lang/Integer; @@ -1864,12 +1868,18 @@ public final class org/jetbrains/exposed/sql/QueriesKt { public static final fun selectBatched (Lorg/jetbrains/exposed/sql/Query;ILkotlin/jvm/functions/Function1;)Ljava/lang/Iterable; public static synthetic fun selectBatched$default (Lorg/jetbrains/exposed/sql/FieldSet;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Iterable; public static synthetic fun selectBatched$default (Lorg/jetbrains/exposed/sql/Query;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Iterable; + public static final fun update (Lorg/jetbrains/exposed/sql/Join;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I public static final fun update (Lorg/jetbrains/exposed/sql/Join;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I + public static final fun update (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;)I public static final fun update (Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;)I + public static synthetic fun update$default (Lorg/jetbrains/exposed/sql/Join;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I public static synthetic fun update$default (Lorg/jetbrains/exposed/sql/Join;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I + public static synthetic fun update$default (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)I public static synthetic fun update$default (Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)I public static final fun updateReturning (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; + public static final fun updateReturning (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; public static synthetic fun updateReturning$default (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; + public static synthetic fun updateReturning$default (Lorg/jetbrains/exposed/sql/Table;Ljava/util/List;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/statements/ReturningStatement; public static final fun upsert (Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Column;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/exposed/sql/statements/UpsertStatement; public static final fun upsert (Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function2;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/exposed/sql/statements/UpsertStatement; public static synthetic fun upsert$default (Lorg/jetbrains/exposed/sql/Table;[Lorg/jetbrains/exposed/sql/Column;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/statements/UpsertStatement; diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt index 11f5fdc513..8987c1019b 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Queries.kt @@ -118,7 +118,10 @@ fun T.deleteWhere(limit: Int? = null, offset: Long? = null, op: T.(I * @return Count of deleted rows. * @sample org.jetbrains.exposed.sql.tests.shared.dml.DeleteTests.testDelete01 */ -inline fun T.deleteWhere(limit: Int? = null, op: T.(ISqlExpressionBuilder) -> Op): Int = +inline fun T.deleteWhere( + limit: Int? = null, + op: T.(ISqlExpressionBuilder) -> Op +): Int = DeleteStatement.where(TransactionManager.current(), this@deleteWhere, op(SqlExpressionBuilder), false, limit) @Deprecated( @@ -142,7 +145,10 @@ fun T.deleteIgnoreWhere(limit: Int? = null, offset: Long? = null, op * @param op Condition that determines which rows to delete. * @return Count of deleted rows. */ -inline fun T.deleteIgnoreWhere(limit: Int? = null, op: T.(ISqlExpressionBuilder) -> Op): Int = +inline fun T.deleteIgnoreWhere( + limit: Int? = null, + op: T.(ISqlExpressionBuilder) -> Op +): Int = DeleteStatement.where(TransactionManager.current(), this@deleteIgnoreWhere, op(SqlExpressionBuilder), true, limit) /** @@ -158,16 +164,31 @@ fun Table.deleteAll(): Int = * 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. + * @param where Condition that determines which rows to delete. * @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 */ inline fun T.deleteReturning( returning: List> = columns, - noinline where: (SqlExpressionBuilder.() -> Op)? = null + where: SqlExpressionBuilder.() -> Op +): ReturningStatement { + val delete = DeleteStatement(this, SqlExpressionBuilder.where(), false, null) + return ReturningStatement(this, returning, delete) +} + +/** + * Represents the SQL statement that deletes all 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. + * @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.deleteReturning( + returning: List> = columns ): ReturningStatement { - val delete = DeleteStatement(this, where?.let { SqlExpressionBuilder.it() }, false, null) + val delete = DeleteStatement(this, null, false, null) return ReturningStatement(this, returning, delete) } @@ -190,10 +211,34 @@ inline fun Join.delete( vararg targetTables: Table, ignore: Boolean = false, limit: Int? = null, - noinline where: (SqlExpressionBuilder.() -> Op)? = null + where: SqlExpressionBuilder.() -> Op +): Int { + val targets = listOf(targetTable) + targetTables + val delete = DeleteStatement(this, SqlExpressionBuilder.where(), ignore, limit, targets) + return delete.execute(TransactionManager.current()) ?: 0 +} + +/** + * Represents the SQL statement that deletes all rows from a table in a join relation. + * + * @param targetTable The specific table from this join relation to delete rows from. + * @param targetTables (Optional) Other tables from this join relation to delete rows from. + * **Note** Targeting multiple tables for deletion is not supported by all vendors. Please check the documentation. + * @param ignore Whether to ignore any possible errors that occur when deleting rows. + * **Note** [ignore] is not supported by all vendors. Please check the documentation. + * @param limit Maximum number of rows to delete. + * **Note** [limit] is not supported by all vendors. Please check the documentation. + * @return The number of deleted rows. + * @sample org.jetbrains.exposed.sql.tests.shared.dml.DeleteTests.testDeleteWithSingleJoin + */ +fun Join.delete( + targetTable: Table, + vararg targetTables: Table, + ignore: Boolean = false, + limit: Int? = null ): Int { val targets = listOf(targetTable) + targetTables - val delete = DeleteStatement(this, where?.let { SqlExpressionBuilder.it() }, ignore, limit, targets) + val delete = DeleteStatement(this, null, ignore, limit, targets) return delete.execute(TransactionManager.current()) ?: 0 } @@ -203,7 +248,7 @@ inline fun Join.delete( * @sample org.jetbrains.exposed.sql.tests.h2.H2Tests.insertInH2 */ inline fun T.insert( - body: T.(InsertStatement) -> Unit + crossinline body: T.(InsertStatement) -> Unit ): InsertStatement = InsertStatement(this).apply { body(this) execute(TransactionManager.current()) @@ -216,7 +261,7 @@ inline fun T.insert( * @sample org.jetbrains.exposed.sql.tests.shared.dml.InsertTests.testGeneratedKey04 */ inline fun , T : IdTable> T.insertAndGetId( - body: T.(InsertStatement>) -> Unit + crossinline body: T.(InsertStatement>) -> Unit ): EntityID = InsertStatement>(this, false).run { body(this) @@ -371,7 +416,7 @@ private fun executeBatch( * @sample org.jetbrains.exposed.sql.tests.shared.dml.InsertTests.testInsertIgnoreAndGetIdWithPredefinedId */ inline fun T.insertIgnore( - body: T.(UpdateBuilder<*>) -> Unit + crossinline body: T.(UpdateBuilder<*>) -> Unit ): InsertStatement = InsertStatement(this, isIgnore = true).apply { body(this) execute(TransactionManager.current()) @@ -388,7 +433,7 @@ inline fun T.insertIgnore( * @sample org.jetbrains.exposed.sql.tests.shared.dml.InsertTests.testInsertIgnoreAndGetId01 */ inline fun , T : IdTable> T.insertIgnoreAndGetId( - body: T.(UpdateBuilder<*>) -> Unit + crossinline body: T.(UpdateBuilder<*>) -> Unit ): EntityID? = InsertStatement>(this, isIgnore = true).run { body(this) @@ -407,7 +452,7 @@ inline fun , T : IdTable> T.insertIgnoreAndGetId( * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReplaceTests.testReplaceWithExpression */ inline fun T.replace( - body: T.(UpdateBuilder<*>) -> Unit + crossinline body: T.(UpdateBuilder<*>) -> Unit ): ReplaceStatement = ReplaceStatement(this).apply { body(this) execute(TransactionManager.current()) @@ -476,7 +521,7 @@ private fun Column<*>.isValidIfAutoIncrement(): Boolean = inline fun T.insertReturning( returning: List> = columns, ignoreErrors: Boolean = false, - body: T.(InsertStatement) -> Unit + crossinline body: T.(InsertStatement) -> Unit ): ReturningStatement { val insert = InsertStatement(this, ignoreErrors) body(insert) @@ -492,11 +537,27 @@ inline fun T.insertReturning( * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpdateTests.testUpdate01 */ inline fun T.update( - noinline where: (SqlExpressionBuilder.() -> Op)? = null, + where: SqlExpressionBuilder.() -> Op, + limit: Int? = null, + crossinline body: T.(UpdateStatement) -> Unit +): Int { + val query = UpdateStatement(this, limit, SqlExpressionBuilder.where()) + body(query) + return query.execute(TransactionManager.current()) ?: 0 +} + +/** + * Represents the SQL statement that updates all rows of a table. + * + * @param limit Maximum number of rows to update. + * @return The number of updated rows. + * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpdateTests.testUpdate01 + */ +inline fun T.update( limit: Int? = null, - body: T.(UpdateStatement) -> Unit + crossinline body: T.(UpdateStatement) -> Unit ): Int { - val query = UpdateStatement(this, limit, where?.let { SqlExpressionBuilder.it() }) + val query = UpdateStatement(this, limit, null) body(query) return query.execute(TransactionManager.current()) ?: 0 } @@ -510,11 +571,27 @@ inline fun T.update( * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpdateTests.testUpdateWithSingleJoin */ inline fun Join.update( - noinline where: (SqlExpressionBuilder.() -> Op)? = null, + where: SqlExpressionBuilder.() -> Op, limit: Int? = null, - body: (UpdateStatement) -> Unit + crossinline body: (UpdateStatement) -> Unit ): Int { - val query = UpdateStatement(this, limit, where?.let { SqlExpressionBuilder.it() }) + val query = UpdateStatement(this, limit, SqlExpressionBuilder.where()) + body(query) + return query.execute(TransactionManager.current()) ?: 0 +} + +/** + * Represents the SQL statement that updates all rows of a join relation. + * + * @param limit Maximum number of rows to update. + * @return The number of updated rows. + * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpdateTests.testUpdateWithSingleJoin + */ +inline fun Join.update( + limit: Int? = null, + crossinline body: (UpdateStatement) -> Unit +): Int { + val query = UpdateStatement(this, limit, null) body(query) return query.execute(TransactionManager.current()) ?: 0 } @@ -523,16 +600,34 @@ inline fun Join.update( * Represents the SQL statement that updates rows of a table and returns specified data from the updated 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 update. + * @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.testUpdateReturning + */ +inline fun T.updateReturning( + returning: List> = columns, + where: SqlExpressionBuilder.() -> Op, + crossinline body: T.(UpdateStatement) -> Unit +): ReturningStatement { + val update = UpdateStatement(this, null, SqlExpressionBuilder.where()) + body(update) + return ReturningStatement(this, returning, update) +} + +/** + * Represents the SQL statement that updates all rows of a table and returns specified data from the updated rows. + * + * @param returning Columns and expressions to include in the returned data. This defaults to all columns in the table. * @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.testUpdateReturning */ inline fun T.updateReturning( returning: List> = columns, - noinline where: (SqlExpressionBuilder.() -> Op)? = null, - body: T.(UpdateStatement) -> Unit + crossinline body: T.(UpdateStatement) -> Unit ): ReturningStatement { - val update = UpdateStatement(this, null, where?.let { SqlExpressionBuilder.it() }) + val update = UpdateStatement(this, null, null) body(update) return ReturningStatement(this, returning, update) } @@ -557,11 +652,11 @@ inline fun T.updateReturning( * @param where Condition that determines which rows to update, if a unique violation is found. * @sample org.jetbrains.exposed.sql.tests.shared.dml.UpsertTests.testUpsertWithUniqueIndexConflict */ -inline fun T.upsert( +fun T.upsert( vararg keys: Column<*>, - noinline onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, + onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, onUpdateExclude: List>? = null, - noinline where: (SqlExpressionBuilder.() -> Op)? = null, + where: (SqlExpressionBuilder.() -> Op)? = null, body: T.(UpsertStatement) -> Unit ) = UpsertStatement(this, keys = keys, onUpdateExclude = onUpdateExclude, where = where?.let { SqlExpressionBuilder.it() }).apply { onUpdate?.let { storeUpdateValues(it) } @@ -606,12 +701,12 @@ fun T.upsert( * expressions mapped to their resulting data. * @sample org.jetbrains.exposed.sql.tests.shared.dml.ReturningTests.testUpsertReturning */ -inline fun T.upsertReturning( +fun T.upsertReturning( vararg keys: Column<*>, returning: List> = columns, - noinline onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, + onUpdate: (UpsertBuilder.(UpdateStatement) -> Unit)? = null, onUpdateExclude: List>? = null, - noinline where: (SqlExpressionBuilder.() -> Op)? = null, + where: (SqlExpressionBuilder.() -> Op)? = null, body: T.(UpsertStatement) -> Unit ): ReturningStatement { val upsert = UpsertStatement(this, keys = keys, onUpdateExclude, where?.let { SqlExpressionBuilder.it() }) @@ -776,10 +871,31 @@ fun Table.exists(): Boolean = currentDialect.tableExists(this) */ inline fun D.mergeFrom( source: S, - noinline on: (SqlExpressionBuilder.() -> Op)? = null, - body: MergeTableStatement.() -> Unit + on: SqlExpressionBuilder.() -> Op, + crossinline body: MergeTableStatement.() -> Unit +): MergeTableStatement { + return MergeTableStatement(this, source, on = SqlExpressionBuilder.on()).apply { + body(this) + execute(TransactionManager.current()) + } +} + +/** + * Performs an SQL MERGE operation to insert, update, or delete records in the target table based on + * a comparison with a source table. + * + * @param D The target table type extending from [Table]. + * @param S The source table type extending from [Table]. + * @param source An instance of the source table. + * @param body A lambda where [MergeTableStatement] can be configured with specific actions to perform + * when records are matched or not matched. + * @return A [MergeTableStatement] which represents the MERGE operation with the configured actions. + */ +inline fun D.mergeFrom( + source: S, + crossinline body: MergeTableStatement.() -> Unit ): MergeTableStatement { - return MergeTableStatement(this, source, on = on?.invoke(SqlExpressionBuilder)).apply { + return MergeTableStatement(this, source, on = null).apply { body(this) execute(TransactionManager.current()) } @@ -800,7 +916,7 @@ inline fun D.mergeFrom( inline fun T.mergeFrom( selectQuery: QueryAlias, on: SqlExpressionBuilder.() -> Op, - body: MergeSelectStatement.() -> Unit + crossinline body: MergeSelectStatement.() -> Unit ): MergeSelectStatement { return MergeSelectStatement(this, selectQuery, SqlExpressionBuilder.on()).apply { body(this)