From 9f34c5cfe360c5e0f09df409d83e04206bd02883 Mon Sep 17 00:00:00 2001 From: "Andrey.Tarashevskiy" Date: Tue, 20 Apr 2021 12:32:36 +0300 Subject: [PATCH] Fixes for inserts with select and h2 #492, #1164, #1209 --- .../kotlin/org/jetbrains/exposed/sql/ColumnType.kt | 2 +- .../kotlin/org/jetbrains/exposed/sql/Queries.kt | 14 +++++++++----- .../org/jetbrains/exposed/sql/vendors/Default.kt | 2 ++ .../sql/tests/shared/dml/InsertSelectTests.kt | 4 +++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt index ffb74cd844..4256b5258a 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt @@ -103,7 +103,7 @@ class AutoIncColumnType( /** Returns the name of the sequence used to generate new values for this auto-increment column. */ val autoincSeq: String? - get() = _autoincSeq ?: fallbackSeqName.takeIf { currentDialect.needsSequenceToAutoInc } + get() = _autoincSeq.takeIf { currentDialect.supportsCreateSequence } ?: fallbackSeqName.takeIf { currentDialect.needsSequenceToAutoInc } val nextValExpression: NextVal<*>? get() = nextValValue.takeIf { autoincSeq != null } 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 901f9d94e9..74e1ab0806 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 @@ -159,11 +159,15 @@ fun T.replace(body: T.(UpdateBuilder<*>) -> Unit): ReplaceStatement< /** * @sample org.jetbrains.exposed.sql.tests.shared.DMLTests.testInsertSelect01 */ -fun T.insert(selectQuery: AbstractQuery<*>, columns: List> = this.columns.filterNot { it.columnType.isAutoInc }) = - InsertSelectStatement(columns, selectQuery).execute(TransactionManager.current()) - -fun T.insertIgnore(selectQuery: AbstractQuery<*>, columns: List> = this.columns.filterNot { it.columnType.isAutoInc }) = - InsertSelectStatement(columns, selectQuery, true).execute(TransactionManager.current()) +fun T.insert( + selectQuery: AbstractQuery<*>, + columns: List> = this.columns.filter { !it.columnType.isAutoInc || it.autoIncColumnType?.nextValExpression != null } +) = InsertSelectStatement(columns, selectQuery).execute(TransactionManager.current()) + +fun T.insertIgnore( + selectQuery: AbstractQuery<*>, + columns: List> = this.columns.filter { !it.columnType.isAutoInc || it.autoIncColumnType?.nextValExpression != null } +) = InsertSelectStatement(columns, selectQuery, true).execute(TransactionManager.current()) /** * @sample org.jetbrains.exposed.sql.tests.shared.DMLTests.testUpdate01 diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt index 480ad9613a..49b4db9d9f 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt @@ -361,8 +361,10 @@ abstract class FunctionProvider { val autoIncColumn = table.autoIncColumn val nextValExpression = autoIncColumn?.autoIncColumnType?.nextValExpression?.takeIf { autoIncColumn !in columns } + val isInsertFromSelect = expr.isNotEmpty() && !expr.startsWith("VALUES") val (columnsToInsert, valuesExpr) = when { + isInsertFromSelect -> columns to expr nextValExpression != null && columns.isNotEmpty() -> (columns + autoIncColumn) to expr.dropLast(1) + ", $nextValExpression)" nextValExpression != null -> listOf(autoIncColumn) to "VALUES ($nextValExpression)" columns.isNotEmpty() -> columns to expr diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/InsertSelectTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/InsertSelectTests.kt index d910522282..b08fdcfec9 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/InsertSelectTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/InsertSelectTests.kt @@ -11,8 +11,10 @@ class InsertSelectTests : DatabaseTestsBase() { @Test fun testInsertSelect01() { withCitiesAndUsers(exclude = listOf(TestDB.ORACLE)) { cities, users, userData -> + val nextVal = cities.id.autoIncColumnType?.nextValExpression val substring = users.name.substring(1, 2) - cities.insert(users.slice(substring).selectAll().orderBy(users.id).limit(2)) + val slice = listOfNotNull(nextVal, substring) + cities.insert(users.slice(slice).selectAll().orderBy(users.id).limit(2)) val r = cities.slice(cities.name).selectAll().orderBy(cities.id, SortOrder.DESC).limit(2).toList() assertEquals(2, r.size)