diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java index a9557cb257..5c117404ba 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapForInsert.java @@ -35,6 +35,7 @@ */ package org.jooq.impl; +import static org.jooq.Clause.FIELD_ROW; import static org.jooq.impl.Utils.visitAll; import java.util.Collection; @@ -55,7 +56,8 @@ class FieldMapForInsert extends AbstractQueryPartMap, Field> { /** * Generated UID */ - private static final long serialVersionUID = -2192833491610583485L; + private static final long serialVersionUID = -2192833491610583485L; + private static final Clause[] CLAUSES = { FIELD_ROW }; FieldMapForInsert() { } @@ -63,30 +65,30 @@ class FieldMapForInsert extends AbstractQueryPartMap, Field> { @Override public final void toSQL(RenderContext context) { boolean indent = (size() > 1); - + context.sql("("); - + if (indent) { context.formatIndentStart(); } - + String separator = ""; for (Field field : values()) { context.sql(separator); - + if (indent) { context.formatNewLine(); } - + context.visit(field); separator = ", "; } - + if (indent) { context.formatIndentEnd() .formatNewLine(); } - + context.sql(")"); } @@ -133,7 +135,7 @@ class FieldMapForInsert extends AbstractQueryPartMap, Field> { @Override public final Clause[] clauses(Context ctx) { - return null; + return CLAUSES; } final void putFields(Collection> fields) { diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index b2e6f238e9..0dc386fc65 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java @@ -116,8 +116,6 @@ class FieldMapsForInsert extends AbstractQueryPart { } private void toSQLInsertSelect(RenderContext context) { - context.start(INSERT_SELECT); - Select select = null; for (FieldMapForInsert map : insertMaps) { if (map != null) { @@ -133,7 +131,6 @@ class FieldMapsForInsert extends AbstractQueryPart { } context.visit(select); - context.end(INSERT_SELECT); } private void toSQL92Values(RenderContext context) { diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java index f68bc27dfe..00ec883e74 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java @@ -36,6 +36,8 @@ package org.jooq.impl; import static org.jooq.Clause.INSERT; +import static org.jooq.Clause.INSERT_INSERT_INTO; +import static org.jooq.Clause.INSERT_SELECT; import static org.jooq.impl.Utils.visitAll; import org.jooq.BindContext; @@ -74,22 +76,31 @@ class InsertSelectQueryImpl extends AbstractQuery implements I @Override public final void toSQL(RenderContext context) { - context.keyword("insert into") + context.start(INSERT_INSERT_INTO) + .keyword("insert into") .sql(" ") .visit(into) .sql(" ("); + // [#989] Avoid qualifying fields in INSERT field declaration + boolean qualify = context.qualify(); + context.qualify(false); + String separator = ""; for (Field field : fields) { context.sql(separator) - .literal(field.getName()); + .visit(field); separator = ", "; } + context.qualify(qualify); context.sql(")") + .end(INSERT_INSERT_INTO) .formatSeparator() - .visit(select); + .start(INSERT_SELECT) + .visit(select) + .end(INSERT_SELECT); } @Override diff --git a/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java b/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java index c7e56ffa5f..39ca2ed942 100644 --- a/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java +++ b/jOOQ/src/test/java/org/jooq/test/VisitContextTest.java @@ -60,6 +60,7 @@ import static org.jooq.Clause.FIELD_VALUE; import static org.jooq.Clause.INSERT; import static org.jooq.Clause.INSERT_INSERT_INTO; import static org.jooq.Clause.INSERT_RETURNING; +import static org.jooq.Clause.INSERT_SELECT; import static org.jooq.Clause.INSERT_VALUES; import static org.jooq.Clause.SELECT; import static org.jooq.Clause.SELECT_CONNECT_BY; @@ -69,6 +70,7 @@ import static org.jooq.Clause.SELECT_HAVING; import static org.jooq.Clause.SELECT_ORDER_BY; import static org.jooq.Clause.SELECT_SELECT; import static org.jooq.Clause.SELECT_START_WITH; +import static org.jooq.Clause.SELECT_UNION_ALL; import static org.jooq.Clause.SELECT_WHERE; import static org.jooq.Clause.TABLE; import static org.jooq.Clause.TABLE_REFERENCE; @@ -223,16 +225,152 @@ public class VisitContextTest extends AbstractTest { asList(INSERT, INSERT_INSERT_INTO, FIELD), asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), asList(INSERT, INSERT_VALUES), - asList(INSERT, INSERT_VALUES, FIELD), - asList(INSERT, INSERT_VALUES, FIELD, FIELD_VALUE), - asList(INSERT, INSERT_VALUES, FIELD), - asList(INSERT, INSERT_VALUES, FIELD, FIELD_VALUE), - asList(INSERT, INSERT_VALUES, FIELD), - asList(INSERT, INSERT_VALUES, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), asList(INSERT, INSERT_RETURNING) )); } + @Test + public void test_INSERT_VALUES_multiple() { + + // Postgres has a native implementation for multi-value inserts + ctx.configuration().set(POSTGRES); + ctx.insertInto(TABLE1) + .values(1, "value", null) + .values(2, "value", null) + .getSQL(); + + assertEvents(asList( + asList(INSERT), + asList(INSERT, INSERT_INSERT_INTO), + asList(INSERT, INSERT_INSERT_INTO, TABLE), + asList(INSERT, INSERT_INSERT_INTO, TABLE, TABLE_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_VALUES), + asList(INSERT, INSERT_VALUES, FIELD_ROW), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD), + asList(INSERT, INSERT_VALUES, FIELD_ROW, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_RETURNING) + )); + } + + @Test + public void test_INSERT_VALUES_multiple_emulated() { + + // Oracle emulates multi-record inserts through INSERT .. SELECT + ctx.insertInto(TABLE1) + .values(1, "value", null) + .values(2, "value", null) + .getSQL(); + + assertEvents(asList( + asList(INSERT), + asList(INSERT, INSERT_INSERT_INTO), + asList(INSERT, INSERT_INSERT_INTO, TABLE), + asList(INSERT, INSERT_INSERT_INTO, TABLE, TABLE_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_SELECT), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_FROM), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_FROM, TABLE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_WHERE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_START_WITH), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_CONNECT_BY), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_GROUP_BY), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_HAVING), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_ORDER_BY), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_FROM), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_FROM, TABLE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_WHERE), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_START_WITH), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_CONNECT_BY), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_GROUP_BY), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_HAVING), + asList(INSERT, INSERT_SELECT, SELECT_UNION_ALL, SELECT, SELECT_ORDER_BY), + asList(INSERT, INSERT_RETURNING) + )); + } + + @Test + public void test_INSERT_SELECT() { + ctx.insertInto(TABLE1) + .select(select(val(1), val("value"), val(null))) + .getSQL(); + + assertEvents(asList( + asList(INSERT), + asList(INSERT, INSERT_INSERT_INTO), + asList(INSERT, INSERT_INSERT_INTO, TABLE), + asList(INSERT, INSERT_INSERT_INTO, TABLE, TABLE_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_INSERT_INTO, FIELD), + asList(INSERT, INSERT_INSERT_INTO, FIELD, FIELD_REFERENCE), + asList(INSERT, INSERT_SELECT), + asList(INSERT, INSERT_SELECT, SELECT), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT, FIELD), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_SELECT, FIELD, FIELD_VALUE), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_FROM), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_FROM, TABLE), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_WHERE), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_START_WITH), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_CONNECT_BY), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_GROUP_BY), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_HAVING), + asList(INSERT, INSERT_SELECT, SELECT, SELECT_ORDER_BY) + )); + } + @Test public void test_UPDATE_SET_simple() { ctx.update(TABLE1)