[#1069] Add support for INSERT INTO table(field1, field2, ...) SELECT syntax - as opposed to the existing INSERT INTO table SELECT

This commit is contained in:
Lukas Eder 2012-01-27 10:45:41 +00:00
parent 80da298f5e
commit d249ea6457
9 changed files with 107 additions and 35 deletions

View File

@ -287,6 +287,7 @@ public class FactoryProxy implements FactoryOperations, MethodInterceptor {
}
@Override
@Deprecated
public final <R extends Record> Insert<R> insertInto(Table<R> into, Select<?> select) {
return getDelegate().insertInto(into, select);
}

View File

@ -4395,23 +4395,35 @@ public abstract class jOOQAbstractTest<
break;
}
Insert<A> i = create().insertInto(
TAuthor(),
create().select(vals(
1000,
val("Lukas")))
.select(vals(
"Eder",
val(new Date(363589200000L)),
castNull(Integer.class),
nullField)));
Insert<A> 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

View File

@ -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();
* </pre></code>
*
* @deprecated - 2.0.3 - Use any of these methods instead:
* <ul>
* <li>{@link #insertInto(Table)} and
* {@link InsertSetStep#select(Select)}</li> <li>
* {@link #insertInto(Table, Field...)} and
* {@link InsertValuesStep#select(Select)}</li> <li>
* {@link #insertInto(Table, Collection)} and
* {@link InsertValuesStep#select(Select)}</li>
* </ul>
*/
@Deprecated
@Support
<R extends Record> Insert<R> insertInto(Table<R> into, Select<?> select);

View File

@ -99,4 +99,18 @@ public interface InsertSetStep<R extends Record> {
*/
@Support
InsertValuesStep<R> values(Collection<?> values);
/**
* Use a <code>SELECT</code> statement as the source of values for the
* <code>INSERT</code> statement
* <p>
* This variant of the <code>INSERT .. SELECT</code> 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 <code>INTO</code> clause.
* Use {@link FactoryOperations#insertInto(Table, Field...)} or
* {@link FactoryOperations#insertInto(Table, Collection)} instead, to
* define a field set for insertion.
*/
@Support
Insert<R> select(Select<?> select);
}

View File

@ -73,4 +73,17 @@ public interface InsertValuesStep<R extends Record> extends InsertOnDuplicateSte
*/
@Support
InsertValuesStep<R> values(Collection<?> values);
/**
* Use a <code>SELECT</code> statement as the source of values for the
* <code>INSERT</code> statement
* <p>
* This variant of the <code>INSERT .. SELECT</code> statement expects a
* select returning exactly as many fields as specified previously in the
* <code>INTO</code> clause:
* {@link FactoryOperations#insertInto(Table, Field...)} or
* {@link FactoryOperations#insertInto(Table, Collection)}
*/
@Support
Insert<R> select(Select<?> select);
}

View File

@ -1056,8 +1056,9 @@ public class Factory implements FactoryOperations {
* {@inheritDoc}
*/
@Override
@Deprecated
public final <R extends Record> Insert<R> insertInto(Table<R> into, Select<?> select) {
return new InsertSelectQueryImpl<R>(this, into, select);
return new InsertSelectQueryImpl<R>(this, into, into.getFields(), select);
}
/**

View File

@ -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<R extends Record>
// The DSL API
// -------------------------------------------------------------------------
@Override
public final Insert<R> select(Select<?> select) {
Configuration configuration = getDelegate().internalAPI(AttachableInternal.class).getConfiguration();
return new InsertSelectQueryImpl<R>(configuration, into, fields, select);
}
@Override
public final InsertImpl<R> values(Object... values) {
return values0(vals(convert(getFields(), values)));

View File

@ -55,15 +55,17 @@ class InsertSelectQueryImpl<R extends Record> 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<Field<?>> fields;
private final Select<?> select;
public InsertSelectQueryImpl(Configuration configuration, Table<?> into, Select<?> select) {
InsertSelectQueryImpl(Configuration configuration, Table<?> into, List<Field<?>> 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<R extends Record> 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<R extends Record> extends AbstractQuery implements I
@Override
public final void bind(BindContext context) {
context.bind(into);
context.bind(into.getFields());
context.bind(fields);
context.bind(select);
}
}

View File

@ -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<Table1Record> q = create.insertInto(TABLE1, create.selectQuery());
Insert<Table1Record> 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));