[#1583] Add support for row expressions in UPDATE statements: UPDATE ..

SET (A, B, C) = (SELECT X, Y, Z)
This commit is contained in:
Lukas Eder 2012-10-29 21:23:01 +01:00
parent 67a2c5f6ee
commit 6543cb0f42
8 changed files with 704 additions and 12 deletions

View File

@ -730,6 +730,24 @@ public abstract class BaseTest<
return record;
}
/**
* Convenience method to get an author
*/
protected final A getAuthor(int id) {
return create().selectFrom(TAuthor())
.where(TAuthor_ID().equal(id))
.fetchOne();
}
/**
* Convenience method to get a book
*/
protected final B getBook(int id) {
return create().selectFrom(TBook())
.where(TBook_ID().equal(id))
.fetchOne();
}
@SuppressWarnings("unchecked")
protected Sequence<? extends Number> SAuthorID() throws IllegalAccessException, NoSuchFieldException {
return (Sequence<? extends Number>) cSequences().getField("S_AUTHOR_ID").get(cSequences());

View File

@ -35,6 +35,7 @@
*/
package org.jooq.test._.testcases;
import static java.util.Arrays.asList;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@ -46,6 +47,7 @@ import static org.jooq.SQLDialect.DERBY;
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.INGRES;
import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.SQLITE;
import static org.jooq.SQLDialect.SQLSERVER;
@ -55,6 +57,7 @@ import static org.jooq.impl.Factory.castNull;
import static org.jooq.impl.Factory.count;
import static org.jooq.impl.Factory.inline;
import static org.jooq.impl.Factory.max;
import static org.jooq.impl.Factory.row;
import static org.jooq.impl.Factory.select;
import static org.jooq.impl.Factory.selectOne;
import static org.jooq.impl.Factory.val;
@ -444,6 +447,96 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T725,
assertEquals("Hitchcock", author.getValue(TAuthor_LAST_NAME()));
}
@Test
public void testUpdateWithRowValueExpression() throws Exception {
if (asList(ASE, CUBRID, DERBY, FIREBIRD, MYSQL, SQLSERVER, SQLITE, SYBASE).contains(getDialect())) {
log.info("SKIPPING", "UPDATE with row value expression tests");
return;
}
jOOQAbstractTest.reset = false;
A author;
// Multi-row UPDATE with degree 1
// ------------------------------
assertEquals(1,
create().update(TAuthor())
.set(row(TAuthor_FIRST_NAME()), row(val("row1")))
.where(TAuthor_ID().equal(1))
.execute());
author = getAuthor(1);
assertEquals("row1", author.getValue(TAuthor_FIRST_NAME()));
// Postgres doesn't support subselects here
if (!asList(POSTGRES).contains(getDialect())) {
assertEquals(1,
create().update(TAuthor())
.set(row(TAuthor_FIRST_NAME()), select(val("select1")))
.where(TAuthor_ID().equal(1))
.execute());
author = getAuthor(1);
assertEquals("select1", author.getValue(TAuthor_FIRST_NAME()));
}
// Multi-row UPDATE with degree 2
// ------------------------------
assertEquals(1,
create().update(TAuthor())
.set(row(TAuthor_FIRST_NAME(), TAuthor_LAST_NAME()),
row(val("row2a"), val("row2b")))
.where(TAuthor_ID().equal(1))
.execute());
author = getAuthor(1);
assertEquals("row2a", author.getValue(TAuthor_FIRST_NAME()));
assertEquals("row2b", author.getValue(TAuthor_LAST_NAME()));
// Postgres doesn't support subselects here
if (!asList(POSTGRES).contains(getDialect())) {
assertEquals(1,
create().update(TAuthor())
.set(row(TAuthor_FIRST_NAME(), TAuthor_LAST_NAME()),
select(val("select2a"), val("select2b")))
.where(TAuthor_ID().equal(1))
.execute());
author = getAuthor(1);
assertEquals("select2a", author.getValue(TAuthor_FIRST_NAME()));
assertEquals("select2b", author.getValue(TAuthor_LAST_NAME()));
}
// Multi-row UPDATE with degree 3 (higher degrees are currently not tested)
// ------------------------------------------------------------------------
assertEquals(1,
create().update(TAuthor())
.set(row(TAuthor_FIRST_NAME(), TAuthor_LAST_NAME(), TAuthor_YEAR_OF_BIRTH()),
row(val("row3a"), val("row3b"), val(3)))
.where(TAuthor_ID().equal(1))
.execute());
author = getAuthor(1);
assertEquals("row3a", author.getValue(TAuthor_FIRST_NAME()));
assertEquals("row3b", author.getValue(TAuthor_LAST_NAME()));
assertEquals(3, (int) author.getValue(TAuthor_YEAR_OF_BIRTH()));
// Postgres doesn't support subselects here
if (!asList(POSTGRES).contains(getDialect())) {
assertEquals(1,
create().update(TAuthor())
.set(row(TAuthor_FIRST_NAME(), TAuthor_LAST_NAME(), TAuthor_YEAR_OF_BIRTH()),
select(val("select3a"), val("select3b"), val(33)))
.where(TAuthor_ID().equal(1))
.execute());
author = getAuthor(1);
assertEquals("select3a", author.getValue(TAuthor_FIRST_NAME()));
assertEquals("select3b", author.getValue(TAuthor_LAST_NAME()));
assertEquals(33, (int) author.getValue(TAuthor_YEAR_OF_BIRTH()));
}
}
@Test
public void testInsertReturning() throws Exception {
if (TTriggers() == null) {

View File

@ -1243,6 +1243,11 @@ public abstract class jOOQAbstractTest<
new InsertUpdateTests(this).testInsertWithSelectAsField();
}
@Test
public void testUpdateWithRowValueExpression() throws Exception {
new InsertUpdateTests(this).testUpdateWithRowValueExpression();
}
@Test
public void testUpdateSelect() throws Exception {
new InsertUpdateTests(this).testUpdateSelect();

View File

@ -36,6 +36,13 @@
package org.jooq;
import static org.jooq.SQLDialect.DB2;
import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.INGRES;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
import java.util.Collection;
/**
@ -47,6 +54,102 @@ import java.util.Collection;
@SuppressWarnings("deprecation")
public interface UpdateQuery<R extends Record> extends StoreQuery<R>, ConditionProvider, Update<R> {
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1> void addValues(Row1<T1> row, Row1<T1> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2> void addValues(Row2<T1, T2> row, Row2<T1, T2> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3> void addValues(Row3<T1, T2, T3> row, Row3<T1, T2, T3> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4> void addValues(Row4<T1, T2, T3, T4> row, Row4<T1, T2, T3, T4> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5> void addValues(Row5<T1, T2, T3, T4, T5> row, Row5<T1, T2, T3, T4, T5> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5, T6> void addValues(Row6<T1, T2, T3, T4, T5, T6> row, Row6<T1, T2, T3, T4, T5, T6> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5, T6, T7> void addValues(Row7<T1, T2, T3, T4, T5, T6, T7> row, Row7<T1, T2, T3, T4, T5, T6, T7> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5, T6, T7, T8> void addValues(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Row8<T1, T2, T3, T4, T5, T6, T7, T8> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1> void addValues(Row1<T1> row, Select<? extends Record1<T1>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2> void addValues(Row2<T1, T2> row, Select<? extends Record2<T1, T2>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3> void addValues(Row3<T1, T2, T3> row, Select<? extends Record3<T1, T2, T3>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4> void addValues(Row4<T1, T2, T3, T4> row, Select<? extends Record4<T1, T2, T3, T4>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5> void addValues(Row5<T1, T2, T3, T4, T5> row, Select<? extends Record5<T1, T2, T3, T4, T5>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5, T6> void addValues(Row6<T1, T2, T3, T4, T5, T6> row, Select<? extends Record6<T1, T2, T3, T4, T5, T6>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5, T6, T7> void addValues(Row7<T1, T2, T3, T4, T5, T6, T7> row, Select<? extends Record7<T1, T2, T3, T4, T5, T6, T7>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5, T6, T7, T8> void addValues(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Select<? extends Record8<T1, T2, T3, T4, T5, T6, T7, T8>> select);
// ------------------------------------------------------------------------
// Methods from ConditionProvider
// ------------------------------------------------------------------------

View File

@ -0,0 +1,182 @@
/**
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq;
import static org.jooq.SQLDialect.DB2;
import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.INGRES;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
/**
* This type is used for the {@link Update}'s DSL API.
* <p>
* Example: <code><pre>
* Factory create = new Factory();
*
* create.update(table)
* .set(field1, value1)
* .set(field2, value2)
* .where(field1.greaterThan(100))
* .execute();
* </pre></code>
*
* @author Lukas Eder
*/
public interface UpdateSetFirstStep<R extends Record> extends UpdateSetStep<R> {
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1> UpdateWhereStep<R> set(Row1<T1> row, Row1<T1> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2> UpdateWhereStep<R> set(Row2<T1, T2> row, Row2<T1, T2> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3> UpdateWhereStep<R> set(Row3<T1, T2, T3> row, Row3<T1, T2, T3> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4> UpdateWhereStep<R> set(Row4<T1, T2, T3, T4> row, Row4<T1, T2, T3, T4> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5> UpdateWhereStep<R> set(Row5<T1, T2, T3, T4, T5> row, Row5<T1, T2, T3, T4, T5> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5, T6> UpdateWhereStep<R> set(Row6<T1, T2, T3, T4, T5, T6> row, Row6<T1, T2, T3, T4, T5, T6> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5, T6, T7> UpdateWhereStep<R> set(Row7<T1, T2, T3, T4, T5, T6, T7> row, Row7<T1, T2, T3, T4, T5, T6, T7> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
* <p>
* This is simulated using a subquery for the <code>value</code>, where row
* value expressions aren't supported.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE, POSTGRES })
<T1, T2, T3, T4, T5, T6, T7, T8> UpdateWhereStep<R> set(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Row8<T1, T2, T3, T4, T5, T6, T7, T8> value);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1> UpdateWhereStep<R> set(Row1<T1> row, Select<? extends Record1<T1>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2> UpdateWhereStep<R> set(Row2<T1, T2> row, Select<? extends Record2<T1, T2>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3> UpdateWhereStep<R> set(Row3<T1, T2, T3> row, Select<? extends Record3<T1, T2, T3>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4> UpdateWhereStep<R> set(Row4<T1, T2, T3, T4> row, Select<? extends Record4<T1, T2, T3, T4>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5> UpdateWhereStep<R> set(Row5<T1, T2, T3, T4, T5> row, Select<? extends Record5<T1, T2, T3, T4, T5>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5, T6> UpdateWhereStep<R> set(Row6<T1, T2, T3, T4, T5, T6> row, Select<? extends Record6<T1, T2, T3, T4, T5, T6>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5, T6, T7> UpdateWhereStep<R> set(Row7<T1, T2, T3, T4, T5, T6, T7> row, Select<? extends Record7<T1, T2, T3, T4, T5, T6, T7>> select);
/**
* Specify a multi-column set clause for the <code>UPDATE</code> statement.
*/
@Support({ DB2, H2, HSQLDB, INGRES, ORACLE })
<T1, T2, T3, T4, T5, T6, T7, T8> UpdateWhereStep<R> set(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Select<? extends Record8<T1, T2, T3, T4, T5, T6, T7, T8>> select);
}

View File

@ -102,7 +102,7 @@ import org.jooq.UDT;
import org.jooq.UDTRecord;
import org.jooq.UpdatableRecord;
import org.jooq.UpdateQuery;
import org.jooq.UpdateSetStep;
import org.jooq.UpdateSetFirstStep;
import org.jooq.conf.Settings;
import org.jooq.conf.SettingsTools;
import org.jooq.exception.DataAccessException;
@ -1196,7 +1196,7 @@ public class Executor implements FactoryOperations {
* {@inheritDoc}
*/
@Override
public final <R extends Record> UpdateSetStep<R> update(Table<R> table) {
public final <R extends Record> UpdateSetFirstStep<R> update(Table<R> table) {
return new UpdateImpl<R>(this, table);
}

View File

@ -48,11 +48,29 @@ import org.jooq.Field;
import org.jooq.Operator;
import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.Row1;
import org.jooq.Row2;
import org.jooq.Row3;
import org.jooq.Row4;
import org.jooq.Row5;
import org.jooq.Row6;
import org.jooq.Row7;
import org.jooq.Row8;
import org.jooq.Select;
import org.jooq.Table;
import org.jooq.UpdateConditionStep;
import org.jooq.UpdateQuery;
import org.jooq.UpdateSetFirstStep;
import org.jooq.UpdateSetMoreStep;
import org.jooq.UpdateWhereStep;
/**
* A wrapper for an {@link UpdateQuery}
@ -64,6 +82,7 @@ final class UpdateImpl<R extends Record>
implements
// Cascading interface implementations for Update behaviour
UpdateSetFirstStep<R>,
UpdateSetMoreStep<R>,
UpdateConditionStep<R> {
@ -94,6 +113,102 @@ final class UpdateImpl<R extends Record>
return this;
}
@Override
public final <T1> UpdateWhereStep<R> set(Row1<T1> row, Row1<T1> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2> UpdateWhereStep<R> set(Row2<T1, T2> row, Row2<T1, T2> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2, T3> UpdateWhereStep<R> set(Row3<T1, T2, T3> row, Row3<T1, T2, T3> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2, T3, T4> UpdateWhereStep<R> set(Row4<T1, T2, T3, T4> row, Row4<T1, T2, T3, T4> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2, T3, T4, T5> UpdateWhereStep<R> set(Row5<T1, T2, T3, T4, T5> row, Row5<T1, T2, T3, T4, T5> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2, T3, T4, T5, T6> UpdateWhereStep<R> set(Row6<T1, T2, T3, T4, T5, T6> row, Row6<T1, T2, T3, T4, T5, T6> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7> UpdateWhereStep<R> set(Row7<T1, T2, T3, T4, T5, T6, T7> row, Row7<T1, T2, T3, T4, T5, T6, T7> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7, T8> UpdateWhereStep<R> set(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Row8<T1, T2, T3, T4, T5, T6, T7, T8> value) {
getDelegate().addValues(row, value);
return this;
}
@Override
public final <T1> UpdateWhereStep<R> set(Row1<T1> row, Select<? extends Record1<T1>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2> UpdateWhereStep<R> set(Row2<T1, T2> row, Select<? extends Record2<T1, T2>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2, T3> UpdateWhereStep<R> set(Row3<T1, T2, T3> row, Select<? extends Record3<T1, T2, T3>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2, T3, T4> UpdateWhereStep<R> set(Row4<T1, T2, T3, T4> row, Select<? extends Record4<T1, T2, T3, T4>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2, T3, T4, T5> UpdateWhereStep<R> set(Row5<T1, T2, T3, T4, T5> row, Select<? extends Record5<T1, T2, T3, T4, T5>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2, T3, T4, T5, T6> UpdateWhereStep<R> set(Row6<T1, T2, T3, T4, T5, T6> row, Select<? extends Record6<T1, T2, T3, T4, T5, T6>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7> UpdateWhereStep<R> set(Row7<T1, T2, T3, T4, T5, T6, T7> row, Select<? extends Record7<T1, T2, T3, T4, T5, T6, T7>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7, T8> UpdateWhereStep<R> set(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Select<? extends Record8<T1, T2, T3, T4, T5, T6, T7, T8>> select) {
getDelegate().addValues(row, select);
return this;
}
@Override
public final UpdateImpl<R> where(Condition... conditions) {
getDelegate().addConditions(conditions);

View File

@ -36,6 +36,11 @@
package org.jooq.impl;
import static java.util.Arrays.asList;
import static org.jooq.SQLDialect.INGRES;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.impl.Factory.select;
import java.util.Collection;
import java.util.Map;
@ -45,7 +50,25 @@ import org.jooq.Configuration;
import org.jooq.Field;
import org.jooq.Operator;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record6;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.RenderContext;
import org.jooq.Row;
import org.jooq.Row1;
import org.jooq.Row2;
import org.jooq.Row3;
import org.jooq.Row4;
import org.jooq.Row5;
import org.jooq.Row6;
import org.jooq.Row7;
import org.jooq.Row8;
import org.jooq.Select;
import org.jooq.Table;
import org.jooq.UpdateQuery;
@ -58,6 +81,9 @@ class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
private final FieldMapForUpdate updateMap;
private final ConditionProviderImpl condition;
private Row multiRow;
private Row multiValue;
private Select<?> multiSelect;
UpdateQueryImpl(Configuration configuration, Table<R> table) {
super(configuration, table);
@ -81,13 +107,98 @@ class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
}
@Override
public final void addValues(Map<? extends Field<?>, ?> map) {
updateMap.set(map);
public final <T1> void addValues(Row1<T1> row, Row1<T1> value) {
addValues0(row, value);
}
@Override
public final void bind(BindContext context) {
context.bind(getInto()).bind(updateMap).bind(condition);
public final <T1, T2> void addValues(Row2<T1, T2> row, Row2<T1, T2> value) {
addValues0(row, value);
}
@Override
public final <T1, T2, T3> void addValues(Row3<T1, T2, T3> row, Row3<T1, T2, T3> value) {
addValues0(row, value);
}
@Override
public final <T1, T2, T3, T4> void addValues(Row4<T1, T2, T3, T4> row, Row4<T1, T2, T3, T4> value) {
addValues0(row, value);
}
@Override
public final <T1, T2, T3, T4, T5> void addValues(Row5<T1, T2, T3, T4, T5> row, Row5<T1, T2, T3, T4, T5> value) {
addValues0(row, value);
}
@Override
public final <T1, T2, T3, T4, T5, T6> void addValues(Row6<T1, T2, T3, T4, T5, T6> row, Row6<T1, T2, T3, T4, T5, T6> value) {
addValues0(row, value);
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7> void addValues(Row7<T1, T2, T3, T4, T5, T6, T7> row, Row7<T1, T2, T3, T4, T5, T6, T7> value) {
addValues0(row, value);
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7, T8> void addValues(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Row8<T1, T2, T3, T4, T5, T6, T7, T8> value) {
addValues0(row, value);
}
private final void addValues0(Row row, Row value) {
multiRow = row;
multiValue = value;
}
@Override
public final <T1> void addValues(Row1<T1> row, Select<? extends Record1<T1>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2> void addValues(Row2<T1, T2> row, Select<? extends Record2<T1, T2>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2, T3> void addValues(Row3<T1, T2, T3> row, Select<? extends Record3<T1, T2, T3>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2, T3, T4> void addValues(Row4<T1, T2, T3, T4> row, Select<? extends Record4<T1, T2, T3, T4>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2, T3, T4, T5> void addValues(Row5<T1, T2, T3, T4, T5> row, Select<? extends Record5<T1, T2, T3, T4, T5>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2, T3, T4, T5, T6> void addValues(Row6<T1, T2, T3, T4, T5, T6> row, Select<? extends Record6<T1, T2, T3, T4, T5, T6>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7> void addValues(Row7<T1, T2, T3, T4, T5, T6, T7> row, Select<? extends Record7<T1, T2, T3, T4, T5, T6, T7>> select) {
addValues0(row, select);
}
@Override
public final <T1, T2, T3, T4, T5, T6, T7, T8> void addValues(Row8<T1, T2, T3, T4, T5, T6, T7, T8> row, Select<? extends Record8<T1, T2, T3, T4, T5, T6, T7, T8>> select) {
addValues0(row, select);
}
private final void addValues0(Row row, Select<?> select) {
multiRow = row;
multiSelect = select;
}
@Override
public final void addValues(Map<? extends Field<?>, ?> map) {
updateMap.set(map);
}
@Override
@ -121,10 +232,49 @@ class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
.sql(getInto())
.declareTables(false)
.formatSeparator()
.keyword("set ")
.formatIndentLockStart()
.sql(updateMap)
.formatIndentLockEnd();
.keyword("set ");
// A multi-row update was specified
if (multiRow != null) {
boolean qualify = context.qualify();
context.qualify(false)
.sql(multiRow)
.qualify(qualify)
.sql(" = ");
// Some dialects don't really support row value expressions on the
// right hand side of a SET clause
if (multiValue != null && !asList(INGRES, ORACLE).contains(context.getDialect())) {
context.sql(multiValue);
}
// Subselects or subselect simulatinos of row value expressions
else {
Select<?> select = multiSelect;
if (multiValue != null) {
select = select(multiValue.getFields());
}
context.sql("(")
.formatIndentStart()
.formatNewLine()
.subquery(true)
.sql(select)
.subquery(false)
.formatIndentEnd()
.formatNewLine()
.sql(")");
}
}
// A regular (non-multi-row) update was specified
else {
context.formatIndentLockStart()
.sql(updateMap)
.formatIndentLockEnd();
}
if (!(getWhere() instanceof TrueCondition)) {
context.formatSeparator()
@ -134,7 +284,33 @@ class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
}
@Override
public boolean isExecutable() {
return updateMap.size() > 0;
public final void bind(BindContext context) {
context.bind(getInto());
// A multi-row update was specified
if (multiRow != null) {
context.bind(multiRow);
if (multiValue != null) {
context.bind(multiValue);
}
else {
context.subquery(true)
.bind(multiSelect)
.subquery(false);
}
}
// A regular (non-multi-row) update was specified
else {
context.bind(updateMap);
}
context.bind(condition);
}
@Override
public final boolean isExecutable() {
return updateMap.size() > 0 || multiRow != null;
}
}