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
This commit is contained in:
committed by
Jens Schauder
parent
c2e163b5c2
commit
0d1ba211c5
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
};
|
||||
|
||||
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 {
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
};
|
||||
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
"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);
|
||||
|
||||
Reference in New Issue
Block a user