[#1506] Allow for inserting empty records (e.g. INSERT INTO .. VALUES () or INSERT INTO .. DEFAULT VALUES)

This commit is contained in:
Lukas Eder 2013-12-31 17:38:56 +01:00
parent 52e786b0b6
commit d6aa41d487
6 changed files with 93 additions and 7 deletions

View File

@ -67,6 +67,7 @@ import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.max;
import static org.jooq.impl.DSL.row;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.selectCount;
import static org.jooq.impl.DSL.selectOne;
import static org.jooq.impl.DSL.tableByName;
import static org.jooq.impl.DSL.trueCondition;
@ -225,6 +226,19 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
}
}
@Test
public void testInsertDefaultValues() throws Exception {
jOOQAbstractTest.reset = false;
assertEquals(1,
create().insertInto(TTriggers())
.defaultValues()
.execute());
assertEquals(1, (int) create().fetchOne(selectCount().from(TTriggers())).getValue(0, int.class));
assertEquals(1, create().delete(TTriggers()).execute());
}
@Test
public void testInsertImplicit() throws Exception {
jOOQAbstractTest.reset = false;

View File

@ -1006,6 +1006,11 @@ public abstract class jOOQAbstractTest<
new InsertUpdateTests(this).testInsertIdentity();
}
@Test
public void testInsertDefaultValues() throws Exception {
new InsertUpdateTests(this).testInsertDefaultValues();
}
@Test
public void testTableMapping() throws Exception {
new SchemaAndMappingTests(this).testTableMapping();

View File

@ -175,6 +175,12 @@ public interface InsertQuery<R extends Record> extends StoreQuery<R>, Insert<R>
@Support({ HSQLDB, MARIADB, MYSQL })
void addValuesForUpdate(Map<? extends Field<?>, ?> map);
/**
* Set an empty record with the <code>DEFAULT VALUES</code> clause.
*/
@Support
void setDefaultValues();
/**
* {@inheritDoc}
* <p>

View File

@ -122,6 +122,12 @@ public interface InsertSetStep<R extends Record> {
@Support
InsertValuesStepN<R> values(Collection<?> values);
/**
* Add an empty record with default values.
*/
@Support
InsertReturningStep<R> defaultValues();
/**
* Use a <code>SELECT</code> statement as the source of values for the
* <code>INSERT</code> statement.

View File

@ -45,6 +45,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
import org.jooq.AttachableInternal;
import org.jooq.Configuration;
import org.jooq.Field;
@ -86,7 +88,8 @@ import org.jooq.Table;
/**
* @author Lukas Eder
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({ "rawtypes", "unchecked" })
@Generated("This class was generated using jOOQ-tools")
class InsertImpl<R extends Record, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>
extends AbstractDelegatingQuery<InsertQuery<R>>
implements
@ -416,6 +419,15 @@ class InsertImpl<R extends Record, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
return this;
}
/**
* Add an empty record with default values.
*/
@Override
public final InsertImpl defaultValues() {
getDelegate().setDefaultValues();
return this;
}
@Override
public final InsertImpl onDuplicateKeyUpdate() {
onDuplicateKeyUpdate = true;

View File

@ -84,6 +84,7 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
private final FieldMapForUpdate updateMap;
private final FieldMapsForInsert insertMaps;
private boolean defaultValues;
private boolean onDuplicateKeyUpdate;
private boolean onDuplicateKeyIgnore;
@ -137,6 +138,11 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
updateMap.set(map);
}
@Override
public final void setDefaultValues() {
defaultValues = true;
}
@Override
public final void addValues(Map<? extends Field<?>, ?> map) {
insertMaps.getMap().set(map);
@ -387,11 +393,48 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
.keyword((onDuplicateKeyIgnore && asList(MARIADB, MYSQL).contains(context.configuration().dialect())) ? "ignore " : "")
.keyword("into")
.sql(" ")
.visit(getInto())
.sql(" ");
insertMaps.insertMaps.get(0).toSQLReferenceKeys(context);
context.end(INSERT_INSERT_INTO)
.visit(insertMaps);
.visit(getInto());
// [#1506] with DEFAULT VALUES, we might not have any columns to render
if (insertMaps.isExecutable()) {
context.sql(" ");
insertMaps.insertMaps.get(0).toSQLReferenceKeys(context);
}
context.end(INSERT_INSERT_INTO);
if (defaultValues) {
switch (context.configuration().dialect().family()) {
/* [pro] xx
xxxx xxxx
xxxx xxxxxxx
xx [/pro] */
case DERBY:
case MARIADB:
case MYSQL:
context.sql(" ").keyword("values").sql("(");
int count = getInto().fields().length;
String separator = "";
for (int i = 0; i < count; i++) {
context.sql(separator);
context.keyword("default");
separator = ", ";
}
context.sql(")");
break;
default:
context.sql(" ").keyword("default values");
break;
}
}
else {
context.visit(insertMaps);
}
}
private final void bindInsert(BindContext context) {
@ -448,6 +491,6 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
@Override
public final boolean isExecutable() {
return insertMaps.isExecutable();
return insertMaps.isExecutable() || defaultValues;
}
}