Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / iapi / store / access / RowUtil.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/iapi/store/access/RowUtil.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/iapi/store/access/RowUtil.java
new file mode 100644 (file)
index 0000000..c01105c
--- /dev/null
@@ -0,0 +1,692 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.iapi.store.access.RowUtil\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.iapi.store.access;\r
+\r
+import org.apache.derby.iapi.error.StandardException; \r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+import org.apache.derby.iapi.services.io.Storable;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.store.raw.FetchDescriptor;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+/**\r
+  A set of static utility methods to work with rows.\r
+  <P>\r
+  A row or partial row is described by two or three parameters.\r
+  <OL>\r
+  <LI>DataValueDescriptor[] row - an array of objects, one per column.\r
+  <LI>FormatableBitSet validColumns - \r
+      an indication of which objects in row map to which columns\r
+  </OL>\r
+  These objects can describe a complete row or a partial row. A partial row is \r
+  one where a sub-set (e.g. columns 0, 4 and 7) of the columns are supplied \r
+  for update, or requested to be fetched on a read.  Here's an example\r
+  of code to set up a partial column list to fetch the 0th (type FOO), \r
+  4th (type BAR), and 7th (type MMM) columns from a row with 10 columns, note\r
+  that the format for a partial row changed from a "packed" representation\r
+  in the 3.0 release to a "sparse" representation in later releases:\r
+\r
+  <blockquote><pre>\r
+\r
+  // allocate/initialize the row \r
+  DataValueDescriptor row = new DataValueDescriptor[10]\r
+  row[0] = new FOO();\r
+  row[4] = new BAR();\r
+  row[7] = new MMM();\r
+  \r
+  // allocate/initialize the bit set \r
+  FormatableBitSet FormatableBitSet = new FormatableBitSet(10);\r
+  \r
+  FormatableBitSet.set(0);\r
+  FormatableBitSet.set(4);\r
+  FormatableBitSet.set(7);\r
+  </blockquote></pre>\r
+\r
+\r
+  <BR><B>Column mapping<B><BR>\r
+  When validColumns is null:\r
+  <UL>\r
+  <LI> The number of columns is given by row.length\r
+  <LI> Column N maps to row[N], where column numbers start at zero.\r
+  </UL>\r
+  <BR>\r
+  When validColumns is not null, then\r
+  <UL>\r
+  <LI> The number of requested columns is given by the number of bits set in \r
+       validColumns.\r
+  <LI> Column N is not in the partial row if validColumns.isSet(N) \r
+       returns false.\r
+  <LI> Column N is in the partial row if validColumns.isSet(N) returns true.\r
+  <LI> If column N is in the partial row then it maps to row[N].\r
+          If N >= row.length then the column is taken as non existent for an\r
+          insert or update, and not fetched on a fetch.\r
+  </UL>\r
+  If row.length is greater than the number of columns indicated by validColumns\r
+  the extra entries are ignored.\r
+\r
+**/\r
+public class RowUtil\r
+{\r
+       private RowUtil() {}\r
+\r
+       /**\r
+               An object that can be used on a fetch to indicate no fields\r
+               need to be fetched.\r
+       */\r
+       public static final DataValueDescriptor[] EMPTY_ROW = \r
+        new DataValueDescriptor[0];\r
+\r
+       /**\r
+               An object that can be used on a fetch as a FormatableBitSet to indicate no fields\r
+               need to be fetched.\r
+       */\r
+       public static final FormatableBitSet EMPTY_ROW_BITSET  = \r
+        new FormatableBitSet(0);\r
+\r
+       /**\r
+               An object that can be used on a fetch as a FormatableBitSet to indicate no fields\r
+               need to be fetched.\r
+       */\r
+       public static final FetchDescriptor EMPTY_ROW_FETCH_DESCRIPTOR  = \r
+        new FetchDescriptor(0);\r
+\r
+       private static final FetchDescriptor[] ROWUTIL_FETCH_DESCRIPTOR_CONSTANTS  =\r
+        {EMPTY_ROW_FETCH_DESCRIPTOR,\r
+         new FetchDescriptor(1, 1),\r
+         new FetchDescriptor(2, 2),\r
+         new FetchDescriptor(3, 3),\r
+         new FetchDescriptor(4, 4),\r
+         new FetchDescriptor(5, 5),\r
+         new FetchDescriptor(6, 6),\r
+         new FetchDescriptor(7, 7)};\r
+\r
+\r
+       /**\r
+               Get the object for a column identifer (0 based) from a complete or \r
+        partial row.\r
+\r
+               @param row the row\r
+               @param columnList valid columns in the row\r
+               @param columnId which column to return (0 based)\r
+\r
+               @return the obejct for the column, or null if the column is not represented.\r
+       */\r
+       public static DataValueDescriptor getColumn(\r
+    DataValueDescriptor[]   row, \r
+    FormatableBitSet                 columnList, \r
+    int                     columnId) \r
+    {\r
+\r
+               if (columnList == null)\r
+                       return columnId < row.length ? row[columnId] : null;\r
+\r
+\r
+               if (!(columnList.getLength() > columnId && columnList.isSet(columnId)))\r
+                       return null;\r
+\r
+        return columnId < row.length ? row[columnId] : null;\r
+\r
+       }\r
+\r
+       public static Object getColumn(\r
+    Object[]   row, \r
+    FormatableBitSet                 columnList, \r
+    int                     columnId) \r
+    {\r
+\r
+               if (columnList == null)\r
+                       return columnId < row.length ? row[columnId] : null;\r
+\r
+\r
+               if (!(columnList.getLength() > columnId && columnList.isSet(columnId)))\r
+                       return null;\r
+\r
+        return columnId < row.length ? row[columnId] : null;\r
+\r
+       }\r
+\r
+       /**\r
+               Get a FormatableBitSet representing all the columns represented in\r
+               a qualifier list.\r
+\r
+               @return a FormatableBitSet describing the valid columns.\r
+       */\r
+       public static FormatableBitSet getQualifierBitSet(Qualifier[][] qualifiers) \r
+    {\r
+               FormatableBitSet qualifierColumnList = new FormatableBitSet();\r
+\r
+               if (qualifiers != null) \r
+        {\r
+                       for (int i = 0; i < qualifiers.length; i++)\r
+                       {\r
+                for (int j = 0; j < qualifiers[i].length; j++)\r
+                {\r
+                    int colId = qualifiers[i][j].getColumnId();\r
+\r
+                    // we are about to set bit colId, need length to be colId+1\r
+                    qualifierColumnList.grow(colId+1);\r
+                    qualifierColumnList.set(colId);\r
+                }\r
+                       }\r
+               }\r
+\r
+               return qualifierColumnList;\r
+       }\r
+\r
+    /**\r
+     * Get the number of columns represented by a FormatableBitSet.\r
+     * <p>\r
+     * This is simply a count of the number of bits set in the FormatableBitSet.\r
+     * <p>\r
+     *\r
+     * @param maxColumnNumber Because the FormatableBitSet.size() can't be used as\r
+     *                        the number of columns, allow caller to tell\r
+     *                        the maximum column number if it knows.  \r
+     *                        -1  means caller does not know.\r
+     *                        >=0 number is the largest column number.\r
+     *                           \r
+     * @param columnList valid columns in the row\r
+     *\r
+        * @return The number of columns represented in the FormatableBitSet.\r
+     **/\r
+    public static int getNumberOfColumns(\r
+    int     maxColumnNumber,\r
+    FormatableBitSet  columnList)\r
+    {\r
+        if (SanityManager.DEBUG)\r
+            SanityManager.ASSERT(columnList != null);\r
+\r
+        int max_col_number = columnList.getLength();\r
+\r
+               if (maxColumnNumber > 0 && maxColumnNumber < max_col_number)\r
+                       max_col_number = maxColumnNumber;\r
+\r
+        int ret_num_cols = 0;\r
+\r
+        for (int i = 0; i < max_col_number; i++)\r
+        {\r
+            if (columnList.isSet(i))\r
+                ret_num_cols++;\r
+        }\r
+\r
+        return(ret_num_cols);\r
+    }\r
+\r
+       /**\r
+               See if a row actually contains no columns.\r
+               Returns true if row is null or row.length is zero.\r
+\r
+               @return true if row is empty.\r
+       */\r
+       public static boolean isRowEmpty(\r
+    DataValueDescriptor[]   row) \r
+    {\r
+\r
+               if (row == null)\r
+                       return true;\r
+\r
+               if (row.length == 0)\r
+                       return true;\r
+\r
+               return false;\r
+       }\r
+\r
+       /**\r
+               Return the column number of the first column out of range, or a number\r
+        less than zero if all columns are in range.\r
+       */\r
+       public static int columnOutOfRange(\r
+    DataValueDescriptor[]   row, \r
+    FormatableBitSet                 columnList, \r
+    int                     maxColumns) \r
+    {\r
+\r
+               if (columnList == null) {\r
+                       if (row.length > maxColumns)\r
+                               return maxColumns;\r
+\r
+                       return -1;\r
+               }\r
+\r
+               int size = columnList.getLength();\r
+               for (int i = maxColumns; i < size; i++) {\r
+                       if (columnList.isSet(i))\r
+                               return i;\r
+               }\r
+\r
+               return -1;\r
+       }\r
+\r
+       /**\r
+               Get the next valid column after or including start column.\r
+               Returns -1 if no valid columns exist after startColumn\r
+       */\r
+       public static int nextColumn(\r
+    Object[]   row, \r
+    FormatableBitSet                 columnList, \r
+    int                     startColumn) \r
+    {\r
+\r
+               if (columnList != null) {\r
+\r
+                       int size = columnList.getLength();\r
+\r
+                       for (; startColumn < size; startColumn++) {\r
+                               if (columnList.isSet(startColumn)) {\r
+                                       return startColumn;\r
+                               }\r
+                       }\r
+\r
+                       return -1;\r
+               }\r
+\r
+               if (row == null)\r
+                       return -1;\r
+\r
+               return startColumn < row.length ? startColumn : -1;\r
+       }\r
+\r
+    /**\r
+     * Return a FetchDescriptor which describes a single column set.\r
+     * <p>\r
+     * This routine returns one of a set of constant FetchDescriptor's, and\r
+     * should not be altered by the caller.\r
+     **/\r
+    public static final FetchDescriptor getFetchDescriptorConstant(\r
+    int     single_column_number)\r
+    {\r
+        if (single_column_number < ROWUTIL_FETCH_DESCRIPTOR_CONSTANTS.length)\r
+        {\r
+            return(ROWUTIL_FETCH_DESCRIPTOR_CONSTANTS[single_column_number]);\r
+        }\r
+        else\r
+        {\r
+            return(\r
+                new FetchDescriptor(\r
+                    single_column_number, single_column_number));\r
+        }\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Methods dealing with cloning and row copying util functions\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Generate a template row of DataValueDescriptor's\r
+     * <p>\r
+     * Generate an array of DataValueDescriptor objects which will be used to \r
+     * make calls to newRowFromClassInfoTemplate(), to repeatedly and\r
+     * efficiently generate new rows.  This is important for certain \r
+     * applications like the sorter and fetchSet which generate large numbers\r
+     * of "new" empty rows.\r
+     * <p>\r
+     *\r
+        * @return The new row.\r
+     *\r
+     * @param column_list A bit set indicating which columns to include in row.\r
+     * @param format_ids  an array of format id's, one per column in row.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public static DataValueDescriptor[] newTemplate(\r
+    DataValueFactory    dvf,\r
+    FormatableBitSet    column_list,\r
+    int[]               format_ids,\r
+    int[]               collation_ids) \r
+        throws StandardException\r
+    {\r
+        int                   num_cols = format_ids.length;\r
+        DataValueDescriptor[] ret_row  = new DataValueDescriptor[num_cols];\r
+\r
+               int column_listSize = \r
+            (column_list == null) ? 0 : column_list.getLength();\r
+\r
+        for (int i = 0; i < num_cols; i++)\r
+        {\r
+            // does caller want this column?\r
+            if ((column_list != null)   && \r
+                !((column_listSize > i) && \r
+                (column_list.isSet(i))))\r
+            {\r
+                // no - column should be skipped.\r
+            }\r
+            else\r
+            {\r
+                // yes - create the column \r
+\r
+                // get empty instance of object identified by the format id.\r
+\r
+                ret_row[i] = dvf.getNull(format_ids[i], collation_ids[i]);\r
+            }\r
+        }\r
+\r
+        return(ret_row);\r
+    }\r
+\r
+\r
+    private static void newRowFromClassInfoTemplateError()\r
+    {\r
+        if (SanityManager.DEBUG)\r
+            SanityManager.THROWASSERT(\r
+                "unexpected error in newRowFromClassInfoTemplate()");\r
+    }\r
+\r
+    /**\r
+     * Generate an "empty" row from an array of DataValueDescriptor objects.\r
+     * <p>\r
+     * Generate an array of new'd objects by using the getNewNull()\r
+     * method on each of the DataValueDescriptor objects.  \r
+     * <p>\r
+     *\r
+        * @return The new row.\r
+     *\r
+     * @param  template            An array of DataValueDescriptor objects \r
+     *                             each of which can be used to create a new \r
+     *                             instance of the appropriate type to build a \r
+     *                             new empty template row.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public static DataValueDescriptor[] newRowFromTemplate(\r
+    DataValueDescriptor[]    template) \r
+        throws StandardException\r
+    {\r
+\r
+        DataValueDescriptor[] columns = \r
+            new DataValueDescriptor[template.length];\r
+\r
+        \r
+        for (int column_index = template.length; column_index-- > 0;)\r
+        {\r
+            if (template[column_index] != null)\r
+            {\r
+                // get empty instance of DataValueDescriptor identified by \r
+                // the format id.\r
+                columns[column_index] = template[column_index].getNewNull();\r
+            }\r
+        }\r
+\r
+               return columns;\r
+    }\r
+\r
+\r
+    /**\r
+     * return string version of row.\r
+     * <p>\r
+     * For debugging only. \r
+     *\r
+        * @return The string version of row.\r
+     *\r
+     * @param row The row.\r
+     *\r
+     **/\r
+    public static String toString(Object[] row)\r
+    {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+\r
+            String str = new String();\r
+\r
+            if (row != null)\r
+            {\r
+                if (row.length == 0)\r
+                {\r
+                    str = "empty row";\r
+                }\r
+                else\r
+                {\r
+                    for (int i = 0; i < row.length; i++)\r
+                        str += "col[" + i + "]=" + row[i];\r
+                }\r
+            }\r
+            else\r
+            {\r
+                str = "row is null";\r
+            }\r
+\r
+            return(str);\r
+        }\r
+        else\r
+        {\r
+            return(null);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * return string version of a HashTable returned from a FetchSet.\r
+     * <p>\r
+     *\r
+        * @return The string version of row.\r
+     *\r
+     *\r
+     **/\r
+\r
+    // For debugging only. \r
+    public static String toString(Hashtable hash_table)\r
+    {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            String str = new String();\r
+\r
+            Object  row_or_vector;\r
+\r
+            for (Enumeration e = hash_table.elements(); e.hasMoreElements();)\r
+            {\r
+                row_or_vector = e.nextElement();\r
+\r
+                if (row_or_vector instanceof Object[])\r
+                {\r
+                    // it's a row\r
+                    str += RowUtil.toString((Object[]) row_or_vector);\r
+                    str += "\n";\r
+                }\r
+                else if (row_or_vector instanceof Vector)\r
+                {\r
+                    // it's a vector\r
+                    Vector vec = (Vector) row_or_vector;\r
+\r
+                    for (int i = 0; i < vec.size(); i++)\r
+                    {\r
+                        str += \r
+                            "vec[" + i + "]:" + \r
+                            RowUtil.toString((Object[]) vec.elementAt(i));\r
+\r
+                        str += "\n";\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    str += "BAD ENTRY\n";\r
+                }\r
+            }\r
+            return(str);\r
+        }\r
+        else\r
+        {\r
+            return(null);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Process the qualifier list on the row, return true if it qualifies.\r
+     * <p>\r
+     * A two dimensional array is to be used to pass around a AND's and OR's in\r
+     * conjunctive normal form.  The top slot of the 2 dimensional array is \r
+     * optimized for the more frequent where no OR's are present.  The first \r
+     * array slot is always a list of AND's to be treated as described above \r
+     * for single dimensional AND qualifier arrays.  The subsequent slots are \r
+     * to be treated as AND'd arrays or OR's.  Thus the 2 dimensional array \r
+     * qual[][] argument is to be treated as the following, note if \r
+     * qual.length = 1 then only the first array is valid and it is and an \r
+     * array of and clauses:\r
+     *\r
+     * (qual[0][0] and qual[0][0] ... and qual[0][qual[0].length - 1])\r
+     * and\r
+     * (qual[1][0] or  qual[1][1] ... or  qual[1][qual[1].length - 1])\r
+     * and\r
+     * (qual[2][0] or  qual[2][1] ... or  qual[2][qual[2].length - 1])\r
+     * ...\r
+     * and\r
+     * (qual[qual.length - 1][0] or  qual[1][1] ... or  qual[1][2])\r
+     *\r
+     * \r
+        * @return true if the row qualifies.\r
+     *\r
+     * @param row               The row being qualified.\r
+     * @param qual_list         2 dimensional array representing conjunctive\r
+     *                          normal form of simple qualifiers.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       public static final boolean qualifyRow(\r
+    Object[]        row, \r
+    Qualifier[][]   qual_list)\r
+                throws StandardException\r
+       {\r
+        boolean     row_qualifies = true;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(row != null);\r
+        }\r
+\r
+        // First do the qual[0] which is an array of qualifer terms.\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            // routine should not be called if there is no qualifier\r
+            SanityManager.ASSERT(qual_list != null);\r
+            SanityManager.ASSERT(qual_list.length > 0);\r
+        }\r
+\r
+        for (int i = 0; i < qual_list[0].length; i++)\r
+        {\r
+            // process each AND clause \r
+\r
+            row_qualifies = false;\r
+\r
+            // process each OR clause.\r
+\r
+            Qualifier q = qual_list[0][i];\r
+\r
+            // Get the column from the possibly partial row, of the \r
+            // q.getColumnId()'th column in the full row.\r
+            DataValueDescriptor columnValue = \r
+                    (DataValueDescriptor) row[q.getColumnId()];\r
+\r
+            row_qualifies =\r
+                columnValue.compare(\r
+                    q.getOperator(),\r
+                    q.getOrderable(),\r
+                    q.getOrderedNulls(),\r
+                    q.getUnknownRV());\r
+\r
+            if (q.negateCompareResult())\r
+                row_qualifies = !row_qualifies;\r
+\r
+            // Once an AND fails the whole Qualification fails - do a return!\r
+            if (!row_qualifies)\r
+                return(false);\r
+        }\r
+\r
+        // all the qual[0] and terms passed, now process the OR clauses\r
+\r
+        for (int and_idx = 1; and_idx < qual_list.length; and_idx++)\r
+        {\r
+            // loop through each of the "and" clause.\r
+\r
+            row_qualifies = false;\r
+\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                // Each OR clause must be non-empty.\r
+                SanityManager.ASSERT(qual_list[and_idx].length > 0);\r
+            }\r
+\r
+            for (int or_idx = 0; or_idx < qual_list[and_idx].length; or_idx++)\r
+            {\r
+                // Apply one qualifier to the row.\r
+                Qualifier q      = qual_list[and_idx][or_idx];\r
+                int       col_id = q.getColumnId();\r
+\r
+                if (SanityManager.DEBUG)\r
+                {\r
+                    SanityManager.ASSERT(\r
+                        (col_id < row.length),\r
+                        "Qualifier is referencing a column not in the row.");\r
+                }\r
+\r
+                // Get the column from the possibly partial row, of the \r
+                // q.getColumnId()'th column in the full row.\r
+                DataValueDescriptor columnValue = \r
+                    (DataValueDescriptor) row[q.getColumnId()];\r
+\r
+                if (SanityManager.DEBUG)\r
+                {\r
+                    if (columnValue == null)\r
+                        SanityManager.THROWASSERT(\r
+                            "1:row = " + RowUtil.toString(row) +\r
+                            "row.length = " + row.length +\r
+                            ";q.getColumnId() = " + q.getColumnId());\r
+                }\r
+\r
+                // do the compare between the column value and value in the\r
+                // qualifier.\r
+                row_qualifies = \r
+                    columnValue.compare(\r
+                            q.getOperator(),\r
+                            q.getOrderable(),\r
+                            q.getOrderedNulls(),\r
+                            q.getUnknownRV());\r
+\r
+                if (q.negateCompareResult())\r
+                    row_qualifies = !row_qualifies;\r
+\r
+                // SanityManager.DEBUG_PRINT("StoredPage.qual", "processing qual[" + and_idx + "][" + or_idx + "] = " + qual_list[and_idx][or_idx] );\r
+\r
+                // SanityManager.DEBUG_PRINT("StoredPage.qual", "value = " + row_qualifies);\r
+\r
+                // processing "OR" clauses, so as soon as one is true, break\r
+                // to go and process next AND clause.\r
+                if (row_qualifies)\r
+                    break;\r
+\r
+            }\r
+\r
+            // The qualifier list represented a set of "AND'd" \r
+            // qualifications so as soon as one is false processing is done.\r
+            if (!row_qualifies)\r
+                break;\r
+        }\r
+\r
+        return(row_qualifies);\r
+    }\r
+\r
+}\r