Browse Source

Avoid selection of duplicate columns.

Closes #1865
3.3.x
Jens Schauder 1 year ago
parent
commit
cacb14cf94
No known key found for this signature in database
GPG Key ID: 74F6C554AE971567
  1. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java
  2. 72
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java

2
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java

@ -514,7 +514,7 @@ class SqlGenerator {
Table table = getTable(); Table table = getTable();
List<Expression> columnExpressions = new ArrayList<>(); Set<Expression> columnExpressions = new LinkedHashSet<>();
List<Join> joinTables = new ArrayList<>(); List<Join> joinTables = new ArrayList<>();
for (PersistentPropertyPath<RelationalPersistentProperty> path : mappingContext for (PersistentPropertyPath<RelationalPersistentProperty> path : mappingContext

72
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java

@ -43,6 +43,7 @@ import org.springframework.data.relational.core.dialect.SqlServerDialect;
import org.springframework.data.relational.core.mapping.AggregatePath; import org.springframework.data.relational.core.mapping.AggregatePath;
import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.DefaultNamingStrategy; import org.springframework.data.relational.core.mapping.DefaultNamingStrategy;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@ -388,7 +389,8 @@ class SqlGeneratorUnitTests {
void findAllByPropertyWithKey() { void findAllByPropertyWithKey() {
// this would get called when ListParent is th element type of a Map // this would get called when ListParent is th element type of a Map
String sql = sqlGenerator.getFindAllByProperty(BACKREF, new AggregatePath.ColumnInfo(unquoted("key-column"),unquoted("key-column")), false); String sql = sqlGenerator.getFindAllByProperty(BACKREF,
new AggregatePath.ColumnInfo(unquoted("key-column"), unquoted("key-column")), false);
assertThat(sql).isEqualTo("SELECT dummy_entity.id1 AS id1, dummy_entity.x_name AS x_name, " // assertThat(sql).isEqualTo("SELECT dummy_entity.id1 AS id1, dummy_entity.x_name AS x_name, " //
+ "dummy_entity.x_other AS x_other, " // + "dummy_entity.x_other AS x_other, " //
@ -451,9 +453,9 @@ class SqlGeneratorUnitTests {
Identifier emptyIdentifier = Identifier.of(EMPTY, 0, Object.class); Identifier emptyIdentifier = Identifier.of(EMPTY, 0, Object.class);
assertThatThrownBy(() -> sqlGenerator.getFindAllByProperty(emptyIdentifier, assertThatThrownBy(() -> sqlGenerator.getFindAllByProperty(emptyIdentifier,
new AggregatePath.ColumnInfo(unquoted("key-column"), unquoted("key-column")), false)) // new AggregatePath.ColumnInfo(unquoted("key-column"), unquoted("key-column")), false)) //
.isInstanceOf(IllegalArgumentException.class) // .isInstanceOf(IllegalArgumentException.class) //
.hasMessageContaining( .hasMessageContaining(
"An empty SqlIdentifier can't be used in condition. Make sure that all composite primary keys are defined in the query"); "An empty SqlIdentifier can't be used in condition. Make sure that all composite primary keys are defined in the query");
} }
@Test // DATAJDBC-219 @Test // DATAJDBC-219
@ -625,18 +627,18 @@ class SqlGeneratorUnitTests {
assertThat( assertThat(
createSqlGenerator(Chain4.class).createDeleteByPath(getPath("chain3.chain2.chain1.chain0", Chain4.class))) // createSqlGenerator(Chain4.class).createDeleteByPath(getPath("chain3.chain2.chain1.chain0", Chain4.class))) //
.isEqualTo("DELETE FROM chain0 " + // .isEqualTo("DELETE FROM chain0 " + //
"WHERE chain0.chain1 IN (" + // "WHERE chain0.chain1 IN (" + //
"SELECT chain1.x_one " + // "SELECT chain1.x_one " + //
"FROM chain1 " + // "FROM chain1 " + //
"WHERE chain1.chain2 IN (" + // "WHERE chain1.chain2 IN (" + //
"SELECT chain2.x_two " + // "SELECT chain2.x_two " + //
"FROM chain2 " + // "FROM chain2 " + //
"WHERE chain2.chain3 IN (" + // "WHERE chain2.chain3 IN (" + //
"SELECT chain3.x_three " + // "SELECT chain3.x_three " + //
"FROM chain3 " + // "FROM chain3 " + //
"WHERE chain3.chain4 = :rootId" + // "WHERE chain3.chain4 = :rootId" + //
")))"); ")))");
} }
@Test // DATAJDBC-359 @Test // DATAJDBC-359
@ -644,7 +646,7 @@ class SqlGeneratorUnitTests {
assertThat(createSqlGenerator(NoIdChain4.class) assertThat(createSqlGenerator(NoIdChain4.class)
.createDeleteByPath(getPath("chain3.chain2.chain1.chain0", NoIdChain4.class))) // .createDeleteByPath(getPath("chain3.chain2.chain1.chain0", NoIdChain4.class))) //
.isEqualTo("DELETE FROM no_id_chain0 WHERE no_id_chain0.no_id_chain4 = :rootId"); .isEqualTo("DELETE FROM no_id_chain0 WHERE no_id_chain0.no_id_chain4 = :rootId");
} }
@Test // DATAJDBC-359 @Test // DATAJDBC-359
@ -652,16 +654,16 @@ class SqlGeneratorUnitTests {
assertThat(createSqlGenerator(IdIdNoIdChain.class) assertThat(createSqlGenerator(IdIdNoIdChain.class)
.createDeleteByPath(getPath("idNoIdChain.chain4.chain3.chain2.chain1.chain0", IdIdNoIdChain.class))) // .createDeleteByPath(getPath("idNoIdChain.chain4.chain3.chain2.chain1.chain0", IdIdNoIdChain.class))) //
.isEqualTo( // .isEqualTo( //
"DELETE FROM no_id_chain0 " // "DELETE FROM no_id_chain0 " //
+ "WHERE no_id_chain0.no_id_chain4 IN (" // + "WHERE no_id_chain0.no_id_chain4 IN (" //
+ "SELECT no_id_chain4.x_four " // + "SELECT no_id_chain4.x_four " //
+ "FROM no_id_chain4 " // + "FROM no_id_chain4 " //
+ "WHERE no_id_chain4.id_no_id_chain IN (" // + "WHERE no_id_chain4.id_no_id_chain IN (" //
+ "SELECT id_no_id_chain.x_id " // + "SELECT id_no_id_chain.x_id " //
+ "FROM id_no_id_chain " // + "FROM id_no_id_chain " //
+ "WHERE id_no_id_chain.id_id_no_id_chain = :rootId" // + "WHERE id_no_id_chain.id_id_no_id_chain = :rootId" //
+ "))"); + "))");
} }
@Test // DATAJDBC-340 @Test // DATAJDBC-340
@ -926,6 +928,16 @@ class SqlGeneratorUnitTests {
"WHERE referenced_entity.parentId"); "WHERE referenced_entity.parentId");
} }
@Test // GH-1865
void mappingMapKeyToChildShouldNotResultInDuplicateColumn() {
SqlGenerator sqlGenerator = createSqlGenerator(Child.class);
String sql = sqlGenerator.getFindAllByProperty(Identifier.of(unquoted("parent"), 23, Parent.class),
context.getAggregatePath(getPath("children", Parent.class)).getTableInfo().qualifierColumnInfo(), false);
assertThat(sql).containsOnlyOnce("child.NICK_NAME AS NICK_NAME");
}
@Nullable @Nullable
private SqlIdentifier getAlias(Object maybeAliased) { private SqlIdentifier getAlias(Object maybeAliased) {
@ -1117,4 +1129,10 @@ class SqlGeneratorUnitTests {
@Id Long id; @Id Long id;
IdNoIdChain idNoIdChain; IdNoIdChain idNoIdChain;
} }
record Parent(@Id Long id, String name, @MappedCollection(keyColumn = "NICK_NAME") Map<String, Child> children) {
}
record Child(@Column("NICK_NAME") String nickName, String name) {
}
} }

Loading…
Cancel
Save