001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.DropIndexConstantAction
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:
028: import org.apache.derby.iapi.sql.depend.Dependency;
029: import org.apache.derby.iapi.sql.depend.Dependent;
030:
031: import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
032: import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
033: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
034: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
035: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
036:
037: import org.apache.derby.iapi.sql.depend.DependencyManager;
038: import org.apache.derby.iapi.reference.SQLState;
039: import org.apache.derby.iapi.sql.execute.ConstantAction;
040:
041: import org.apache.derby.iapi.sql.Activation;
042:
043: import org.apache.derby.iapi.store.access.TransactionController;
044:
045: import org.apache.derby.catalog.UUID;
046:
047: import java.util.Enumeration;
048:
049: /**
050: * This class describes actions that are ALWAYS performed for a
051: * DROP INDEX Statement at Execution time.
052: *
053: * @author Jeff Lichtman Cribbed from DropTableConstantAction
054: */
055:
056: class DropIndexConstantAction extends IndexConstantAction {
057:
058: private String fullIndexName;
059: private long tableConglomerateId;
060:
061: // CONSTRUCTORS
062:
063: /**
064: * Make the ConstantAction for a DROP INDEX statement.
065: *
066: *
067: * @param fullIndexName Fully qualified index name
068: * @param indexName Index name.
069: * @param tableName The table name
070: * @param schemaName Schema that index lives in.
071: * @param tableId UUID for table
072: * @param tableConglomerateId heap Conglomerate Id for table
073: *
074: */
075: DropIndexConstantAction(String fullIndexName, String indexName,
076: String tableName, String schemaName, UUID tableId,
077: long tableConglomerateId) {
078: super (tableId, indexName, tableName, schemaName);
079: this .fullIndexName = fullIndexName;
080: this .tableConglomerateId = tableConglomerateId;
081: }
082:
083: // OBJECT METHODS
084:
085: public String toString() {
086: // Do not put this under SanityManager.DEBUG - it is needed for
087: // error reporting.
088: return "DROP INDEX " + fullIndexName;
089: }
090:
091: // INTERFACE METHODS
092:
093: /**
094: * This is the guts of the Execution-time logic for DROP INDEX.
095: *
096: *
097: * @exception StandardException Thrown on failure
098: */
099: public void executeConstantAction(Activation activation)
100: throws StandardException {
101: TableDescriptor td;
102: ConglomerateDescriptor cd;
103:
104: LanguageConnectionContext lcc = activation
105: .getLanguageConnectionContext();
106: DataDictionary dd = lcc.getDataDictionary();
107: DependencyManager dm = dd.getDependencyManager();
108: TransactionController tc = lcc.getTransactionExecute();
109:
110: /*
111: ** Inform the data dictionary that we are about to write to it.
112: ** There are several calls to data dictionary "get" methods here
113: ** that might be done in "read" mode in the data dictionary, but
114: ** it seemed safer to do this whole operation in "write" mode.
115: **
116: ** We tell the data dictionary we're done writing at the end of
117: ** the transaction.
118: */
119: dd.startWriting(lcc);
120:
121: // need to lock heap in exclusive mode first. Because we can't first
122: // shared lock the row in SYSCONGLOMERATES and later exclusively lock
123: // it, this is potential deadlock (track 879). Also td need to be
124: // gotten after we get the lock, a concurrent thread could be modifying
125: // table shape (track 3804, 3825)
126:
127: // older version (or target) has to get td first, potential deadlock
128: if (tableConglomerateId == 0) {
129: td = dd.getTableDescriptor(tableId);
130: if (td == null) {
131: throw StandardException.newException(
132: SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION,
133: tableName);
134: }
135: tableConglomerateId = td.getHeapConglomerateId();
136: }
137: lockTableForDDL(tc, tableConglomerateId, true);
138:
139: td = dd.getTableDescriptor(tableId);
140: if (td == null) {
141: throw StandardException.newException(
142: SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION,
143: tableName);
144: }
145:
146: /*
147: ** If the schema descriptor is null, then
148: ** we must have just read ourselves in.
149: ** So we will get the corresponding schema
150: ** descriptor from the data dictionary.
151: */
152: SchemaDescriptor sd = dd.getSchemaDescriptor(schemaName, tc,
153: true);
154:
155: /* Get the conglomerate descriptor for the index, along
156: * with an exclusive row lock on the row in sys.sysconglomerates
157: * in order to ensure that no one else compiles against the
158: * index.
159: */
160: cd = dd.getConglomerateDescriptor(indexName, sd, true);
161:
162: if (cd == null) {
163: throw StandardException.newException(
164: SQLState.LANG_INDEX_NOT_FOUND_DURING_EXECUTION,
165: fullIndexName);
166: }
167:
168: /* Prepare all dependents to invalidate. (This is there chance
169: * to say that they can't be invalidated.)
170: * We check for invalidation before we drop the conglomerate descriptor
171: * since the conglomerate descriptor may be looked up as part of
172: * decoding tuples in SYSDEPENDS.
173: */
174: dropIndex(dm, dd, tc, cd, td, activation
175: .getLanguageConnectionContext());
176: }
177:
178: public static void dropIndex(DependencyManager dm,
179: DataDictionary dd, TransactionController tc,
180: ConglomerateDescriptor cd, TableDescriptor td,
181: LanguageConnectionContext lcc) throws StandardException {
182: if (SanityManager.DEBUG) {
183: SanityManager.ASSERT(tc != null, "tc is null");
184: SanityManager.ASSERT(cd != null, "cd is null");
185: }
186:
187: // only drop the conglomerate if no similar index but with different
188: // name. Get from dd in case we drop other dup indexes with a cascade operation
189:
190: if (dd.getConglomerateDescriptors(cd.getConglomerateNumber()).length == 1) {
191: /* Drop statistics */
192: dd
193: .dropStatisticsDescriptors(td.getUUID(), cd
194: .getUUID(), tc);
195:
196: /* Drop the conglomerate */
197: tc.dropConglomerate(cd.getConglomerateNumber());
198: }
199:
200: // invalidate any prepared statements that
201: // depended on the index (including this one)
202: dm.invalidateFor(cd, DependencyManager.DROP_INDEX, lcc);
203:
204: /* Drop the conglomerate descriptor */
205: dd.dropConglomerateDescriptor(cd, tc);
206:
207: /*
208: ** Remove the conglomerate descriptor from the list hanging off of the
209: ** table descriptor
210: */
211: td.removeConglomerateDescriptor(cd);
212: }
213:
214: }
|