001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.IndexSetChanger
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.execute;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025: import org.apache.derby.iapi.error.StandardException;
026: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
027: import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
028: import org.apache.derby.iapi.sql.execute.ExecRow;
029: import org.apache.derby.iapi.sql.execute.ExecutionFactory;
030:
031: import org.apache.derby.iapi.sql.Activation;
032:
033: import org.apache.derby.iapi.store.access.ConglomerateController;
034: import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
035: import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
036: import org.apache.derby.iapi.store.access.TransactionController;
037:
038: import org.apache.derby.iapi.types.RowLocation;
039:
040: import org.apache.derby.iapi.services.io.FormatableBitSet;
041:
042: /**
043: Perform Index maintenace associated with DML operations for a table's
044: indexes.
045: */
046: public class IndexSetChanger {
047: //
048: //Index row generators.
049: IndexRowGenerator[] irgs;
050: //
051: //Index conglomerate ids. indexCIDS[ix] is the conglomerate id
052: //for the index with IndexRowGenerator irgs[ix].
053: long[] indexCIDS;
054: private DynamicCompiledOpenConglomInfo[] indexDCOCIs;
055: private StaticCompiledOpenConglomInfo[] indexSCOCIs;
056: String[] indexNames;
057: ConglomerateController baseCC;
058: FormatableBitSet baseRowReadMap;
059:
060: // TransactionController for management of temporary conglomerates
061: TransactionController tc;
062:
063: TemporaryRowHolderImpl rowHolder;
064:
065: IndexChanger[] indexChangers;
066:
067: // Lock mode for the indexes
068: private int lockMode;
069:
070: //Set on open.
071: boolean[] fixOnUpdate;
072:
073: boolean isOpen = false;
074:
075: //
076: //Name for the set of no indexes
077: private static final int NO_INDEXES = 0;
078: //
079: //Name for the set of indexes we change on a update operation
080: private static final int UPDATE_INDEXES = 1;
081: //
082: //Name for the set of all indexes.
083: private static final int ALL_INDEXES = 2;
084:
085: //
086: //To start, no indexes are open.
087: private int whatIsOpen = NO_INDEXES;
088:
089: private int isolationLevel;
090: private Activation activation;
091:
092: /**
093: Create a new IndexSetChanger
094:
095: @param irgs the IndexRowGenerators for the table's indexes. We use
096: positions in this array as local id's for indexes.
097: @param indexCIDS the conglomerate ids for the table's indexes.
098: indexCIDS[ix] corresponds to the same index as irgs[ix].
099: @param indexSCOCIs the SCOCIs for the table's idexes.
100: indexSCOCIs[ix] corresponds to the same index as irgs[ix].
101: @param indexDCOCIs the DCOCIs for the table's idexes.
102: indexDCOCIs[ix] corresponds to the same index as irgs[ix].
103: @param baseCC a ConglomerateController for the base table.
104: @param tc a TransactionController for managing temporary conglomerates
105: @param lockMode The lock mode (granularity) for the indexes.
106: @param baseRowReadMap Map of columns read in. 1 based.
107: @param isolationLevel Isolation level to use
108: @param activation Current activation
109: @exception StandardException Thrown on error
110: */
111: public IndexSetChanger(IndexRowGenerator[] irgs, long[] indexCIDS,
112: StaticCompiledOpenConglomInfo[] indexSCOCIs,
113: DynamicCompiledOpenConglomInfo[] indexDCOCIs,
114: String[] indexNames, ConglomerateController baseCC,
115: TransactionController tc, int lockMode,
116: FormatableBitSet baseRowReadMap, int isolationLevel,
117: Activation activation) throws StandardException {
118: this .irgs = irgs;
119: this .indexCIDS = indexCIDS;
120: this .indexSCOCIs = indexSCOCIs;
121: this .indexDCOCIs = indexDCOCIs;
122: this .indexNames = indexNames;
123: this .baseCC = baseCC;
124: this .tc = tc;
125: this .lockMode = lockMode;
126: this .baseRowReadMap = baseRowReadMap;
127: this .isolationLevel = isolationLevel;
128: this .activation = activation;
129:
130: if (SanityManager.DEBUG) {
131: SanityManager
132: .ASSERT(indexCIDS != null, "indexCIDS is null");
133: }
134:
135: indexChangers = new IndexChanger[irgs.length];
136: }
137:
138: /**
139: Open this IndexSetchanger.
140:
141: @param fixOnUpdate indicates which indexes to correct due
142: to an update. The entries in this array must be in the
143: same order as the entries in the irgs array that was
144: passed to the constructor.
145:
146: @exception StandardException Thrown on error
147: */
148: public void open(boolean[] fixOnUpdate) throws StandardException {
149: if (SanityManager.DEBUG)
150: SanityManager.ASSERT(!isOpen,
151: "IndexSetChanger already open");
152:
153: this .fixOnUpdate = fixOnUpdate;
154: isOpen = true;
155: }
156:
157: /**
158: * Set the row holder for all underlying changers to use.
159: * If the row holder is set, underlying changers wont bother
160: * saving copies of rows needed for deferred
161: * processing. Also, it will never close the
162: * passed in rowHolder.
163: *
164: * @param rowHolder the row holder
165: */
166: public void setRowHolder(TemporaryRowHolderImpl rowHolder) {
167: this .rowHolder = rowHolder;
168: }
169:
170: /**
171: Open the indexes that must be fixed if they are not already
172: open.
173:
174: @param whatToOpen must be one of ALL_INDEXES or UPDATE_INDEXES.
175: @exception StandardException Thrown on error
176: */
177: private void openIndexes(int whatToOpen) throws StandardException {
178: if (SanityManager.DEBUG)
179: SanityManager.ASSERT(isOpen, "IndexSetChanger closed");
180:
181: if (whatIsOpen >= whatToOpen)
182: return;
183:
184: for (int ix = 0; ix < indexChangers.length; ix++) {
185: if (whatToOpen == UPDATE_INDEXES && !fixOnUpdate[ix])
186: continue;
187:
188: /* Instantiate an index changer, if it doesn't exist,
189: * otherwise we propagate the CC for the heap to
190: * the index changer.
191: */
192: if (indexChangers[ix] == null) {
193: /* DataDictionary doesn't have compiled info. */
194: indexChangers[ix] = new IndexChanger(
195: irgs[ix],
196: indexCIDS[ix],
197: (indexSCOCIs == null) ? (StaticCompiledOpenConglomInfo) null
198: : indexSCOCIs[ix],
199: (indexDCOCIs == null) ? (DynamicCompiledOpenConglomInfo) null
200: : indexDCOCIs[ix],
201: (indexNames == null) ? null : indexNames[ix],
202: baseCC, tc, lockMode, baseRowReadMap,
203: isolationLevel, activation);
204: indexChangers[ix].setRowHolder(rowHolder);
205: } else {
206: indexChangers[ix].setBaseCC(baseCC);
207: }
208: indexChangers[ix].open();
209: }
210: whatIsOpen = whatToOpen;
211: }
212:
213: /**
214: Perform index maintenance associated with deleting a row
215: from a table.
216:
217: @param baseRow the deleted row.
218: @param baseRowLocation the deleted row's base conglomerate
219: location
220: @exception StandardException Thrown on error
221: */
222: public void delete(ExecRow baseRow, RowLocation baseRowLocation)
223: throws StandardException {
224: openIndexes(ALL_INDEXES);
225: for (int ix = 0; ix < indexChangers.length; ix++)
226: indexChangers[ix].delete(baseRow, baseRowLocation);
227: }
228:
229: /**
230: Perform index maintenance associated with insering a row
231: into a table.
232:
233: @param baseRow the row.
234: @param baseRowLocation the row's base conglomerate
235: location
236: @exception StandardException Thrown on error
237: */
238: public void insert(ExecRow baseRow, RowLocation baseRowLocation)
239: throws StandardException {
240: openIndexes(ALL_INDEXES);
241: for (int ix = 0; ix < indexChangers.length; ix++)
242: indexChangers[ix].insert(baseRow, baseRowLocation);
243: }
244:
245: /**
246: Perform index maintenance associated with updating a row
247: in a table.
248:
249: @param oldBaseRow the old image of the row.
250: @param newBaseRow the new image of the row.
251: @param baseRowLocation the row's base conglomerate
252: location
253: @exception StandardException Thrown on error
254: */
255: public void update(ExecRow oldBaseRow, ExecRow newBaseRow,
256: RowLocation baseRowLocation) throws StandardException {
257: openIndexes(UPDATE_INDEXES);
258: for (int ix = 0; ix < indexChangers.length; ix++)
259: if (fixOnUpdate[ix])
260: indexChangers[ix].update(oldBaseRow, newBaseRow,
261: baseRowLocation);
262: }
263:
264: /**
265: * Propagate the heap's ConglomerateController to
266: * all of the underlying index changers.
267: *
268: * @param baseCC The heap's ConglomerateController.
269: */
270: public void setBaseCC(ConglomerateController baseCC) {
271: for (int ix = 0; ix < indexChangers.length; ix++) {
272: if (indexChangers[ix] != null) {
273: indexChangers[ix].setBaseCC(baseCC);
274: }
275: }
276: this .baseCC = baseCC;
277: }
278:
279: /**
280: Finish processing the changes for this IndexSetChanger. This means
281: doing the deferred inserts for updates of unique indexes.
282:
283: @exception StandardException Thrown on error
284: */
285: public void finish() throws StandardException {
286: for (int ix = 0; ix < indexChangers.length; ix++) {
287: if (indexChangers[ix] != null) {
288: indexChangers[ix].finish();
289: }
290: }
291: }
292:
293: /**
294: Close this IndexSetChanger.
295:
296: @exception StandardException Thrown on error
297: */
298: public void close() throws StandardException {
299: whatIsOpen = NO_INDEXES;
300: for (int ix = 0; ix < indexChangers.length; ix++) {
301: if (indexChangers[ix] != null) {
302: indexChangers[ix].close();
303: }
304: }
305: fixOnUpdate = null;
306: isOpen = false;
307: rowHolder = null;
308: }
309:
310: /**
311: Create a string describing the state of this IndexSetChanger
312: */
313: public String toString() {
314: if (SanityManager.DEBUG) {
315: String whatIsOpen_s = null;
316: switch (whatIsOpen) {
317: case NO_INDEXES:
318: whatIsOpen_s = "No open indexes ";
319: break;
320: case UPDATE_INDEXES:
321: whatIsOpen_s = "Update indexes open ";
322: break;
323: case ALL_INDEXES:
324: whatIsOpen_s = "All indexes open ";
325: break;
326: default:
327: SanityManager.THROWASSERT("bad whatIsOpen value "
328: + whatIsOpen);
329: break;
330: }
331:
332: String fixOnUpdate_s = "fixOnUpdate=(";
333: for (int ix = 0; ix < fixOnUpdate.length; ix++) {
334: if (ix > 0)
335: fixOnUpdate_s += ",";
336:
337: fixOnUpdate_s += fixOnUpdate[ix];
338: }
339: fixOnUpdate_s += ")";
340:
341: String indexDesc_s = "\n";
342: for (int ix = 0; ix < indexCIDS.length; ix++) {
343: if (indexChangers[ix] == null)
344: indexDesc_s += " Index[" + ix + "] cid="
345: + indexCIDS[ix] + " closed. \n";
346: else
347: indexDesc_s += " "
348: + indexChangers[ix].toString() + "\n";
349: }
350:
351: return "IndexSetChanger: " + whatIsOpen_s + fixOnUpdate_s
352: + indexDesc_s;
353: }
354:
355: return null;
356: }
357: }
|