Skip to content
Closed
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.4.0-821-support-sort-null-handling-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data Relational Parent</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-jdbc-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.4.0-821-support-sort-null-handling-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-jdbc</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.4.0-821-support-sort-null-handling-SNAPSHOT</version>

<name>Spring Data JDBC</name>
<description>Spring Data module for JDBC repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.4.0-821-support-sort-null-handling-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2021 the original author or authors.
* Copyright 2017-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.
Expand Down Expand Up @@ -51,6 +51,7 @@
* @author Milan Milanov
* @author Myeonghyeon Lee
* @author Mikhail Polivakha
* @author Chirag Tailor
*/
class SqlGenerator {

Expand Down Expand Up @@ -714,7 +715,7 @@ private OrderByField orderToOrderByField(Sort.Order order) {

SqlIdentifier columnName = this.entity.getRequiredPersistentProperty(order.getProperty()).getColumnName();
Column column = Column.create(columnName, this.getTable());
return OrderByField.from(column, order.getDirection());
return OrderByField.from(column, order.getDirection()).withNullHandling(order.getNullHandling());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,21 @@ void saveAndLoadManyEntitiesWithReferencedEntitySortedAndPaged() {
.containsExactly("Star");
}

@Test // GH-821
@EnabledOnFeature({SUPPORTS_QUOTED_IDS, SUPPORTS_NULL_HANDLING})
void saveAndLoadManyEntitiesWithReferencedEntitySortedWithNullHandling() {

template.save(createLegoSet(null));
template.save(createLegoSet("Star"));
template.save(createLegoSet("Frozen"));

Iterable<LegoSet> reloadedLegoSets = template.findAll(LegoSet.class, Sort.by(new Sort.Order(Sort.Direction.ASC, "name", Sort.NullHandling.NULLS_LAST)));

assertThat(reloadedLegoSets) //
.extracting("name") //
.containsExactly("Frozen", "Star", null);
}

@Test // DATAJDBC-112
@EnabledOnFeature(SUPPORTS_QUOTED_IDS)
void saveAndLoadManyEntitiesByIdWithReferencedEntity() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2021 the original author or authors.
* Copyright 2017-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.
Expand All @@ -25,7 +25,6 @@

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Version;
Expand Down Expand Up @@ -64,6 +63,7 @@
* @author Milan Milanov
* @author Myeonghyeon Lee
* @author Mikhail Polivakha
* @author Chirag Tailor
*/
class SqlGeneratorUnitTests {

Expand Down Expand Up @@ -245,6 +245,26 @@ void findAllSortedByMultipleFields() {
"x_other ASC");
}

@Test // GH-821
void findAllSortedWithNullHandling_resolvesNullHandlingWhenDialectSupportsIt() {

SqlGenerator sqlGenerator = createSqlGenerator(DummyEntity.class, PostgresDialect.INSTANCE);

String sql = sqlGenerator.getFindAll(Sort.by(new Sort.Order(Sort.Direction.ASC, "name", Sort.NullHandling.NULLS_LAST)));

assertThat(sql).contains("ORDER BY \"dummy_entity\".\"x_name\" ASC NULLS LAST");
}

@Test // GH-821
void findAllSortedWithNullHandling_ignoresNullHandlingWhenDialectDoesNotSupportIt() {

SqlGenerator sqlGenerator = createSqlGenerator(DummyEntity.class, SqlServerDialect.INSTANCE);

String sql = sqlGenerator.getFindAll(Sort.by(new Sort.Order(Sort.Direction.ASC, "name", Sort.NullHandling.NULLS_LAST)));

assertThat(sql).endsWith("ORDER BY dummy_entity.x_name ASC");
}

@Test // DATAJDBC-101
void findAllPagedByUnpaged() {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-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.
Expand Down Expand Up @@ -29,6 +29,7 @@
* presence or absence of features in tests.
*
* @author Jens Schauder
* @author Chirag Tailor
*/
public class TestDatabaseFeatures {

Expand Down Expand Up @@ -83,6 +84,10 @@ private void supportsMultiDimensionalArrays() {
assumeThat(database).isNotIn(Database.H2, Database.Hsql);
}

private void supportsNullHandling() {
assumeThat(database).isNotIn(Database.MySql, Database.MariaDb, Database.SqlServer);
}

public void databaseIs(Database database) {
assumeThat(this.database).isEqualTo(database);
}
Expand Down Expand Up @@ -115,6 +120,7 @@ public enum Feature {
SUPPORTS_ARRAYS(TestDatabaseFeatures::supportsArrays), //
SUPPORTS_GENERATED_IDS_IN_REFERENCED_ENTITIES(TestDatabaseFeatures::supportsGeneratedIdsInReferencedEntities), //
SUPPORTS_NANOSECOND_PRECISION(TestDatabaseFeatures::supportsNanosecondPrecision), //
SUPPORTS_NULL_HANDLING(TestDatabaseFeatures::supportsNullHandling),
IS_POSTGRES(f -> f.databaseIs(Database.PostgreSql)), //
IS_HSQL(f -> f.databaseIs(Database.Hsql));

Expand Down
4 changes: 2 additions & 2 deletions spring-data-relational/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-relational</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.4.0-821-support-sort-null-handling-SNAPSHOT</version>

<name>Spring Data Relational</name>
<description>Spring Data Relational support</description>

<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>2.4.0-821-support-sort-null-handling-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* 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.
Expand All @@ -18,6 +18,7 @@
import java.util.OptionalLong;
import java.util.function.Function;

import org.springframework.data.domain.Sort;
import org.springframework.data.relational.core.sql.LockMode;
import org.springframework.data.relational.core.sql.LockOptions;
import org.springframework.data.relational.core.sql.Select;
Expand All @@ -28,6 +29,7 @@
*
* @author Mark Paluch
* @author Myeonghyeon Lee
* @author Chirag Tailor
* @since 1.1
*/
public abstract class AbstractDialect implements Dialect {
Expand All @@ -42,7 +44,7 @@ public SelectRenderContext getSelectContext() {
Function<Select, ? extends CharSequence> afterFromTable = getAfterFromTable();
Function<Select, ? extends CharSequence> afterOrderBy = getAfterOrderBy();

return new DialectSelectRenderContext(afterFromTable, afterOrderBy);
return new DialectSelectRenderContext(afterFromTable, afterOrderBy, orderByNullHandling());
}

/**
Expand Down Expand Up @@ -105,12 +107,14 @@ static class DialectSelectRenderContext implements SelectRenderContext {

private final Function<Select, ? extends CharSequence> afterFromTable;
private final Function<Select, ? extends CharSequence> afterOrderBy;
private final OrderByNullHandling orderByNullHandling;

DialectSelectRenderContext(Function<Select, ? extends CharSequence> afterFromTable,
Function<Select, ? extends CharSequence> afterOrderBy) {
Function<Select, ? extends CharSequence> afterOrderBy, OrderByNullHandling orderByNullHandling) {

this.afterFromTable = afterFromTable;
this.afterOrderBy = afterOrderBy;
this.orderByNullHandling = orderByNullHandling;
}

/*
Expand All @@ -130,6 +134,11 @@ static class DialectSelectRenderContext implements SelectRenderContext {
public Function<Select, ? extends CharSequence> afterOrderBy(boolean hasOrderBy) {
return afterOrderBy;
}

@Override
public String evaluateOrderByNullHandling(Sort.NullHandling nullHandling) {
return orderByNullHandling.evaluate(nullHandling);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-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.
Expand All @@ -25,6 +25,7 @@
* An SQL dialect for DB2.
*
* @author Jens Schauder
* @author Chirag Tailor
* @since 2.0
*/
public class Db2Dialect extends AbstractDialect {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* 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.
Expand Down Expand Up @@ -33,6 +33,7 @@
* @author Myeonghyeon Lee
* @author Christoph Strobl
* @author Mikhail Polivakha
* @author Chirag Tailor
* @since 1.1
*/
public interface Dialect {
Expand Down Expand Up @@ -120,4 +121,13 @@ default Set<Class<?>> simpleTypes() {
default InsertRenderContext getInsertRenderContext() {
return InsertRenderContexts.DEFAULT;
}

/**
* Return the {@link OrderByNullHandling} used by this dialect.
*
* @return the {@link OrderByNullHandling} used by this dialect.
*/
default OrderByNullHandling orderByNullHandling() {
return OrderByNullHandling.SQL_STANDARD;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* 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.
Expand Down Expand Up @@ -30,6 +30,7 @@
* @author Mark Paluch
* @author Myeonghyeon Lee
* @author Christph Strobl
* @author Chirag Tailor
* @since 2.0
*/
public class H2Dialect extends AbstractDialect {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* 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.
Expand All @@ -20,6 +20,7 @@
*
* @author Jens Schauder
* @author Myeonghyeon Lee
* @author Chirag Tailor
*/
public class HsqlDbDialect extends AbstractDialect {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,9 @@ public IdentifierProcessing getIdentifierProcessing() {
public Collection<Object> getConverters() {
return Collections.singletonList(TimestampAtUtcToOffsetDateTimeConverter.INSTANCE);
}

@Override
public OrderByNullHandling orderByNullHandling() {
return OrderByNullHandling.NONE;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* 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.
Expand All @@ -20,14 +20,14 @@
import org.springframework.data.convert.WritingConverter;

import java.util.Collection;
import java.util.Collections;

import static java.util.Arrays.*;

/**
* An SQL dialect for Oracle.
*
* @author Jens Schauder
* @author Chirag Tailor
* @since 2.1
*/
public class OracleDialect extends AnsiDialect {
Expand Down
Loading