db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bpendle...@apache.org
Subject svn commit: r567314 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/sql/execute/ engine/org/apache/derby/iapi/store/access/ engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/sql/compile/ engine/org/apache/derby/impl/sql/exec...
Date Sat, 18 Aug 2007 18:56:16 GMT
Author: bpendleton
Date: Sat Aug 18 11:56:14 2007
New Revision: 567314

URL: http://svn.apache.org/viewvc?view=rev&rev=567314
Log:
DERBY-2887: NULLS FIRST/LAST for ORDER BY

This change implements the SQL Standard 10.10 Sort Specification List feature:

  <null ordering :== NULLS FIRST | NULLS LAST

The implementation adds a new boolean argument to the DataType.compare()
function to allow control over whether NULL values should be compared
as lower than non-NULL values or as higher. The change also adds code to
the parser to recognize the new syntax, and to pass it to the execution
layer via the compiler data structures.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/ColumnOrdering.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataType.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumn.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumnList.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexColumnOrder.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeSort.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderby.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderbyElimination.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderbyElimination.sql
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_ColumnOrderingImpl.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java Sat Aug 18 11:56:14 2007
@@ -1415,7 +1415,8 @@
                                       int opType,
                                       boolean all,
                                       int intermediateOrderByColumnsSavedObject,
