[jOOQ/jOOQ#11731] Emulate Oracle INSERT .. SELECT.. RETURNING

This commit is contained in:
Lukas Eder 2022-04-22 20:31:32 +02:00
parent abd9e5b7fc
commit 033ba61598
4 changed files with 99 additions and 39 deletions

View File

@ -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<R extends Record> extends AbstractRowCountQuery

View File

@ -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<Record> insertSelect(Context<?> ctx, GeneratorStatementType statementType) {
Select<Record> 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<Field<?>> 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<Field<?>> fields = keysFlattened(ctx, GeneratorStatementType.INSERT);
Set<Field<?>> fields;
fields = keysFlattened(ctx, GeneratorStatementType.INSERT);
if (!fields.isEmpty())
ctx.sql(" (").visit(wrap(fields).qualify(false)).sql(')');

View File

@ -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
}

View File

@ -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 <code>AS</code> keyword is required for
* aliasing, e.g. XML.