--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.execute.IndexSetChanger\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.execute;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;\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.sql.Activation;\r
+\r
+import org.apache.derby.iapi.store.access.ConglomerateController;\r
+import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+import org.apache.derby.iapi.types.RowLocation;\r
+\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+\r
+/**\r
+ Perform Index maintenace associated with DML operations for a table's\r
+ indexes.\r
+ */\r
+public class IndexSetChanger\r
+{\r
+ //\r
+ //Index row generators.\r
+ IndexRowGenerator[] irgs;\r
+ //\r
+ //Index conglomerate ids. indexCIDS[ix] is the conglomerate id\r
+ //for the index with IndexRowGenerator irgs[ix].\r
+ long[] indexCIDS;\r
+ private DynamicCompiledOpenConglomInfo[] indexDCOCIs;\r
+ private StaticCompiledOpenConglomInfo[] indexSCOCIs;\r
+ String[] indexNames;\r
+ ConglomerateController baseCC;\r
+ FormatableBitSet baseRowReadMap;\r
+\r
+ // TransactionController for management of temporary conglomerates\r
+ TransactionController tc;\r
+\r
+ TemporaryRowHolderImpl rowHolder;\r
+\r
+ IndexChanger[] indexChangers;\r
+\r
+ // Lock mode for the indexes\r
+ private int lockMode;\r
+\r
+ //Set on open.\r
+ boolean[] fixOnUpdate;\r
+ \r
+ boolean isOpen = false;\r
+ \r
+ //\r
+ //Name for the set of no indexes\r
+ private static final int NO_INDEXES = 0;\r
+ //\r
+ //Name for the set of indexes we change on a update operation\r
+ private static final int UPDATE_INDEXES = 1;\r
+ //\r
+ //Name for the set of all indexes.\r
+ private static final int ALL_INDEXES = 2;\r
+ \r
+ //\r
+ //To start, no indexes are open.\r
+ private int whatIsOpen = NO_INDEXES;\r
+\r
+ private int isolationLevel;\r
+ private Activation activation;\r
+\r
+ /**\r
+ Create a new IndexSetChanger\r
+\r
+ @param irgs the IndexRowGenerators for the table's indexes. We use\r
+ positions in this array as local id's for indexes.\r
+ @param indexCIDS the conglomerate ids for the table's indexes.\r
+ indexCIDS[ix] corresponds to the same index as irgs[ix].\r
+ @param indexSCOCIs the SCOCIs for the table's idexes. \r
+ indexSCOCIs[ix] corresponds to the same index as irgs[ix].\r
+ @param indexDCOCIs the DCOCIs for the table's idexes. \r
+ indexDCOCIs[ix] corresponds to the same index as irgs[ix].\r
+ @param baseCC a ConglomerateController for the base table.\r
+ @param tc a TransactionController for managing temporary conglomerates\r
+ @param lockMode The lock mode (granularity) for the indexes.\r
+ @param baseRowReadMap Map of columns read in. 1 based.\r
+ @param isolationLevel Isolation level to use\r
+ @param activation Current activation\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public IndexSetChanger(IndexRowGenerator[] irgs,\r
+ long[] indexCIDS,\r
+ StaticCompiledOpenConglomInfo[] indexSCOCIs,\r
+ DynamicCompiledOpenConglomInfo[] indexDCOCIs,\r
+ String[] indexNames,\r
+ ConglomerateController baseCC,\r
+ TransactionController tc,\r
+ int lockMode,\r
+ FormatableBitSet baseRowReadMap,\r
+ int isolationLevel,\r
+ Activation activation)\r
+ throws StandardException\r
+ {\r
+ this.irgs = irgs;\r
+ this.indexCIDS = indexCIDS;\r
+ this.indexSCOCIs = indexSCOCIs;\r
+ this.indexDCOCIs = indexDCOCIs;\r
+ this.indexNames = indexNames;\r
+ this.baseCC = baseCC;\r
+ this.tc = tc;\r
+ this.lockMode = lockMode;\r
+ this.baseRowReadMap = baseRowReadMap;\r
+ this.isolationLevel = isolationLevel;\r
+ this.activation = activation;\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(indexCIDS != null, "indexCIDS is null");\r
+ }\r
+\r
+ indexChangers = new IndexChanger[irgs.length];\r
+ }\r
+ \r
+ /**\r
+ Open this IndexSetchanger.\r
+\r
+ @param fixOnUpdate indicates which indexes to correct due\r
+ to an update. The entries in this array must be in the\r
+ same order as the entries in the irgs array that was\r
+ passed to the constructor.\r
+\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public void open(boolean[] fixOnUpdate)\r
+ throws StandardException\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ SanityManager.ASSERT( ! isOpen, "IndexSetChanger already open");\r
+\r
+ this.fixOnUpdate = fixOnUpdate;\r
+ isOpen = true;\r
+ }\r
+\r
+ /**\r
+ * Set the row holder for all underlying changers to use.\r
+ * If the row holder is set, underlying changers wont bother \r
+ * saving copies of rows needed for deferred\r
+ * processing. Also, it will never close the\r
+ * passed in rowHolder.\r
+ *\r
+ * @param rowHolder the row holder\r
+ */\r
+ public void setRowHolder(TemporaryRowHolderImpl rowHolder)\r
+ {\r
+ this.rowHolder = rowHolder;\r
+ }\r
+\r
+ /**\r
+ Open the indexes that must be fixed if they are not already\r
+ open.\r
+\r
+ @param whatToOpen must be one of ALL_INDEXES or UPDATE_INDEXES.\r
+ @exception StandardException Thrown on error\r
+ */\r
+ private void openIndexes(int whatToOpen)\r
+ throws StandardException\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ SanityManager.ASSERT( isOpen, "IndexSetChanger closed");\r
+\r
+ if (whatIsOpen >= whatToOpen) return;\r
+ \r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ {\r
+ if (whatToOpen == UPDATE_INDEXES &&\r
+ !fixOnUpdate[ix])\r
+ continue;\r
+ \r
+ /* Instantiate an index changer, if it doesn't exist,\r
+ * otherwise we propagate the CC for the heap to\r
+ * the index changer.\r
+ */\r
+ if (indexChangers[ix] == null)\r
+ {\r
+ /* DataDictionary doesn't have compiled info. */\r
+ indexChangers[ix] =\r
+ new IndexChanger(irgs[ix],\r
+ indexCIDS[ix],\r
+ (indexSCOCIs == null) ? \r
+ (StaticCompiledOpenConglomInfo) null :\r
+ indexSCOCIs[ix],\r
+ (indexDCOCIs == null) ? \r
+ (DynamicCompiledOpenConglomInfo) null :\r
+ indexDCOCIs[ix],\r
+ (indexNames == null) ? null : \r
+ indexNames[ix],\r
+ baseCC,\r
+ tc,\r
+ lockMode,\r
+ baseRowReadMap,\r
+ isolationLevel,\r
+ activation);\r
+ indexChangers[ix].setRowHolder(rowHolder);\r
+ }\r
+ else\r
+ {\r
+ indexChangers[ix].setBaseCC(baseCC);\r
+ }\r
+ indexChangers[ix].open();\r
+ }\r
+ whatIsOpen = whatToOpen;\r
+ }\r
+\r
+ /**\r
+ Perform index maintenance associated with deleting a row\r
+ from a table.\r
+\r
+ @param baseRow the deleted row.\r
+ @param baseRowLocation the deleted row's base conglomerate\r
+ location\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public void delete(ExecRow baseRow,\r
+ RowLocation baseRowLocation)\r
+ throws StandardException\r
+ {\r
+ openIndexes(ALL_INDEXES);\r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ indexChangers[ix].delete(baseRow,baseRowLocation);\r
+ }\r
+\r
+ /**\r
+ Perform index maintenance associated with insering a row\r
+ into a table.\r
+\r
+ @param baseRow the row.\r
+ @param baseRowLocation the row's base conglomerate\r
+ location\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public void insert(ExecRow baseRow,\r
+ RowLocation baseRowLocation)\r
+ throws StandardException\r
+ {\r
+ openIndexes(ALL_INDEXES);\r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ indexChangers[ix].insert(baseRow,baseRowLocation);\r
+ }\r
+\r
+ /**\r
+ Perform index maintenance associated with updating a row\r
+ in a table.\r
+\r
+ @param oldBaseRow the old image of the row.\r
+ @param newBaseRow the new image of the row.\r
+ @param baseRowLocation the row's base conglomerate\r
+ location\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public void update(ExecRow oldBaseRow,\r
+ ExecRow newBaseRow,\r
+ RowLocation baseRowLocation)\r
+ throws StandardException\r
+ {\r
+ openIndexes(UPDATE_INDEXES);\r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ if (fixOnUpdate[ix])\r
+ indexChangers[ix].update(oldBaseRow,\r
+ newBaseRow,\r
+ baseRowLocation);\r
+ }\r
+\r
+ /**\r
+ * Propagate the heap's ConglomerateController to\r
+ * all of the underlying index changers.\r
+ *\r
+ * @param baseCC The heap's ConglomerateController.\r
+ */\r
+ public void setBaseCC(ConglomerateController baseCC)\r
+ {\r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ {\r
+ if (indexChangers[ix] != null)\r
+ {\r
+ indexChangers[ix].setBaseCC(baseCC);\r
+ }\r
+ }\r
+ this.baseCC = baseCC;\r
+ }\r
+\r
+ /**\r
+ Finish processing the changes for this IndexSetChanger. This means\r
+ doing the deferred inserts for updates of unique indexes.\r
+\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public void finish()\r
+ throws StandardException\r
+ {\r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ {\r
+ if (indexChangers[ix] != null)\r
+ {\r
+ indexChangers[ix].finish();\r
+ }\r
+ }\r
+ }\r
+ \r
+ /**\r
+ Close this IndexSetChanger.\r
+\r
+ @exception StandardException Thrown on error\r
+ */\r
+ public void close()\r
+ throws StandardException\r
+ {\r
+ whatIsOpen = NO_INDEXES;\r
+ for (int ix = 0; ix < indexChangers.length; ix++)\r
+ {\r
+ if (indexChangers[ix] != null)\r
+ {\r
+ indexChangers[ix].close();\r
+ }\r
+ }\r
+ fixOnUpdate = null;\r
+ isOpen = false;\r
+ rowHolder = null;\r
+ }\r
+\r
+ /**\r
+ Create a string describing the state of this IndexSetChanger\r
+ */\r
+ public String toString()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ String whatIsOpen_s = null;\r
+ switch (whatIsOpen)\r
+ {\r
+ case NO_INDEXES:\r
+ whatIsOpen_s = "No open indexes ";\r
+ break;\r
+ case UPDATE_INDEXES:\r
+ whatIsOpen_s = "Update indexes open ";\r
+ break;\r
+ case ALL_INDEXES:\r
+ whatIsOpen_s = "All indexes open ";\r
+ break;\r
+ default:\r
+ SanityManager.THROWASSERT("bad whatIsOpen value "+whatIsOpen);\r
+ break;\r
+ }\r
+\r
+ String fixOnUpdate_s = "fixOnUpdate=(";\r
+ for (int ix = 0; ix < fixOnUpdate.length; ix++)\r
+ {\r
+ if (ix > 0)\r
+ fixOnUpdate_s+=",";\r
+\r
+ fixOnUpdate_s += fixOnUpdate[ix];\r
+ }\r
+ fixOnUpdate_s +=")";\r
+\r
+ String indexDesc_s = "\n";\r
+ for (int ix = 0; ix < indexCIDS.length; ix++)\r
+ {\r
+ if (indexChangers[ix] == null)\r
+ indexDesc_s += " Index["+ix+"] cid="+\r
+ indexCIDS[ix]+" closed. \n";\r
+ else\r
+ indexDesc_s +=\r
+ " "+\r
+ indexChangers[ix].toString() + "\n";\r
+ }\r
+\r
+ return "IndexSetChanger: "+\r
+ whatIsOpen_s+\r
+ fixOnUpdate_s+\r
+ indexDesc_s;\r
+ }\r
+\r
+ return null;\r
+ }\r
+}\r