Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / sql / compile / OrderByList.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/sql/compile/OrderByList.java
new file mode 100644 (file)
index 0000000..0749a17
--- /dev/null
@@ -0,0 +1,743 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.sql.compile.OrderByList\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package        org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+import org.apache.derby.iapi.sql.compile.CostEstimate;\r
+import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;\r
+import org.apache.derby.iapi.sql.compile.RowOrdering;\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.impl.sql.compile.ActivationClassBuilder;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.ResultSet;\r
+\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.services.loader.GeneratedMethod;\r
+\r
+import org.apache.derby.iapi.store.access.ColumnOrdering;\r
+import org.apache.derby.iapi.store.access.SortCostController;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.reference.Limits;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import java.util.Properties;\r
+\r
+/**\r
+ * An OrderByList is an ordered list of columns in the ORDER BY clause.\r
+ * That is, the order of columns in this list is significant - the\r
+ * first column in the list is the most significant in the ordering,\r
+ * and the last column in the list is the least significant.\r
+ *\r
+ */\r
+public class OrderByList extends OrderedColumnList\r
+                                               implements RequiredRowOrdering {\r
+\r
+       private boolean allAscending = true;\r
+       private boolean alwaysSort;\r
+       private ResultSetNode resultToSort;\r
+       private SortCostController scc;\r
+       private Object[] resultRow;\r
+       private ColumnOrdering[] columnOrdering;\r
+       private int estimatedRowSize;\r
+       private boolean sortNeeded = true;\r
+\r
+       /**\r
+               Add a column to the list\r
+       \r
+               @param column   The column to add to the list\r
+        */\r
+       public void addOrderByColumn(OrderByColumn column) \r
+       {\r
+               addElement(column);\r
+\r
+               if (! column.isAscending())\r
+                       allAscending = false;\r
+       }\r
+\r
+       /**\r
+        * Are all columns in the list ascending.\r
+        *\r
+        * @return      Whether or not all columns in the list ascending.\r
+        */\r
+       boolean allAscending()\r
+       {\r
+               return allAscending;\r
+       }\r
+\r
+       /**\r
+               Get a column from the list\r
+       \r
+               @param position The column to get from the list\r
+        */\r
+       public OrderByColumn getOrderByColumn(int position) {\r
+               if (SanityManager.DEBUG)\r
+               SanityManager.ASSERT(position >=0 && position < size());\r
+               return (OrderByColumn) elementAt(position);\r
+       }\r
+\r
+       /**\r
+               Print the list.\r
+       \r
+               @param depth            The depth at which to indent the sub-nodes\r
+        */\r
+       public void printSubNodes(int depth) {\r
+\r
+               if (SanityManager.DEBUG) \r
+               {\r
+                       for (int index = 0; index < size(); index++)\r
+                       {\r
+                               ( (OrderByColumn) (elementAt(index)) ).treePrint(depth);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+               Bind the update columns by their names to the target resultset\r
+               of the cursor specification.\r
+\r
+               @param target   The underlying result set\r
+       \r
+               @exception StandardException            Thrown on error\r
+        */\r
+       public void bindOrderByColumns(ResultSetNode target)\r
+                                       throws StandardException {\r
+\r
+               /* Remember the target for use in optimization */\r
+               resultToSort = target;\r
+\r
+               int size = size();\r
+\r
+               /* Only 1012 columns allowed in ORDER BY clause */\r
+               if (size > Limits.DB2_MAX_ELEMENTS_IN_ORDER_BY)\r
+               {\r
+                       throw StandardException.newException(SQLState.LANG_TOO_MANY_ELEMENTS);\r
+               }\r
+\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(index);\r
+                       obc.bindOrderByColumn(target, this);\r
+\r
+                       /*\r
+                       ** Always sort if we are ordering on an expression, and not\r
+                       ** just a column.\r
+                       */\r
+                       if ( !\r
+                        (obc.getResultColumn().getExpression() instanceof ColumnReference))\r
+                       {\r
+                               alwaysSort = true;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Adjust addedColumnOffset values due to removal of a duplicate column\r
+        *\r
+        * This routine is called by bind processing when it identifies and\r
+        * removes a column from the result column list which was pulled up due\r
+        * to its presence in the ORDER BY clause, but which was later found to\r
+        * be a duplicate. The OrderByColumn instance for the removed column\r
+        * has been adjusted to point to the true column in the result column\r
+        * list and its addedColumnOffset has been reset to -1. This routine\r
+        * finds any other OrderByColumn instances which had an offset greater\r
+        * than that of the column that has been deleted, and decrements their\r
+        * addedColumOffset to account for the deleted column's removal.\r
+        *\r
+        * @param gap   column which has been removed from the result column list\r
+        */\r
+       void closeGap(int gap)\r
+       {\r
+               for (int index = 0; index < size(); index++)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(index);\r
+                       obc.collapseAddedColumnGap(gap);\r
+               }\r
+       }\r
+\r
+       /**\r
+               Pull up Order By columns by their names to the target resultset\r
+               of the cursor specification.\r
+\r
+               @param target   The underlying result set\r
+       \r
+        */\r
+       public void pullUpOrderByColumns(ResultSetNode target)\r
+                                       throws StandardException {\r
+\r
+               /* Remember the target for use in optimization */\r
+               resultToSort = target;\r
+\r
+               int size = size();\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(index);\r
+                       obc.pullUpOrderByColumn(target);\r
+               }\r
+\r
+       }\r
+\r
+       /**\r
+        * Is this order by list an in order prefix of the specified RCL.\r
+        * This is useful when deciding if an order by list can be eliminated\r
+        * due to a sort from an underlying distinct or union.\r
+        *\r
+        * @param sourceRCL     The source RCL.\r
+        *\r
+        * @return Whether or not this order by list an in order prefix of the specified RCL.\r
+        */\r
+       boolean isInOrderPrefix(ResultColumnList sourceRCL)\r
+       {\r
+               boolean inOrderPrefix = true;\r
+               int rclSize = sourceRCL.size();\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (size() > sourceRCL.size())\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                       "size() (" + size() + \r
+                                       ") expected to be <= sourceRCL.size() (" +\r
+                                       sourceRCL.size() + ")");\r
+                       }\r
+               }\r
+\r
+               int size = size();\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       if (((OrderByColumn) elementAt(index)).getResultColumn() !=\r
+                               (ResultColumn) sourceRCL.elementAt(index))\r
+                       {\r
+                               return false;\r
+                       }\r
+               }\r
+               return true;\r
+       }\r
+\r
+       /**\r
+        * Order by columns now point to the PRN above the node of interest.\r
+        * We need them to point to the RCL under that one.  This is useful\r
+        * when combining sorts where we need to reorder the sorting\r
+        * columns.\r
+        */\r
+       void resetToSourceRCs()\r
+       {\r
+               int size = size();\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(index);\r
+                       obc.resetToSourceRC();\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Build a new RCL with the same RCs as the passed in RCL\r
+        * but in an order that matches the ordering columns.\r
+        *\r
+        * @param resultColumns The RCL to reorder.\r
+        *      \r
+        *      @exception StandardException            Thrown on error\r
+        */\r
+       ResultColumnList reorderRCL(ResultColumnList resultColumns)\r
+               throws StandardException\r
+       {\r
+               ResultColumnList newRCL = (ResultColumnList) getNodeFactory().getNode(\r
+                                                                                               C_NodeTypes.RESULT_COLUMN_LIST,\r
+                                                                                               getContextManager());\r
+\r
+               /* The new RCL starts with the ordering columns */\r
+               int size = size();\r
+               for (int index = 0; index < size; index++)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(index);\r
+                       newRCL.addElement(obc.getResultColumn());\r
+                       resultColumns.removeElement(obc.getResultColumn());\r
+               }\r
+\r
+               /* And ends with the non-ordering columns */\r
+               newRCL.destructiveAppend(resultColumns);\r
+               newRCL.resetVirtualColumnIds();\r
+               newRCL.copyOrderBySelect(resultColumns);\r
+               return newRCL;\r
+       }\r
+\r
+       /**\r
+               Remove any constant columns from this order by list.\r
+               Constant columns are ones where all of the column references\r
+               are equal to constant expressions according to the given\r
+               predicate list.\r
+        */\r
+       void removeConstantColumns(PredicateList whereClause)\r
+       {\r
+               /* Walk the list backwards so we can remove elements safely */\r
+               for (int loc = size() - 1;\r
+                        loc >= 0;\r
+                        loc--)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(loc);\r
+\r
+                       if (obc.constantColumn(whereClause))\r
+                       {\r
+                               removeElementAt(loc);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+               Remove any duplicate columns from this order by list.\r
+               For example, one may "ORDER BY 1, 1, 2" can be reduced\r
+               to "ORDER BY 1, 2".\r
+               Beetle 5401.\r
+        */\r
+       void removeDupColumns()\r
+       {\r
+               /* Walk the list backwards so we can remove elements safely */\r
+               for (int loc = size() - 1; loc > 0; loc--)\r
+               {\r
+                       OrderByColumn obc = (OrderByColumn) elementAt(loc);\r
+                       int           colPosition = obc.getColumnPosition();\r
+\r
+                       for (int inner = 0; inner < loc; inner++)\r
+                       {\r
+                               OrderByColumn prev_obc = (OrderByColumn) elementAt(inner);\r
+                               if (colPosition == prev_obc.getColumnPosition())\r
+                               {\r
+                                       removeElementAt(loc);\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+       generate the sort result set operating over the source\r
+               expression.\r
+\r
+               @param acb the tool for building the class\r
+               @param mb       the method the generated code is to go into\r
+               @exception StandardException thrown on failure\r
+        */\r
+       public void generate(ActivationClassBuilder acb, \r
+                                                               MethodBuilder mb,\r
+                                                               ResultSetNode child)\r
+                                                       throws StandardException \r
+       {\r
+               /*\r
+               ** If sorting is not required, don't generate a sort result set -\r
+               ** just return the child result set.\r
+               */\r
+               if ( ! sortNeeded) {\r
+                       child.generate(acb, mb);\r
+                       return;\r
+               }\r
+\r
+               /* Get the next ResultSet#, so we can number this ResultSetNode, its\r
+                * ResultColumnList and ResultSet.\r
+                *\r
+                * REMIND: to do this properly (if order bys can live throughout\r
+                * the tree) there ought to be an OrderByNode that holds its own\r
+                * ResultColumnList that is a lsit of virtual column nodes pointing\r
+                * to the source's result columns.  But since we know it is outermost,\r
+                * we just gloss over that and get ourselves a resultSetNumber\r
+                * directly.\r
+                */\r
+               CompilerContext cc = getCompilerContext();\r
+\r
+\r
+               /*\r
+                       create the orderItem and stuff it in.\r
+                */\r
+               int orderItem = acb.addItem(acb.getColumnOrdering(this));\r
+\r
+\r
+               /* Generate the SortResultSet:\r
+                *      arg1: childExpress - Expression for childResultSet\r
+                *  arg2: distinct - always false, we have a separate node\r
+                *                              for distincts\r
+                *  arg3: isInSortedOrder - is the source result set in sorted order\r
+                *  arg4: orderItem - entry in saved objects for the ordering\r
+                *  arg5: rowAllocator - method to construct rows for fetching\r
+                *                      from the sort\r
+                *  arg6: row size\r
+                *  arg7: resultSetNumber\r
+                *  arg8: estimated row count\r
+                *  arg9: estimated cost\r
+                */\r
+\r
+               acb.pushGetResultSetFactoryExpression(mb);\r
+\r
+               child.generate(acb, mb);\r
+\r
+               int resultSetNumber = cc.getNextResultSetNumber();\r
+\r
+               // is a distinct query\r
+               mb.push(false);\r
+\r
+               // not in sorted order\r
+               mb.push(false);\r
+\r
+               mb.push(orderItem);\r
+\r
+               // row allocator\r
+               child.getResultColumns().generateHolder(acb, mb);\r
+\r
+               mb.push(child.getResultColumns().getTotalColumnSize());\r
+\r
+               mb.push(resultSetNumber);\r
+\r
+               // Get the cost estimate for the child\r
+               // RESOLVE - we will eventually include the cost of the sort\r
+               CostEstimate costEstimate = child.getFinalCostEstimate(); \r
+\r
+               mb.push(costEstimate.rowCount());\r
+               mb.push(costEstimate.getEstimatedCost());\r
+\r
+               mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getSortResultSet",\r
+                                                       ClassName.NoPutResultSet, 9);\r
+\r
+       }\r
+\r
+       /* RequiredRowOrdering interface */\r
+\r
+       /**\r
+        * @see RequiredRowOrdering#sortRequired\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public int sortRequired(RowOrdering rowOrdering) throws StandardException\r
+       {\r
+               return sortRequired(rowOrdering, (JBitSet) null);\r
+       }\r
+\r
+       /**\r
+        * @see RequiredRowOrdering#sortRequired\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public int sortRequired(RowOrdering rowOrdering, JBitSet tableMap)\r
+                               throws StandardException\r
+       {\r
+               /*\r
+               ** Currently, all indexes are ordered ascending, so a descending\r
+               ** ORDER BY always requires a sort.\r
+               */\r
+               if (alwaysSort)\r
+               {\r
+                       return RequiredRowOrdering.SORT_REQUIRED;\r
+               }\r
+\r
+               /*\r
+               ** Step through the columns in this list, and ask the\r
+               ** row ordering whether it is ordered on each column.\r
+               */\r
+               int position = 0;\r
+               int size = size();\r
+               for (int loc = 0; loc < size; loc++)\r
+               {\r
+                       OrderByColumn obc = getOrderByColumn(loc);\r
+\r
+                       // ResultColumn rc = obc.getResultColumn();\r
+\r
+                       /*\r
+                       ** This presumes that the OrderByColumn refers directly to\r
+                       ** the base column, i.e. there is no intervening VirtualColumnNode.\r
+                       */\r
+                       // ValueNode expr = obc.getNonRedundantExpression();\r
+                       ValueNode expr = obc.getResultColumn().getExpression();\r
+\r
+                       if ( ! (expr instanceof ColumnReference))\r
+                       {\r
+                               return RequiredRowOrdering.SORT_REQUIRED;\r
+                       }\r
+\r
+                       ColumnReference cr = (ColumnReference) expr;\r
+\r
+                       /*\r
+                       ** Check whether the table referred to is in the table map (if any).\r
+                       ** If it isn't, we may have an ordering that does not require\r
+                       ** sorting for the tables in a partial join order.  Look for\r
+                       ** columns beyond this column to see whether a referenced table\r
+                       ** is found - if so, sorting is required (for example, in a\r
+                       ** case like ORDER BY S.A, T.B, S.C, sorting is required).\r
+                       */\r
+                       if (tableMap != null)\r
+                       {\r
+                               if ( ! tableMap.get(cr.getTableNumber()))\r
+                               {\r
+                                       /* Table not in partial join order */\r
+                                       for (int remainingPosition = loc + 1;\r
+                                                remainingPosition < size();\r
+                                                remainingPosition++)\r
+                                       {\r
+                                               OrderByColumn remainingobc = getOrderByColumn(loc);\r
+\r
+                                               ResultColumn remainingrc =\r
+                                                                                               remainingobc.getResultColumn();\r
+\r
+                                               ValueNode remainingexpr = remainingrc.getExpression();\r
+\r
+                                               if (remainingexpr instanceof ColumnReference)\r
+                                               {\r
+                                                       ColumnReference remainingcr =\r
+                                                                                       (ColumnReference) remainingexpr;\r
+                                                       if (tableMap.get(remainingcr.getTableNumber()))\r
+                                                       {\r
+                                                               return RequiredRowOrdering.SORT_REQUIRED;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       return RequiredRowOrdering.NOTHING_REQUIRED;\r
+                               }\r
+                       }\r
+\r
+                       if ( ! rowOrdering.alwaysOrdered(cr.getTableNumber()))\r
+                       {\r
+                               /*\r
+                               ** Check whether the ordering is ordered on this column in\r
+                               ** this position.\r
+                               */\r
+                               if ( ! rowOrdering.orderedOnColumn(\r
+                                       obc.isAscending() ?\r
+                                                               RowOrdering.ASCENDING : RowOrdering.DESCENDING,\r
+                                       position,\r
+                                       cr.getTableNumber(),\r
+                                       cr.getColumnNumber()\r
+                                       ))\r
+                               {\r
+                                       return RequiredRowOrdering.SORT_REQUIRED;\r
+                               }\r
+\r
+                               /*\r
+                               ** The position to ask about is for the columns in tables\r
+                               ** that are *not* always ordered.  The always-ordered tables\r
+                               ** are not counted as part of the list of ordered columns\r
+                               */\r
+                               position++;\r
+                       }\r
+               }\r
+\r
+               return RequiredRowOrdering.NOTHING_REQUIRED;\r
+       }\r
+\r
+       /**\r
+        * @see RequiredRowOrdering#estimateCost\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       public void estimateCost(double estimatedInputRows,\r
+                                                               RowOrdering rowOrdering,\r
+                                                               CostEstimate resultCost)\r
+                                       throws StandardException\r
+       {\r
+               /*\r
+               ** Do a bunch of set-up the first time: get the SortCostController,\r
+               ** the template row, the ColumnOrdering array, and the estimated\r
+               ** row size.\r
+               */\r
+               if (scc == null)\r
+               {\r
+                       scc = getCompilerContext().getSortCostController();\r
+\r
+                       resultRow =\r
+                               resultToSort.getResultColumns().buildEmptyRow().getRowArray();\r
+                       columnOrdering = getColumnOrdering();\r
+                       estimatedRowSize =\r
+                                               resultToSort.getResultColumns().getTotalColumnSize();\r
+               }\r
+\r
+               long inputRows = (long) estimatedInputRows;\r
+               long exportRows = inputRows;\r
+               double sortCost;\r
+\r
+               sortCost = scc.getSortCost(\r
+                                                                       (DataValueDescriptor[]) resultRow,\r
+                                                                       columnOrdering,\r
+                                                                       false,\r
+                                                                       inputRows,\r
+                                                                       exportRows,\r
+                                                                       estimatedRowSize\r
+                                                                       );\r
+\r
+               resultCost.setCost(sortCost, estimatedInputRows, estimatedInputRows);\r
+       }\r
+\r
+       /** @see RequiredRowOrdering#sortNeeded */\r
+       public void sortNeeded()\r
+       {\r
+               sortNeeded = true;\r
+       }\r
+\r
+       /** @see RequiredRowOrdering#sortNotNeeded */\r
+       public void sortNotNeeded()\r
+       {\r
+               sortNeeded = false;\r
+       }\r
+\r
+       /**\r
+        * Remap all ColumnReferences in this tree to be clones of the\r
+        * underlying expression.\r
+        *\r
+        * @exception StandardException         Thrown on error\r
+        */\r
+       void remapColumnReferencesToExpressions() throws StandardException\r
+       {\r
+       }\r
+\r
+       /**\r
+        * Get whether or not a sort is needed.\r
+        *\r
+        * @return Whether or not a sort is needed.\r
+        */\r
+       public boolean getSortNeeded()\r
+       {\r
+               return sortNeeded;\r
+       }\r
+\r
+       /**\r
+        * Determine whether or not this RequiredRowOrdering has a\r
+        * DESCENDING requirement for the column referenced by the\r
+        * received ColumnReference.\r
+        */\r
+       boolean requiresDescending(ColumnReference cRef, int numOptimizables)\r
+               throws StandardException\r
+       {\r
+               int size = size();\r
+\r
+               /* Start by getting the table number and column position for\r
+                * the table to which the ColumnReference points.\r
+                */\r
+               JBitSet tNum = new JBitSet(numOptimizables);\r
+               BaseTableNumbersVisitor btnVis = new BaseTableNumbersVisitor(tNum);\r
+\r
+               cRef.accept(btnVis);\r
+               int crTableNumber = tNum.getFirstSetBit();\r
+               int crColPosition = btnVis.getColumnNumber();\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       /* We assume that we only ever get here if the column\r
+                        * reference points to a specific column in a specific\r
+                        * table...\r
+                        */\r
+                       if ((crTableNumber < 0) || (crColPosition < 0))\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                       "Failed to find table/column number for column '" +\r
+                                       cRef.getColumnName() + "' when checking for an " +\r
+                                       "ORDER BY requirement.");\r
+                       }\r
+\r
+                       /* Since we started with a single ColumnReference there\r
+                        * should be exactly one table number.\r
+                        */\r
+                       if (!tNum.hasSingleBitSet())\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                       "Expected ColumnReference '" + cRef.getColumnName() +\r
+                                       "' to reference exactly one table, but tables found " +\r
+                                       "were: " + tNum);\r
+                       }\r
+               }\r
+\r
+               /* Walk through the various ORDER BY elements to see if\r
+                * any of them point to the same table and column that\r
+                * we found above.\r
+                */\r
+               for (int loc = 0; loc < size; loc++)\r
+               {\r
+                       OrderByColumn obc = getOrderByColumn(loc);\r
+                       ResultColumn rcOrderBy = obc.getResultColumn();\r
+\r
+                       btnVis.reset();\r
+                       rcOrderBy.accept(btnVis);\r
+                       int obTableNumber = tNum.getFirstSetBit();\r
+                       int obColPosition = btnVis.getColumnNumber();\r
+\r
+                       /* ORDER BY target should always have a table number and\r
+                        * a column position.  It may not necessarily be a base\r
+                        * table, but there should be some FromTable for which\r
+                        * we have a ResultColumnList, and the ORDER BY should\r
+                        * reference one of the columns in that list (otherwise\r
+                        * we shouldn't have made it this far).\r
+                        */\r
+                       if (SanityManager.DEBUG)\r
+                       {\r
+                               /* Since we started with a single ResultColumn there\r
+                                * should exactly one table number.\r
+                                */\r
+                               if (!tNum.hasSingleBitSet())\r
+                               {\r
+                                       SanityManager.THROWASSERT("Expected ResultColumn '" +\r
+                                               rcOrderBy.getColumnName() + "' to reference " +\r
+                                               "exactly one table, but found: " + tNum);\r
+                               }\r
+\r
+                               if (obColPosition < 0)\r
+                               {\r
+                                       SanityManager.THROWASSERT(\r
+                                               "Failed to find orderBy column number " +\r
+                                               "for ORDER BY check on column '" + \r
+                                               cRef.getColumnName() + "'.");\r
+                               }\r
+                       }\r
+\r
+                       if (crTableNumber != obTableNumber)\r
+                               continue;\r
+\r
+                       /* They point to the same base table, so check the\r
+                        * column positions.\r
+                        */\r
+\r
+                       if (crColPosition == obColPosition)\r
+                       {\r
+                               /* This ORDER BY element points to the same table\r
+                                * and column as the received ColumnReference.  So\r
+                                * return whether or not this ORDER BY element is\r
+                                * descending.\r
+                                */\r
+                               return !obc.isAscending();\r
+                       }\r
+               }\r
+\r
+               /* None of the ORDER BY elements referenced the same table\r
+                * and column as the received ColumnReference, so there\r
+                * is no descending requirement for the ColumnReference's\r
+                * source (at least not from this OrderByList).\r
+                */\r
+               return false;\r
+       }\r
+}\r