DATAJDBC-479 - Use SqlIdentifier in SQL AST.

We now use SqlIdentifier to encapsulate names and aliases of tables, columns and functions.

We now use proper delegation to ConditionVisitor to render a JOIN condition.
Previously, we used toString() of Condition segments which rendered an approximation of the condition.
ConditionVisitor applies RenderContext settings that consider identifier quoting and normalization strategies.

Original pull request: #187.
This commit is contained in:
Mark Paluch
2020-01-29 09:12:02 +01:00
committed by Jens Schauder
parent 595559bf28
commit 592f483699
36 changed files with 606 additions and 146 deletions

View File

@@ -18,10 +18,8 @@ package org.springframework.data.jdbc.core.convert;
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 @@ class SqlContext {
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());
}
}

View File

@@ -35,6 +35,7 @@ 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.util.Lazy;
@@ -64,7 +65,7 @@ class SqlGenerator {
private final JdbcConverter converter;
private final RelationalPersistentEntity<?> entity;
private final MappingContext<RelationalPersistentEntity<?>, RelationalPersistentProperty> mappingContext;
private final IdentifierProcessing identifierProcessing;
private final RenderContext renderContext;
private final SqlContext sqlContext;
private final SqlRenderer sqlRenderer;
@@ -92,16 +93,15 @@ class SqlGenerator {
* @param entity must not be {@literal null}.
* @param dialect must not be {@literal null}.
*/
SqlGenerator(RelationalMappingContext mappingContext, JdbcConverter converter, RelationalPersistentEntity<?> entity,
Dialect dialect) {
SqlGenerator(RelationalMappingContext mappingContext, JdbcConverter converter,RelationalPersistentEntity<?> entity, Dialect dialect) {
this.mappingContext = mappingContext;
this.converter = converter;
this.entity = entity;
this.identifierProcessing = dialect.getIdentifierProcessing();
this.sqlContext = new SqlContext(entity, this.identifierProcessing);
this.sqlContext = new SqlContext(entity);
this.sqlRenderer = SqlRenderer.create(new RenderContextFactory(dialect).createRenderContext());
this.columns = new Columns(entity, mappingContext, converter);
this.renderContext = new RenderContextFactory(dialect).createRenderContext();
}
/**
@@ -125,10 +125,9 @@ class SqlGenerator {
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;
@@ -151,7 +150,7 @@ class SqlGenerator {
}
private BindMarker getBindMarker(SqlIdentifier columnName) {
return SQL.bindMarker(":" + parameterPattern.matcher(columnName.getReference(identifierProcessing)).replaceAll(""));
return SQL.bindMarker(":" + parameterPattern.matcher(renderReference(columnName)).replaceAll(""));
}
/**
@@ -210,21 +209,19 @@ class SqlGenerator {
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);
@@ -235,8 +232,7 @@ class SqlGenerator {
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);
}
@@ -372,7 +368,7 @@ class SqlGenerator {
return selectBuilder(Collections.emptyList());
}
private SelectBuilder.SelectWhere selectBuilder(Collection<String> keyColumns) {
private SelectBuilder.SelectWhere selectBuilder(Collection<SqlIdentifier> keyColumns) {
Table table = getTable();
@@ -396,7 +392,7 @@ class SqlGenerator {
}
}
for (String keyColumn : keyColumns) {
for (SqlIdentifier keyColumn : keyColumns) {
columnExpressions.add(table.column(keyColumn).as(keyColumn));
}
@@ -485,8 +481,8 @@ class SqlGenerator {
return new Join( //
currentTable, //
currentTable.column(path.getReverseColumnName().toSql(identifierProcessing)), //
parentTable.column(idDefiningParentPath.getIdColumnName().toSql(identifierProcessing)) //
currentTable.column(path.getReverseColumnName()), //
parentTable.column(idDefiningParentPath.getIdColumnName()) //
);
}
@@ -526,14 +522,14 @@ class SqlGenerator {
Table table = getTable();
Set<SqlIdentifier> columnNamesForInsert = new TreeSet<>(Comparator.comparing(id -> id.toSql(identifierProcessing)));
Set<SqlIdentifier> 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;
@@ -551,8 +547,7 @@ class SqlGenerator {
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);
@@ -565,7 +560,7 @@ class SqlGenerator {
List<AssignValue> assignments = columns.getUpdateableColumns() //
.stream() //
.map(columnName -> Assignments.value( //
table.column(columnName.toSql(identifierProcessing)), //
table.column(columnName), //
getBindMarker(columnName))) //
.collect(Collectors.toList());
@@ -582,8 +577,7 @@ class SqlGenerator {
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);
@@ -591,19 +585,19 @@ class SqlGenerator {
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<Column, Condition> 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) {
@@ -659,6 +653,10 @@ class SqlGenerator {
return sqlContext.getVersionColumn();
}
private String renderReference(SqlIdentifier identifier) {
return identifier.getReference(renderContext.getIdentifierProcessing());
}
private List<OrderByField> extractOrderByFields(Sort sort) {
return sort.stream()
.map(order -> OrderByField.from(Column.create(order.getProperty(), this.getTable()), order.getDirection()))

View File

@@ -40,14 +40,16 @@ 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, converter,
return CACHE.computeIfAbsent(domainType,
t -> new SqlGenerator(context, converter,
context.getRequiredPersistentEntity(t), dialect));
}
}

View File

@@ -85,7 +85,10 @@ public class JdbcMappingContext extends RelationalMappingContext {
@Override
protected RelationalPersistentProperty createPersistentProperty(Property property,
RelationalPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
return new BasicJdbcPersistentProperty(property, owner, simpleTypeHolder, this.getNamingStrategy());
BasicJdbcPersistentProperty persistentProperty = new BasicJdbcPersistentProperty(property, owner, simpleTypeHolder,
this.getNamingStrategy());
persistentProperty.setForceQuote(isForceQuote());
return persistentProperty;
}
@Override

View File

@@ -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;
}
}

View File

@@ -24,6 +24,7 @@ import java.util.function.Consumer;
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;

View File

@@ -22,6 +22,7 @@ import org.assertj.core.api.SoftAssertions;
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;
@@ -33,6 +34,7 @@ import org.springframework.data.relational.core.mapping.PersistentPropertyPathEx
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.SqlIdentifier;
/**
* Unit tests for the {@link SqlGenerator} in a context of the {@link Embedded} annotation.
@@ -49,6 +51,7 @@ public class SqlGeneratorEmbeddedUnitTests {
@Before
public void setUp() {
this.context.setForceQuote(false);
this.sqlGenerator = createSqlGenerator(DummyEntity.class);
}
@@ -201,7 +204,8 @@ public class SqlGeneratorEmbeddedUnitTests {
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 +228,8 @@ public class SqlGeneratorEmbeddedUnitTests {
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 +245,8 @@ public class SqlGeneratorEmbeddedUnitTests {
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 +256,11 @@ public class SqlGeneratorEmbeddedUnitTests {
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 +269,8 @@ public class SqlGeneratorEmbeddedUnitTests {
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 +278,7 @@ public class SqlGeneratorEmbeddedUnitTests {
.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();

View File

@@ -25,6 +25,7 @@ import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.PersistentPropertyPathTestUtils;
import org.springframework.data.jdbc.testing.AnsiDialect;
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;

View File

@@ -47,6 +47,10 @@ 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.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;
import org.springframework.data.relational.core.sql.Table;
import org.springframework.data.relational.domain.Identifier;
@@ -555,11 +559,11 @@ public class SqlGeneratorUnitTests {
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"));
});
}
@@ -587,11 +591,12 @@ public class SqlGeneratorUnitTests {
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"));
});
}
@@ -603,13 +608,14 @@ public class SqlGeneratorUnitTests {
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"));
});
}
@@ -624,7 +630,8 @@ public class SqlGeneratorUnitTests {
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
@@ -632,7 +639,8 @@ public class SqlGeneratorUnitTests {
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
@@ -646,11 +654,11 @@ public class SqlGeneratorUnitTests {
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();

View File

@@ -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);
}
}