--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.sql.dictionary.IndexRowGenerator\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.sql.dictionary;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;\r
+\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+\r
+import org.apache.derby.iapi.sql.execute.ExecutionContext;\r
+import org.apache.derby.iapi.sql.execute.ExecIndexRow;\r
+import org.apache.derby.iapi.sql.execute.ExecRow;\r
+import org.apache.derby.iapi.sql.execute.ExecutionFactory;\r
+\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.RowLocation;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+\r
+import org.apache.derby.iapi.services.io.Formatable;\r
+import org.apache.derby.iapi.services.io.FormatIdUtil;\r
+import org.apache.derby.iapi.services.io.StoredFormatIds;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.services.context.ContextService;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.catalog.IndexDescriptor;\r
+import org.apache.derby.catalog.types.IndexDescriptorImpl;\r
+\r
+import java.io.ObjectInput;\r
+import java.io.ObjectOutput;\r
+import java.io.IOException;\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+\r
+/**\r
+ * This class extends IndexDescriptor for internal use by the\r
+ * DataDictionary.\r
+ */\r
+public class IndexRowGenerator implements IndexDescriptor, Formatable\r
+{\r
+ IndexDescriptor id;\r
+ private ExecutionFactory ef;\r
+\r
+ /**\r
+ * Constructor for an IndexRowGeneratorImpl\r
+ *\r
+ * @param indexType The type of index\r
+ * @param isUnique True means the index is unique\r
+ * @param baseColumnPositions An array of column positions in the base\r
+ * table. Each index column corresponds to a\r
+ * column position in the base table.\r
+ * @param isAscending An array of booleans telling asc/desc on each\r
+ * column.\r
+ * @param numberOfOrderedColumns In the future, it will be possible\r
+ * to store non-ordered columns in an\r
+ * index. These will be useful for\r
+ * covered queries.\r
+ */\r
+ public IndexRowGenerator(String indexType,\r
+ boolean isUnique,\r
+ int[] baseColumnPositions,\r
+ boolean[] isAscending,\r
+ int numberOfOrderedColumns)\r
+ {\r
+ id = new IndexDescriptorImpl(indexType,\r
+ isUnique,\r
+ baseColumnPositions,\r
+ isAscending,\r
+ numberOfOrderedColumns);\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(baseColumnPositions != null,\r
+ "baseColumnPositions are null");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Constructor for an IndexRowGeneratorImpl\r
+ *\r
+ * @param indexDescriptor An IndexDescriptor to delegate calls to\r
+ */\r
+ public IndexRowGenerator(IndexDescriptor indexDescriptor)\r
+ {\r
+ id = indexDescriptor;\r
+ }\r
+\r
+ /**\r
+ * Get a template for the index row, to be used with getIndexRow.\r
+ *\r
+ * @return A row template for the index row.\r
+ */\r
+ public ExecIndexRow getIndexRowTemplate()\r
+ {\r
+ return getExecutionFactory().getIndexableRow(\r
+ id.baseColumnPositions().length + 1);\r
+ }\r
+\r
+ /**\r
+ * Get an index row for this index given a row from the base table\r
+ * and the RowLocation of the base row. This method can be used\r
+ * to get the new index row for inserts, and the old and new index\r
+ * rows for deletes and updates. For updates, the result row has\r
+ * all the old column values followed by all of the new column values,\r
+ * so you must form a row using the new column values to pass to\r
+ * this method to get the new index row.\r
+ *\r
+ * @param baseRow A row in the base table\r
+ * @param rowLocation The RowLocation of the row in the base table\r
+ * @param indexRow A template for the index row. It must have the\r
+ * correct number of columns.\r
+ * @param bitSet If non-null, then baseRow is a partial row and the\r
+ * set bits in bitSet represents the column mapping for\r
+ * the partial row to the complete base row. <B> WARNING:\r
+ * </B> ONE based!!!\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void getIndexRow(ExecRow baseRow,\r
+ RowLocation rowLocation,\r
+ ExecIndexRow indexRow,\r
+ FormatableBitSet bitSet)\r
+ throws StandardException\r
+ {\r
+ /*\r
+ ** Set the columns in the index row that are based on columns in\r
+ ** the base row.\r
+ */\r
+ int[] baseColumnPositions = id.baseColumnPositions();\r
+ int colCount = baseColumnPositions.length;\r
+\r
+ if (bitSet == null)\r
+ {\r
+ /*\r
+ ** Set the columns in the index row that are based on columns in\r
+ ** the base row.\r
+ */\r
+ for (int i = 0; i < colCount ; i++)\r
+ {\r
+ indexRow.setColumn(i + 1,\r
+ baseRow.getColumn(baseColumnPositions[i]));\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(!bitSet.get(0), "element zero of the bitSet passed into getIndexRow() is not false, bitSet should be 1 based");\r
+ }\r
+ \r
+ /*\r
+ ** Set the columns in the index row that are based on columns in\r
+ ** the base row.\r
+ */\r
+ for (int i = 0; i < colCount; i++)\r
+ {\r
+ int fullColumnNumber = baseColumnPositions[i];\r
+ int partialColumnNumber = 0;\r
+ for (int index = 1; index <= fullColumnNumber; index++)\r
+ {\r
+ if (bitSet.get(index))\r
+ {\r
+ partialColumnNumber++;\r
+ }\r
+ }\r
+ indexRow.setColumn(i + 1,\r
+ baseRow.getColumn(partialColumnNumber));\r
+ }\r
+ }\r
+\r
+ /* Set the row location in the last column of the index row */\r
+ indexRow.setColumn(colCount + 1, rowLocation);\r
+ }\r
+\r
+ /**\r
+ * Get a NULL Index Row for this index. This is useful to create objects \r
+ * that need to be passed to ScanController.\r
+ *\r
+ * @param columnList ColumnDescriptors describing the base table.\r
+ * @param rowLocation empty row location.\r
+ *\r
+ * @exception StandardException thrown on error.\r
+ */\r
+ public ExecIndexRow getNullIndexRow(ColumnDescriptorList columnList,\r
+ RowLocation rowLocation)\r
+ throws StandardException \r
+ {\r
+ int[] baseColumnPositions = id.baseColumnPositions();\r
+ int i;\r
+ ExecIndexRow indexRow = getIndexRowTemplate();\r
+\r
+ for (i = 0; i < baseColumnPositions.length; i++)\r
+ {\r
+ DataTypeDescriptor dtd =\r
+ columnList.elementAt(baseColumnPositions[i] - 1).getType();\r
+ indexRow.setColumn(i + 1, dtd.getNull());\r
+ }\r
+\r
+ indexRow.setColumn(i + 1, rowLocation);\r
+ return indexRow;\r
+ }\r
+\r
+ /**\r
+ * Return true iff a change to a set of columns changes the index for this\r
+ * IndexRowGenerator.\r
+ *\r
+ * @param changedColumnIds - holds the 1 based column ids for the changed\r
+ * columns.\r
+ * @return true iff a change to one of the columns in changedColumnIds\r
+ * effects this index. \r
+ */\r
+ public boolean indexChanged(int[] changedColumnIds)\r
+ {\r
+ int[] baseColumnPositions = id.baseColumnPositions();\r
+\r
+ for (int ix = 0; ix < changedColumnIds.length; ix++)\r
+ {\r
+ for (int iy = 0; iy < baseColumnPositions.length; iy++)\r
+ {\r
+ if (changedColumnIds[ix] == baseColumnPositions[iy])\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Return an array of collation ids for this table.\r
+ * <p>\r
+ * Return an array of collation ids, one for each column in the\r
+ * columnDescriptorList. This is useful for passing collation id info\r
+ * down to store, for instance in createConglomerate() to create\r
+ * the index.\r
+ *\r
+ * This is only expected to get called during ddl, so object allocation\r
+ * is ok. \r
+ *\r
+ * @param columnList ColumnDescriptors describing the base table.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ public int[] getColumnCollationIds(ColumnDescriptorList columnList)\r
+ throws StandardException\r
+ {\r
+ int[] base_cols = id.baseColumnPositions();\r
+ int[] collation_ids = new int[base_cols.length + 1];\r
+\r
+ for (int i = 0; i < base_cols.length; i++)\r
+ {\r
+ collation_ids[i] =\r
+ columnList.elementAt(\r
+ base_cols[i] - 1).getType().getCollationType();\r
+ }\r
+\r
+ // row location column at end is always basic collation type.\r
+ collation_ids[collation_ids.length - 1] = \r
+ StringDataValue.COLLATION_TYPE_UCS_BASIC; \r
+\r
+ return(collation_ids);\r
+ }\r
+\r
+ \r
+ /**\r
+ * Get the IndexDescriptor that this IndexRowGenerator is based on.\r
+ */\r
+ public IndexDescriptor getIndexDescriptor()\r
+ {\r
+ return id;\r
+ }\r
+\r
+ /** Zero-argument constructor for Formatable interface */\r
+ public IndexRowGenerator()\r
+ {\r
+ }\r
+\r
+ /** @see IndexDescriptor#isUnique */\r
+ public boolean isUnique()\r
+ {\r
+ return id.isUnique();\r
+ }\r
+\r
+ /** @see IndexDescriptor#baseColumnPositions */\r
+ public int[] baseColumnPositions()\r
+ {\r
+ return id.baseColumnPositions();\r
+ }\r
+\r
+ /** @see IndexDescriptor#getKeyColumnPosition */\r
+ public Integer getKeyColumnPosition(Integer heapColumnPosition)\r
+ {\r
+ return id.getKeyColumnPosition(heapColumnPosition);\r
+ }\r
+\r
+ /** @see IndexDescriptor#getKeyColumnPosition */\r
+ public int getKeyColumnPosition(int heapColumnPosition)\r
+ {\r
+ return id.getKeyColumnPosition(heapColumnPosition);\r
+ }\r
+\r
+ /** @see IndexDescriptor#numberOfOrderedColumns */\r
+ public int numberOfOrderedColumns()\r
+ {\r
+ return id.numberOfOrderedColumns();\r
+ }\r
+\r
+ /** @see IndexDescriptor#indexType */\r
+ public String indexType()\r
+ {\r
+ return id.indexType();\r
+ }\r
+\r
+ public String toString()\r
+ {\r
+ return id.toString();\r
+ }\r
+\r
+ /** @see IndexDescriptor#isAscending */\r
+ public boolean isAscending(Integer keyColumnPosition)\r
+ {\r
+ return id.isAscending(keyColumnPosition);\r
+ }\r
+\r
+ /** @see IndexDescriptor#isDescending */\r
+ public boolean isDescending(Integer keyColumnPosition)\r
+ {\r
+ return id.isDescending(keyColumnPosition);\r
+ }\r
+\r
+ /** @see IndexDescriptor#isAscending */\r
+ public boolean[] isAscending()\r
+ {\r
+ return id.isAscending();\r
+ }\r
+\r
+ /** @see IndexDescriptor#setBaseColumnPositions */\r
+ public void setBaseColumnPositions(int[] baseColumnPositions)\r
+ {\r
+ id.setBaseColumnPositions(baseColumnPositions);\r
+ }\r
+\r
+ /** @see IndexDescriptor#setIsAscending */\r
+ public void setIsAscending(boolean[] isAscending)\r
+ {\r
+ id.setIsAscending(isAscending);\r
+ }\r
+\r
+ /** @see IndexDescriptor#setNumberOfOrderedColumns */\r
+ public void setNumberOfOrderedColumns(int numberOfOrderedColumns)\r
+ {\r
+ id.setNumberOfOrderedColumns(numberOfOrderedColumns);\r
+ }\r
+\r
+ /**\r
+ * Test for value equality\r
+ *\r
+ * @param other The other indexrowgenerator to compare this one with\r
+ *\r
+ * @return true if this indexrowgenerator has the same value as other\r
+ */\r
+\r
+ public boolean equals(Object other)\r
+ {\r
+ return id.equals(other);\r
+ }\r
+\r
+ /**\r
+ @see java.lang.Object#hashCode\r
+ */\r
+ public int hashCode()\r
+ {\r
+ return id.hashCode();\r
+ }\r
+\r
+ private ExecutionFactory getExecutionFactory()\r
+ {\r
+ if (ef == null)\r
+ {\r
+ ExecutionContext ec;\r
+\r
+ ec = (ExecutionContext)\r
+ ContextService.getContext(ExecutionContext.CONTEXT_ID);\r
+ ef = ec.getExecutionFactory();\r
+ }\r
+ return ef;\r
+ }\r
+\r
+ ////////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // EXTERNALIZABLE\r
+ //\r
+ ////////////////////////////////////////////////////////////////////////////\r
+\r
+ /**\r
+ * @see java.io.Externalizable#readExternal\r
+ *\r
+ * @exception IOException Thrown on read error\r
+ * @exception ClassNotFoundException Thrown on read error\r
+ */\r
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException\r
+ {\r
+ id = (IndexDescriptor)in.readObject();\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @exception IOException Thrown on write error\r
+ */\r
+ public void writeExternal(ObjectOutput out) throws IOException\r
+ {\r
+ out.writeObject(id);\r
+ }\r
+\r
+ /* TypedFormat interface */\r
+ public int getTypeFormatId()\r
+ {\r
+ return StoredFormatIds.INDEX_ROW_GENERATOR_V01_ID;\r
+ }\r
+\r
+}\r