Skip to content

Commit d3e6db2

Browse files
schaudermp911de
authored andcommitted
DATAJDBC-547 - Fixes lock statement for fully qualified table names in PostgreSQL.
Original pull request: #221.
1 parent 2336838 commit d3e6db2

11 files changed

+216
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright 2017-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jdbc.core;
17+
18+
import org.junit.ClassRule;
19+
import org.junit.Rule;
20+
import org.junit.Test;
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.context.ApplicationEventPublisher;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.context.annotation.Import;
26+
import org.springframework.data.annotation.Id;
27+
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
28+
import org.springframework.data.jdbc.core.convert.JdbcConverter;
29+
import org.springframework.data.jdbc.testing.TestConfiguration;
30+
import org.springframework.data.relational.core.mapping.NamingStrategy;
31+
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
32+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
33+
import org.springframework.test.context.ContextConfiguration;
34+
import org.springframework.test.context.junit4.rules.SpringClassRule;
35+
import org.springframework.test.context.junit4.rules.SpringMethodRule;
36+
import org.springframework.transaction.annotation.Transactional;
37+
38+
import static org.assertj.core.api.Assertions.*;
39+
40+
/**
41+
* Integration tests for {@link JdbcAggregateTemplate} using an entity mapped with an explicite schema.
42+
*
43+
* @author Jens Schauder
44+
*/
45+
@ContextConfiguration
46+
@Transactional
47+
public class JdbcAggregateTemplateSchemaIntegrationTests {
48+
49+
@ClassRule public static final SpringClassRule classRule = new SpringClassRule();
50+
@Rule public SpringMethodRule methodRule = new SpringMethodRule();
51+
52+
@Autowired JdbcAggregateOperations template;
53+
@Autowired NamedParameterJdbcOperations jdbcTemplate;
54+
55+
56+
@Test
57+
public void insertFindUpdateDelete() {
58+
59+
DummyEntity entity = new DummyEntity();
60+
entity.name = "Alfred";
61+
entity.reference = new Referenced();
62+
entity.reference.name = "Peter";
63+
64+
template.save(entity);
65+
66+
DummyEntity reloaded = template.findById(entity.id, DummyEntity.class);
67+
68+
assertThat(reloaded).isNotNull();
69+
70+
reloaded.name += " E. Neumann";
71+
72+
template.save(reloaded);
73+
74+
template.deleteById(reloaded.id, DummyEntity.class);
75+
}
76+
77+
static class DummyEntity {
78+
79+
@Id Long id;
80+
String name;
81+
Referenced reference;
82+
}
83+
84+
static class Referenced {
85+
String name;
86+
}
87+
88+
@Configuration
89+
@Import(TestConfiguration.class)
90+
static class Config {
91+
92+
@Bean
93+
Class<?> testClass() {
94+
return JdbcAggregateTemplateSchemaIntegrationTests.class;
95+
}
96+
97+
@Bean
98+
JdbcAggregateOperations operations(ApplicationEventPublisher publisher, RelationalMappingContext context,
99+
DataAccessStrategy dataAccessStrategy, JdbcConverter converter) {
100+
return new JdbcAggregateTemplate(publisher, context, converter, dataAccessStrategy);
101+
}
102+
103+
@Bean
104+
NamingStrategy namingStrategy() {
105+
return new NamingStrategy() {
106+
@Override
107+
public String getSchema() {
108+
return "other";
109+
}
110+
};
111+
}
112+
}
113+
}

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MariaDBDataSourceConfiguration.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ protected DataSource createDataSource() {
5151

5252
if (MARIADB_CONTAINER == null) {
5353

54-
MariaDBContainer<?> container = new MariaDBContainer<>().withConfigurationOverride("");
54+
MariaDBContainer<?> container = new MariaDBContainer<>()
55+
.withUsername("root")
56+
.withPassword("")
57+
.withConfigurationOverride("");
5558
container.start();
5659

5760
MARIADB_CONTAINER = container;

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/MySqlDataSourceConfiguration.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ protected DataSource createDataSource() {
5454

5555
if (MYSQL_CONTAINER == null) {
5656

57-
MySQLContainer<?> container = new MySQLContainer<>().withConfigurationOverride("");
57+
MySQLContainer<?> container = new MySQLContainer<>()
58+
.withUsername("root")
59+
.withPassword("")
60+
.withConfigurationOverride("");
61+
5862
container.start();
5963

6064
MYSQL_CONTAINER = container;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CREATE SCHEMA OTHER;
2+
3+
CREATE TABLE OTHER.DUMMY_ENTITY
4+
(
5+
ID SERIAL PRIMARY KEY,
6+
NAME VARCHAR(30)
7+
);
8+
9+
CREATE TABLE OTHER.REFERENCED
10+
(
11+
DUMMY_ENTITY INTEGER,
12+
NAME VARCHAR(30)
13+
);
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CREATE SCHEMA OTHER;
2+
3+
CREATE TABLE OTHER.DUMMY_ENTITY
4+
(
5+
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
6+
NAME VARCHAR(30)
7+
);
8+
9+
10+
CREATE TABLE OTHER.REFERENCED
11+
(
12+
DUMMY_ENTITY INTEGER,
13+
NAME VARCHAR(30)
14+
);
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CREATE SCHEMA OTHER;
2+
3+
CREATE TABLE OTHER.DUMMY_ENTITY
4+
(
5+
ID BIGINT AUTO_INCREMENT PRIMARY KEY,
6+
NAME VARCHAR(30)
7+
);
8+
9+
10+
CREATE TABLE OTHER.REFERENCED
11+
(
12+
DUMMY_ENTITY INTEGER,
13+
NAME VARCHAR(30)
14+
);
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CREATE SCHEMA OTHER;
2+
3+
CREATE TABLE OTHER.DUMMY_ENTITY
4+
(
5+
ID BIGINT AUTO_INCREMENT PRIMARY KEY,
6+
NAME VARCHAR(30)
7+
);
8+
9+
10+
CREATE TABLE OTHER.REFERENCED
11+
(
12+
DUMMY_ENTITY INTEGER,
13+
NAME VARCHAR(30)
14+
);
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CREATE SCHEMA OTHER;
2+
3+
CREATE TABLE OTHER.DUMMY_ENTITY
4+
(
5+
ID SERIAL PRIMARY KEY,
6+
NAME VARCHAR(30)
7+
);
8+
9+
CREATE TABLE OTHER.REFERENCED
10+
(
11+
DUMMY_ENTITY INTEGER,
12+
NAME VARCHAR(30)
13+
);
14+

spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
import java.util.List;
1919

2020
import org.springframework.data.relational.core.sql.IdentifierProcessing;
21-
import org.springframework.data.relational.core.sql.LockOptions;
22-
import org.springframework.data.relational.core.sql.Table;
2321
import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing;
2422
import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting;
23+
import org.springframework.data.relational.core.sql.LockOptions;
24+
import org.springframework.data.relational.core.sql.Table;
2525
import org.springframework.util.Assert;
2626
import org.springframework.util.ClassUtils;
2727

@@ -30,6 +30,7 @@
3030
*
3131
* @author Mark Paluch
3232
* @author Myeonghyeon Lee
33+
* @author Jens Schauder
3334
* @since 1.1
3435
*/
3536
public class PostgresDialect extends AbstractDialect {
@@ -131,7 +132,9 @@ public String getLock(LockOptions lockOptions) {
131132
return "";
132133
}
133134

134-
String tableName = tables.get(0).getName().toSql(this.identifierProcessing);
135+
String tableName = tables.get(0) // get the first table
136+
.getName().getSimpleIdentifier() // without schema
137+
.toSql(this.identifierProcessing);
135138

136139
switch (lockOptions.getLockMode()) {
137140

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/CompositeSqlIdentifier.java

+5
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public String getReference(IdentifierProcessing processing) {
7474
throw new UnsupportedOperationException("A Composite SQL Identifiers can't be used as a reference name");
7575
}
7676

77+
@Override
78+
public SqlIdentifier getSimpleIdentifier() {
79+
return parts[parts.length - 1];
80+
}
81+
7782
/*
7883
* (non-Javadoc)
7984
* @see java.lang.Object#equals(java.lang.Object)

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SqlIdentifier.java

+10
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ default String getReference() {
9999
*/
100100
SqlIdentifier transform(UnaryOperator<String> transformationFunction);
101101

102+
/**
103+
* Returns the last part of an identifier. For a fully qualified column name {@literal schema.table.column} it will
104+
* just return the column part. If the identifier consists of only a single part, that part is returned.
105+
*
106+
* @return Guaranteed to be not {@literal null}.
107+
*/
108+
default SqlIdentifier getSimpleIdentifier() {
109+
return this;
110+
}
111+
102112
/**
103113
* Create a new quoted identifier given {@code name}.
104114
*

0 commit comments

Comments
 (0)