diff --git a/jOOQ-spring/src/main/java/org/jooq/util/spring/FactoryProxy.java b/jOOQ-spring/src/main/java/org/jooq/util/spring/FactoryProxy.java index 2e7faf4f6d..c6ed98d03d 100644 --- a/jOOQ-spring/src/main/java/org/jooq/util/spring/FactoryProxy.java +++ b/jOOQ-spring/src/main/java/org/jooq/util/spring/FactoryProxy.java @@ -287,6 +287,7 @@ public class FactoryProxy implements FactoryOperations, MethodInterceptor { } @Override + @Deprecated public final Insert insertInto(Table into, Select select) { return getDelegate().insertInto(into, select); } diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 8e7d64a7a6..763f446e4f 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -4395,23 +4395,35 @@ public abstract class jOOQAbstractTest< break; } - Insert i = create().insertInto( - TAuthor(), - create().select(vals( - 1000, - val("Lukas"))) - .select(vals( - "Eder", - val(new Date(363589200000L)), - castNull(Integer.class), - nullField))); + Insert i = + create().insertInto(TAuthor()) + .select(create().select(vals( + 1000, + val("Lukas"))) + .select(vals( + "Eder", + val(new Date(363589200000L)), + castNull(Integer.class), + nullField))); - i.execute(); + assertEquals(1, i.execute()); - A author = create().fetchOne(TAuthor(), TAuthor_FIRST_NAME().equal("Lukas")); - assertEquals("Lukas", author.getValue(TAuthor_FIRST_NAME())); - assertEquals("Eder", author.getValue(TAuthor_LAST_NAME())); - assertEquals(null, author.getValue(TAuthor_YEAR_OF_BIRTH())); + A author1 = create().fetchOne(TAuthor(), TAuthor_FIRST_NAME().equal("Lukas")); + assertEquals(1000, (int) author1.getValue(TAuthor_ID())); + assertEquals("Lukas", author1.getValue(TAuthor_FIRST_NAME())); + assertEquals("Eder", author1.getValue(TAuthor_LAST_NAME())); + assertEquals(null, author1.getValue(TAuthor_YEAR_OF_BIRTH())); + + // [#1069] Run checks for INSERT INTO t(a, b) SELECT x, y syntax + i = create().insertInto(TAuthor(), TAuthor_ID(), TAuthor_LAST_NAME()) + .select(create().select(vals(1001, "Hesse"))); + + assertEquals(1, i.execute()); + A author2 = create().fetchOne(TAuthor(), TAuthor_LAST_NAME().equal("Hesse")); + assertEquals(1001, (int) author2.getValue(TAuthor_ID())); + assertEquals(null, author2.getValue(TAuthor_FIRST_NAME())); + assertEquals("Hesse", author2.getValue(TAuthor_LAST_NAME())); + assertEquals(null, author2.getValue(TAuthor_YEAR_OF_BIRTH())); } @Test diff --git a/jOOQ/src/main/java/org/jooq/FactoryOperations.java b/jOOQ/src/main/java/org/jooq/FactoryOperations.java index f1ce63e610..2bb4061f8e 100644 --- a/jOOQ/src/main/java/org/jooq/FactoryOperations.java +++ b/jOOQ/src/main/java/org/jooq/FactoryOperations.java @@ -416,12 +416,20 @@ public interface FactoryOperations extends Configuration { * Factory create = new Factory(); * * create.insertInto(table, create.select(1)) - * .onDuplicateKeyUpdate() - * .set(field1, value1) - * .set(field2, value2) * .execute(); * + * + * @deprecated - 2.0.3 - Use any of these methods instead: + *
    + *
  • {@link #insertInto(Table)} and + * {@link InsertSetStep#select(Select)}
  • + * {@link #insertInto(Table, Field...)} and + * {@link InsertValuesStep#select(Select)}
  • + * {@link #insertInto(Table, Collection)} and + * {@link InsertValuesStep#select(Select)}
  • + *
*/ + @Deprecated @Support Insert insertInto(Table into, Select select); diff --git a/jOOQ/src/main/java/org/jooq/InsertSetStep.java b/jOOQ/src/main/java/org/jooq/InsertSetStep.java index fcb0b9170b..c1a0fe92b2 100644 --- a/jOOQ/src/main/java/org/jooq/InsertSetStep.java +++ b/jOOQ/src/main/java/org/jooq/InsertSetStep.java @@ -99,4 +99,18 @@ public interface InsertSetStep { */ @Support InsertValuesStep values(Collection values); + + /** + * Use a SELECT statement as the source of values for the + * INSERT statement + *

+ * This variant of the INSERT .. SELECT statement does not + * allow for specifying a subset of the fields inserted into. It will insert + * into all fields of the table specified in the INTO clause. + * Use {@link FactoryOperations#insertInto(Table, Field...)} or + * {@link FactoryOperations#insertInto(Table, Collection)} instead, to + * define a field set for insertion. + */ + @Support + Insert select(Select select); } diff --git a/jOOQ/src/main/java/org/jooq/InsertValuesStep.java b/jOOQ/src/main/java/org/jooq/InsertValuesStep.java index 8d8a4a49b5..ed7d518fa5 100644 --- a/jOOQ/src/main/java/org/jooq/InsertValuesStep.java +++ b/jOOQ/src/main/java/org/jooq/InsertValuesStep.java @@ -73,4 +73,17 @@ public interface InsertValuesStep extends InsertOnDuplicateSte */ @Support InsertValuesStep values(Collection values); + + /** + * Use a SELECT statement as the source of values for the + * INSERT statement + *

+ * This variant of the INSERT .. SELECT statement expects a + * select returning exactly as many fields as specified previously in the + * INTO clause: + * {@link FactoryOperations#insertInto(Table, Field...)} or + * {@link FactoryOperations#insertInto(Table, Collection)} + */ + @Support + Insert select(Select select); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Factory.java b/jOOQ/src/main/java/org/jooq/impl/Factory.java index f748882a59..63b676384b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Factory.java +++ b/jOOQ/src/main/java/org/jooq/impl/Factory.java @@ -1056,8 +1056,9 @@ public class Factory implements FactoryOperations { * {@inheritDoc} */ @Override + @Deprecated public final Insert insertInto(Table into, Select select) { - return new InsertSelectQueryImpl(this, into, select); + return new InsertSelectQueryImpl(this, into, into.getFields(), select); } /** diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java index 6c1692dd82..9b1452bf2b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java @@ -44,8 +44,10 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import org.jooq.AttachableInternal; import org.jooq.Configuration; import org.jooq.Field; +import org.jooq.Insert; import org.jooq.InsertOnDuplicateSetMoreStep; import org.jooq.InsertQuery; import org.jooq.InsertResultStep; @@ -54,6 +56,7 @@ import org.jooq.InsertValuesStep; import org.jooq.Query; import org.jooq.Record; import org.jooq.Result; +import org.jooq.Select; import org.jooq.Table; /** @@ -108,6 +111,12 @@ class InsertImpl // The DSL API // ------------------------------------------------------------------------- + @Override + public final Insert select(Select select) { + Configuration configuration = getDelegate().internalAPI(AttachableInternal.class).getConfiguration(); + return new InsertSelectQueryImpl(configuration, into, fields, select); + } + @Override public final InsertImpl values(Object... values) { return values0(vals(convert(getFields(), values))); diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java index 3def0947ff..1f9952de00 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertSelectQueryImpl.java @@ -55,15 +55,17 @@ class InsertSelectQueryImpl extends AbstractQuery implements I /** * Generated UID */ - private static final long serialVersionUID = -1540775270159018516L; + private static final long serialVersionUID = -1540775270159018516L; - private final Table into; - private final Select select; + private final Table into; + private final List> fields; + private final Select select; - public InsertSelectQueryImpl(Configuration configuration, Table into, Select select) { + InsertSelectQueryImpl(Configuration configuration, Table into, List> fields, Select select) { super(configuration); this.into = into; + this.fields = (fields == null || fields.isEmpty()) ? into.getFields() : fields; this.select = select; } @@ -77,7 +79,7 @@ class InsertSelectQueryImpl extends AbstractQuery implements I context.sql("insert into ").sql(into).sql(" ("); String separator = ""; - for (Field field : into.getFields()) { + for (Field field : fields) { context.sql(separator).literal(field.getName()); separator = ", "; } @@ -88,7 +90,7 @@ class InsertSelectQueryImpl extends AbstractQuery implements I @Override public final void bind(BindContext context) { context.bind(into); - context.bind(into.getFields()); + context.bind(fields); context.bind(select); } } diff --git a/jOOQ/src/test/java/org/jooq/test/jOOQTest.java b/jOOQ/src/test/java/org/jooq/test/jOOQTest.java index 2a1809ca3b..7736aa7828 100644 --- a/jOOQ/src/test/java/org/jooq/test/jOOQTest.java +++ b/jOOQ/src/test/java/org/jooq/test/jOOQTest.java @@ -723,20 +723,20 @@ public class jOOQTest { @Test public void testLikeCondition() throws Exception { Condition c1 = FIELD_NAME1.like("%a%"); - assertEquals("\"TABLE1\".\"ID1\" like '%a%')", r_refI().render(c1)); - assertEquals("\"TABLE1\".\"ID1\" like ?)", r_ref().render(c1)); + assertEquals("\"TABLE1\".\"NAME1\" like '%a%'", r_refI().render(c1)); + assertEquals("\"TABLE1\".\"NAME1\" like ?", r_ref().render(c1)); Condition c2 = FIELD_NAME1.notLike("%a%"); - assertEquals("\"TABLE1\".\"ID1\" not like '%a%')", r_refI().render(c2)); - assertEquals("\"TABLE1\".\"ID1\" not like ?)", r_ref().render(c2)); + assertEquals("\"TABLE1\".\"NAME1\" not like '%a%'", r_refI().render(c2)); + assertEquals("\"TABLE1\".\"NAME1\" not like ?", r_ref().render(c2)); Condition c3 = FIELD_NAME1.like("%a%", '!'); - assertEquals("\"TABLE1\".\"ID1\" like '%a%' escape '!')", r_refI().render(c3)); - assertEquals("\"TABLE1\".\"ID1\" like ? escape '!')", r_ref().render(c3)); + assertEquals("\"TABLE1\".\"NAME1\" like '%a%' escape '!'", r_refI().render(c3)); + assertEquals("\"TABLE1\".\"NAME1\" like ? escape '!'", r_ref().render(c3)); Condition c4 = FIELD_NAME1.notLike("%a%", '!'); - assertEquals("\"TABLE1\".\"ID1\" not like '%a%' escape '!')", r_refI().render(c4)); - assertEquals("\"TABLE1\".\"ID1\" not like ? escape '!')", r_ref().render(c4)); + assertEquals("\"TABLE1\".\"NAME1\" not like '%a%' escape '!'", r_refI().render(c4)); + assertEquals("\"TABLE1\".\"NAME1\" not like ? escape '!'", r_ref().render(c4)); } @Test @@ -1334,12 +1334,24 @@ public class jOOQTest { @Test public void testInsertSelect2() throws Exception { - Insert q = create.insertInto(TABLE1, create.selectQuery()); + Insert q = create.insertInto(TABLE1).select(create.selectQuery()); assertEquals("insert into \"TABLE1\" (\"ID1\", \"NAME1\", \"DATE1\") select 1 from dual", r_refI().render(q)); assertEquals("insert into \"TABLE1\" (\"ID1\", \"NAME1\", \"DATE1\") select 1 from dual", r_ref().render(q)); - q = create.insertInto(TABLE1, create.select(val(1), FIELD_NAME1).from(TABLE1).where(FIELD_NAME1.equal("abc"))); + // [#1069] Allow for specifying custom fields + q = create.insertInto(TABLE1, FIELD_ID1).select(create.selectQuery()); + + assertEquals("insert into \"TABLE1\" (\"ID1\") select 1 from dual", r_refI().render(q)); + assertEquals("insert into \"TABLE1\" (\"ID1\") select 1 from dual", r_ref().render(q)); + + // [#1069] Allow for specifying custom fields + q = create.insertInto(TABLE1, FIELD_ID1, FIELD_NAME1).select(create.selectQuery()); + + assertEquals("insert into \"TABLE1\" (\"ID1\", \"NAME1\") select 1 from dual", r_refI().render(q)); + assertEquals("insert into \"TABLE1\" (\"ID1\", \"NAME1\") select 1 from dual", r_ref().render(q)); + + q = create.insertInto(TABLE1).select(create.select(val(1), FIELD_NAME1).from(TABLE1).where(FIELD_NAME1.equal("abc"))); assertEquals("insert into \"TABLE1\" (\"ID1\", \"NAME1\", \"DATE1\") select 1, \"TABLE1\".\"NAME1\" from \"TABLE1\" where \"TABLE1\".\"NAME1\" = 'abc'", r_refI().render(q)); assertEquals("insert into \"TABLE1\" (\"ID1\", \"NAME1\", \"DATE1\") select ?, \"TABLE1\".\"NAME1\" from \"TABLE1\" where \"TABLE1\".\"NAME1\" = ?", r_ref().render(q));