-                                      int intermediateOrderByDirectionSavedObject)
+                                      int intermediateOrderByDirectionSavedObject,
+                                      int intermediateOrderByNullsLowSavedObject)
         throws StandardException;
                                                      
                                                      

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/ColumnOrdering.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/ColumnOrdering.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/ColumnOrdering.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/ColumnOrdering.java Sat Aug 18 11:56:14 2007
@@ -37,5 +37,15 @@
 {
 	int getColumnId();
 	boolean getIsAscending();
+        /**
+         * Indicate whether NULL values should be ordered below non-NULL.
+         *
+         * This function returns TRUE if the user has specified, via the
+         * <null ordering> clause in the ORDER BY clause, that NULL values
+         * of this column should sort lower than non-NULL values.
+         *
+         * @return whether nulls should sort low
+         */
+	public boolean getIsNullsOrderedLow();
 }
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataType.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataType.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataType.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataType.java Sat Aug 18 11:56:14 2007
@@ -846,6 +846,105 @@
 	}
 
 	/**
+	 * Compare this Orderable with another, with configurable null ordering.
+	 * The caller gets to determine how nulls
+	 * should be treated - they can either be ordered values or unknown
+	 * values. The caller also gets to decide, if they are ordered,
+         * whether they should be lower than non-NULL values, or higher
+	 *
+	 * @param op	Orderable.ORDER_OP_EQUALS means do an = comparison.
+	 *				Orderable.ORDER_OP_LESSTHAN means compare this < other.
+	 *				Orderable.ORDER_OP_LESSOREQUALS means compare this <= other.
+	 * @param other	The DataValueDescriptor to compare this one to.
+	 * @param orderedNulls	True means to treat nulls as ordered values,
+	 *						that is, treat SQL null as equal to null, and either greater or less
+	 *						than all other values.
+	 *						False means to treat nulls as unknown values,
+	 *						that is, the result of any comparison with a null
+	 *						is the UNKNOWN truth value.
+         * @param nullsOrderedLow       True means NULL less than non-NULL,
+         *                              false means NULL greater than non-NULL.
+         *                              Only relevant if orderedNulls is true.
+	 * @param unknownRV		The return value to use if the result of the
+	 *						comparison is the UNKNOWN truth value.  In other
+	 *						words, if orderedNulls is false, and a null is
+	 *						involved in the comparison, return unknownRV.
+	 *						This parameter is not used orderedNulls is true.
+	 *
+	 * @return	true if the comparison is true (duh!)
+	 *
+	 * @exception StandardException		Thrown on error
+	 */
+	public boolean compare(int op,
+						   DataValueDescriptor other,
+						   boolean orderedNulls,
+						   boolean nullsOrderedLow,
+						   boolean unknownRV)
+		throws StandardException
+	{
+		/* Use compare method from dominant type, flipping the operator
+		 * to reflect flipping of sides.
+		 */
+		if (typePrecedence() < other.typePrecedence())
+		{
+			return other.compare(flip(op), this, orderedNulls,
+                                nullsOrderedLow, unknownRV);
+		}
+
+		int result = compare(other, nullsOrderedLow);
+
+		switch(op)
+		{
+		case ORDER_OP_LESSTHAN:
+			return (result < 0);   // this <  other
+		case ORDER_OP_EQUALS:
+			return (result == 0);  // this == other
+		case ORDER_OP_LESSOREQUALS:
+			return (result <= 0);  // this <= other
+		// flipped operators
+		case ORDER_OP_GREATERTHAN:
+			return (result > 0);   // this > other
+		case ORDER_OP_GREATEROREQUALS:
+			return (result >= 0);  // this >= other
+		default:
+			if (SanityManager.DEBUG)
+				SanityManager.THROWASSERT("Invalid Operator");
+			return false;
+		}
+	}
+
+	/**
+	 * Compare this Orderable with another, with configurable null ordering.
+	 * This method treats nulls as ordered values, but allows the caller
+         * to specify whether they should be lower than all non-NULL values,
+         * or higher than all non-NULL values.
+	 *
+	 * @param other		The Orderable to compare this one to.
+         % @param nullsOrderedLow True if null should be lower than non-NULL
+	 *
+	 * @return  <0 - this Orderable is less than other.
+	 * 			 0 - this Orderable equals other.
+	 *			>0 - this Orderable is greater than other.
+     *
+     *			The code should not explicitly look for -1, or 1.
+	 *
+	 * @exception StandardException		Thrown on error
+	 */
+	public int compare(DataValueDescriptor other, boolean nullsOrderedLow)
+            throws StandardException
+        {
+            if (this.isNull() || other.isNull())
+            {
+                if (!isNull())
+                    return nullsOrderedLow ? 1 : -1;
+                if (!other.isNull())
+                    return nullsOrderedLow ? -1 : 1;
+                return 0; // both null
+            }
+            return compare(other);
+        } 
+
+	/**
 	 * Wrapper method for the "compare(DataValueDescriptor)" method of
 	 * this class.  Allows sorting of an array of DataValueDescriptors
 	 * using the JVMs own sorting algorithm.  Currently used for

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueDescriptor.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataValueDescriptor.java Sat Aug 18 11:56:14 2007
@@ -720,7 +720,7 @@
 	/**
 	 * Compare this Orderable with a given Orderable for the purpose of
 	 * index positioning.  This method treats nulls as ordered values -
-	 * that is, it treats SQL null as equal to null and less than all
+	 * that is, it treats SQL null as equal to null and greater than all
 	 * other values.
 	 *
 	 * @param other		The Orderable to compare this one to.
@@ -736,6 +736,26 @@
 	int compare(DataValueDescriptor other) throws StandardException;
 
 	/**
+	 * Compare this Orderable with another, with configurable null ordering.
+	 * This method treats nulls as ordered values, but allows the caller
+         * to specify whether they should be lower than all non-NULL values,
+         * or higher than all non-NULL values.
+	 *
+	 * @param other		The Orderable to compare this one to.
+         % @param nullsOrderedLow True if null should be lower than non-NULL
+	 *
+	 * @return  <0 - this Orderable is less than other.
+	 * 			 0 - this Orderable equals other.
+	 *			>0 - this Orderable is greater than other.
+     *
+     *			The code should not explicitly look for -1, or 1.
+	 *
+	 * @exception StandardException		Thrown on error
+	 */
+	int compare(DataValueDescriptor other, boolean nullsOrderedLow)
+            throws StandardException;
+
+	/**
 	 * Compare this Orderable with a given Orderable for the purpose of
 	 * qualification and sorting.  The caller gets to determine how nulls
 	 * should be treated - they can either be ordered values or unknown
@@ -765,6 +785,44 @@
     int         op, 
     DataValueDescriptor   other,
     boolean     orderedNulls, 
+    boolean     unknownRV)
+				throws StandardException;
+
+	/**
+	 * Compare this Orderable with another, with configurable null ordering.
+	 * The caller gets to determine how nulls
+	 * should be treated - they can either be ordered values or unknown
+	 * values. The caller also gets to decide, if they are ordered,
+         * whether they should be lower than non-NULL values, or higher
+	 *
+	 * @param op	Orderable.ORDER_OP_EQUALS means do an = comparison.
+	 *				Orderable.ORDER_OP_LESSTHAN means compare this < other.
+	 *				Orderable.ORDER_OP_LESSOREQUALS means compare this <= other.
+	 * @param other	The DataValueDescriptor to compare this one to.
+	 * @param orderedNulls	True means to treat nulls as ordered values,
+	 *						that is, treat SQL null as equal to null, and either greater or less
+	 *						than all other values.
+	 *						False means to treat nulls as unknown values,
+	 *						that is, the result of any comparison with a null
+	 *						is the UNKNOWN truth value.
+         * @param nullsOrderedLow       True means NULL less than non-NULL,
+         *                              false means NULL greater than non-NULL.
+         *                              Only relevant if orderedNulls is true.
+	 * @param unknownRV		The return value to use if the result of the
+	 *						comparison is the UNKNOWN truth value.  In other
+	 *						words, if orderedNulls is false, and a null is
+	 *						involved in the comparison, return unknownRV.
+	 *						This parameter is not used orderedNulls is true.
+	 *
+	 * @return	true if the comparison is true (duh!)
+	 *
+	 * @exception StandardException		Thrown on error
+	 */
+	boolean compare(
+    int         op, 
+    DataValueDescriptor   other,
+    boolean     orderedNulls, 
+    boolean     nullsOrderedLow,
     boolean     unknownRV)
 				throws StandardException;
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java Sat Aug 18 11:56:14 2007
@@ -86,6 +86,7 @@
 
     private int[] intermediateOrderByColumns; // The input result sets will be ordered on these columns. 0 indexed
     private int[] intermediateOrderByDirection; // ascending = 1, descending = -1
