From eb1ea5ddd2f5d358a56cbcf9d1384fbbfde2fada Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Wed, 26 Sep 2018 10:57:33 +0200 Subject: [PATCH] NEW: collation support for orderBy (#1492) --- src/main/java/io/ebean/OrderBy.java | 63 +++++++++++++++++-- .../tests/unitinternal/TestOrderByParse.java | 47 ++++++++++++++ 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/ebean/OrderBy.java b/src/main/java/io/ebean/OrderBy.java index e9f68f6f5..438396109 100644 --- a/src/main/java/io/ebean/OrderBy.java +++ b/src/main/java/io/ebean/OrderBy.java @@ -5,6 +5,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import io.ebean.util.StringHelper; + /** * Represents an Order By for a Query. *

@@ -74,6 +76,15 @@ public final class OrderBy implements Serializable { return query; } + /** + * Add a property with ascending order to this OrderBy. + */ + public Query asc(String propertyName, String collation) { + + list.add(new Property(propertyName, true, collation)); + return query; + } + /** * Add a property with descending order to this OrderBy. */ @@ -83,6 +94,16 @@ public final class OrderBy implements Serializable { return query; } + /** + * Add a property with descending order to this OrderBy. + */ + public Query desc(String propertyName, String collation) { + + list.add(new Property(propertyName, false, collation)); + return query; + } + + /** * Return true if the property is known to be contained in the order by clause. */ @@ -231,6 +252,8 @@ public final class OrderBy implements Serializable { private boolean ascending; + private String collation; + private String nulls; private String highLow; @@ -247,17 +270,32 @@ public final class OrderBy implements Serializable { this.highLow = highLow; } + public Property(String property, boolean ascending, String collation) { + this.property = property; + this.ascending = ascending; + this.collation = collation; + } + + public Property(String property, boolean ascending, String collation, String nulls, String highLow) { + this.property = property; + this.ascending = ascending; + this.collation = collation; + this.nulls = nulls; + this.highLow = highLow; + } + /** * Return a copy of this Property with the path trimmed. */ public Property copyWithTrim(String path) { - return new Property(property.substring(path.length() + 1), ascending, nulls, highLow); + return new Property(property.substring(path.length() + 1), ascending, collation, nulls, highLow); } @Override public int hashCode() { int hc = property.hashCode(); hc = hc * 92821 + (ascending ? 0 : 1); + hc = hc * 92821 + (collation == null ? 0 : collation.hashCode()); hc = hc * 92821 + (nulls == null ? 0 : nulls.hashCode()); hc = hc * 92821 + (highLow == null ? 0 : highLow.hashCode()); return hc; @@ -273,6 +311,7 @@ public final class OrderBy implements Serializable { } Property e = (Property) obj; if (ascending != e.ascending) return false; + if (collation != e.collation) return false; if (!property.equals(e.property)) return false; if (nulls != null ? !nulls.equals(e.nulls) : e.nulls != null) return false; return highLow != null ? highLow.equals(e.highLow) : e.highLow == null; @@ -284,7 +323,7 @@ public final class OrderBy implements Serializable { } public String toStringFormat() { - if (nulls == null) { + if (nulls == null && collation == null) { if (ascending) { return property; } else { @@ -292,11 +331,25 @@ public final class OrderBy implements Serializable { } } else { StringBuilder sb = new StringBuilder(); - sb.append(property); + + // collate + if (collation != null) { + if (collation.contains("${}")) { + // this is a complex collation, e.g. DB2 - we must replace the property + sb.append(StringHelper.replaceString(collation, "${}", property)); + } else { + sb.append(property); + sb.append(" COLLATE ").append(collation); + } + } else { + sb.append(property); + } if (!ascending) { sb.append(" ").append("desc"); } - sb.append(" ").append(nulls).append(" ").append(highLow); + if (nulls != null) { + sb.append(" ").append(nulls).append(" ").append(highLow); + } return sb.toString(); } } @@ -319,7 +372,7 @@ public final class OrderBy implements Serializable { * Return a copy of this property. */ public Property copy() { - return new Property(property, ascending, nulls, highLow); + return new Property(property, ascending, collation, nulls, highLow); } /** diff --git a/src/test/java/org/tests/unitinternal/TestOrderByParse.java b/src/test/java/org/tests/unitinternal/TestOrderByParse.java index 5fc876353..0dc23eccb 100644 --- a/src/test/java/org/tests/unitinternal/TestOrderByParse.java +++ b/src/test/java/org/tests/unitinternal/TestOrderByParse.java @@ -153,4 +153,51 @@ public class TestOrderByParse extends BaseTestCase { assertEquals("id, name", copy.toStringFormat()); } + + @Test + public void testParsingWithCollation() { + + OrderBy o1 = new OrderBy<>(); + o1.asc("id", "latin_1"); + assertTrue(o1.getProperties().size() == 1); + assertTrue(o1.getProperties().get(0).getProperty().equals("id")); + assertTrue(o1.getProperties().get(0).isAscending()); + assertEquals("id COLLATE latin_1", o1.toStringFormat()); + + o1 = new OrderBy<>(); + o1.desc("id", "latin_1"); + assertTrue(o1.getProperties().size() == 1); + assertTrue(o1.getProperties().get(0).getProperty().equals("id")); + assertTrue(!o1.getProperties().get(0).isAscending()); + assertEquals("id COLLATE latin_1 desc", o1.toStringFormat()); + + o1 = new OrderBy<>(); + o1.desc("id", "latin_1"); + o1.asc("date"); + assertTrue(o1.getProperties().size() == 2); + assertTrue(o1.getProperties().get(0).getProperty().equals("id")); + assertTrue(o1.getProperties().get(1).getProperty().equals("date")); + assertTrue(!o1.getProperties().get(0).isAscending()); + assertTrue(o1.getProperties().get(1).isAscending()); + assertEquals("id COLLATE latin_1 desc, date", o1.toStringFormat()); + + o1 = new OrderBy<>(); + o1.desc("id", "latin_1"); + o1.asc("name", "latin_2"); + assertTrue(o1.getProperties().size() == 2); + assertTrue(o1.getProperties().get(0).getProperty().equals("id")); + assertTrue(o1.getProperties().get(1).getProperty().equals("name")); + assertTrue(!o1.getProperties().get(0).isAscending()); + assertTrue(o1.getProperties().get(1).isAscending()); + assertEquals("id COLLATE latin_1 desc, name COLLATE latin_2", o1.toStringFormat()); + + // functional (DB2) syntax + o1 = new OrderBy<>(); + o1.desc("id", "COLLATION_KEY(${}, 'latin_1')"); + assertTrue(o1.getProperties().size() == 1); + assertTrue(o1.getProperties().get(0).getProperty().equals("id")); + assertTrue(!o1.getProperties().get(0).isAscending()); + assertEquals("COLLATION_KEY(id, 'latin_1') desc", o1.toStringFormat()); + + } }