Special Cloudscape Programming
Page 7 of 7

Programming Orderable Classes

Cloudscape allows you to perform ordering, comparisons operations, and index creation on special Java data types called orderable Java data types. (For a complete list of their capabilities and SQL-J examples, see Orderable Java Data Types in the Cloudscape Reference Manual. For more SQL-J examples, see Orderable Java Data Types.)

This section discusses how details of creating orderable Java data types and provides detailed implementation notes.

It also discusses requirements for Java data types that will use the = or <> comparison operators (not just orderable Java data types).

Requirements for Orderable Java Data Types

Cloudscape can put objects in the correct order if those objects provide a special method for that purpose, the compareTo method.

Therefore, to qualify as an orderable Java data type, a Java class must meet the following requirements:

  • In a JDK 1.1 environment, it has a method with the this exact signature:

    public int compareTo(Object o)

    For the behavior of the compareTo method (see Notes on compareTo Implementation).

  • In a JDK 1.2 environment, it implements the interface java.lang.Comparable or follows the rules for the JDK 1.1 environment.
  • In either environment, it must override the hashCode() and equals(Object o) methods in java.lang.Object correctly, which is a requirements for all Java data types if the = and <> operators are going to work correctly (See Notes on Implementing the equals and hashCode Methods).

Given these rules, a Java data type should be orderable in both environments, thus allowing a database to move freely between a JDK 1.1 and a JDK1.2 environment.

Notes on compareTo Implementation

The behavior of the compareTo method is defined by the JDK 1.2 interface java.lang.Comparable, which is copied here:

  • public int compareTo(Object o)

    Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

    The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)

    The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.

    Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

    It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is "Note: this class has a natural ordering that is inconsistent with equals."

NOTE: On this last point, although the JDK rules only strongly recommend that the ordering be consistent with equals, Cloudscape requires it.

Any ordering or index maintenance in Cloudscape depends on the correct implementation of the compareTo method. If a class's compareTo method does not follow the implementation rules, the results of any query involving such an object are not defined. It is also expected that calling the compareTo method of an object does not change the state of the object or that of the passed in object.

NOTE: The compareTo method should not do anything bizarre such as make random comparisons, call database-side JDBC, or alter the object. In addition, the method should be time-invariant. That is, a.compareTo(b) must return the same thing forever. So, it should not depend on things like the current date. Otherwise, an index built today could be inconsistent tomorrow.

NOTE: compareTo and equals must work correctly with subclasses. If you define a column to serialize a particular class or interface, all subclasses that you store in the column must implement the Orderable interface in exactly the same way as the superclass. They must use the same ordering as the superclass.

Notes on Implementing the equals and hashCode Methods

The operators = and <> are allowed even on non-orderable Java data types provided that they correctly implement the following methods:

  • equals (Object o)
  • hashCode()

(See Java Data Types and Equality Operations in the Cloudscape Reference Manual.)

The behavior of the equals method is defined by the class java.lang.Object. The API documentation is copied here:

  • public boolean equals(Object obj)

    Compares two Objects for equality.

    The equals method implements an equivalence relation:

    It is reflexive: for any reference value x, x.equals(x) should return true.

    It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

    It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.

    It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false.

    For any reference value x, x.equals(null) should return false.

The behavior of the hashCode method is also defined by the API. Typically implementation of hashCode is related to implementation of equals.

If a Java data type is orderable, Cloudscape uses the type's compareTo method (not the equals method) to implement the = and <> operators. Cloudscape may use the hashCode method for DISTINCT operations.

Therefore, correct comparisons in Cloudscape depend on the correct implementation of the compareTo or equals methods. If a class's compareTo or equals method does not follow the implementation rules the results of any query involving such an object are not defined.

NOTE: The equals method should not do anything bizarre such as make random comparisons, call database-side JDBC, or alter the object. compareTo and equals must work correctly with subclasses.

Comparison Operators and Objects of Different Types

When comparisons between different data types are supported, what happens when comparisons between objects when one of the types is orderable and the other is not?

One of the Java Data Types is Orderable

Expressions using the comparison operators are converted to internal Java expressions as shown in the following tables.

If a is an orderable Java data type and b is an orderable or non-orderable Java data types:

SQL-J Expression

Equivalent Java Expression

a < b

a.compareTo(b) < 0

a <= b

a.compareTo(b) <= 0

a > b

a.compareTo(b) > 0

a >= b

a.compareTo(b) >= 0

a = b

a.compareTo(b) == 0

a <> b

a.compareTo(b) != 0

If a is not an orderable Java data type, but b is:

SQL-J Expression

Equivalent Java Expression

a < b

b.compareTo(a) > 0

a <= b

b.compareTo(a) >= 0

a > b

b.compareTo(a) < 0

a >= b

b.compareTo(a) <= 0

a = b

b.compareTo(a) == 0

a <> b

b.compareTo(a) != 0

Built-in data types are converted to their corresponding Java type before being used as parameters in the method calls shown in these tables.

Neither Java Data Type Is Orderable

(If neither Java Data Type is Orderable, only the = and <> operators are allowed.)

If a is a non-orderable Java data type, the internal method calls are:

SQL-J Expression

Equivalent Java Expression

a = b

a.equals(b)

a <> b

! a.equals(b)

If a is a built-in type but b is a Java data type:

SQL-J Expression

Equivalent Java Expression

a = b

b.equals(a)

a <> b

! b.equals(a)

To force use of the specific method comparison (equals or compareTo), use the desired method call explicitly. For example:

SELECT CITY FROM CITIES WHERE city.equals(?)

NOTE: The JBMSTours sample application includes three orderable types. One is JBMSTours.serializabletypes.City. Look at this type if you want a concrete example.