Skip to content
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