From 033ba6159814c2e3cb8601bb9d7044cb56cbd142 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 22 Apr 2022 20:31:32 +0200 Subject: [PATCH] [jOOQ/jOOQ#11731] Emulate Oracle INSERT .. SELECT.. RETURNING --- .../java/org/jooq/impl/AbstractDMLQuery.java | 14 ++- .../org/jooq/impl/FieldMapsForInsert.java | 107 +++++++++++++----- .../java/org/jooq/impl/InsertQueryImpl.java | 6 + jOOQ/src/main/java/org/jooq/impl/Tools.java | 11 +- 4 files changed, 99 insertions(+), 39 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java index f0ba880e59..6090b19557 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java @@ -98,7 +98,6 @@ import static org.jooq.impl.Tools.anyMatch; import static org.jooq.impl.Tools.autoAlias; import static org.jooq.impl.Tools.flattenCollection; import static org.jooq.impl.Tools.map; -import static org.jooq.impl.Tools.BooleanDataKey.DATA_EMULATE_BULK_INSERT_RETURNING; import static org.jooq.impl.Tools.BooleanDataKey.DATA_UNALIAS_ALIASED_EXPRESSIONS; import static org.jooq.impl.Tools.DataKey.DATA_DML_TARGET_TABLE; import static org.jooq.impl.Tools.DataKey.DATA_TOP_LEVEL_CTE; @@ -121,7 +120,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.regex.Pattern; import org.jooq.Asterisk; import org.jooq.Binding; @@ -148,7 +146,6 @@ import org.jooq.Result; import org.jooq.Row; import org.jooq.RowId; import org.jooq.SQLDialect; -import org.jooq.SchemaMapping; import org.jooq.Scope; import org.jooq.Select; import org.jooq.SelectFieldOrAsterisk; @@ -157,9 +154,6 @@ import org.jooq.TableField; import org.jooq.UniqueKey; import org.jooq.Update; import org.jooq.conf.ExecuteWithoutWhere; -import org.jooq.conf.MappedSchema; -import org.jooq.conf.MappedTable; -import org.jooq.conf.RenderMapping; import org.jooq.conf.RenderNameCase; import org.jooq.conf.SettingsTools; import org.jooq.exception.DataAccessException; @@ -636,6 +630,14 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index bb9ba4c7f9..702d8c8193 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java @@ -60,7 +60,6 @@ import static org.jooq.impl.Tools.flatten; import static org.jooq.impl.Tools.flattenCollection; import static org.jooq.impl.Tools.flattenFieldOrRows; import static org.jooq.impl.Tools.lazy; -import static org.jooq.impl.Tools.BooleanDataKey.DATA_EMULATE_BULK_INSERT_RETURNING; import java.util.AbstractList; import java.util.AbstractMap; @@ -95,6 +94,7 @@ import org.jooq.conf.WriteIfReadonly; import org.jooq.exception.DataTypeException; import org.jooq.impl.AbstractStoreQuery.UnknownField; import org.jooq.impl.QOM.UNotYetImplemented; +import org.jooq.impl.Tools.BooleanDataKey; /** * @author Lukas Eder @@ -135,13 +135,23 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + + + + + + + + + + + + + + // Single record inserts can use the standard syntax in any dialect - - - - - else if (rows == 1 ) { + else if (rows == 1 && supportsValues(ctx)) { ctx.formatSeparator() .start(INSERT_VALUES) .visit(K_VALUES) @@ -170,16 +180,6 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple - - - - - - - - - - @@ -302,6 +302,8 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + private final boolean supportsValues(Context ctx) { + switch (ctx.family()) { @@ -316,6 +318,15 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + + + + + default: + return true; + } + } + final Select insertSelect(Context ctx, GeneratorStatementType statementType) { Select select = null; @@ -334,12 +345,10 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple } final void toSQL92Values(Context ctx) { - toSQL92Values(ctx, false); - } - - final void toSQL92Values(Context ctx, boolean emulateBulkInsertReturning) { boolean indent = (values.size() > 1); - boolean castFirstRowNumericValues = false ; + + + // [#2823] [#10033] Few dialects need bind value casts for INSERT .. VALUES(?, ?) // Some regressions have been observed e.g. in PostgreSQL with JSON types, so let's be careful. @@ -347,7 +356,7 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple if (!CASTS_NEEDED.contains(ctx.dialect())) ctx.castMode(CastMode.NEVER); - for (int row = 0; row < rows ; row++) { + for (int row = 0; row < rows; row++) { if (row > 0) ctx.sql(", "); @@ -358,8 +367,6 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple ctx.formatIndentStart(); String separator = ""; - int i = 0; - for (List> list : valuesFlattened(ctx, GeneratorStatementType.INSERT).values()) { ctx.sql(separator); @@ -379,9 +386,6 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple - - - ctx.visit(list.get(row)); separator = ", "; } @@ -398,6 +402,51 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple ctx.castMode(previous); } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // ------------------------------------------------------------------------- // The FieldMapsForInsert API // ------------------------------------------------------------------------- @@ -600,13 +649,15 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple } // [#989] Avoid qualifying fields in INSERT field declaration - Set> fields = keysFlattened(ctx, GeneratorStatementType.INSERT); + Set> fields; + fields = keysFlattened(ctx, GeneratorStatementType.INSERT); + if (!fields.isEmpty()) ctx.sql(" (").visit(wrap(fields).qualify(false)).sql(')'); diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java index 8a77b70ce6..9bf2e5a895 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java @@ -129,6 +129,7 @@ import org.jooq.UniqueKey; import org.jooq.conf.WriteIfReadonly; import org.jooq.impl.FieldMapForUpdate.SetClause; import org.jooq.impl.QOM.UNotYetImplemented; +import org.jooq.impl.Tools.BooleanDataKey; import org.jooq.impl.Tools.DataExtendedKey; import org.jooq.tools.StringUtils; @@ -1004,4 +1005,9 @@ implements + + + + + } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 0fb56b25c6..1ad4f9a48b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -474,6 +474,12 @@ final class Tools { + + + + + + /** * [#1629] The {@link Connection#getAutoCommit()} flag value before starting * a new transaction. @@ -539,11 +545,6 @@ final class Tools { */ DATA_NESTED_SET_OPERATIONS, - /** - * [#5191] Whether INSERT RETURNING is being emulated for bulk insertions. - */ - DATA_EMULATE_BULK_INSERT_RETURNING, - /** * [#9925] In some cases the AS keyword is required for * aliasing, e.g. XML.