Skip to content

Commit

Permalink
fix: EXPOSED-493 Update with join query throws if WHERE clause present
Browse files Browse the repository at this point in the history
- Break up new tests into separate unit tests
- Fix typos in update(where) unsupported exceptions
- Rebase from main
  • Loading branch information
bog-walk committed Aug 20, 2024
1 parent b28fe48 commit e17ce9c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,13 @@ internal object H2FunctionProvider : FunctionProvider() {
transaction.throwUnsupportedException("H2 doesn't support WHERE in UPDATE with join clause.")
}
val tableToUpdate = columnsAndValues.map { it.first.table }.distinct().singleOrNull()
?: transaction.throwUnsupportedException("H2 supports a join updates with a single table columns to update.")
?: transaction.throwUnsupportedException(
"H2 doesn't support UPDATE with join clause that uses columns from multiple tables."
)
val joinPart = targets.joinParts.singleOrNull()
?: transaction.throwUnsupportedException("H2 supports a join updates with only one table to join.")
?: transaction.throwUnsupportedException(
"H2 doesn't support UPDATE with join clause that uses multiple tables to join."
)
if (joinPart.joinType != JoinType.INNER) {
exposedLogger.warn("All tables in UPDATE statement will be joined with inner join")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,6 @@ class UpdateTests : DatabaseTestsBase() {
assertEquals(it[users.name], it[userData.comment])
assertEquals(0, it[userData.value])
}

val userAlias = users.selectAll().where { users.cityId neq 1 }.alias("u2")
val joinWithSubQuery = userData.innerJoin(userAlias, { userData.user_id }, { userAlias[users.id] })
joinWithSubQuery.update {
it[userData.value] = 123
}

joinWithSubQuery.selectAll().forEach {
assertEquals(123, it[userData.value])
}

if (currentTestDB in TestDB.ALL_H2_V1) { // h2_v1 treats 'U2' query as a table/view dependent on USERS
exec("${users.dropStatement().single()} CASCADE")
}
}
}

Expand All @@ -122,22 +108,6 @@ class UpdateTests : DatabaseTestsBase() {
assertEquals(it[users.name], it[userData.comment])
assertEquals(123, it[userData.value])
}

val singleJoinQuery = userData.joinQuery(
on = { userData.user_id eq it[users.id] },
joinPart = { users.selectAll().where { users.cityId neq 1 } }
)
val doubleJoinQuery = singleJoinQuery.joinQuery(
on = { userData.user_id eq it[users.id] },
joinPart = { users.selectAll().where { users.name like "%ey" } }
)
doubleJoinQuery.update {
it[userData.value] = 0
}

doubleJoinQuery.selectAll().forEach {
assertEquals(0, it[userData.value])
}
}
}

Expand Down Expand Up @@ -175,16 +145,6 @@ class UpdateTests : DatabaseTestsBase() {
it[tableB.bar] = "baz"
}
assertEquals(0, joinWithConstraint.selectAll().count())

val subquery = tableA.selectAll().where { tableA.foo eq "foo" }.alias("sq")
val joinWithSubquery = tableB.innerJoin(subquery, { tableB.tableAId }, { subquery[tableA.id] })
joinWithSubquery.update({ tableB.bar eq "baz" }) {
it[tableB.bar] = "zip"
}

joinWithSubquery.selectAll().single().also {
assertEquals("zip", it[tableB.bar])
}
} else {
expectException<UnsupportedByDialectException> {
join.update({ tableA.foo eq "foo" }) {
Expand All @@ -195,6 +155,50 @@ class UpdateTests : DatabaseTestsBase() {
}
}

@Test
fun testUpdateWithJoinQuery() {
withCitiesAndUsers(exclude = TestDB.ALL_H2_V1 + TestDB.SQLITE) { _, users, userData ->
// single join query using join()
val userAlias = users.selectAll().where { users.cityId neq 1 }.alias("u2")
val joinWithSubQuery = userData.innerJoin(userAlias, { userData.user_id }, { userAlias[users.id] })
joinWithSubQuery.update {
it[userData.value] = 123
}

joinWithSubQuery.selectAll().forEach {
assertEquals(123, it[userData.value])
}

if (currentTestDB !in TestDB.ALL_H2) { // does not support either multi-table joins or update(where)
// single join query using join() with update(where)
joinWithSubQuery.update({ userData.comment like "Comment%" }) {
it[userData.value] = 0
}

joinWithSubQuery.selectAll().forEach {
assertEquals(0, it[userData.value])
}

// multiple join queries using joinQuery()
val singleJoinQuery = userData.joinQuery(
on = { userData.user_id eq it[users.id] },
joinPart = { users.selectAll().where { users.cityId neq 1 } }
)
val doubleJoinQuery = singleJoinQuery.joinQuery(
on = { userData.user_id eq it[users.id] },
joinPart = { users.selectAll().where { users.name like "%ey" } }
)
doubleJoinQuery.update {
it[userData.value] = 99
}

doubleJoinQuery.selectAll().forEach {
assertEquals(99, it[userData.value])
}
}
}
}

@Test
fun `test that column length checked in update `() {
val stringTable = object : IntIdTable("StringTable") {
Expand Down

0 comments on commit e17ce9c

Please sign in to comment.