diff --git a/pom.xml b/pom.xml
index 4959b322ae..3e488ee85c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-relational-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAJDBC-476-SNAPSHOT
pom
Spring Data Relational Parent
diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml
index 858a5f4b4b..555cc5931b 100644
--- a/spring-data-jdbc-distribution/pom.xml
+++ b/spring-data-jdbc-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-relational-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAJDBC-476-SNAPSHOT
../pom.xml
diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml
index 17204c4a0f..2e821d833a 100644
--- a/spring-data-jdbc/pom.xml
+++ b/spring-data-jdbc/pom.xml
@@ -6,7 +6,7 @@
4.0.0
spring-data-jdbc
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAJDBC-476-SNAPSHOT
Spring Data JDBC
Spring Data module for JDBC repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-relational-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAJDBC-476-SNAPSHOT
diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlContext.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlContext.java
index c89218d366..d79d7cfb90 100644
--- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlContext.java
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlContext.java
@@ -18,10 +18,8 @@
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.sql.Column;
-import org.springframework.data.relational.core.sql.SQL;
-import org.springframework.data.relational.core.sql.Table;
-import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.SqlIdentifier;
+import org.springframework.data.relational.core.sql.Table;
/**
* Utility to get from path to SQL DSL elements.
@@ -35,21 +33,19 @@ class SqlContext {
private final RelationalPersistentEntity> entity;
private final Table table;
- private final IdentifierProcessing identifierProcessing;
- SqlContext(RelationalPersistentEntity> entity, IdentifierProcessing identifierProcessing) {
+ SqlContext(RelationalPersistentEntity> entity) {
- this.identifierProcessing = identifierProcessing;
this.entity = entity;
- this.table = SQL.table(entity.getTableName().toSql(this.identifierProcessing));
+ this.table = Table.create(entity.getTableName());
}
Column getIdColumn() {
- return table.column(entity.getIdColumn().toSql(identifierProcessing));
+ return table.column(entity.getIdColumn());
}
Column getVersionColumn() {
- return table.column(entity.getRequiredVersionProperty().getColumnName().toSql(identifierProcessing));
+ return table.column(entity.getRequiredVersionProperty().getColumnName());
}
Table getTable() {
@@ -59,17 +55,15 @@ Table getTable() {
Table getTable(PersistentPropertyPathExtension path) {
SqlIdentifier tableAlias = path.getTableAlias();
- Table table = SQL.table(path.getTableName().toSql(identifierProcessing));
- return tableAlias == null ? table : table.as(tableAlias.toSql(identifierProcessing));
+ Table table = Table.create(path.getTableName());
+ return tableAlias == null ? table : table.as(tableAlias);
}
Column getColumn(PersistentPropertyPathExtension path) {
- return getTable(path).column(path.getColumnName().toSql(identifierProcessing))
- .as(path.getColumnAlias().toSql(identifierProcessing));
+ return getTable(path).column(path.getColumnName()).as(path.getColumnAlias());
}
Column getReverseColumn(PersistentPropertyPathExtension path) {
- return getTable(path).column(path.getReverseColumnName().toSql(identifierProcessing))
- .as(path.getReverseColumnNameAlias().toSql(identifierProcessing));
+ return getTable(path).column(path.getReverseColumnName()).as(path.getReverseColumnNameAlias());
}
}
diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java
index 9d9f79233b..f811f815c5 100644
--- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java
@@ -35,15 +35,16 @@
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
+import org.springframework.data.relational.core.dialect.Dialect;
+import org.springframework.data.relational.core.dialect.RenderContextFactory;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.*;
+import org.springframework.data.relational.core.sql.render.RenderContext;
import org.springframework.data.relational.core.sql.render.SqlRenderer;
import org.springframework.data.relational.domain.Identifier;
-import org.springframework.data.relational.core.sql.IdentifierProcessing;
-import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.Lazy;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -69,7 +70,7 @@ class SqlGenerator {
private static final Pattern parameterPattern = Pattern.compile("\\W");
private final RelationalPersistentEntity> entity;
private final MappingContext, RelationalPersistentProperty> mappingContext;
- private final IdentifierProcessing identifierProcessing;
+ private final RenderContext renderContext;
private final SqlContext sqlContext;
private final Columns columns;
@@ -93,16 +94,15 @@ class SqlGenerator {
*
* @param mappingContext must not be {@literal null}.
* @param entity must not be {@literal null}.
- * @param identifierProcessing must not be {@literal null}.
+ * @param dialect must not be {@literal null}.
*/
- SqlGenerator(RelationalMappingContext mappingContext, RelationalPersistentEntity> entity,
- IdentifierProcessing identifierProcessing) {
+ SqlGenerator(RelationalMappingContext mappingContext, RelationalPersistentEntity> entity, Dialect dialect) {
this.mappingContext = mappingContext;
this.entity = entity;
- this.identifierProcessing = identifierProcessing;
- this.sqlContext = new SqlContext(entity, identifierProcessing);
+ this.sqlContext = new SqlContext(entity);
this.columns = new Columns(entity, mappingContext);
+ this.renderContext = new RenderContextFactory(dialect).createRenderContext();
}
/**
@@ -126,10 +126,9 @@ private Condition getSubselectCondition(PersistentPropertyPathExtension path,
return rootCondition.apply(filterColumn);
}
- Table subSelectTable = SQL.table(parentPath.getTableName().toSql(identifierProcessing));
- Column idColumn = subSelectTable.column(parentPath.getIdColumnName().toSql(identifierProcessing));
- Column selectFilterColumn = subSelectTable
- .column(parentPath.getEffectiveIdColumnName().toSql(identifierProcessing));
+ Table subSelectTable = Table.create(parentPath.getTableName());
+ Column idColumn = subSelectTable.column(parentPath.getIdColumnName());
+ Column selectFilterColumn = subSelectTable.column(parentPath.getEffectiveIdColumnName());
Condition innerCondition;
@@ -152,7 +151,7 @@ private Condition getSubselectCondition(PersistentPropertyPathExtension path,
}
private BindMarker getBindMarker(SqlIdentifier columnName) {
- return SQL.bindMarker(":" + parameterPattern.matcher(columnName.getReference(identifierProcessing)).replaceAll(""));
+ return SQL.bindMarker(":" + parameterPattern.matcher(renderReference(columnName)).replaceAll(""));
}
/**
@@ -191,21 +190,19 @@ String getFindAllByProperty(Identifier parentIdentifier, @Nullable SqlIdentifier
Assert.isTrue(keyColumn != null || !ordered,
"If the SQL statement should be ordered a keyColumn to order by must be provided.");
+ Table table = getTable();
+
SelectBuilder.SelectWhere builder = selectBuilder( //
keyColumn == null //
? Collections.emptyList() //
- : Collections.singleton(keyColumn.toSql(identifierProcessing)) //
+ : Collections.singleton(keyColumn) //
);
- Table table = getTable();
-
Condition condition = buildConditionForBackReference(parentIdentifier, table);
SelectBuilder.SelectWhereAndOr withWhereClause = builder.where(condition);
Select select = ordered //
- ? withWhereClause
- .orderBy(table.column(keyColumn.toSql(identifierProcessing)).as(keyColumn.toSql(identifierProcessing)))
- .build() //
+ ? withWhereClause.orderBy(table.column(keyColumn).as(keyColumn)).build() //
: withWhereClause.build();
return render(select);
@@ -216,8 +213,7 @@ private Condition buildConditionForBackReference(Identifier parentIdentifier, Ta
Condition condition = null;
for (SqlIdentifier backReferenceColumn : parentIdentifier.toMap().keySet()) {
- Condition newCondition = table.column(backReferenceColumn.toSql(identifierProcessing))
- .isEqualTo(getBindMarker(backReferenceColumn));
+ Condition newCondition = table.column(backReferenceColumn).isEqualTo(getBindMarker(backReferenceColumn));
condition = condition == null ? newCondition : condition.and(newCondition);
}
@@ -353,7 +349,7 @@ private SelectBuilder.SelectWhere selectBuilder() {
return selectBuilder(Collections.emptyList());
}
- private SelectBuilder.SelectWhere selectBuilder(Collection keyColumns) {
+ private SelectBuilder.SelectWhere selectBuilder(Collection keyColumns) {
Table table = getTable();
@@ -377,7 +373,7 @@ private SelectBuilder.SelectWhere selectBuilder(Collection keyColumns) {
}
}
- for (String keyColumn : keyColumns) {
+ for (SqlIdentifier keyColumn : keyColumns) {
columnExpressions.add(table.column(keyColumn).as(keyColumn));
}
@@ -440,8 +436,8 @@ Join getJoin(PersistentPropertyPathExtension path) {
return new Join( //
currentTable, //
- currentTable.column(path.getReverseColumnName().toSql(identifierProcessing)), //
- parentTable.column(idDefiningParentPath.getIdColumnName().toSql(identifierProcessing)) //
+ currentTable.column(path.getReverseColumnName()), //
+ parentTable.column(idDefiningParentPath.getIdColumnName()) //
);
}
@@ -481,14 +477,14 @@ private String createInsertSql(Set additionalColumns) {
Table table = getTable();
- Set columnNamesForInsert = new TreeSet<>(Comparator.comparing(id -> id.toSql(identifierProcessing)));
+ Set columnNamesForInsert = new TreeSet<>(Comparator.comparing(SqlIdentifier::getReference));
columnNamesForInsert.addAll(columns.getInsertableColumns());
columnNamesForInsert.addAll(additionalColumns);
InsertBuilder.InsertIntoColumnsAndValuesWithBuild insert = Insert.builder().into(table);
for (SqlIdentifier cn : columnNamesForInsert) {
- insert = insert.column(table.column(cn.toSql(identifierProcessing)));
+ insert = insert.column(table.column(cn));
}
InsertBuilder.InsertValuesWithBuild insertWithValues = null;
@@ -506,8 +502,7 @@ private String createUpdateSql() {
private String createUpdateWithVersionSql() {
Update update = createBaseUpdate() //
- .and(getVersionColumn()
- .isEqualTo(SQL.bindMarker(":" + VERSION_SQL_PARAMETER.getReference(identifierProcessing)))) //
+ .and(getVersionColumn().isEqualTo(SQL.bindMarker(":" + renderReference(VERSION_SQL_PARAMETER)))) //
.build();
return render(update);
@@ -520,7 +515,7 @@ private UpdateBuilder.UpdateWhereAndOr createBaseUpdate() {
List assignments = columns.getUpdateableColumns() //
.stream() //
.map(columnName -> Assignments.value( //
- table.column(columnName.toSql(identifierProcessing)), //
+ table.column(columnName), //
getBindMarker(columnName))) //
.collect(Collectors.toList());
@@ -537,8 +532,7 @@ private String createDeleteSql() {
private String createDeleteByIdAndVersionSql() {
Delete delete = createBaseDeleteById(getTable()) //
- .and(getVersionColumn()
- .isEqualTo(SQL.bindMarker(":" + VERSION_SQL_PARAMETER.getReference(identifierProcessing)))) //
+ .and(getVersionColumn().isEqualTo(SQL.bindMarker(":" + renderReference(VERSION_SQL_PARAMETER)))) //
.build();
return render(delete);
@@ -546,19 +540,19 @@ private String createDeleteByIdAndVersionSql() {
private DeleteBuilder.DeleteWhereAndOr createBaseDeleteById(Table table) {
return Delete.builder().from(table)
- .where(getIdColumn().isEqualTo(SQL.bindMarker(":" + ID_SQL_PARAMETER.getReference(identifierProcessing))));
+ .where(getIdColumn().isEqualTo(SQL.bindMarker(":" + renderReference(ID_SQL_PARAMETER))));
}
private String createDeleteByPathAndCriteria(PersistentPropertyPathExtension path,
Function rootCondition) {
- Table table = SQL.table(path.getTableName().toSql(identifierProcessing));
+ Table table = Table.create(path.getTableName());
DeleteBuilder.DeleteWhere builder = Delete.builder() //
.from(table);
Delete delete;
- Column filterColumn = table.column(path.getReverseColumnName().toSql(identifierProcessing));
+ Column filterColumn = table.column(path.getReverseColumnName());
if (path.getLength() == 1) {
@@ -587,19 +581,19 @@ private String createDeleteByListSql() {
}
private String render(Select select) {
- return SqlRenderer.create().render(select);
+ return SqlRenderer.create(renderContext).render(select);
}
private String render(Insert insert) {
- return SqlRenderer.create().render(insert);
+ return SqlRenderer.create(renderContext).render(insert);
}
private String render(Update update) {
- return SqlRenderer.create().render(update);
+ return SqlRenderer.create(renderContext).render(update);
}
private String render(Delete delete) {
- return SqlRenderer.create().render(delete);
+ return SqlRenderer.create(renderContext).render(delete);
}
private Table getTable() {
@@ -614,6 +608,10 @@ private Column getVersionColumn() {
return sqlContext.getVersionColumn();
}
+ private String renderReference(SqlIdentifier identifier) {
+ return identifier.getReference(renderContext.getIdentifierProcessing());
+ }
+
/**
* Value object representing a {@code JOIN} association.
*/
diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGeneratorSource.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGeneratorSource.java
index 963d414664..0c5c0d5573 100644
--- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGeneratorSource.java
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGeneratorSource.java
@@ -28,6 +28,7 @@
* domain type, the same generator will get returned.
*
* @author Jens Schauder
+ * @author Mark Paluch
*/
@RequiredArgsConstructor
public class SqlGeneratorSource {
@@ -37,14 +38,15 @@ public class SqlGeneratorSource {
private final Dialect dialect;
/**
- * @return the {@link Dialect} used by the created {@link SqlGenerator} instances. Guaranteed to be not {@literal null}.
+ * @return the {@link Dialect} used by the created {@link SqlGenerator} instances. Guaranteed to be not
+ * {@literal null}.
*/
public Dialect getDialect() {
return dialect;
}
-
SqlGenerator getSqlGenerator(Class> domainType) {
- return CACHE.computeIfAbsent(domainType, t -> new SqlGenerator(context, context.getRequiredPersistentEntity(t), dialect.getIdentifierProcessing()));
+ return CACHE.computeIfAbsent(domainType,
+ t -> new SqlGenerator(context, context.getRequiredPersistentEntity(t), dialect));
}
}
diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java
index 98bd8a8911..886470fea7 100644
--- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java
@@ -85,7 +85,10 @@ protected RelationalPersistentEntity createPersistentEntity(TypeInformati
@Override
protected RelationalPersistentProperty createPersistentProperty(Property property,
RelationalPersistentEntity> owner, SimpleTypeHolder simpleTypeHolder) {
- return new BasicJdbcPersistentProperty(property, owner, simpleTypeHolder, this);
+ BasicJdbcPersistentProperty persistentProperty = new BasicJdbcPersistentProperty(property, owner, simpleTypeHolder,
+ this);
+ persistentProperty.setForceQuote(isForceQuote());
+ return persistentProperty;
}
@Override
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierProcessingAdapter.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierProcessingAdapter.java
new file mode 100644
index 0000000000..a20be2c00a
--- /dev/null
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierProcessingAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jdbc.core.convert;
+
+import org.springframework.data.relational.core.dialect.AbstractDialect;
+import org.springframework.data.relational.core.dialect.Dialect;
+import org.springframework.data.relational.core.dialect.HsqlDbDialect;
+import org.springframework.data.relational.core.dialect.LimitClause;
+import org.springframework.data.relational.core.sql.IdentifierProcessing;
+
+/**
+ * {@link Dialect} adapter that delegates to the given {@link IdentifierProcessing}.
+ *
+ * @author Mark Paluch
+ */
+public class IdentifierProcessingAdapter extends AbstractDialect implements Dialect {
+
+ private final IdentifierProcessing identifierProcessing;
+
+ public IdentifierProcessingAdapter(IdentifierProcessing identifierProcessing) {
+ this.identifierProcessing = identifierProcessing;
+ }
+
+ @Override
+ public LimitClause limit() {
+ return HsqlDbDialect.INSTANCE.limit();
+ }
+
+ @Override
+ public IdentifierProcessing getIdentifierProcessing() {
+ return identifierProcessing;
+ }
+}
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorContextBasedNamingStrategyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorContextBasedNamingStrategyUnitTests.java
index 8582f43af2..4c9a4e0446 100644
--- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorContextBasedNamingStrategyUnitTests.java
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorContextBasedNamingStrategyUnitTests.java
@@ -24,6 +24,7 @@
import org.assertj.core.api.SoftAssertions;
import org.junit.Test;
+
import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.PersistentPropertyPathTestUtils;
@@ -32,9 +33,6 @@
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
-import org.springframework.data.relational.core.sql.IdentifierProcessing;
-import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing;
-import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting;
/**
* Unit tests to verify a contextual {@link NamingStrategy} implementation that customizes using a user-centric
@@ -218,8 +216,7 @@ private SqlGenerator configureSqlGenerator(NamingStrategy namingStrategy) {
RelationalMappingContext context = new JdbcMappingContext(namingStrategy);
RelationalPersistentEntity> persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class);
- return new SqlGenerator(context, persistentEntity,
- IdentifierProcessing.create(new Quoting(""), LetterCasing.AS_IS));
+ return new SqlGenerator(context, persistentEntity, UnquotedDialect.INSTANCE);
}
@SuppressWarnings("unused")
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java
index 84960bf40f..c5c8a0a3b5 100644
--- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java
@@ -22,6 +22,7 @@
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+
import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.PropertyPathTestingUtils;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
@@ -32,9 +33,7 @@
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.sql.Aliased;
-import org.springframework.data.relational.core.sql.IdentifierProcessing;
-import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing;
-import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
/**
* Unit tests for the {@link SqlGenerator} in a context of the {@link Embedded} annotation.
@@ -48,13 +47,13 @@ public class SqlGeneratorEmbeddedUnitTests {
@Before
public void setUp() {
+ this.context.setForceQuote(false);
this.sqlGenerator = createSqlGenerator(DummyEntity.class);
}
SqlGenerator createSqlGenerator(Class> type) {
RelationalPersistentEntity> persistentEntity = context.getRequiredPersistentEntity(type);
- return new SqlGenerator(context, persistentEntity,
- IdentifierProcessing.create(new Quoting(""), LetterCasing.AS_IS));
+ return new SqlGenerator(context, persistentEntity, UnquotedDialect.INSTANCE);
}
@Test // DATAJDBC-111
@@ -201,7 +200,8 @@ public void columnForEmbeddedProperty() {
assertThat(generatedColumn("embeddable.test", DummyEntity.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias)
- .containsExactly("test", "dummy_entity", null, "test");
+ .containsExactly(SqlIdentifier.unquoted("test"), SqlIdentifier.unquoted("dummy_entity"), null,
+ SqlIdentifier.unquoted("test"));
}
@Test // DATAJDBC-340
@@ -224,7 +224,8 @@ public void columnForPrefixedEmbeddedProperty() {
assertThat(generatedColumn("prefixedEmbeddable.test", DummyEntity.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias)
- .containsExactly("prefix_test", "dummy_entity", null, "prefix_test");
+ .containsExactly(SqlIdentifier.unquoted("prefix_test"), SqlIdentifier.unquoted("dummy_entity"), null,
+ SqlIdentifier.unquoted("prefix_test"));
}
@Test // DATAJDBC-340
@@ -240,7 +241,8 @@ public void columnForCascadedEmbeddedProperty() {
assertThat(generatedColumn("embeddable.embeddable.attr1", DummyEntity.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias)
- .containsExactly("attr1", "dummy_entity", null, "attr1");
+ .containsExactly(SqlIdentifier.unquoted("attr1"), SqlIdentifier.unquoted("dummy_entity"), null,
+ SqlIdentifier.unquoted("attr1"));
}
@Test // DATAJDBC-340
@@ -250,11 +252,11 @@ public void joinForEmbeddedWithReference() {
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(join.getJoinTable().getName()).isEqualTo("other_entity");
+ softly.assertThat(join.getJoinTable().getName()).isEqualTo(SqlIdentifier.unquoted("other_entity"));
softly.assertThat(join.getJoinColumn().getTable()).isEqualTo(join.getJoinTable());
- softly.assertThat(join.getJoinColumn().getName()).isEqualTo("dummy_entity2");
- softly.assertThat(join.getParentId().getName()).isEqualTo("id");
- softly.assertThat(join.getParentId().getTable().getName()).isEqualTo("dummy_entity2");
+ softly.assertThat(join.getJoinColumn().getName()).isEqualTo(SqlIdentifier.unquoted("dummy_entity2"));
+ softly.assertThat(join.getParentId().getName()).isEqualTo(SqlIdentifier.unquoted("id"));
+ softly.assertThat(join.getParentId().getTable().getName()).isEqualTo(SqlIdentifier.unquoted("dummy_entity2"));
});
}
@@ -263,7 +265,8 @@ public void columnForEmbeddedWithReferenceProperty() {
assertThat(generatedColumn("embedded.other.value", DummyEntity2.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias)
- .containsExactly("value", "other_entity", "prefix_other", "prefix_other_value");
+ .containsExactly(SqlIdentifier.unquoted("value"), SqlIdentifier.unquoted("other_entity"),
+ SqlIdentifier.quoted("prefix_other"), SqlIdentifier.unquoted("prefix_other_value"));
}
private SqlGenerator.Join generateJoin(String path, Class> type) {
@@ -271,7 +274,7 @@ private SqlGenerator.Join generateJoin(String path, Class> type) {
.getJoin(new PersistentPropertyPathExtension(context, PropertyPathTestingUtils.toPath(path, type, context)));
}
- private String getAlias(Object maybeAliased) {
+ private SqlIdentifier getAlias(Object maybeAliased) {
if (maybeAliased instanceof Aliased) {
return ((Aliased) maybeAliased).getAlias();
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorFixedNamingStrategyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorFixedNamingStrategyUnitTests.java
index e905d9f964..0ded6245f4 100644
--- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorFixedNamingStrategyUnitTests.java
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorFixedNamingStrategyUnitTests.java
@@ -24,11 +24,11 @@
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.PersistentPropertyPathTestUtils;
import org.springframework.data.mapping.PersistentPropertyPath;
+import org.springframework.data.relational.core.dialect.HsqlDbDialect;
import org.springframework.data.relational.core.mapping.NamingStrategy;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
-import org.springframework.data.relational.core.sql.IdentifierProcessing;
/**
* Unit tests the {@link SqlGenerator} with a fixed {@link NamingStrategy} implementation containing a hard wired
@@ -196,7 +196,7 @@ private SqlGenerator configureSqlGenerator(NamingStrategy namingStrategy) {
RelationalMappingContext context = new JdbcMappingContext(namingStrategy);
RelationalPersistentEntity> persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class);
- return new SqlGenerator(context, persistentEntity, IdentifierProcessing.ANSI);
+ return new SqlGenerator(context, persistentEntity, HsqlDbDialect.INSTANCE);
}
@SuppressWarnings("unused")
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java
index 92537b0a60..b260b12732 100644
--- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java
@@ -41,11 +41,12 @@
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.Aliased;
-import org.springframework.data.relational.core.sql.Table;
-import org.springframework.data.relational.domain.Identifier;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing;
import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
+import org.springframework.data.relational.core.sql.Table;
+import org.springframework.data.relational.domain.Identifier;
/**
* Unit tests for the {@link SqlGenerator}.
@@ -79,7 +80,7 @@ SqlGenerator createSqlGenerator(Class> type, IdentifierProcessing identifierPr
RelationalPersistentEntity> persistentEntity = context.getRequiredPersistentEntity(type);
- return new SqlGenerator(context, persistentEntity, identifierProcessing);
+ return new SqlGenerator(context, persistentEntity, new IdentifierProcessingAdapter(identifierProcessing));
}
@Test // DATAJDBC-112
@@ -451,11 +452,11 @@ public void joinForSimpleReference() {
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(join.getJoinTable().getName()).isEqualTo("\"REFERENCED_ENTITY\"");
+ softly.assertThat(join.getJoinTable().getName()).isEqualTo(SqlIdentifier.quoted("REFERENCED_ENTITY"));
softly.assertThat(join.getJoinColumn().getTable()).isEqualTo(join.getJoinTable());
- softly.assertThat(join.getJoinColumn().getName()).isEqualTo("\"DUMMY_ENTITY\"");
- softly.assertThat(join.getParentId().getName()).isEqualTo("\"id1\"");
- softly.assertThat(join.getParentId().getTable().getName()).isEqualTo("\"DUMMY_ENTITY\"");
+ softly.assertThat(join.getJoinColumn().getName()).isEqualTo(SqlIdentifier.quoted("DUMMY_ENTITY"));
+ softly.assertThat(join.getParentId().getName()).isEqualTo(SqlIdentifier.quoted("id1"));
+ softly.assertThat(join.getParentId().getTable().getName()).isEqualTo(SqlIdentifier.quoted("DUMMY_ENTITY"));
});
}
@@ -483,11 +484,12 @@ public void joinForSecondLevelReference() {
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(join.getJoinTable().getName()).isEqualTo("\"SECOND_LEVEL_REFERENCED_ENTITY\"");
+ softly.assertThat(join.getJoinTable().getName())
+ .isEqualTo(SqlIdentifier.quoted("SECOND_LEVEL_REFERENCED_ENTITY"));
softly.assertThat(join.getJoinColumn().getTable()).isEqualTo(join.getJoinTable());
- softly.assertThat(join.getJoinColumn().getName()).isEqualTo("\"REFERENCED_ENTITY\"");
- softly.assertThat(join.getParentId().getName()).isEqualTo("\"X_L1ID\"");
- softly.assertThat(join.getParentId().getTable().getName()).isEqualTo("\"REFERENCED_ENTITY\"");
+ softly.assertThat(join.getJoinColumn().getName()).isEqualTo(SqlIdentifier.quoted("REFERENCED_ENTITY"));
+ softly.assertThat(join.getParentId().getName()).isEqualTo(SqlIdentifier.quoted("X_L1ID"));
+ softly.assertThat(join.getParentId().getTable().getName()).isEqualTo(SqlIdentifier.quoted("REFERENCED_ENTITY"));
});
}
@@ -499,13 +501,14 @@ public void joinForOneToOneWithoutId() {
SoftAssertions.assertSoftly(softly -> {
- softly.assertThat(joinTable.getName()).isEqualTo("\"NO_ID_CHILD\"");
+ softly.assertThat(joinTable.getName()).isEqualTo(SqlIdentifier.quoted("NO_ID_CHILD"));
softly.assertThat(joinTable).isInstanceOf(Aliased.class);
- softly.assertThat(((Aliased) joinTable).getAlias()).isEqualTo("\"child\"");
+ softly.assertThat(((Aliased) joinTable).getAlias()).isEqualTo(SqlIdentifier.quoted("child"));
softly.assertThat(join.getJoinColumn().getTable()).isEqualTo(joinTable);
- softly.assertThat(join.getJoinColumn().getName()).isEqualTo("\"PARENT_OF_NO_ID_CHILD\"");
- softly.assertThat(join.getParentId().getName()).isEqualTo("\"X_ID\"");
- softly.assertThat(join.getParentId().getTable().getName()).isEqualTo("\"PARENT_OF_NO_ID_CHILD\"");
+ softly.assertThat(join.getJoinColumn().getName()).isEqualTo(SqlIdentifier.quoted("PARENT_OF_NO_ID_CHILD"));
+ softly.assertThat(join.getParentId().getName()).isEqualTo(SqlIdentifier.quoted("X_ID"));
+ softly.assertThat(join.getParentId().getTable().getName())
+ .isEqualTo(SqlIdentifier.quoted("PARENT_OF_NO_ID_CHILD"));
});
}
@@ -520,7 +523,8 @@ public void simpleColumn() {
assertThat(generatedColumn("id", DummyEntity.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias)
- .containsExactly("\"id1\"", "\"DUMMY_ENTITY\"", null, "\"id1\"");
+ .containsExactly(SqlIdentifier.quoted("id1"), SqlIdentifier.quoted("DUMMY_ENTITY"), null,
+ SqlIdentifier.quoted("id1"));
}
@Test // DATAJDBC-340
@@ -528,7 +532,8 @@ public void columnForIndirectProperty() {
assertThat(generatedColumn("ref.l1id", DummyEntity.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias) //
- .containsExactly("\"X_L1ID\"", "\"REFERENCED_ENTITY\"", "\"ref\"", "\"REF_X_L1ID\"");
+ .containsExactly(SqlIdentifier.quoted("X_L1ID"), SqlIdentifier.quoted("REFERENCED_ENTITY"),
+ SqlIdentifier.quoted("ref"), SqlIdentifier.quoted("REF_X_L1ID"));
}
@Test // DATAJDBC-340
@@ -542,11 +547,11 @@ public void columnForReferencedEntityWithoutId() {
assertThat(generatedColumn("child", ParentOfNoIdChild.class)) //
.extracting(c -> c.getName(), c -> c.getTable().getName(), c -> getAlias(c.getTable()), this::getAlias) //
- .containsExactly("\"PARENT_OF_NO_ID_CHILD\"", "\"NO_ID_CHILD\"", "\"child\"",
- "\"CHILD_PARENT_OF_NO_ID_CHILD\"");
+ .containsExactly(SqlIdentifier.quoted("PARENT_OF_NO_ID_CHILD"), SqlIdentifier.quoted("NO_ID_CHILD"),
+ SqlIdentifier.quoted("child"), SqlIdentifier.quoted("CHILD_PARENT_OF_NO_ID_CHILD"));
}
- private String getAlias(Object maybeAliased) {
+ private SqlIdentifier getAlias(Object maybeAliased) {
if (maybeAliased instanceof Aliased) {
return ((Aliased) maybeAliased).getAlias();
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/UnquotedDialect.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/UnquotedDialect.java
new file mode 100644
index 0000000000..8355177907
--- /dev/null
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/UnquotedDialect.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.jdbc.core.convert;
+
+import org.springframework.data.relational.core.dialect.AbstractDialect;
+import org.springframework.data.relational.core.dialect.Dialect;
+import org.springframework.data.relational.core.dialect.HsqlDbDialect;
+import org.springframework.data.relational.core.dialect.LimitClause;
+import org.springframework.data.relational.core.sql.IdentifierProcessing;
+import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing;
+import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting;
+
+/**
+ * Simple {@link Dialect} that provides unquoted {@link IdentifierProcessing}.
+ *
+ * @author Mark Paluch
+ */
+public class UnquotedDialect extends AbstractDialect implements Dialect {
+
+ public static final UnquotedDialect INSTANCE = new UnquotedDialect();
+
+ private UnquotedDialect() {}
+
+ @Override
+ public LimitClause limit() {
+ return HsqlDbDialect.INSTANCE.limit();
+ }
+
+ @Override
+ public IdentifierProcessing getIdentifierProcessing() {
+ return IdentifierProcessing.create(new Quoting(""), LetterCasing.AS_IS);
+ }
+}
diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml
index 0a529399c3..0d7d811664 100644
--- a/spring-data-relational/pom.xml
+++ b/spring-data-relational/pom.xml
@@ -6,7 +6,7 @@
4.0.0
spring-data-relational
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAJDBC-476-SNAPSHOT
Spring Data Relational
Spring Data Relational support
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-relational-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAJDBC-476-SNAPSHOT
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/RenderContextFactory.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/RenderContextFactory.java
index 92fdba6407..20b576fe25 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/RenderContextFactory.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/RenderContextFactory.java
@@ -17,6 +17,7 @@
import lombok.RequiredArgsConstructor;
+import org.springframework.data.relational.core.sql.IdentifierProcessing;
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;
@@ -68,7 +69,7 @@ public RenderContext createRenderContext() {
SelectRenderContext select = dialect.getSelectContext();
- return new DialectRenderContext(namingStrategy, select);
+ return new DialectRenderContext(namingStrategy, dialect.getIdentifierProcessing(), select);
}
/**
@@ -79,6 +80,8 @@ static class DialectRenderContext implements RenderContext {
private final RenderNamingStrategy renderNamingStrategy;
+ private final IdentifierProcessing identifierProcessing;
+
private final SelectRenderContext selectRenderContext;
/*
@@ -90,6 +93,15 @@ public RenderNamingStrategy getNamingStrategy() {
return renderNamingStrategy;
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.relational.core.sql.render.RenderContext#getIdentifierProcessing()
+ */
+ @Override
+ public IdentifierProcessing getIdentifierProcessing() {
+ return identifierProcessing;
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.relational.core.sql.render.RenderContext#getSelect()
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
index fe6f351499..7d2db50682 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
@@ -130,11 +130,11 @@ protected Association createAssociation() {
throw new UnsupportedOperationException();
}
- boolean isForceQuote() {
+ public boolean isForceQuote() {
return forceQuote;
}
- void setForceQuote(boolean forceQuote) {
+ public void setForceQuote(boolean forceQuote) {
this.forceQuote = forceQuote;
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifier.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifier.java
index b9ac437249..34dcde8f3d 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifier.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifier.java
@@ -80,11 +80,14 @@ public String getReference(IdentifierProcessing processing) {
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o) {
return true;
+ }
+
if (o instanceof SqlIdentifier) {
return toString().equals(o.toString());
}
+
return false;
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentEntityImpl.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentEntityImpl.java
index 9e5360aec6..262e5d830b 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentEntityImpl.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentEntityImpl.java
@@ -64,11 +64,11 @@ private SqlIdentifier createDerivedSqlIdentifier(String name) {
return new DerivedSqlIdentifier(name, isForceQuote());
}
- boolean isForceQuote() {
+ public boolean isForceQuote() {
return forceQuote;
}
- void setForceQuote(boolean forceQuote) {
+ public void setForceQuote(boolean forceQuote) {
this.forceQuote = forceQuote;
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Aliased.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Aliased.java
index f1cebb4413..5616a25a67 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Aliased.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Aliased.java
@@ -26,5 +26,5 @@ public interface Aliased {
/**
* @return the alias name.
*/
- String getAlias();
+ SqlIdentifier getAlias();
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/AliasedExpression.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/AliasedExpression.java
index 9d6622405c..c6ec61b9f7 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/AliasedExpression.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/AliasedExpression.java
@@ -24,12 +24,20 @@
class AliasedExpression extends AbstractSegment implements Aliased, Expression {
private final Expression expression;
- private final String alias;
+ private final SqlIdentifier alias;
public AliasedExpression(Expression expression, String alias) {
super(expression);
+ this.expression = expression;
+ this.alias = SqlIdentifier.unquoted(alias);
+ }
+
+ public AliasedExpression(Expression expression, SqlIdentifier alias) {
+
+ super(expression);
+
this.expression = expression;
this.alias = alias;
}
@@ -39,7 +47,7 @@ public AliasedExpression(Expression expression, String alias) {
* @see org.springframework.data.relational.core.sql.Aliased#getAlias()
*/
@Override
- public String getAlias() {
+ public SqlIdentifier getAlias() {
return alias;
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/BindMarker.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/BindMarker.java
index e63a9c659d..a295c6aece 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/BindMarker.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/BindMarker.java
@@ -47,8 +47,8 @@ static class NamedBindMarker extends BindMarker implements Named {
* @see org.springframework.data.relational.core.sql.Named#getName()
*/
@Override
- public String getName() {
- return name;
+ public SqlIdentifier getName() {
+ return SqlIdentifier.unquoted(name);
}
/*
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Column.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Column.java
index 537d1f9d7c..1707091511 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Column.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Column.java
@@ -29,7 +29,7 @@
*/
public class Column extends AbstractSegment implements Expression, Named {
- private final String name;
+ private final SqlIdentifier name;
private final Table table;
Column(String name, Table table) {
@@ -37,6 +37,15 @@ public class Column extends AbstractSegment implements Expression, Named {
super(table);
Assert.notNull(name, "Name must not be null");
+ this.name = SqlIdentifier.unquoted(name);
+ this.table = table;
+ }
+
+ Column(SqlIdentifier name, Table table) {
+
+ super(table);
+ Assert.notNull(name, "Name must not be null");
+
this.name = name;
this.table = table;
}
@@ -53,6 +62,22 @@ public static Column create(String name, Table table) {
Assert.hasText(name, "Name must not be null or empty");
Assert.notNull(table, "Table must not be null");
+ return new Column(SqlIdentifier.unquoted(name), table);
+ }
+
+ /**
+ * Creates a new {@link Column} associated with a {@link Table}.
+ *
+ * @param name column name, must not {@literal null}.
+ * @param table the table, must not be {@literal null}.
+ * @return the new {@link Column}.
+ * @since 2.0
+ */
+ public static Column create(SqlIdentifier name, Table table) {
+
+ Assert.notNull(name, "Name must not be null");
+ Assert.notNull(table, "Table must not be null");
+
return new Column(name, table);
}
@@ -83,6 +108,20 @@ public Column as(String alias) {
Assert.hasText(alias, "Alias must not be null or empty");
+ return new AliasedColumn(name, table, SqlIdentifier.unquoted(alias));
+ }
+
+ /**
+ * Creates a new aliased {@link Column}.
+ *
+ * @param alias column alias name, must not {@literal null}.
+ * @return the aliased {@link Column}.
+ * @since 2.0
+ */
+ public Column as(SqlIdentifier alias) {
+
+ Assert.notNull(alias, "Alias must not be null");
+
return new AliasedColumn(name, table, alias);
}
@@ -250,7 +289,7 @@ public AssignValue set(Expression value) {
* @see org.springframework.data.relational.core.sql.Named#getName()
*/
@Override
- public String getName() {
+ public SqlIdentifier getName() {
return name;
}
@@ -258,8 +297,8 @@ public String getName() {
* @return the column name as it is used in references. This can be the actual {@link #getName() name} or an
* {@link Aliased#getAlias() alias}.
*/
- public String getReferenceName() {
- return name;
+ public SqlIdentifier getReferenceName() {
+ return getName();
}
/**
@@ -294,9 +333,14 @@ String getPrefix() {
*/
static class AliasedColumn extends Column implements Aliased {
- private final String alias;
+ private final SqlIdentifier alias;
private AliasedColumn(String name, Table table, String alias) {
+ super(name, table);
+ this.alias = SqlIdentifier.unquoted(alias);
+ }
+
+ private AliasedColumn(SqlIdentifier name, Table table, SqlIdentifier alias) {
super(name, table);
this.alias = alias;
}
@@ -306,7 +350,7 @@ private AliasedColumn(String name, Table table, String alias) {
* @see org.springframework.data.relational.core.sql.Aliased#getAlias()
*/
@Override
- public String getAlias() {
+ public SqlIdentifier getAlias() {
return alias;
}
@@ -315,7 +359,7 @@ public String getAlias() {
* @see org.springframework.data.relational.core.sql.Column#getReferenceName()
*/
@Override
- public String getReferenceName() {
+ public SqlIdentifier getReferenceName() {
return getAlias();
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSqlIdentifier.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSqlIdentifier.java
index d3ced46790..9e44f2531d 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSqlIdentifier.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSqlIdentifier.java
@@ -76,11 +76,14 @@ public String getReference(IdentifierProcessing processing) {
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o) {
return true;
+ }
+
if (o instanceof SqlIdentifier) {
return toString().equals(o.toString());
}
+
return false;
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Named.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Named.java
index 8ef9facac5..4af7b67e9b 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Named.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Named.java
@@ -26,5 +26,5 @@ public interface Named {
/**
* @return the name of the underlying element.
*/
- String getName();
+ SqlIdentifier getName();
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SimpleFunction.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SimpleFunction.java
index ba97eb2aa8..b764bf0894 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SimpleFunction.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SimpleFunction.java
@@ -65,6 +65,20 @@ public SimpleFunction as(String alias) {
Assert.hasText(alias, "Alias must not be null or empty");
+ return new AliasedFunction(functionName, expressions, SqlIdentifier.unquoted(alias));
+ }
+
+ /**
+ * Expose this function result under a column {@code alias}.
+ *
+ * @param alias column alias name, must not {@literal null}.
+ * @return the aliased {@link SimpleFunction}.
+ * @since 2.0
+ */
+ public SimpleFunction as(SqlIdentifier alias) {
+
+ Assert.notNull(alias, "Alias must not be null");
+
return new AliasedFunction(functionName, expressions, alias);
}
@@ -97,9 +111,9 @@ public String toString() {
*/
static class AliasedFunction extends SimpleFunction implements Aliased {
- private final String alias;
+ private final SqlIdentifier alias;
- AliasedFunction(String functionName, List expressions, String alias) {
+ AliasedFunction(String functionName, List expressions, SqlIdentifier alias) {
super(functionName, expressions);
this.alias = alias;
}
@@ -109,7 +123,7 @@ static class AliasedFunction extends SimpleFunction implements Aliased {
* @see org.springframework.data.relational.core.sql.Aliased#getAlias()
*/
@Override
- public String getAlias() {
+ public SqlIdentifier getAlias() {
return alias;
}
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SqlIdentifier.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SqlIdentifier.java
index 39e267968f..f3d43b0c4c 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SqlIdentifier.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SqlIdentifier.java
@@ -69,6 +69,17 @@ public String toString() {
*/
String getReference(IdentifierProcessing processing);
+ /**
+ * Return the reference name without any further transformation. The reference name is used for programmatic access to
+ * the object identified by this {@link SqlIdentifier}.
+ *
+ * @return
+ * @see IdentifierProcessing#NONE
+ */
+ default String getReference() {
+ return getReference(IdentifierProcessing.NONE);
+ }
+
/**
* Return the identifier for SQL usage after applying {@link IdentifierProcessing} rules. The identifier name is used
* to construct SQL statements.
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Table.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Table.java
index e371f69f4d..98dad4339e 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Table.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Table.java
@@ -33,9 +33,14 @@
*/
public class Table extends AbstractSegment {
- private final String name;
+ private final SqlIdentifier name;
Table(String name) {
+ super();
+ this.name = SqlIdentifier.unquoted(name);
+ }
+
+ Table(SqlIdentifier name) {
super();
this.name = name;
}
@@ -48,7 +53,21 @@ public class Table extends AbstractSegment {
*/
public static Table create(String name) {
- Assert.hasText(name, "Name must not be null or empty!");
+ Assert.hasText(name, "Name must not be null or empty");
+
+ return new Table(name);
+ }
+
+ /**
+ * Creates a new {@link Table} given {@code name}.
+ *
+ * @param name must not be {@literal null} or empty.
+ * @return the new {@link Table}.
+ * @since 2.0
+ */
+ public static Table create(SqlIdentifier name) {
+
+ Assert.notNull(name, "Name must not be null");
return new Table(name);
}
@@ -78,6 +97,20 @@ public Table as(String alias) {
Assert.hasText(alias, "Alias must not be null or empty!");
+ return new AliasedTable(name, SqlIdentifier.unquoted(alias));
+ }
+
+ /**
+ * Creates a new {@link Table} aliased to {@code alias}.
+ *
+ * @param alias must not be {@literal null} or empty.
+ * @return the new {@link Table} using the {@code alias}.
+ * @since 2.0
+ */
+ public Table as(SqlIdentifier alias) {
+
+ Assert.notNull(alias, "Alias must not be null");
+
return new AliasedTable(name, alias);
}
@@ -97,6 +130,23 @@ public Column column(String name) {
return new Column(name, this);
}
+ /**
+ * Creates a new {@link Column} associated with this {@link Table}.
+ *
+ * Note: This {@link Table} does not track column creation and there is no possibility to enumerate all
+ * {@link Column}s that were created for this table.
+ *
+ * @param name column name, must not be {@literal null} or empty.
+ * @return a new {@link Column} associated with this {@link Table}.
+ * @since 2.0
+ */
+ public Column column(SqlIdentifier name) {
+
+ Assert.notNull(name, "Name must not be null");
+
+ return new Column(name, this);
+ }
+
/**
* Creates a {@link List} of {@link Column}s associated with this {@link Table}.
*
@@ -113,6 +163,28 @@ public List columns(String... names) {
return columns(Arrays.asList(names));
}
+ /**
+ * Creates a {@link List} of {@link Column}s associated with this {@link Table}.
+ *
+ * Note: This {@link Table} does not track column creation and there is no possibility to enumerate all
+ * {@link Column}s that were created for this table.
+ *
+ * @param names column names, must not be {@literal null} or empty.
+ * @return a new {@link List} of {@link Column}s associated with this {@link Table}.
+ * @since 2.0
+ */
+ public List columns(SqlIdentifier... names) {
+
+ Assert.notNull(names, "Names must not be null");
+
+ List columns = new ArrayList<>();
+ for (SqlIdentifier name : names) {
+ columns.add(column(name));
+ }
+
+ return columns;
+ }
+
/**
* Creates a {@link List} of {@link Column}s associated with this {@link Table}.
*
@@ -153,7 +225,7 @@ public AsteriskFromTable asterisk() {
* (non-Javadoc)
* @see org.springframework.data.relational.core.sql.Named#getName()
*/
- public String getName() {
+ public SqlIdentifier getName() {
return name;
}
@@ -161,7 +233,7 @@ public String getName() {
* @return the table name as it is used in references. This can be the actual {@link #getName() name} or an
* {@link Aliased#getAlias() alias}.
*/
- public String getReferenceName() {
+ public SqlIdentifier getReferenceName() {
return name;
}
@@ -171,7 +243,7 @@ public String getReferenceName() {
*/
@Override
public String toString() {
- return name;
+ return name.toString();
}
/**
@@ -179,12 +251,20 @@ public String toString() {
*/
static class AliasedTable extends Table implements Aliased {
- private final String alias;
+ private final SqlIdentifier alias;
AliasedTable(String name, String alias) {
super(name);
- Assert.hasText(alias, "Alias must not be null or empty!");
+ Assert.hasText(alias, "Alias must not be null or empty");
+
+ this.alias = SqlIdentifier.unquoted(alias);
+ }
+
+ AliasedTable(SqlIdentifier name, SqlIdentifier alias) {
+ super(name);
+
+ Assert.notNull(alias, "Alias must not be null");
this.alias = alias;
}
@@ -194,7 +274,7 @@ static class AliasedTable extends Table implements Aliased {
* @see org.springframework.data.relational.core.sql.Aliased#getAlias()
*/
@Override
- public String getAlias() {
+ public SqlIdentifier getAlias() {
return alias;
}
@@ -203,7 +283,7 @@ public String getAlias() {
* @see org.springframework.data.relational.core.sql.Table#getReferenceName()
*/
@Override
- public String getReferenceName() {
+ public SqlIdentifier getReferenceName() {
return getAlias();
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ColumnVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ColumnVisitor.java
index 27e2927088..6ac108cdb3 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ColumnVisitor.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ColumnVisitor.java
@@ -16,6 +16,7 @@
package org.springframework.data.relational.core.sql.render;
import org.springframework.data.relational.core.sql.Column;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.core.sql.Table;
import org.springframework.data.relational.core.sql.Visitable;
import org.springframework.lang.Nullable;
@@ -32,7 +33,7 @@ class ColumnVisitor extends TypedSubtreeVisitor {
private final RenderTarget target;
private final boolean considerTablePrefix;
- private @Nullable String tableName;
+ private @Nullable SqlIdentifier tableName;
ColumnVisitor(RenderContext context, boolean considerTablePrefix, RenderTarget target) {
this.context = context;
@@ -47,13 +48,14 @@ class ColumnVisitor extends TypedSubtreeVisitor {
@Override
Delegation leaveMatched(Column segment) {
- String column = context.getNamingStrategy().getName(segment);
- StringBuilder builder = new StringBuilder(
- tableName != null ? tableName.length() + column.length() : column.length());
+ SqlIdentifier column = context.getNamingStrategy().getName(segment);
+ StringBuilder builder = new StringBuilder();
if (considerTablePrefix && tableName != null) {
- builder.append(tableName);
+
+ builder.append(NameRenderer.render(context, SqlIdentifier.from(tableName, column)));
+ } else {
+ builder.append(NameRenderer.render(context, segment));
}
- builder.append(column);
target.onRendered(builder);
return super.leaveMatched(segment);
@@ -67,7 +69,7 @@ Delegation leaveMatched(Column segment) {
Delegation leaveNested(Visitable segment) {
if (segment instanceof Table) {
- tableName = context.getNamingStrategy().getReferenceName((Table) segment) + '.';
+ tableName = context.getNamingStrategy().getReferenceName((Table) segment);
}
return super.leaveNested(segment);
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ExpressionVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ExpressionVisitor.java
index 71ca846392..408da4df27 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ExpressionVisitor.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/ExpressionVisitor.java
@@ -61,14 +61,13 @@ Delegation enterMatched(Expression segment) {
if (segment instanceof Column) {
- RenderNamingStrategy namingStrategy = context.getNamingStrategy();
Column column = (Column) segment;
- value = namingStrategy.getReferenceName(column.getTable()) + "." + namingStrategy.getReferenceName(column);
+ value = NameRenderer.fullyQualifiedReference(context, column);
} else if (segment instanceof BindMarker) {
if (segment instanceof Named) {
- value = ((Named) segment).getName();
+ value = NameRenderer.render(context, (Named) segment);
} else {
value = segment.toString();
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/FromTableVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/FromTableVisitor.java
index 623f9b4a10..93d8a470a7 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/FromTableVisitor.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/FromTableVisitor.java
@@ -47,9 +47,9 @@ Delegation enterMatched(Table segment) {
StringBuilder builder = new StringBuilder();
- builder.append(context.getNamingStrategy().getName(segment));
+ builder.append(NameRenderer.render(context, segment));
if (segment instanceof Aliased) {
- builder.append(" ").append(((Aliased) segment).getAlias());
+ builder.append(" ").append(NameRenderer.render(context, (Aliased) segment));
}
parent.onRendered(builder);
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/JoinVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/JoinVisitor.java
index 135606930a..e5934b586a 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/JoinVisitor.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/JoinVisitor.java
@@ -33,12 +33,14 @@ class JoinVisitor extends TypedSubtreeVisitor {
private final RenderContext context;
private final RenderTarget parent;
private final StringBuilder joinClause = new StringBuilder();
+ private final ConditionVisitor conditionVisitor;
private boolean inCondition = false;
private boolean hasSeenCondition = false;
JoinVisitor(RenderContext context, RenderTarget parent) {
this.context = context;
this.parent = parent;
+ this.conditionVisitor = new ConditionVisitor(context);
}
/*
@@ -61,18 +63,16 @@ Delegation enterMatched(Join segment) {
Delegation enterNested(Visitable segment) {
if (segment instanceof Table && !inCondition) {
- joinClause.append(context.getNamingStrategy().getName(((Table) segment)));
+ joinClause.append(NameRenderer.render(context, (Table) segment));
if (segment instanceof Aliased) {
- joinClause.append(" AS ").append(((Aliased) segment).getAlias());
+ joinClause.append(" AS ").append(NameRenderer.render(context, (Aliased) segment));
}
} else if (segment instanceof Condition) {
- // TODO: Use proper delegation for condition rendering.
inCondition = true;
if (!hasSeenCondition) {
hasSeenCondition = true;
- joinClause.append(" ON ");
- joinClause.append(segment);
+ return Delegation.delegateTo(conditionVisitor);
}
}
@@ -88,6 +88,14 @@ Delegation leaveNested(Visitable segment) {
if (segment instanceof Condition) {
inCondition = false;
+
+ if (hasSeenCondition) {
+
+ joinClause.append(" ON ");
+ joinClause.append(conditionVisitor.getRenderedPart());
+
+ hasSeenCondition = false;
+ }
}
return super.leaveNested(segment);
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NameRenderer.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NameRenderer.java
new file mode 100644
index 0000000000..22a6a7e330
--- /dev/null
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NameRenderer.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.relational.core.sql.render;
+
+import org.springframework.data.relational.core.sql.Aliased;
+import org.springframework.data.relational.core.sql.Column;
+import org.springframework.data.relational.core.sql.IdentifierProcessing;
+import org.springframework.data.relational.core.sql.Named;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
+import org.springframework.data.relational.core.sql.Table;
+
+/**
+ * Utility to render {@link Column} and {@link Table} names using {@link SqlIdentifier} and {@link RenderContext} to
+ * SQL.
+ *
+ * @author Mark Paluch
+ */
+class NameRenderer {
+
+ /**
+ * Render the {@link Table#getName() table name } with considering the {@link RenderNamingStrategy#getName(Table)
+ * naming strategy}.
+ *
+ * @param context
+ * @param table
+ * @return
+ */
+ static CharSequence render(RenderContext context, Table table) {
+ return render(context, context.getNamingStrategy().getName(table));
+ }
+
+ /**
+ * Render the {@link Column#getName() column name} with considering the {@link RenderNamingStrategy#getName(Column)
+ * naming strategy}.
+ *
+ * @param context
+ * @param table
+ * @return
+ */
+ static CharSequence render(RenderContext context, Column column) {
+ return render(context, context.getNamingStrategy().getName(column));
+ }
+
+ /**
+ * Render the {@link Named#getName() name}.
+ *
+ * @param context
+ * @param table
+ * @return
+ */
+ static CharSequence render(RenderContext context, Named named) {
+ return render(context, named.getName());
+ }
+
+ /**
+ * Render the {@link Aliased#getAlias() alias}.
+ *
+ * @param context
+ * @param table
+ * @return
+ */
+ static CharSequence render(RenderContext context, Aliased aliased) {
+ return render(context, aliased.getAlias());
+ }
+
+ /**
+ * Render the {@link Table#getReferenceName()} table reference name} with considering the
+ * {@link RenderNamingStrategy#getReferenceName(Table) naming strategy}.
+ *
+ * @param context
+ * @param table
+ * @return
+ */
+ static CharSequence reference(RenderContext context, Table table) {
+ return render(context, context.getNamingStrategy().getReferenceName(table));
+ }
+
+ /**
+ * Render the {@link Column#getReferenceName()} column reference name} with considering the
+ * {@link RenderNamingStrategy#getReferenceName(Column) naming strategy}.
+ *
+ * @param context
+ * @param table
+ * @return
+ */
+ static CharSequence reference(RenderContext context, Column column) {
+ return render(context, context.getNamingStrategy().getReferenceName(column));
+ }
+
+ /**
+ * Render the fully-qualified table and column name with considering the naming strategies of each component.
+ *
+ * @param context
+ * @param column
+ * @return
+ * @see RenderNamingStrategy#getReferenceName
+ */
+ static CharSequence fullyQualifiedReference(RenderContext context, Column column) {
+
+ RenderNamingStrategy namingStrategy = context.getNamingStrategy();
+
+ return render(context, SqlIdentifier.from(namingStrategy.getReferenceName(column.getTable()),
+ namingStrategy.getReferenceName(column)));
+ }
+
+ /**
+ * Render the {@link SqlIdentifier#toSql(IdentifierProcessing) identifier to SQL} considering
+ * {@link IdentifierProcessing}.
+ *
+ * @param context
+ * @param identifier
+ * @return
+ */
+ static CharSequence render(RenderContext context, SqlIdentifier identifier) {
+ return identifier.toSql(context.getIdentifierProcessing());
+ }
+
+ private NameRenderer() {}
+}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NamingStrategies.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NamingStrategies.java
index 7cd4ed0c8d..c9b4b56693 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NamingStrategies.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/NamingStrategies.java
@@ -21,6 +21,7 @@
import java.util.function.Function;
import org.springframework.data.relational.core.sql.Column;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.core.sql.Table;
import org.springframework.util.Assert;
@@ -121,23 +122,23 @@ static class DelegatingRenderNamingStrategy implements RenderNamingStrategy {
private final Function mappingFunction;
@Override
- public String getName(Column column) {
- return mappingFunction.apply(delegate.getName(column));
+ public SqlIdentifier getName(Column column) {
+ return delegate.getName(column).transform(mappingFunction::apply);
}
@Override
- public String getReferenceName(Column column) {
- return mappingFunction.apply(delegate.getReferenceName(column));
+ public SqlIdentifier getReferenceName(Column column) {
+ return delegate.getReferenceName(column).transform(mappingFunction::apply);
}
@Override
- public String getName(Table table) {
- return mappingFunction.apply(delegate.getName(table));
+ public SqlIdentifier getName(Table table) {
+ return delegate.getName(table).transform(mappingFunction::apply);
}
@Override
- public String getReferenceName(Table table) {
- return mappingFunction.apply(delegate.getReferenceName(table));
+ public SqlIdentifier getReferenceName(Table table) {
+ return delegate.getReferenceName(table).transform(mappingFunction::apply);
}
}
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java
index 9f3e7b3de6..1916bf2c32 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java
@@ -77,7 +77,7 @@ Delegation leaveMatched(OrderByField segment) {
Delegation leaveNested(Visitable segment) {
if (segment instanceof Column) {
- builder.append(context.getNamingStrategy().getReferenceName(((Column) segment)));
+ builder.append(NameRenderer.reference(context, (Column) segment));
}
return super.leaveNested(segment);
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderContext.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderContext.java
index d489d605ee..011175d6a5 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderContext.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderContext.java
@@ -15,6 +15,8 @@
*/
package org.springframework.data.relational.core.sql.render;
+import org.springframework.data.relational.core.sql.IdentifierProcessing;
+
/**
* Render context providing {@link RenderNamingStrategy} and other resources that are required during rendering.
*
@@ -30,6 +32,14 @@ public interface RenderContext {
*/
RenderNamingStrategy getNamingStrategy();
+ /**
+ * Returns the configured {@link IdentifierProcessing}.
+ *
+ * @return the {@link IdentifierProcessing}.
+ * @since 2.0
+ */
+ IdentifierProcessing getIdentifierProcessing();
+
/**
* @return the {@link SelectRenderContext}.
*/
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderNamingStrategy.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderNamingStrategy.java
index 3bf18df6fe..50b12bf564 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderNamingStrategy.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/RenderNamingStrategy.java
@@ -18,6 +18,7 @@
import java.util.function.Function;
import org.springframework.data.relational.core.sql.Column;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.core.sql.Table;
import org.springframework.data.relational.core.sql.render.NamingStrategies.DelegatingRenderNamingStrategy;
import org.springframework.util.Assert;
@@ -38,7 +39,7 @@ public interface RenderNamingStrategy {
* @return the {@link Column#getName() column name}.
* @see Column#getName()
*/
- default String getName(Column column) {
+ default SqlIdentifier getName(Column column) {
return column.getName();
}
@@ -49,7 +50,7 @@ default String getName(Column column) {
* @return the {@link Column#getName() column reference name}.
* @see Column#getReferenceName() ()
*/
- default String getReferenceName(Column column) {
+ default SqlIdentifier getReferenceName(Column column) {
return column.getReferenceName();
}
@@ -60,7 +61,7 @@ default String getReferenceName(Column column) {
* @return the {@link Table#getName() table name}.
* @see Table#getName()
*/
- default String getName(Table table) {
+ default SqlIdentifier getName(Table table) {
return table.getName();
}
@@ -71,7 +72,7 @@ default String getName(Table table) {
* @return the {@link Table#getReferenceName() table name}.
* @see Table#getReferenceName()
*/
- default String getReferenceName(Table table) {
+ default SqlIdentifier getReferenceName(Table table) {
return table.getReferenceName();
}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SelectListVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SelectListVisitor.java
index 290ca0b82d..420bcbfb8e 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SelectListVisitor.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SelectListVisitor.java
@@ -40,7 +40,6 @@ class SelectListVisitor extends TypedSubtreeVisitor implements PartR
private boolean insideFunction = false; // this is hackery and should be fix with a proper visitor for
// subelements.
-
SelectListVisitor(RenderContext context, RenderTarget target) {
this.context = context;
this.target = target;
@@ -84,14 +83,14 @@ Delegation leaveMatched(SelectList segment) {
Delegation leaveNested(Visitable segment) {
if (segment instanceof Table) {
- builder.append(context.getNamingStrategy().getReferenceName((Table) segment)).append('.');
+ builder.append(NameRenderer.reference(context, (Table) segment)).append('.');
}
if (segment instanceof SimpleFunction) {
builder.append(")");
if (segment instanceof Aliased) {
- builder.append(" AS ").append(((Aliased) segment).getAlias());
+ builder.append(" AS ").append(NameRenderer.render(context, (Aliased) segment));
}
insideFunction = false;
@@ -101,9 +100,9 @@ Delegation leaveNested(Visitable segment) {
requiresComma = true;
} else if (segment instanceof Column) {
- builder.append(context.getNamingStrategy().getName((Column) segment));
+ builder.append(NameRenderer.render(context, (Column) segment));
if (segment instanceof Aliased && !insideFunction) {
- builder.append(" AS ").append(((Aliased) segment).getAlias());
+ builder.append(" AS ").append(NameRenderer.render(context, (Aliased) segment));
}
requiresComma = true;
} else if (segment instanceof AsteriskFromTable) {
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SimpleRenderContext.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SimpleRenderContext.java
index 8edffe020d..cfbaf970fa 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SimpleRenderContext.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/SimpleRenderContext.java
@@ -17,6 +17,8 @@
import lombok.Value;
+import org.springframework.data.relational.core.sql.IdentifierProcessing;
+
/**
* Default {@link RenderContext} implementation.
*
@@ -28,6 +30,11 @@ class SimpleRenderContext implements RenderContext {
private final RenderNamingStrategy namingStrategy;
+ @Override
+ public IdentifierProcessing getIdentifierProcessing() {
+ return IdentifierProcessing.NONE;
+ }
+
@Override
public SelectRenderContext getSelect() {
return DefaultSelectRenderContext.INSTANCE;
diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SelectBuilderUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SelectBuilderUnitTests.java
index 1d88a9672f..a71f92670e 100644
--- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SelectBuilderUnitTests.java
+++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SelectBuilderUnitTests.java
@@ -73,7 +73,7 @@ public void selectWithWhere() {
Column foo = table.column("foo");
Comparison condition = foo.isEqualTo(SQL.literalOf("bar"));
- Select select = builder.select(foo).from(table.getName()).where(condition).build();
+ Select select = builder.select(foo).from(table).where(condition).build();
CapturingVisitor visitor = new CapturingVisitor();
select.visit(visitor);
diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java
index 1e183b57ea..077d134584 100644
--- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java
+++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/SelectRendererUnitTests.java
@@ -17,8 +17,10 @@
import static org.assertj.core.api.Assertions.*;
-import org.junit.Ignore;
import org.junit.Test;
+
+import org.springframework.data.relational.core.dialect.PostgresDialect;
+import org.springframework.data.relational.core.dialect.RenderContextFactory;
import org.springframework.data.relational.core.sql.Column;
import org.springframework.data.relational.core.sql.Conditions;
import org.springframework.data.relational.core.sql.Expressions;
@@ -26,6 +28,7 @@
import org.springframework.data.relational.core.sql.OrderByField;
import org.springframework.data.relational.core.sql.SQL;
import org.springframework.data.relational.core.sql.Select;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.core.sql.Table;
import org.springframework.util.StringUtils;
@@ -329,4 +332,21 @@ public void shouldRenderFunctionWithAlias() {
assertThat(rendered).isEqualTo("SELECT COUNT(foo.*) AS counter FROM foo");
}
+
+ @Test // DATAJDBC-479
+ public void shouldRenderWithRenderContext() {
+
+ Table table = Table.create(SqlIdentifier.quoted("my_table"));
+ Table join_table = Table.create(SqlIdentifier.quoted("join_table"));
+ Select select = Select.builder() //
+ .select(Functions.count(table.asterisk()).as("counter"), table.column(SqlIdentifier.quoted("reserved_keyword"))) //
+ .from(table) //
+ .join(join_table).on(table.column("source")).equals(join_table.column("target")).build();
+
+ String rendered = SqlRenderer.create(new RenderContextFactory(PostgresDialect.INSTANCE).createRenderContext())
+ .render(select);
+
+ assertThat(rendered).isEqualTo(
+ "SELECT COUNT(\"my_table\".*) AS counter, \"my_table\".\"reserved_keyword\" FROM \"my_table\" JOIN \"join_table\" ON \"my_table\".source = \"join_table\".target");
+ }
}