Skip to content

Commit 0d1ba21

Browse files
mp911deschauder
authored andcommitted
Polishing.
Reuse H2 dialect settings in R2DBC-specific H2 dialect. Refactor ArrayColumns support classes, into toplevel-types. Let R2DBC H2 sublass the relational H2Dialect to decouple from Postgres. See #1287 Original pull request #1297
1 parent c2e163b commit 0d1ba21

File tree

9 files changed

+152
-93
lines changed

9 files changed

+152
-93
lines changed

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

+2-7
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,14 @@
2323
* {@link org.springframework.data.relational.core.dialect.ArrayColumns} that offer JDBC-specific functionality.
2424
*
2525
* @author Jens Schauder
26+
* @author Mark Paluch
2627
* @since 2.3
2728
*/
2829
public interface JdbcArrayColumns extends ArrayColumns {
2930

3031
@Override
3132
default Class<?> getArrayType(Class<?> userType) {
32-
33-
Class<?> componentType = userType;
34-
while (componentType.isArray()) {
35-
componentType = componentType.getComponentType();
36-
}
37-
38-
return componentType;
33+
return ArrayColumns.unwrapComponentType(userType);
3934
}
4035

4136
/**

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcPostgresDialect.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ public JdbcArrayColumns getArraySupport() {
3838
return ARRAY_COLUMNS;
3939
}
4040

41-
static class JdbcPostgresArrayColumns extends PostgresArrayColumns implements JdbcArrayColumns {
41+
static class JdbcPostgresArrayColumns implements JdbcArrayColumns {
4242

4343
@Override
44-
public Class<?> getArrayType(Class<?> userType) {
45-
return JdbcArrayColumns.super.getArrayType(userType);
44+
public boolean isSupported() {
45+
return true;
4646
}
4747

4848
@Override
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,57 @@
1+
/*
2+
* Copyright 2019-2022 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+
*/
116
package org.springframework.data.r2dbc.dialect;
217

3-
import org.springframework.data.relational.core.dialect.AnsiDialect;
4-
import org.springframework.data.relational.core.dialect.LockClause;
18+
import org.springframework.data.relational.core.dialect.ArrayColumns;
19+
import org.springframework.data.relational.core.dialect.ObjectArrayColumns;
520
import org.springframework.data.relational.core.sql.SqlIdentifier;
21+
import org.springframework.data.util.Lazy;
22+
import org.springframework.r2dbc.core.binding.BindMarkersFactory;
623

724
/**
8-
* An SQL dialect for H2 in Postgres Compatibility mode.
25+
* R2DBC dialect for H2.
926
*
1027
* @author Mark Paluch
1128
* @author Jens Schauder
1229
* @author Diego Krupitza
1330
*/
14-
public class H2Dialect extends PostgresDialect {
31+
public class H2Dialect extends org.springframework.data.relational.core.dialect.H2Dialect implements R2dbcDialect {
1532

1633
/**
1734
* Singleton instance.
1835
*/
1936
public static final H2Dialect INSTANCE = new H2Dialect();
2037

38+
private static final BindMarkersFactory INDEXED = BindMarkersFactory.indexed("$", 1);
39+
40+
private final Lazy<ArrayColumns> arrayColumns = Lazy
41+
.of(() -> new SimpleTypeArrayColumns(ObjectArrayColumns.INSTANCE, getSimpleTypeHolder()));
42+
43+
@Override
44+
public BindMarkersFactory getBindMarkersFactory() {
45+
return INDEXED;
46+
}
47+
2148
@Override
2249
public String renderForGeneratedValues(SqlIdentifier identifier) {
2350
return identifier.getReference(getIdentifierProcessing());
2451
}
2552

2653
@Override
27-
public LockClause lock() {
28-
// H2 Dialect does not support the same lock keywords as PostgreSQL, but it supports the ANSI SQL standard.
29-
// see https://www.h2database.com/html/commands.html
30-
// and https://www.h2database.com/html/features.html#compatibility
31-
return AnsiDialect.INSTANCE.lock();
54+
public ArrayColumns getArraySupport() {
55+
return this.arrayColumns.get();
3256
}
33-
3457
}

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

+3-35
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
import org.springframework.data.geo.Circle;
2525
import org.springframework.data.geo.Point;
2626
import org.springframework.data.geo.Polygon;
27-
import org.springframework.data.mapping.model.SimpleTypeHolder;
2827
import org.springframework.data.relational.core.dialect.ArrayColumns;
28+
import org.springframework.data.relational.core.dialect.ObjectArrayColumns;
2929
import org.springframework.data.util.Lazy;
3030
import org.springframework.lang.NonNull;
3131
import org.springframework.r2dbc.core.binding.BindMarkersFactory;
@@ -79,9 +79,8 @@ public class PostgresDialect extends org.springframework.data.relational.core.di
7979

8080
private static final BindMarkersFactory INDEXED = BindMarkersFactory.indexed("$", 1);
8181

82-
private final Lazy<ArrayColumns> arrayColumns = Lazy.of(() -> new R2dbcArrayColumns(
83-
org.springframework.data.relational.core.dialect.PostgresDialect.INSTANCE.getArraySupport(),
84-
getSimpleTypeHolder()));
82+
private final Lazy<ArrayColumns> arrayColumns = Lazy
83+
.of(() -> new SimpleTypeArrayColumns(ObjectArrayColumns.INSTANCE, getSimpleTypeHolder()));
8584

8685
/*
8786
* (non-Javadoc)
@@ -137,37 +136,6 @@ public Collection<Object> getConverters() {
137136
return converters;
138137
}
139138

140-
private static class R2dbcArrayColumns implements ArrayColumns {
141-
142-
private final ArrayColumns delegate;
143-
private final SimpleTypeHolder simpleTypeHolder;
144-
145-
R2dbcArrayColumns(ArrayColumns delegate, SimpleTypeHolder simpleTypeHolder) {
146-
this.delegate = delegate;
147-
this.simpleTypeHolder = simpleTypeHolder;
148-
}
149-
150-
@Override
151-
public boolean isSupported() {
152-
return this.delegate.isSupported();
153-
}
154-
155-
@Override
156-
public Class<?> getArrayType(Class<?> userType) {
157-
158-
Class<?> typeToUse = userType;
159-
while (typeToUse.getComponentType() != null) {
160-
typeToUse = typeToUse.getComponentType();
161-
}
162-
163-
if (!this.simpleTypeHolder.isSimpleType(typeToUse)) {
164-
throw new IllegalArgumentException("Unsupported array type: " + ClassUtils.getQualifiedName(typeToUse));
165-
}
166-
167-
return this.delegate.getArrayType(typeToUse);
168-
}
169-
}
170-
171139
/**
172140
* If the class is present on the class path, invoke the specified consumer {@code action} with the class object,
173141
* otherwise do nothing.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2022 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.r2dbc.dialect;
17+
18+
import org.springframework.data.mapping.model.SimpleTypeHolder;
19+
import org.springframework.data.relational.core.dialect.ArrayColumns;
20+
import org.springframework.util.ClassUtils;
21+
22+
/**
23+
* {@link ArrayColumns} support based on {@link SimpleTypeHolder store-native simple types}.
24+
*
25+
* @author Mark Paluch
26+
* @since 3.0
27+
*/
28+
record SimpleTypeArrayColumns(ArrayColumns delegate, SimpleTypeHolder simpleTypeHolder) implements ArrayColumns {
29+
30+
@Override
31+
public boolean isSupported() {
32+
return this.delegate.isSupported();
33+
}
34+
35+
@Override
36+
public Class<?> getArrayType(Class<?> userType) {
37+
38+
Class<?> typeToUse = ArrayColumns.unwrapComponentType(userType);
39+
40+
if (!this.simpleTypeHolder.isSimpleType(typeToUse)) {
41+
throw new IllegalArgumentException(
42+
"Unsupported array type: %s".formatted(ClassUtils.getQualifiedName(typeToUse)));
43+
}
44+
45+
return this.delegate.getArrayType(typeToUse);
46+
}
47+
}

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

+1-19
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
import org.springframework.data.relational.core.sql.IdentifierProcessing;
1919
import org.springframework.data.relational.core.sql.LockOptions;
20-
import org.springframework.util.Assert;
21-
import org.springframework.util.ClassUtils;
2220

2321
/**
2422
* An SQL dialect for the ANSI SQL standard.
@@ -72,7 +70,7 @@ public Position getClausePosition() {
7270
}
7371
};
7472

75-
private final AnsiArrayColumns ARRAY_COLUMNS = new AnsiArrayColumns();
73+
private final ArrayColumns ARRAY_COLUMNS = ObjectArrayColumns.INSTANCE;
7674

7775
@Override
7876
public LimitClause limit() {
@@ -89,22 +87,6 @@ public ArrayColumns getArraySupport() {
8987
return ARRAY_COLUMNS;
9088
}
9189

92-
static class AnsiArrayColumns implements ArrayColumns {
93-
94-
@Override
95-
public boolean isSupported() {
96-
return true;
97-
}
98-
99-
@Override
100-
public Class<?> getArrayType(Class<?> userType) {
101-
102-
Assert.notNull(userType, "Array component type must not be null");
103-
104-
return ClassUtils.resolvePrimitiveIfNecessary(userType);
105-
}
106-
}
107-
10890
@Override
10991
public IdentifierProcessing getIdentifierProcessing() {
11092
return IdentifierProcessing.ANSI;

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

+17
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,21 @@ public Class<?> getArrayType(Class<?> userType) {
5858
throw new UnsupportedOperationException("Array types not supported");
5959
}
6060
}
61+
62+
/**
63+
* Unwrap the nested {@link Class#getComponentType()} from a given {@link Class}.
64+
*
65+
* @param clazz the type to inspect.
66+
* @return the unwrapped component type.
67+
* @since 3.0
68+
*/
69+
static Class<?> unwrapComponentType(Class<?> clazz) {
70+
71+
Class<?> componentType = clazz;
72+
while (componentType.isArray()) {
73+
componentType = componentType.getComponentType();
74+
}
75+
76+
return componentType;
77+
}
6178
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2022 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.relational.core.dialect;
17+
18+
import org.springframework.util.Assert;
19+
import org.springframework.util.ClassUtils;
20+
21+
/**
22+
* {@link ArrayColumns} support using the actual object type or {@link Class#isPrimitive() boxed primitives} Java types.
23+
*
24+
* @author Mark Paluch
25+
* @since 3.0
26+
* @see ClassUtils#resolvePrimitiveIfNecessary
27+
*/
28+
public class ObjectArrayColumns implements ArrayColumns {
29+
30+
public static final ObjectArrayColumns INSTANCE = new ObjectArrayColumns();
31+
32+
@Override
33+
public boolean isSupported() {
34+
return true;
35+
}
36+
37+
@Override
38+
public Class<?> getArrayType(Class<?> userType) {
39+
40+
Assert.notNull(userType, "Array component type must not be null");
41+
42+
return ClassUtils.resolvePrimitiveIfNecessary(ArrayColumns.unwrapComponentType(userType));
43+
}
44+
}

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

+2-19
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.springframework.data.relational.core.sql.SimpleFunction;
3333
import org.springframework.data.relational.core.sql.SqlIdentifier;
3434
import org.springframework.data.relational.core.sql.TableLike;
35-
import org.springframework.util.Assert;
3635
import org.springframework.util.ClassUtils;
3736

3837
/**
@@ -76,7 +75,7 @@ public Position getClausePosition() {
7675
}
7776
};
7877

79-
private final PostgresArrayColumns ARRAY_COLUMNS = new PostgresArrayColumns();
78+
private static final ObjectArrayColumns ARRAY_COLUMNS = ObjectArrayColumns.INSTANCE;
8079

8180
@Override
8281
public LimitClause limit() {
@@ -146,22 +145,6 @@ public Position getClausePosition() {
146145
}
147146
}
148147

149-
protected static class PostgresArrayColumns implements ArrayColumns {
150-
151-
@Override
152-
public boolean isSupported() {
153-
return true;
154-
}
155-
156-
@Override
157-
public Class<?> getArrayType(Class<?> userType) {
158-
159-
Assert.notNull(userType, "Array component type must not be null");
160-
161-
return ClassUtils.resolvePrimitiveIfNecessary(userType);
162-
}
163-
}
164-
165148
@Override
166149
public IdentifierProcessing getIdentifierProcessing() {
167150
return IdentifierProcessing.create(Quoting.ANSI, LetterCasing.LOWER_CASE);
@@ -179,7 +162,7 @@ public Set<Class<?>> simpleTypes() {
179162
"org.postgresql.geometric.PGline", //
180163
"org.postgresql.geometric.PGpath", //
181164
"org.postgresql.geometric.PGpolygon", //
182-
"org.postgresql.geometric.PGlseg" //
165+
"org.postgresql.geometric.PGlseg" //
183166
);
184167
simpleTypeNames.forEach(name -> ifClassPresent(name, simpleTypes::add));
185168
return Collections.unmodifiableSet(simpleTypes);

0 commit comments

Comments
 (0)