+    private boolean[] intermediateOrderByNullsLow; // TRUE means NULL values should be ordered lower than non-NULL values
 
 	/**
 	 * Initializer for a SetOperatorNode.
@@ -144,6 +145,7 @@
 
         intermediateOrderByColumns = new int[ getResultColumns().size()];
         intermediateOrderByDirection = new int[ intermediateOrderByColumns.length];
+        intermediateOrderByNullsLow = new boolean[ intermediateOrderByColumns.length];
         /* If there is an order by on the result of the intersect then use that because we know that doing so
          * will avoid a sort.  If the output of the intersect/except is small relative to its inputs then in some
          * cases it would be better to sort the inputs on a different sequence of columns, but it is hard to analyze
@@ -160,6 +162,7 @@
                     continue;
                 OrderByColumn orderByColumn = orderByList.getOrderByColumn(i);
                 intermediateOrderByDirection[intermediateOrderByIdx] = orderByColumn.isAscending() ? 1 : -1;
+                intermediateOrderByNullsLow[intermediateOrderByIdx] = orderByColumn.isNullsOrderedLow();
                 int columnIdx = orderByColumn.getResultColumn().getColumnPosition() - 1;
                 intermediateOrderByColumns[intermediateOrderByIdx] = columnIdx;
                 colsOrdered.set( columnIdx);
@@ -170,6 +173,7 @@
                 if( ! colsOrdered.get(i))
                 {
                     intermediateOrderByDirection[intermediateOrderByIdx] = 1;
+                    intermediateOrderByNullsLow[intermediateOrderByIdx] = false;
                     intermediateOrderByColumns[intermediateOrderByIdx] = i;
                     intermediateOrderByIdx++;
                 }
@@ -183,6 +187,7 @@
             for( int i = 0; i < intermediateOrderByColumns.length; i++)
             {
                 intermediateOrderByDirection[i] = 1;
+                intermediateOrderByNullsLow[i] = false;
                 intermediateOrderByColumns[i] = i;
             }
         }
@@ -208,6 +213,8 @@
                           cm);
             if( intermediateOrderByDirection[i] < 0)
                 orderByColumn.setDescending();
+            if( intermediateOrderByNullsLow[i])
+                orderByColumn.setNullsOrderedLow();
             orderByList.addOrderByColumn( orderByColumn);
         }
         orderByList.bindOrderByColumns( rsn);
@@ -344,9 +351,9 @@
          *  6) estimated cost
          *  7) opType
          *  8) all
-         *  9) close method
-         *  10) intermediateOrderByColumns saved object index
-         *  11) intermediateOrderByDirection saved object index
+         *  9) intermediateOrderByColumns saved object index
+         *  10) intermediateOrderByDirection saved object index
+         *  11) intermediateOrderByNullsLow saved object index
          */
 
 		acb.pushGetResultSetFactoryExpression(mb); // instance for getSetOpResultSet
@@ -362,11 +369,12 @@
         mb.push( all);
         mb.push( getCompilerContext().addSavedObject( intermediateOrderByColumns));
         mb.push( getCompilerContext().addSavedObject( intermediateOrderByDirection));
+        mb.push( getCompilerContext().addSavedObject( intermediateOrderByNullsLow));
 
 		mb.callMethod(VMOpcode.INVOKEINTERFACE,
                       (String) null,
                       "getSetOpResultSet",
-                      ClassName.NoPutResultSet, 10);
+                      ClassName.NoPutResultSet, 11);
 	} // end of generate
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java Sat Aug 18 11:56:14 2007
@@ -45,6 +45,7 @@
 
 	private ResultColumn	resultCol;
 	private boolean			ascending = true;
