diff --git a/jOOQ/src/main/java/org/jooq/Record.java b/jOOQ/src/main/java/org/jooq/Record.java index e68fafb753..2d421d253b 100644 --- a/jOOQ/src/main/java/org/jooq/Record.java +++ b/jOOQ/src/main/java/org/jooq/Record.java @@ -98,7 +98,7 @@ import org.jetbrains.annotations.Nullable; *

* jOOQ records have a natural ordering implemented in the same way as this is * defined in the SQL standard. For more details, see the - * {@link #compareTo(Record)} method + * {@link #compareTo(Record)} method. * * @author Lukas Eder * @see Result diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java index cfc50686dd..6434cfb631 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java @@ -1080,19 +1080,18 @@ abstract class AbstractRecord extends AbstractStore implements Record { public int compareTo(Record that) { // Note: keep this implementation in-sync with AbstractStore.equals()! - if (that == null) { + if (that == this) + return 0; + if (that == null) throw new NullPointerException(); - } - if (size() != that.size()) { + if (size() != that.size()) throw new ClassCastException(String.format("Trying to compare incomparable records (wrong degree):\n%s\n%s", this, that)); - } Class[] thisTypes = this.fieldsRow().types(); Class[] thatTypes = that.fieldsRow().types(); - if (!asList(thisTypes).equals(asList(thatTypes))) { + if (!asList(thisTypes).equals(asList(thatTypes))) throw new ClassCastException(String.format("Trying to compare incomparable records (type mismatch):\n%s\n%s", this, that)); - } for (int i = 0; i < size(); i++) { final Object thisValue = get(i); @@ -1100,18 +1099,15 @@ abstract class AbstractRecord extends AbstractStore implements Record { // [#1850] Only return -1/+1 early. In all other cases, // continue checking the remaining fields - if (thisValue == null && thatValue == null) { + if (thisValue == null && thatValue == null) continue; - } // Order column values in a SQL NULLS LAST manner - else if (thisValue == null) { + else if (thisValue == null) return 1; - } - else if (thatValue == null) { + else if (thatValue == null) return -1; - } // [#985] Compare arrays too. else if (thisValue.getClass().isArray() && thatValue.getClass().isArray()) { @@ -1120,30 +1116,26 @@ abstract class AbstractRecord extends AbstractStore implements Record { if (thisValue.getClass() == byte[].class) { int compare = compare((byte[]) thisValue, (byte[]) thatValue); - if (compare != 0) { + if (compare != 0) return compare; - } } // Other primitive types are not expected else if (!thisValue.getClass().getComponentType().isPrimitive()) { int compare = compare((Object[]) thisValue, (Object[]) thatValue); - if (compare != 0) { + if (compare != 0) return compare; - } } - else { + else throw new ClassCastException(String.format("Unsupported data type in natural ordering: %s", thisValue.getClass())); - } } else { - int compare = ((Comparable) thisValue).compareTo(thatValue); + int compare = compare0(thisValue, thatValue); - if (compare != 0) { + if (compare != 0) return compare; - } } } @@ -1161,9 +1153,8 @@ abstract class AbstractRecord extends AbstractStore implements Record { int v1 = (array1[i] & 0xff); int v2 = (array2[i] & 0xff); - if (v1 != v2) { + if (v1 != v2) return v1 < v2 ? -1 : 1; - } } return array1.length - array2.length; @@ -1176,16 +1167,28 @@ abstract class AbstractRecord extends AbstractStore implements Record { int length = Math.min(array1.length, array2.length); for (int i = 0; i < length; i++) { - int compare = ((Comparable) array1[i]).compareTo(array2[i]); + int compare = compare0(array1[i], array2[i]); - if (compare != 0) { + if (compare != 0) return compare; - } } return array1.length - array2.length; } + /** + * Compare two uncomparable objects + */ + final int compare0(Object object1, Object object2) { + return object1 == object2 + ? 0 + : object1 == null + ? -1 + : object2 == null + ? 1 + : object1.hashCode() - object2.hashCode(); + } + // ------------------------------------------------------------------------- // XXX: Deprecated and discouraged methods // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractStore.java b/jOOQ/src/main/java/org/jooq/impl/AbstractStore.java index 33b16f4139..bdb4fd5463 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractStore.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractStore.java @@ -155,9 +155,8 @@ abstract class AbstractStore extends AbstractFormattable implements Attachable { @Override public boolean equals(Object obj) { - if (this == obj) { + if (this == obj) return true; - } // Note: keep this implementation in-sync with AbstractRecord.compareTo()! if (obj instanceof AbstractStore) { @@ -170,39 +169,33 @@ abstract class AbstractStore extends AbstractFormattable implements Attachable { // [#1850] Only return false early. In all other cases, // continue checking the remaining fields - if (thisValue == null && thatValue == null) { + if (thisValue == null && thatValue == null) continue; - } - else if (thisValue == null || thatValue == null) { + else if (thisValue == null || thatValue == null) return false; - } // [#985] Compare arrays too. else if (thisValue.getClass().isArray() && thatValue.getClass().isArray()) { // Might be byte[] if (thisValue.getClass() == byte[].class && thatValue.getClass() == byte[].class) { - if (!Arrays.equals((byte[]) thisValue, (byte[]) thatValue)) { + if (!Arrays.equals((byte[]) thisValue, (byte[]) thatValue)) return false; - } } // Other primitive types are not expected else if (!thisValue.getClass().getComponentType().isPrimitive() && !thatValue.getClass().getComponentType().isPrimitive()) { - if (!Arrays.equals((Object[]) thisValue, (Object[]) thatValue)) { + if (!Arrays.equals((Object[]) thisValue, (Object[]) thatValue)) return false; - } } - else { + else return false; - } } - else if (!thisValue.equals(thatValue)) { + else if (!thisValue.equals(thatValue)) return false; - } } // If we got through the above loop, the two records are equal