Browse Source

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
pull/1304/head
Mark Paluch 3 years ago committed by Jens Schauder
parent
commit
0d1ba211c5
No known key found for this signature in database
GPG Key ID: 45CC872F17423DBF
  1. 9
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcArrayColumns.java
  2. 6
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcPostgresDialect.java
  3. 43
      spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/dialect/H2Dialect.java
  4. 38
      spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/dialect/PostgresDialect.java
  5. 47
      spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/dialect/SimpleTypeArrayColumns.java
  6. 20
      spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/AnsiDialect.java
  7. 17
      spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/ArrayColumns.java
  8. 44
      spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/ObjectArrayColumns.java
  9. 21
      spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java

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

@ -23,19 +23,14 @@ import org.springframework.data.relational.core.dialect.ArrayColumns; @@ -23,19 +23,14 @@ import org.springframework.data.relational.core.dialect.ArrayColumns;
* {@link org.springframework.data.relational.core.dialect.ArrayColumns} that offer JDBC-specific functionality.
*
* @author Jens Schauder
* @author Mark Paluch
* @since 2.3
*/
public interface JdbcArrayColumns extends ArrayColumns {
@Override
default Class<?> getArrayType(Class<?> userType) {
Class<?> componentType = userType;
while (componentType.isArray()) {
componentType = componentType.getComponentType();
}
return componentType;
return ArrayColumns.unwrapComponentType(userType);
}
/**

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

@ -38,11 +38,11 @@ public class JdbcPostgresDialect extends PostgresDialect implements JdbcDialect @@ -38,11 +38,11 @@ public class JdbcPostgresDialect extends PostgresDialect implements JdbcDialect
return ARRAY_COLUMNS;
}
static class JdbcPostgresArrayColumns extends PostgresArrayColumns implements JdbcArrayColumns {
static class JdbcPostgresArrayColumns implements JdbcArrayColumns {
@Override
public Class<?> getArrayType(Class<?> userType) {
return JdbcArrayColumns.super.getArrayType(userType);
public boolean isSupported() {
return true;
}
@Override

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

@ -1,34 +1,57 @@ @@ -1,34 +1,57 @@
/*
* Copyright 2019-2022 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.r2dbc.dialect;
import org.springframework.data.relational.core.dialect.AnsiDialect;
import org.springframework.data.relational.core.dialect.LockClause;
import org.springframework.data.relational.core.dialect.ArrayColumns;
import org.springframework.data.relational.core.dialect.ObjectArrayColumns;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.Lazy;
import org.springframework.r2dbc.core.binding.BindMarkersFactory;
/**
* An SQL dialect for H2 in Postgres Compatibility mode.
* R2DBC dialect for H2.
*
* @author Mark Paluch
* @author Jens Schauder
* @author Diego Krupitza
*/
public class H2Dialect extends PostgresDialect {
public class H2Dialect extends org.springframework.data.relational.core.dialect.H2Dialect implements R2dbcDialect {
/**
* Singleton instance.
*/
public static final H2Dialect INSTANCE = new H2Dialect();
private static final BindMarkersFactory INDEXED = BindMarkersFactory.indexed("$", 1);
private final Lazy<ArrayColumns> arrayColumns = Lazy
.of(() -> new SimpleTypeArrayColumns(ObjectArrayColumns.INSTANCE, getSimpleTypeHolder()));
@Override
public BindMarkersFactory getBindMarkersFactory() {
return INDEXED;
}
@Override
public String renderForGeneratedValues(SqlIdentifier identifier) {
return identifier.getReference(getIdentifierProcessing());
}
@Override
public LockClause lock() {
// H2 Dialect does not support the same lock keywords as PostgreSQL, but it supports the ANSI SQL standard.
// see https://www.h2database.com/html/commands.html
// and https://www.h2database.com/html/features.html#compatibility
return AnsiDialect.INSTANCE.lock();
public ArrayColumns getArraySupport() {
return this.arrayColumns.get();
}
}

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

@ -24,8 +24,8 @@ import org.springframework.data.geo.Box; @@ -24,8 +24,8 @@ import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.relational.core.dialect.ArrayColumns;
import org.springframework.data.relational.core.dialect.ObjectArrayColumns;
import org.springframework.data.util.Lazy;
import org.springframework.lang.NonNull;
import org.springframework.r2dbc.core.binding.BindMarkersFactory;
@ -79,9 +79,8 @@ public class PostgresDialect extends org.springframework.data.relational.core.di @@ -79,9 +79,8 @@ public class PostgresDialect extends org.springframework.data.relational.core.di
private static final BindMarkersFactory INDEXED = BindMarkersFactory.indexed("$", 1);
private final Lazy<ArrayColumns> arrayColumns = Lazy.of(() -> new R2dbcArrayColumns(
org.springframework.data.relational.core.dialect.PostgresDialect.INSTANCE.getArraySupport(),
getSimpleTypeHolder()));
private final Lazy<ArrayColumns> arrayColumns = Lazy
.of(() -> new SimpleTypeArrayColumns(ObjectArrayColumns.INSTANCE, getSimpleTypeHolder()));
/*
* (non-Javadoc)
@ -137,37 +136,6 @@ public class PostgresDialect extends org.springframework.data.relational.core.di @@ -137,37 +136,6 @@ public class PostgresDialect extends org.springframework.data.relational.core.di
return converters;
}
private static class R2dbcArrayColumns implements ArrayColumns {
private final ArrayColumns delegate;
private final SimpleTypeHolder simpleTypeHolder;
R2dbcArrayColumns(ArrayColumns delegate, SimpleTypeHolder simpleTypeHolder) {
this.delegate = delegate;
this.simpleTypeHolder = simpleTypeHolder;
}
@Override
public boolean isSupported() {
return this.delegate.isSupported();
}
@Override
public Class<?> getArrayType(Class<?> userType) {
Class<?> typeToUse = userType;
while (typeToUse.getComponentType() != null) {
typeToUse = typeToUse.getComponentType();
}
if (!this.simpleTypeHolder.isSimpleType(typeToUse)) {
throw new IllegalArgumentException("Unsupported array type: " + ClassUtils.getQualifiedName(typeToUse));
}
return this.delegate.getArrayType(typeToUse);
}
}
/**
* If the class is present on the class path, invoke the specified consumer {@code action} with the class object,
* otherwise do nothing.

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

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
/*
* Copyright 2022 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.r2dbc.dialect;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.relational.core.dialect.ArrayColumns;
import org.springframework.util.ClassUtils;
/**
* {@link ArrayColumns} support based on {@link SimpleTypeHolder store-native simple types}.
*
* @author Mark Paluch
* @since 3.0
*/
record SimpleTypeArrayColumns(ArrayColumns delegate, SimpleTypeHolder simpleTypeHolder) implements ArrayColumns {
@Override
public boolean isSupported() {
return this.delegate.isSupported();
}
@Override
public Class<?> getArrayType(Class<?> userType) {
Class<?> typeToUse = ArrayColumns.unwrapComponentType(userType);
if (!this.simpleTypeHolder.isSimpleType(typeToUse)) {
throw new IllegalArgumentException(
"Unsupported array type: %s".formatted(ClassUtils.getQualifiedName(typeToUse)));
}
return this.delegate.getArrayType(typeToUse);
}
}

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

@ -17,8 +17,6 @@ package org.springframework.data.relational.core.dialect; @@ -17,8 +17,6 @@ package org.springframework.data.relational.core.dialect;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.LockOptions;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* An SQL dialect for the ANSI SQL standard.
@ -72,7 +70,7 @@ public class AnsiDialect extends AbstractDialect { @@ -72,7 +70,7 @@ public class AnsiDialect extends AbstractDialect {
}
};
private final AnsiArrayColumns ARRAY_COLUMNS = new AnsiArrayColumns();
private final ArrayColumns ARRAY_COLUMNS = ObjectArrayColumns.INSTANCE;
@Override
public LimitClause limit() {
@ -89,22 +87,6 @@ public class AnsiDialect extends AbstractDialect { @@ -89,22 +87,6 @@ public class AnsiDialect extends AbstractDialect {
return ARRAY_COLUMNS;
}
static class AnsiArrayColumns implements ArrayColumns {
@Override
public boolean isSupported() {
return true;
}
@Override
public Class<?> getArrayType(Class<?> userType) {
Assert.notNull(userType, "Array component type must not be null");
return ClassUtils.resolvePrimitiveIfNecessary(userType);
}
}
@Override
public IdentifierProcessing getIdentifierProcessing() {
return IdentifierProcessing.ANSI;

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

@ -58,4 +58,21 @@ public interface ArrayColumns { @@ -58,4 +58,21 @@ public interface ArrayColumns {
throw new UnsupportedOperationException("Array types not supported");
}
}
/**
* Unwrap the nested {@link Class#getComponentType()} from a given {@link Class}.
*
* @param clazz the type to inspect.
* @return the unwrapped component type.
* @since 3.0
*/
static Class<?> unwrapComponentType(Class<?> clazz) {
Class<?> componentType = clazz;
while (componentType.isArray()) {
componentType = componentType.getComponentType();
}
return componentType;
}
}

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

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
/*
* Copyright 2022 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.relational.core.dialect;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link ArrayColumns} support using the actual object type or {@link Class#isPrimitive() boxed primitives} Java types.
*
* @author Mark Paluch
* @since 3.0
* @see ClassUtils#resolvePrimitiveIfNecessary
*/
public class ObjectArrayColumns implements ArrayColumns {
public static final ObjectArrayColumns INSTANCE = new ObjectArrayColumns();
@Override
public boolean isSupported() {
return true;
}
@Override
public Class<?> getArrayType(Class<?> userType) {
Assert.notNull(userType, "Array component type must not be null");
return ClassUtils.resolvePrimitiveIfNecessary(ArrayColumns.unwrapComponentType(userType));
}
}

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

@ -32,7 +32,6 @@ import org.springframework.data.relational.core.sql.SQL; @@ -32,7 +32,6 @@ import org.springframework.data.relational.core.sql.SQL;
import org.springframework.data.relational.core.sql.SimpleFunction;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.core.sql.TableLike;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@ -76,7 +75,7 @@ public class PostgresDialect extends AbstractDialect { @@ -76,7 +75,7 @@ public class PostgresDialect extends AbstractDialect {
}
};
private final PostgresArrayColumns ARRAY_COLUMNS = new PostgresArrayColumns();
private static final ObjectArrayColumns ARRAY_COLUMNS = ObjectArrayColumns.INSTANCE;
@Override
public LimitClause limit() {
@ -146,22 +145,6 @@ public class PostgresDialect extends AbstractDialect { @@ -146,22 +145,6 @@ public class PostgresDialect extends AbstractDialect {
}
}
protected static class PostgresArrayColumns implements ArrayColumns {
@Override
public boolean isSupported() {
return true;
}
@Override
public Class<?> getArrayType(Class<?> userType) {
Assert.notNull(userType, "Array component type must not be null");
return ClassUtils.resolvePrimitiveIfNecessary(userType);
}
}
@Override
public IdentifierProcessing getIdentifierProcessing() {
return IdentifierProcessing.create(Quoting.ANSI, LetterCasing.LOWER_CASE);
@ -179,7 +162,7 @@ public class PostgresDialect extends AbstractDialect { @@ -179,7 +162,7 @@ public class PostgresDialect extends AbstractDialect {
"org.postgresql.geometric.PGline", //
"org.postgresql.geometric.PGpath", //
"org.postgresql.geometric.PGpolygon", //
"org.postgresql.geometric.PGlseg" //
"org.postgresql.geometric.PGlseg" //
);
simpleTypeNames.forEach(name -> ifClassPresent(name, simpleTypes::add));
return Collections.unmodifiableSet(simpleTypes);

Loading…
Cancel
Save