Polishing.
Correctly assign SQL type for tuples. See #1323 Original pull request: #1838
This commit is contained in:
@@ -19,7 +19,6 @@ import static org.springframework.data.jdbc.repository.query.JdbcQueryExecution.
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.sql.JDBCType;
|
||||
import java.sql.SQLType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -31,8 +30,10 @@ import java.util.function.Supplier;
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcColumnTypes;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcValue;
|
||||
import org.springframework.data.jdbc.support.JdbcUtil;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
|
||||
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
|
||||
@@ -223,7 +224,7 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
if (actualType != null && actualType.getType().isArray()) {
|
||||
|
||||
TypeInformation<?> nestedElementType = actualType.getRequiredActualType();
|
||||
return writeCollection(collection, JDBCType.OTHER,
|
||||
return writeCollection(collection, parameter.getActualSqlType(),
|
||||
array -> writeArrayValue(parameter, array, nestedElementType));
|
||||
}
|
||||
|
||||
@@ -265,21 +266,29 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
return jdbcValue;
|
||||
}
|
||||
|
||||
private Object[] writeArrayValue(JdbcParameters.JdbcParameter parameter, Object array,
|
||||
private JdbcValue writeArrayValue(JdbcParameters.JdbcParameter parameter, Object array,
|
||||
TypeInformation<?> nestedElementType) {
|
||||
|
||||
int length = Array.getLength(array);
|
||||
Object[] mappedArray = new Object[length];
|
||||
SQLType sqlType = null;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
||||
Object element = Array.get(array, i);
|
||||
JdbcValue elementJdbcValue = converter.writeJdbcValue(element, nestedElementType, parameter.getActualSqlType());
|
||||
JdbcValue converted = converter.writeJdbcValue(element, nestedElementType, parameter.getActualSqlType());
|
||||
|
||||
mappedArray[i] = elementJdbcValue.getValue();
|
||||
if (sqlType == null && converted.getJdbcType() != null) {
|
||||
sqlType = converted.getJdbcType();
|
||||
}
|
||||
mappedArray[i] = converted.getValue();
|
||||
}
|
||||
|
||||
return mappedArray;
|
||||
if (sqlType == null) {
|
||||
sqlType = JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(nestedElementType.getType()));
|
||||
}
|
||||
|
||||
return JdbcValue.of(mappedArray, sqlType);
|
||||
}
|
||||
|
||||
RowMapper<Object> determineRowMapper(ResultProcessor resultProcessor, boolean hasDynamicProjection) {
|
||||
|
||||
@@ -22,13 +22,11 @@ import java.sql.JDBCType;
|
||||
import java.sql.SQLType;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -54,7 +52,12 @@ public final class JdbcUtil {
|
||||
public Integer getVendorTypeNumber() {
|
||||
return JdbcUtils.TYPE_UNKNOWN;
|
||||
}
|
||||
} ;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
};
|
||||
private static final Map<Class<?>, SQLType> sqlTypeMappings = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -66,6 +67,7 @@ import org.springframework.data.jdbc.repository.query.Query;
|
||||
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
|
||||
import org.springframework.data.jdbc.testing.ConditionalOnDatabase;
|
||||
import org.springframework.data.jdbc.testing.DatabaseType;
|
||||
import org.springframework.data.jdbc.testing.EnabledOnDatabase;
|
||||
import org.springframework.data.jdbc.testing.EnabledOnFeature;
|
||||
import org.springframework.data.jdbc.testing.IntegrationTest;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
@@ -107,6 +109,7 @@ import org.springframework.test.jdbc.JdbcTestUtils;
|
||||
* @author Paul Jones
|
||||
*/
|
||||
@IntegrationTest
|
||||
@EnabledOnDatabase(DatabaseType.MARIADB)
|
||||
public class JdbcRepositoryIntegrationTests {
|
||||
|
||||
@Autowired NamedParameterJdbcTemplate template;
|
||||
@@ -1339,15 +1342,15 @@ public class JdbcRepositoryIntegrationTests {
|
||||
}
|
||||
|
||||
@Test // GH-1323
|
||||
@EnabledOnFeature(TestDatabaseFeatures.Feature.WHERE_IN_TUPLE)
|
||||
void queryWithTupleIn() {
|
||||
|
||||
DummyEntity one = repository.save(createDummyEntity("one"));
|
||||
DummyEntity two = repository.save(createDummyEntity( "two"));
|
||||
DummyEntity three = repository.save(createDummyEntity( "three"));
|
||||
DummyEntity two = repository.save(createDummyEntity("two"));
|
||||
DummyEntity three = repository.save(createDummyEntity("three"));
|
||||
|
||||
List<Object[]> tuples = List.of(
|
||||
new Object[]{two.idProp, "two"}, // matches "two"
|
||||
new Object[]{three.idProp, "two"} // matches nothing
|
||||
List<Object[]> tuples = List.of(new Object[] { two.idProp, "two" }, // matches "two"
|
||||
new Object[] { three.idProp, "two" } // matches nothing
|
||||
);
|
||||
|
||||
List<DummyEntity> result = repository.findByListInTuple(tuples);
|
||||
@@ -1887,6 +1890,11 @@ public class JdbcRepositoryIntegrationTests {
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, pointInTime, offsetDateTime, idProp, flag, ref, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DummyEntity{" + "name='" + name + '\'' + ", idProp=" + idProp + '}';
|
||||
}
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.data.jdbc.core.convert.JdbcTypeFactory;
|
||||
import org.springframework.data.jdbc.core.convert.MappingJdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.RelationResolver;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcValue;
|
||||
import org.springframework.data.jdbc.support.JdbcUtil;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.repository.Repository;
|
||||
@@ -338,6 +339,8 @@ class StringBasedJdbcQueryUnitTests {
|
||||
assertThat(parameterSource.getValue("tuples"))
|
||||
.asInstanceOf(LIST)
|
||||
.containsExactly(tuples);
|
||||
|
||||
assertThat(parameterSource.getSqlType("tuples")).isEqualTo(JdbcUtil.TYPE_UNKNOWN.getVendorTypeNumber());
|
||||
}
|
||||
|
||||
@Test // GH-1323
|
||||
|
||||
@@ -79,6 +79,10 @@ public class TestDatabaseFeatures {
|
||||
assumeThat(database).isNotIn(Database.MySql, Database.MariaDb, Database.SqlServer);
|
||||
}
|
||||
|
||||
private void supportsWhereInTuples() {
|
||||
assumeThat(database).isIn(Database.MySql, Database.PostgreSql);
|
||||
}
|
||||
|
||||
public void databaseIs(Database database) {
|
||||
assumeThat(this.database).isEqualTo(database);
|
||||
}
|
||||
@@ -112,6 +116,7 @@ public class TestDatabaseFeatures {
|
||||
SUPPORTS_NANOSECOND_PRECISION(TestDatabaseFeatures::supportsNanosecondPrecision), //
|
||||
SUPPORTS_NULL_PRECEDENCE(TestDatabaseFeatures::supportsNullPrecedence),
|
||||
IS_POSTGRES(f -> f.databaseIs(Database.PostgreSql)), //
|
||||
WHERE_IN_TUPLE(TestDatabaseFeatures::supportsWhereInTuples), //
|
||||
IS_HSQL(f -> f.databaseIs(Database.Hsql));
|
||||
|
||||
private final Consumer<TestDatabaseFeatures> featureMethod;
|
||||
|
||||
Reference in New Issue
Block a user