+	private boolean			nullsOrderedLow = false;
 	private ValueNode expression;
 	private OrderByList     list;
     /**
@@ -94,6 +95,23 @@
 	 */
 	public boolean isAscending() {
 		return ascending;
+	}
+
+	/**
+	 * Mark the column as ordered NULL values lower than non-NULL values.
+	 */
+	public void setNullsOrderedLow() {
+		nullsOrderedLow = true;
+	}
+
+	/**
+	 * Get the column NULL ordering. Overrides
+	 * OrderedColumn.getIsNullsOrderedLow.
+	 *
+	 * @return true if NULLs ordered low, false if NULLs ordered high
+	 */
+	public boolean isNullsOrderedLow() {
+		return nullsOrderedLow;
 	}
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java Sat Aug 18 11:56:14 2007
@@ -469,6 +469,14 @@
 		{
 			OrderByColumn obc = getOrderByColumn(loc);
 
+            // If the user specified NULLS FIRST or NULLS LAST in such a way
+            // as to require NULL values to be re-sorted to be lower than
+            // non-NULL values, then a sort is required, as the index holds
+            // NULL values unconditionally higher than non-NULL values
+            //
+            if (obc.isNullsOrderedLow())
+				return RequiredRowOrdering.SORT_REQUIRED;
+
 			// ResultColumn rc = obc.getResultColumn();
 
 			/*

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumn.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumn.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumn.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumn.java Sat Aug 18 11:56:14 2007
@@ -49,6 +49,20 @@
 	}
 
 	/**
+	 * Indicate whether this column should be ordered NULLS low.
+	 * By default we assume that all ordered columns are ordered
+	 * with NULLS higher than non-null values. If this class is inherited
+	 * by someone that can be specified to have NULLs ordered lower than
+         * non-null values, they are expected to override this method.
+	 *
+	 * @return false
+	 */
+	public boolean isNullsOrderedLow()
+	{
+		return false;
+	}
+
+	/**
 	 * Convert this object to a String.  See comments in QueryTreeNode.java
 	 * for how this should be done for tree printing.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumnList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumnList.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumnList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OrderedColumnList.java Sat Aug 18 11:56:14 2007
@@ -69,7 +69,8 @@
 			if (! hashColumns.containsKey(posInt))
 			{
 				ordering[i] = new IndexColumnOrder(position,
-												oc.isAscending());
+												oc.isAscending(),
+												oc.isNullsOrderedLow());
 				actualCols++;
 				hashColumns.put(posInt, posInt);
 			}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Sat Aug 18 11:56:14 2007
@@ -2165,6 +2165,7 @@
 |	<NAME: "name">
 |	<NCLOB: "nclob">
 |	<NULLABLE: "nullable">
+|	<NULLS: "nulls">
 |	<NUMBER: "number">
 |	<OBJECT: "object">
 |	<PASCAL: "pascal">
@@ -7848,7 +7849,7 @@
 sortSpecification(OrderByList orderCols) throws StandardException :
 {	OrderByColumn orderCol; }
 {
-	orderCol = sortKey() /* [ collateClause() ] */ [ orderingSpecification(orderCol) ]
+	orderCol = sortKey() /* [ collateClause() ] */ [ orderingSpecification(orderCol) ] [ nullOrdering(orderCol) ]
 	{
 		orderCols.addOrderByColumn(orderCol);
 	} 
@@ -7884,6 +7885,38 @@
 }
 
 /*
+ * The data type comparison functions need to know whether NULL values
+ * should sort higher than non-NULL values, or lower. The answer to this
+ * depends on whether the user specified ASCending or DESCending, and on
+ * whether the user specified NULLS FIRST, or NULLS LAST, as follows:
+ *
+ * +===============+========+========+
+ * | ORDER BY says | ASC    | DESC   |
+ * +===============+========+========+
+ * | NULLS FIRST   | less   | greater|
+ * +===============+========+========+
+ * | NULLS LAST    | greater| less   |
+ * +===============+========+========+
+ */
+void
+nullOrdering(OrderByColumn orderCol) :
+{}
+{
+        LOOKAHEAD( { getToken(2).kind == LAST } )
+        <NULLS> <LAST>
+        {
+            if (! orderCol.isAscending())
+                orderCol.setNullsOrderedLow();
+        }
+|
+        <NULLS> <FIRST>
+        {
+            if (orderCol.isAscending())
+                orderCol.setNullsOrderedLow();
+        }
+}
+
+/*
  * <A NAME="forUpdateClause">forUpdateClause</A>
  */
 int
@@ -13123,6 +13156,7 @@
 	|	tok = <NEW>
 	|   tok = <NEW_TABLE>
 	|	tok = <NULLABLE>
+	|	tok = <NULLS>
 	|	tok = <NUMBER>
 	|	tok = <OBJECT>
 	|	tok = <OFF>

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java Sat Aug 18 11:56:14 2007
@@ -1081,7 +1081,8 @@
                                              int opType,
                                              boolean all,
                                             int intermediateOrderByColumnsSavedObject,
