Skip to content

Commit f1e0ecd

Browse files
fix(sqlserver): prevent cast from NVARCHAR to VARCHAR
Related: #158
1 parent 326d1e8 commit f1e0ecd

File tree

8 files changed

+150
-1
lines changed

8 files changed

+150
-1
lines changed

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,31 @@ jobs:
9393
run: mvn -B test
9494
env:
9595
spring_profiles_active: mysql
96+
97+
test-sqlserver:
98+
runs-on: ubuntu-latest
99+
100+
services:
101+
sqlserver:
102+
image: mcr.microsoft.com/mssql/server:2022-preview-ubuntu-22.04
103+
ports:
104+
- 1433:1433
105+
env:
106+
ACCEPT_EULA: Y
107+
MSSQL_SA_PASSWORD: "Changeit_123"
108+
109+
steps:
110+
- name: Checkout repository
111+
uses: actions/checkout@v3
112+
113+
- name: Set up JDK 17
114+
uses: actions/setup-java@v3
115+
with:
116+
java-version: 17
117+
distribution: adopt
118+
cache: maven
119+
120+
- name: Test with Maven
121+
run: mvn -B test
122+
env:
123+
spring_profiles_active: sqlserver

compose.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
services:
2+
postgres:
3+
image: postgres:14
4+
ports:
5+
- 5432:5432
6+
environment:
7+
POSTGRES_PASSWORD: "postgres"
8+
9+
sqlserver:
10+
image: mcr.microsoft.com/mssql/server:2022-preview-ubuntu-22.04
11+
ports:
12+
- 1433:1433
13+
environment:
14+
ACCEPT_EULA: Y
15+
MSSQL_SA_PASSWORD: "Changeit_123"
16+
17+
mysql:
18+
image: mysql:5.7
19+
ports:
20+
- 3306:3306
21+
environment:
22+
MYSQL_DATABASE: test
23+
MYSQL_ROOT_PASSWORD: changeit

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@
163163
<scope>test</scope>
164164
</dependency>
165165

166+
<dependency>
167+
<groupId>com.microsoft.sqlserver</groupId>
168+
<artifactId>mssql-jdbc</artifactId>
169+
<version>12.6.1.jre11</version>
170+
<scope>test</scope>
171+
</dependency>
172+
166173
<dependency>
167174
<groupId>org.slf4j</groupId>
168175
<artifactId>slf4j-reload4j</artifactId>

src/main/java/org/springframework/data/jpa/datatables/GlobalFilter.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,16 @@ private String escapeValue(String filterValue) {
3434
@Override
3535
public Predicate createPredicate(From<?, ?> from, CriteriaBuilder criteriaBuilder, String attributeName) {
3636
Expression<?> expression = from.get(attributeName);
37-
return criteriaBuilder.like(criteriaBuilder.lower(expression.as(String.class)), escapedRawValue, '~');
37+
return criteriaBuilder.like(criteriaBuilder.lower(castAsStringIfNeeded(expression)), escapedRawValue, '~');
38+
}
39+
40+
@SuppressWarnings("unchecked")
41+
private Expression<String> castAsStringIfNeeded(Expression<?> expression) {
42+
if (expression.getJavaType() == String.class) {
43+
return (Expression<String>) expression;
44+
} else {
45+
return expression.as(String.class);
46+
}
3847
}
3948

4049
@Override

src/test/java/org/springframework/data/jpa/datatables/Config.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ public DataSource dataSource_PostgreSQL() throws SQLException {
5454
return dataSource;
5555
}
5656

57+
@Bean
58+
@Profile("sqlserver")
59+
public DataSource dataSource_SQLServer() throws SQLException {
60+
DriverManagerDataSource dataSource = new DriverManagerDataSource();
61+
dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
62+
dataSource.setUrl("jdbc:sqlserver://localhost:1433;encrypt=false;");
63+
dataSource.setUsername("sa");
64+
dataSource.setPassword("Changeit_123");
65+
return dataSource;
66+
}
67+
5768
@Bean
5869
public SessionFactory entityManagerFactory(DataSource dataSource) throws Exception {
5970
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.springframework.data.jpa.datatables.repository;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.Id;
5+
import jakarta.persistence.Table;
6+
import lombok.Data;
7+
import org.hibernate.annotations.Nationalized;
8+
9+
@Entity
10+
@Data
11+
@Table(name = "users")
12+
public class User {
13+
14+
@Id long id;
15+
@Nationalized String name;
16+
17+
public User() {
18+
}
19+
20+
public User(long id, String name) {
21+
this.id = id;
22+
this.name = name;
23+
}
24+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.springframework.data.jpa.datatables.repository;
2+
3+
public interface UserRepository extends DataTablesRepository<User, Long> {
4+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.springframework.data.jpa.datatables.repository;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.extension.ExtendWith;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.data.jpa.datatables.Config;
7+
import org.springframework.data.jpa.datatables.mapping.DataTablesInput;
8+
import org.springframework.data.jpa.datatables.mapping.DataTablesOutput;
9+
import org.springframework.test.context.ContextConfiguration;
10+
import org.springframework.test.context.junit.jupiter.DisabledIf;
11+
import org.springframework.test.context.junit.jupiter.SpringExtension;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
15+
@ExtendWith(SpringExtension.class)
16+
@ContextConfiguration(classes = Config.class)
17+
public class UserRepositoryTest {
18+
19+
@Autowired private UserRepository userRepository;
20+
21+
private void init() {
22+
userRepository.save(new User(1L, "r"));
23+
userRepository.save(new User(2L, "ř"));
24+
userRepository.save(new User(3L, "ŗ"));
25+
userRepository.save(new User(4L, "ɍ"));
26+
userRepository.save(new User(5L, "ȓ"));
27+
}
28+
29+
@Test
30+
@DisabledIf(value = "#{'${spring.profiles.active}' == 'mysql'}", loadContext = true)
31+
void withNationalizedColumn() {
32+
init();
33+
34+
DataTablesInput input = new DataTablesInput();
35+
input.addColumn("name", true, true, "ř");
36+
37+
DataTablesOutput<User> output = userRepository.findAll(input);
38+
39+
assertThat(output.getRecordsFiltered()).isEqualTo(1);
40+
assertThat(output.getData().get(0).getId()).isEqualTo(2L);
41+
}
42+
43+
}

0 commit comments

Comments
 (0)