Skip to content

Issue/datajdbc 557- Insert into table with only id column #1047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
* @author Mikhail Polivakha
*/
class SqlGenerator {

Expand Down Expand Up @@ -92,12 +93,14 @@ class SqlGenerator {
SqlGenerator(RelationalMappingContext mappingContext, JdbcConverter converter, RelationalPersistentEntity<?> entity,
Dialect dialect) {

final RenderContextFactory renderContextFactory = new RenderContextFactory(dialect);

this.mappingContext = mappingContext;
this.entity = entity;
this.sqlContext = new SqlContext(entity);
this.sqlRenderer = SqlRenderer.create(new RenderContextFactory(dialect).createRenderContext());
this.sqlRenderer = SqlRenderer.create(renderContextFactory.createRenderContext());
this.columns = new Columns(entity, mappingContext, converter);
this.renderContext = new RenderContextFactory(dialect).createRenderContext();
this.renderContext = renderContextFactory.createRenderContext();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
* @author Tyler Van Gorder
* @author Clemens Hahn
* @author Milan Milanov
* @author Mikhail Polivakha
*/
@ContextConfiguration
@Transactional
Expand Down Expand Up @@ -887,6 +888,12 @@ public void saveAndLoadDateTimeWithMicrosecondPrecision() {
assertThat(loaded.testTime).isEqualTo(entity.testTime);
}

@Test // DATAJDBC-557
public void insertWithIdOnly() {
WithIdOnly entity = new WithIdOnly();
assertThat(template.save(entity).id).isNotNull();
}

private <T extends Number> void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate,
Function<Number, T> toConcreteNumber) {
saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0);
Expand Down Expand Up @@ -1254,6 +1261,11 @@ static class WithLocalDateTime {
LocalDateTime testTime;
}

@Table
class WithIdOnly {
@Id Long id;
}

@Configuration
@Import(TestConfiguration.class)
static class Config {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
import org.springframework.data.relational.core.dialect.PostgresDialect;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.SqlIdentifier;
Expand All @@ -59,6 +60,7 @@
* @author Myeonghyeon Lee
* @author Myat Min
* @author Radim Tlusty
* @author Mikhail Polivakha
*/
public class DefaultDataAccessStrategyUnitTests {

Expand Down Expand Up @@ -219,7 +221,7 @@ public void insertWithUndefinedIdRetrievesGeneratedKeys() {

assertThat(generatedId).isEqualTo(GENERATED_ID);

verify(namedJdbcOperations).update(eq("INSERT INTO \"DUMMY_ENTITY\" VALUES ()"),
verify(namedJdbcOperations).update(eq("INSERT INTO \"DUMMY_ENTITY\"" + HsqlDbDialect.INSTANCE.getSqlInsertWithDefaultValues().getDefaultInsertPart()),
paramSourceCaptor.capture(), any(KeyHolder.class));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.dialect.AnsiDialect;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.PostgresDialect;
import org.springframework.data.relational.core.dialect.SqlServerDialect;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.NamingStrategy;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
Expand All @@ -61,6 +63,7 @@
* @author Tom Hombergs
* @author Milan Milanov
* @author Myeonghyeon Lee
* @author Mikhail Polivakha
*/
class SqlGeneratorUnitTests {

Expand Down Expand Up @@ -391,13 +394,22 @@ void updateWithVersion() {
}

@Test // DATAJDBC-264
void getInsertForEmptyColumnList() {
public void getInsertForEmptyColumnListPostgres() {

SqlGenerator sqlGenerator = createSqlGenerator(IdOnlyEntity.class);
SqlGenerator sqlGenerator = createSqlGenerator(IdOnlyEntity.class, PostgresDialect.INSTANCE);

String insert = sqlGenerator.getInsert(emptySet());
String insertSqlStatement = sqlGenerator.getInsert(emptySet());

assertThat(insertSqlStatement).endsWith(" VALUES (DEFAULT) ");
}

@Test //DATAJDBC-557
void gerInsertForEmptyColumnListMsSqlServer() {
SqlGenerator sqlGenerator = createSqlGenerator(IdOnlyEntity.class, SqlServerDialect.INSTANCE);

String insertSqlStatement = sqlGenerator.getInsert(emptySet());

assertThat(insert).endsWith("()");
assertThat(insertSqlStatement).endsWith(" DEFAULT VALUES ");
}

@Test // DATAJDBC-334
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.InsertWithDefaultValues;
import org.springframework.data.relational.core.dialect.LimitClause;
import org.springframework.data.relational.core.dialect.LockClause;
import org.springframework.data.relational.core.sql.render.SelectRenderContext;
Expand All @@ -49,6 +50,7 @@
* Integration tests for {@link AbstractJdbcConfiguration}.
*
* @author Oliver Drotbohm
* @author Mikhail Polivakha
*/
public class AbstractJdbcConfigurationIntegrationTests {

Expand Down Expand Up @@ -167,6 +169,11 @@ public SelectRenderContext getSelectContext() {
public Collection<Object> getConverters() {
return asList(BooleanToNumberConverter.INSTANCE, NumberToBooleanConverter.INSTANCE);
}

@Override
public InsertWithDefaultValues getSqlInsertWithDefaultValues() {
return null;
}
}

@WritingConverter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ DROP TABLE WITH_READ_ONLY;
DROP TABLE VERSIONED_AGGREGATE;
DROP TABLE WITH_LOCAL_DATE_TIME;

DROP TABLE WITH_ID_ONLY;

CREATE TABLE LEGO_SET
(
"id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
Expand Down Expand Up @@ -350,4 +352,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT NOT NULL PRIMARY KEY,
TEST_TIME TIMESTAMP(9)
);

CREATE TABLE WITH_ID_ONLY
(
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT PRIMARY KEY,
TEST_TIME TIMESTAMP(9) WITHOUT TIME ZONE
);

CREATE TABLE WITH_ID_ONLY
(
ID SERIAL PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT PRIMARY KEY,
TEST_TIME TIMESTAMP(9)
);
);

CREATE TABLE WITH_ID_ONLY
(
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY
)
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT PRIMARY KEY,
TEST_TIME TIMESTAMP(6)
);

CREATE TABLE WITH_ID_ONLY
(
ID BIGINT AUTO_INCREMENT PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,11 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT PRIMARY KEY,
TEST_TIME datetime2(7)
);

DROP TABLE IF EXISTS WITH_ID_ONLY;

CREATE TABLE WITH_ID_ONLY
(
ID BIGINT IDENTITY PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT PRIMARY KEY,
TEST_TIME TIMESTAMP(6)
);

CREATE TABLE WITH_ID_ONLY
(
ID BIGINT AUTO_INCREMENT PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ DROP TABLE NO_ID_MAP_CHAIN4 CASCADE CONSTRAINTS PURGE;
DROP TABLE VERSIONED_AGGREGATE CASCADE CONSTRAINTS PURGE;
DROP TABLE WITH_READ_ONLY CASCADE CONSTRAINTS PURGE;
DROP TABLE WITH_LOCAL_DATE_TIME CASCADE CONSTRAINTS PURGE;
DROP TABLE WITH_ID_ONLY CASCADE CONSTRAINTS PURGE;

CREATE TABLE LEGO_SET
(
Expand Down Expand Up @@ -332,4 +333,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID NUMBER PRIMARY KEY,
TEST_TIME TIMESTAMP(9)
);

CREATE TABLE WITH_ID_ONLY
(
ID NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ DROP TABLE CHAIN2;
DROP TABLE CHAIN1;
DROP TABLE CHAIN0;
DROP TABLE WITH_READ_ONLY;
DROP TABLE WITH_ID_ONLY;

CREATE TABLE LEGO_SET
(
Expand Down Expand Up @@ -335,4 +336,9 @@ CREATE TABLE WITH_LOCAL_DATE_TIME
(
ID BIGINT PRIMARY KEY,
TEST_TIME TIMESTAMP(9) WITHOUT TIME ZONE
);

CREATE TABLE WITH_ID_ONLY
(
ID SERIAL PRIMARY KEY
);
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* @author Jens Schauder
* @author Myeonghyeon Lee
* @author Christoph Strobl
* @author Mikhail Polivakha
* @since 1.1
*/
public interface Dialect {
Expand Down Expand Up @@ -109,4 +110,13 @@ default Collection<Object> getConverters() {
default Set<Class<?>> simpleTypes() {
return Collections.emptySet();
}

/**
* @return an appropriate {@link InsertWithDefaultValues } for that specific dialect.
* for most of the Dialects the default implementation will be valid, but, for
* example, in case of {@link SqlServerDialect} it is not
*/
default InsertWithDefaultValues getSqlInsertWithDefaultValues() {
return new InsertWithDefaultValues() {};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.springframework.data.relational.core.dialect;

import org.springframework.data.relational.core.mapping.InsertDefaultValues;

/**
* This interface aggregates information about an Insert with default values statement.
* @author Mikhail Polivakha
*/
public interface InsertWithDefaultValues {

/**
* @return the part of the sql statement, that follows after <b>INSERT INTO table</b>
*/
default String getDefaultInsertPart() {
return InsertDefaultValues.DEFAULT.getDefaultInsertPart();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.springframework.data.relational.core.dialect;

import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.render.InsertRenderContext;
import org.springframework.data.relational.core.sql.render.NamingStrategies;
import org.springframework.data.relational.core.sql.render.RenderContext;
import org.springframework.data.relational.core.sql.render.RenderNamingStrategy;
Expand All @@ -26,6 +27,7 @@
* Factory for {@link RenderContext} based on {@link Dialect}.
*
* @author Mark Paluch
* @author Mikhail Polivakha
* @since 1.1
*/
public class RenderContextFactory {
Expand Down Expand Up @@ -65,9 +67,9 @@ public void setNamingStrategy(RenderNamingStrategy namingStrategy) {
*/
public RenderContext createRenderContext() {

SelectRenderContext select = dialect.getSelectContext();
SelectRenderContext selectRenderContext = dialect.getSelectContext();

return new DialectRenderContext(namingStrategy, dialect.getIdentifierProcessing(), select);
return new DialectRenderContext(namingStrategy, dialect, selectRenderContext);
}

/**
Expand All @@ -76,17 +78,18 @@ public RenderContext createRenderContext() {
static class DialectRenderContext implements RenderContext {

private final RenderNamingStrategy renderNamingStrategy;
private final IdentifierProcessing identifierProcessing;
private final SelectRenderContext selectRenderContext;
private final Dialect renderingDialect;

DialectRenderContext(RenderNamingStrategy renderNamingStrategy, IdentifierProcessing identifierProcessing, SelectRenderContext selectRenderContext) {
DialectRenderContext(RenderNamingStrategy renderNamingStrategy, Dialect renderingDialect, SelectRenderContext selectRenderContext) {

Assert.notNull(renderNamingStrategy, "RenderNamingStrategy must not be null");
Assert.notNull(identifierProcessing, "IdentifierProcessing must not be null");
Assert.notNull(renderingDialect, "renderingDialect must not be null");
Assert.notNull(renderingDialect.getIdentifierProcessing(), "IdentifierProcessing of renderingDialect must not be null");
Assert.notNull(selectRenderContext, "SelectRenderContext must not be null");

this.renderNamingStrategy = renderNamingStrategy;
this.identifierProcessing = identifierProcessing;
this.renderingDialect = renderingDialect;
this.selectRenderContext = selectRenderContext;
}

Expand All @@ -105,16 +108,26 @@ public RenderNamingStrategy getNamingStrategy() {
*/
@Override
public IdentifierProcessing getIdentifierProcessing() {
return identifierProcessing;
return renderingDialect.getIdentifierProcessing();
}

/*
* (non-Javadoc)
* @see org.springframework.data.relational.core.sql.render.RenderContext#getSelect()
*/
@Override
public SelectRenderContext getSelect() {
public SelectRenderContext getSelectRenderContext() {
return selectRenderContext;
}

@Override
public InsertRenderContext getInsertRenderContext() {
return new InsertRenderContext() {
@Override
public String getInsertDefaultValuesPartSQL() {
return renderingDialect.getSqlInsertWithDefaultValues().getDefaultInsertPart();
}
};
}
}
}
}
Loading