-                                             int intermediateOrderByDirectionSavedObject)
+                                             int intermediateOrderByDirectionSavedObject,
+                                             int intermediateOrderByNullsLowSavedObject)
         throws StandardException
     {
         return new SetOpResultSet( leftSource,
@@ -1093,7 +1094,8 @@
                                    opType,
                                    all,
                                    intermediateOrderByColumnsSavedObject,
-                                   intermediateOrderByDirectionSavedObject);
+                                   intermediateOrderByDirectionSavedObject,
+                                   intermediateOrderByNullsLowSavedObject);
     }
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexColumnOrder.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexColumnOrder.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexColumnOrder.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/IndexColumnOrder.java Sat Aug 18 11:56:14 2007
@@ -54,6 +54,16 @@
 
 	int colNum;
 	boolean ascending;
+        /**
+         * indicate whether NULL values should sort low.
+         *
+         * nullsOrderedLow is usually false, because generally Derby defaults
+         * to have NULL values compare higher than non-null values, but if
+         * the user specifies an ORDER BY clause with a <null ordering>
+         * specification that indicates that NULL values should be ordered
+         * lower than non-NULL values, thien nullsOrderedLow is set to true.
+         */
+        boolean nullsOrderedLow;
 
 	/*
 	 * class interface
@@ -69,11 +79,34 @@
 	public IndexColumnOrder(int colNum) {
 		 this.colNum = colNum;
 		 this.ascending = true;
+                 this.nullsOrderedLow = false;
 	}
 
 	public IndexColumnOrder(int colNum, boolean ascending) {
 		 this.colNum = colNum;
 		 this.ascending = ascending;
+                 this.nullsOrderedLow = false;
+	}
+
+        /**
+         * constructor used by the ORDER BY clause.
+         *
+         * This version of the constructor is used by the compiler when
+         * it processes an ORDER BY clause in a SQL statement. For such
+         * statements, the user gets to control whether NULL values are
+         * ordered as lower than all non-NULL values, or higher than all
+         * non-NULL values.
+         *
+         * @param colNum number of this column
+         * @param ascending whether the ORDER BY is ascendeing or descending
+         * @param nullsLow whether nulls should be ordered low
+         */
+	public IndexColumnOrder(int colNum, boolean ascending,
+                boolean nullsLow)
+        {
+		 this.colNum = colNum;
+		 this.ascending = ascending;
+                 this.nullsOrderedLow = nullsLow;
 	}
 
 	/*
@@ -85,6 +118,19 @@
 
 	public boolean getIsAscending() {
 		return ascending;
+	}
+
+        /**
+         * Indicate whether NULL values should be ordered below non-NULL.
+         *
+         * This function returns TRUE if the user has specified, via the
+         * <null ordering> clause in the ORDER BY clause, that NULL values
+         * of this column should sort lower than non-NULL values.
+         *
+         * @return whether nulls should sort low
+         */
+	public boolean getIsNullsOrderedLow() {
+		return nullsOrderedLow;
 	}
 
 	//////////////////////////////////////////////

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java Sat Aug 18 11:56:14 2007
@@ -63,6 +63,7 @@
 
     private final int[] intermediateOrderByColumns;
     private final int[] intermediateOrderByDirection;
+    private final boolean[] intermediateOrderByNullsLow;
 
     /* Run time statistics variables */
     private int rowsSeenLeft;
@@ -78,7 +79,8 @@
                     int opType,
                     boolean all,
                     int intermediateOrderByColumnsSavedObject,
-                    int intermediateOrderByDirectionSavedObject)
+                    int intermediateOrderByDirectionSavedObject,
+                    int intermediateOrderByNullsLowSavedObject)
     {
 		super(activation, resultSetNumber, 
 			  optimizerEstimatedRowCount, optimizerEstimatedCost);
@@ -92,6 +94,7 @@
         ExecPreparedStatement eps = activation.getPreparedStatement();
         intermediateOrderByColumns = (int[]) eps.getSavedObject(intermediateOrderByColumnsSavedObject);
         intermediateOrderByDirection = (int[]) eps.getSavedObject(intermediateOrderByDirectionSavedObject);
+        intermediateOrderByNullsLow = (boolean[]) eps.getSavedObject(intermediateOrderByNullsLowSavedObject);
         recordConstructorTime();
     }
 
@@ -214,12 +217,14 @@
             int colIdx = intermediateOrderByColumns[i];
             if( leftCols[colIdx].compare( Orderable.ORDER_OP_LESSTHAN,
                                           rightCols[colIdx],
-                                          true, // nulls sort high
+                                          true, // nulls should be ordered
+                                          intermediateOrderByNullsLow[i],
                                           false))
                 return -1 * intermediateOrderByDirection[i];
             if( ! leftCols[colIdx].compare( Orderable.ORDER_OP_EQUALS,
                                             rightCols[colIdx],
-                                            true, // nulls sort high
+                                            true, // nulls should be ordered
+                                            intermediateOrderByNullsLow[i],
                                             false))
                 return intermediateOrderByDirection[i];
         }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeSort.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeSort.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeSort.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/sort/MergeSort.java Sat Aug 18 11:56:14 2007
@@ -123,6 +123,11 @@
 	private boolean columnOrderingAscendingMap[];
 
 	/**
+    A lookup table to speed up lookup of nulls-low ordering of a column, 
+	**/
+	private boolean columnOrderingNullsLowMap[];
+
+	/**
 	The sort observer.  May be null.  Used as a callback.
 	**/
 	SortObserver sortObserver;
@@ -488,10 +493,11 @@
         {
 			// Get columns to compare.
             int colid = this.columnOrderingMap[i];
+            boolean nullsLow = this.columnOrderingNullsLowMap[i];
 
 			// If the columns don't compare equal, we're done.
 			// Return the sense of the comparison.
-			if ((r = r1[colid].compare(r2[colid])) 
+			if ((r = r1[colid].compare(r2[colid], nullsLow)) 
                     != 0)
 			{
 				if (this.columnOrderingAscendingMap[i])
@@ -540,10 +546,12 @@
         // to change throughout a sort.
         columnOrderingMap          = new int[columnOrdering.length];
         columnOrderingAscendingMap = new boolean[columnOrdering.length];
+        columnOrderingNullsLowMap  = new boolean[columnOrdering.length];
         for (int i = 0; i < columnOrdering.length; i++)
         {
             columnOrderingMap[i] = columnOrdering[i].getColumnId();
             columnOrderingAscendingMap[i] = columnOrdering[i].getIsAscending();
+            columnOrderingNullsLowMap[i] = columnOrdering[i].getIsNullsOrderedLow();
         }
 
 		// No inserter or scan yet.

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderby.out
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderby.out?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderby.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderby.out Sat Aug 18 11:56:14 2007
@@ -1761,4 +1761,100 @@
 John      
 ij> drop table person;
 0 rows inserted/updated/deleted
+ij> create table d2887_types(
+   id             int,
+   c1_smallint    smallint,
+   c2_int         integer,
+   c3_bigint      bigint,
+   c4_real        real,
+   c5_float       float,
+   c6_numeric     numeric(10,2),
+   c7_char        char(10),
+   c8_date        date,
+   c9_time        time,
+   c10_timestamp  timestamp,
+   c11_varchar    varchar(50)
+);
+0 rows inserted/updated/deleted
+ij> -- Tests to demonstrate proper operation of <null ordering> (DERBY-2887)
+
+insert into d2887_types values
+  (1, 1, 1, 1, 1.0, 1.0, 1.0, 'one', 
+   '1991-01-01', '11:01:01', '1991-01-01 11:01:01',
+   'one'),
+  (2, 2, 2, 2, 2.0, 2.0, 2.0, 'two', 
+   '1992-02-02', '12:02:02', '1992-02-02 12:02:02',
+   'two'),
+  (3, 3, 3, 3, 3.0, 3.0, 3.0, 'three',
+   '1993-03-03', '03:03:03', '1993-03-03 03:03:03',
+   'three'),
+  (4, null, null, null, null, null, null, null,
+   null, null, null,
+   null);
+4 rows inserted/updated/deleted
+ij> -- Demonstrate various combinations of NULLS FIRST, NULLS LAST, and default,
+-- with various combinations of ASC, DESC, and default, with various
+-- data types. These should all succeed, should all produce output with the
+-- non-null values in the proper order, and should all produce output with
+-- the null values ordered as specified. If null ordering was not specified,
+-- the default Derby behavior is nulls are last if asc, first if desc.
+
+select id, c1_smallint from d2887_types order by c1_smallint nulls first;
+ID         |C1_SM&
+------------------
+4          |NULL  
+1          |1     
+2          |2     
+3          |3     
+ij> select id, c2_int from d2887_types order by c2_int nulls last;
+ID         |C2_INT     
+-----------------------
+1          |1          
+2          |2          
+3          |3          
+4          |NULL       
+ij> select id, c3_bigint from d2887_types order by c3_bigint asc;
+ID         |C3_BIGINT           
+--------------------------------
+1          |1                   
+2          |2                   
+3          |3                   
+4          |NULL                
+ij> select id, c4_real from d2887_types order by c4_real desc;
+ID         |C4_REAL      
+-------------------------
+4          |NULL         
+3          |3.0          
+2          |2.0          
+1          |1.0          
+ij> select id, c5_float from d2887_types order by c5_float asc nulls last;
+ID         |C5_FLOAT              
+----------------------------------
+1          |1.0                   
+2          |2.0                   
+3          |3.0                   
+4          |NULL                  
+ij> select id, c6_numeric from d2887_types order by c6_numeric desc nulls last;
+ID         |C6_NUMERIC  
+------------------------
+3          |3.00        
+2          |2.00        
+1          |1.00        
+4          |NULL        
+ij> select id, c7_char from d2887_types order by c7_char asc nulls first;
+ID         |C7_CHAR   
+----------------------
+4          |NULL      
+1          |one       
+3          |three     
+2          |two       
+ij> select id, c8_date from d2887_types order by c8_date desc nulls first;
+ID         |C8_DATE   
+----------------------
+4          |NULL      
+3          |1993-03-03
+2          |1992-02-02
+1          |1991-01-01
+ij> drop table d2887_types;
+0 rows inserted/updated/deleted
 ij> 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderbyElimination.out
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderbyElimination.out?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderbyElimination.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/orderbyElimination.out Sat Aug 18 11:56:14 2007
@@ -1303,6 +1303,137 @@
 	None
 					qualifiers:
 None
+ij> -- DERBY-2887: investigate affect of NULLS FIRST/LAST on sorting
+insert into t1 values (1, null, 14, null);
+1 row inserted/updated/deleted
+ij> -- should NOT do a sort:
+select c1,c2,c3 from t1 where c1 = 1 order by c1,c2;
+C1         |C2         |C3         
+-----------------------------------
+1          |2          |3          
+1          |2          |4          
+1          |3          |2          
+1          |3          |4          
+1          |4          |2          
+1          |4          |3          
+1          |NULL       |14         
+ij> values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
+1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
                                    
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 -----------------------------------
+Statement Name: 
+	null
+Statement Text: 
+	-- should NOT do a sort:
+select c1,c2,c3 from t1 where c1 = 1 order by c1,c2
+Parse Time: 0
+Bind Time: 0
+Optimize Time: 0
+Generate Time: 0
+Compile Time: 0
+Execute Time: 0
+Begin Compilation Timestamp : null
+End Compilation Timestamp : null
+Begin Execution Timestamp : null
+End Execution Timestamp : null
+Statement Execution Plan Text: 
+Index Scan ResultSet for T1 using index I1 at serializable isolation level using share row locking chosen by the optimizer
+Number of opens = 1
+Rows seen = 7
+Rows filtered = 0
+Fetch Size = 16
+	constructor time (milliseconds) = 0
+	open time (milliseconds) = 0
+	next time (milliseconds) = 0
+	close time (milliseconds) = 0
+	next time in milliseconds/row = 0
+scan information: 
+	Bit set of columns fetched={0, 1, 2}
+	Number of columns fetched=3
+	Number of deleted rows visited=0
+	Number of pages visited=1
+	Number of rows qualified=7
+	Number of rows visited=8
+	Scan type=btree
+	Tree height=-1
+	start position: 
+	>= on first 1 column(s).
+	Ordered null semantics on the following columns: 
+	stop position: 
+	> on first 1 column(s).
+	Ordered null semantics on the following columns: 
+	qualifiers:
+None
+ij> -- Needs to do a sort to get the NULLS FIRST:
+select c1,c2,c3 from t1 where c1 = 1 order by c1,c2 nulls first;
+C1         |C2         |C3         
+-----------------------------------
+1          |NULL       |14         
+1          |2          |4          
+1          |2          |3          
+1          |3          |4          
+1          |3          |2          
+1          |4          |3          
+1          |4          |2          
+ij> values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
+1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
                                    
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 -----------------------------------
+Statement Name: 
+	null
+Statement Text: 
+	-- Needs to do a sort to get the NULLS FIRST:
+select c1,c2,c3 from t1 where c1 = 1 order by c1,c2 nulls first
+Parse Time: 0
+Bind Time: 0
+Optimize Time: 0
+Generate Time: 0
+Compile Time: 0
+Execute Time: 0
+Begin Compilation Timestamp : null
+End Compilation Timestamp : null
+Begin Execution Timestamp : null
+End Execution Timestamp : null
+Statement Execution Plan Text: 
+Sort ResultSet:
+Number of opens = 1
+Rows input = 7
+Rows returned = 7
+Eliminate duplicates = false
+In sorted order = false
+Sort information: 
+	Number of rows input=7
+	Number of rows output=7
+	constructor time (milliseconds) = 0
+	open time (milliseconds) = 0
+	next time (milliseconds) = 0
+	close time (milliseconds) = 0
+Source result set:
+	Index Scan ResultSet for T1 using index I1 at serializable isolation level using share row locking chosen by the optimizer
+	Number of opens = 1
+	Rows seen = 7
+	Rows filtered = 0
+	Fetch Size = 16
+		constructor time (milliseconds) = 0
+		open time (milliseconds) = 0
+		next time (milliseconds) = 0
+		close time (milliseconds) = 0
+		next time in milliseconds/row = 0
+	scan information: 
+		Bit set of columns fetched={0, 1, 2}
+		Number of columns fetched=3
+		Number of deleted rows visited=0
+		Number of pages visited=1
+		Number of rows qualified=7
+		Number of rows visited=8
+		Scan type=btree
+		Tree height=1
+		start position: 
+	>= on first 1 column(s).
+	Ordered null semantics on the following columns: 
+		stop position: 
+	> on first 1 column(s).
+	Ordered null semantics on the following columns: 
+		qualifiers:
+None
 ij> -- test recognition of single row tables
 -- even when scanning heap
 create table u1(c1 int, c2 int);

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql Sat Aug 18 11:56:14 2007
@@ -683,4 +683,54 @@
 drop table person;
 
 
+create table d2887_types(
+   id             int,
+   c1_smallint    smallint,
+   c2_int         integer,
+   c3_bigint      bigint,
+   c4_real        real,
+   c5_float       float,
+   c6_numeric     numeric(10,2),
+   c7_char        char(10),
+   c8_date        date,
+   c9_time        time,
+   c10_timestamp  timestamp,
+   c11_varchar    varchar(50)
+);
+
+-- Tests to demonstrate proper operation of <null ordering> (DERBY-2887)
+
+insert into d2887_types values
+  (1, 1, 1, 1, 1.0, 1.0, 1.0, 'one', 
+   '1991-01-01', '11:01:01', '1991-01-01 11:01:01',
+   'one'),
+  (2, 2, 2, 2, 2.0, 2.0, 2.0, 'two', 
+   '1992-02-02', '12:02:02', '1992-02-02 12:02:02',
+   'two'),
+  (3, 3, 3, 3, 3.0, 3.0, 3.0, 'three',
+   '1993-03-03', '03:03:03', '1993-03-03 03:03:03',
+   'three'),
+  (4, null, null, null, null, null, null, null,
+   null, null, null,
+   null);
+
+
+-- Demonstrate various combinations of NULLS FIRST, NULLS LAST, and default,
+-- with various combinations of ASC, DESC, and default, with various
+-- data types. These should all succeed, should all produce output with the
+-- non-null values in the proper order, and should all produce output with
+-- the null values ordered as specified. If null ordering was not specified,
+-- the default Derby behavior is nulls are last if asc, first if desc.
+
+select id, c1_smallint from d2887_types order by c1_smallint nulls first;
+select id, c2_int from d2887_types order by c2_int nulls last;
+select id, c3_bigint from d2887_types order by c3_bigint asc;
+select id, c4_real from d2887_types order by c4_real desc;
+select id, c5_float from d2887_types order by c5_float asc nulls last;
+select id, c6_numeric from d2887_types order by c6_numeric desc nulls last;
+select id, c7_char from d2887_types order by c7_char asc nulls first;
+select id, c8_date from d2887_types order by c8_date desc nulls first;
+
+drop table d2887_types;
+
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderbyElimination.sql
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderbyElimination.sql?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderbyElimination.sql (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderbyElimination.sql Sat Aug 18 11:56:14 2007
@@ -80,6 +80,17 @@
 select c3, c4 from t1 union select c2, c1 as c4 from t1 order by c4;
 values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
 
+-- DERBY-2887: investigate affect of NULLS FIRST/LAST on sorting
+
+insert into t1 values (1, null, 14, null);
+
+-- should NOT do a sort:
+select c1,c2,c3 from t1 where c1 = 1 order by c1,c2;
+values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
+-- Needs to do a sort to get the NULLS FIRST:
+select c1,c2,c3 from t1 where c1 = 1 order by c1,c2 nulls first;
+values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
+
 -- test recognition of single row tables
 -- even when scanning heap
 create table u1(c1 int, c2 int);

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_ColumnOrderingImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_ColumnOrderingImpl.java?view=diff&rev=567314&r1=567313&r2=567314
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_ColumnOrderingImpl.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_ColumnOrderingImpl.java Sat Aug 18 11:56:14 2007
@@ -59,5 +59,13 @@
 	{
 		return this.isAscending;
 	}
+
+	/**
+	@see ColumnOrdering#getIsNullsOrderedLow
+	**/
+	public boolean getIsNullsOrderedLow()
+	{
+		return false;
+	}
 }
 



Mime
View raw message