001: /*
002:
003: Derby - Class org.apache.derby.iapi.sql.dictionary.ViewDescriptor
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.iapi.sql.dictionary;
023:
024: import org.apache.derby.catalog.UUID;
025:
026: import org.apache.derby.iapi.sql.depend.Dependent;
027: import org.apache.derby.iapi.sql.depend.Provider;
028: import org.apache.derby.iapi.sql.dictionary.GenericDescriptorList;
029: import org.apache.derby.iapi.error.StandardException;
030: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
031: import org.apache.derby.iapi.store.access.TransactionController;
032: import org.apache.derby.iapi.sql.depend.DependencyManager;
033:
034: import org.apache.derby.iapi.services.context.ContextService;
035:
036: import org.apache.derby.iapi.reference.SQLState;
037: import org.apache.derby.iapi.services.sanity.SanityManager;
038: import org.apache.derby.iapi.sql.StatementType;
039: import org.apache.derby.catalog.DependableFinder;
040: import org.apache.derby.catalog.Dependable;
041: import org.apache.derby.iapi.services.io.StoredFormatIds;
042: import org.apache.derby.impl.sql.execute.DropTriggerConstantAction;
043:
044: /**
045: * This is the implementation of ViewDescriptor. Users of View descriptors
046: * should only use the following methods:
047: * <ol>
048: * <li> getUUID
049: * <li> setUUID
050: * <li> getViewText
051: * <li> setViewName
052: * <li> getCheckOptionType
053: * <li> getCompSchemaId
054: * </ol>
055: *
056: * @version 0.1
057: * @author Jeff Lichtman
058: */
059:
060: public final class ViewDescriptor extends TupleDescriptor implements
061: UniqueTupleDescriptor, Dependent, Provider {
062: private final int checkOption;
063: private String viewName;
064: private final String viewText;
065: private UUID uuid;
066: private final UUID compSchemaId;
067:
068: public static final int NO_CHECK_OPTION = 0;
069:
070: /**
071: * Constructor for a ViewDescriptor.
072: *
073: * @param dataDictionary The data dictionary that this descriptor lives in
074: * @param viewID The UUID for the view
075: * @param viewName The name of the view
076: * @param viewText The text of the query expression from the view definition.
077: * @param checkOption int check option type
078: * @param compSchemaId the schemaid to compile in
079: */
080:
081: public ViewDescriptor(DataDictionary dataDictionary, UUID viewID,
082: String viewName, String viewText, int checkOption,
083: UUID compSchemaId) {
084: super (dataDictionary);
085:
086: uuid = viewID;
087: this .viewText = viewText;
088: this .viewName = viewName;
089:
090: /* RESOLVE - No check options for now */
091: if (SanityManager.DEBUG) {
092: if (checkOption != ViewDescriptor.NO_CHECK_OPTION) {
093: SanityManager.THROWASSERT("checkOption (" + checkOption
094: + ") expected to be "
095: + ViewDescriptor.NO_CHECK_OPTION);
096: }
097: }
098: this .checkOption = checkOption;
099: this .compSchemaId = compSchemaId;
100: }
101:
102: //
103: // ViewDescriptor interface
104: //
105:
106: /**
107: * Gets the UUID of the view.
108: *
109: * @return The UUID of the view.
110: */
111: public UUID getUUID() {
112: return uuid;
113: }
114:
115: /**
116: * Sets the UUID of the view.
117: *
118: * @param uuid The UUID of the view.
119: */
120: public void setUUID(UUID uuid) {
121: this .uuid = uuid;
122: }
123:
124: /**
125: * Gets the text of the view definition.
126: *
127: * @return A String containing the text of the CREATE VIEW
128: * statement that created the view
129: */
130: public String getViewText() {
131: return viewText;
132: }
133:
134: /**
135: * Sets the name of the view.
136: *
137: * @param name The name of the view.
138: */
139: public void setViewName(String name) {
140: viewName = name;
141: }
142:
143: /**
144: * Gets an identifier telling what type of check option
145: * is on this view.
146: *
147: * @return An identifier telling what type of check option
148: * is on the view.
149: */
150: public int getCheckOptionType() {
151: return checkOption;
152: }
153:
154: /**
155: * Get the compilation type schema id when this view
156: * was first bound.
157: *
158: * @return the schema UUID
159: */
160: public UUID getCompSchemaId() {
161: return compSchemaId;
162: }
163:
164: //
165: // Provider interface
166: //
167:
168: /**
169: @return the stored form of this provider
170:
171: @see Dependable#getDependableFinder
172: */
173: public DependableFinder getDependableFinder() {
174: return getDependableFinder(StoredFormatIds.VIEW_DESCRIPTOR_FINDER_V01_ID);
175: }
176:
177: /**
178: * Return the name of this Provider. (Useful for errors.)
179: *
180: * @return String The name of this provider.
181: */
182: public String getObjectName() {
183: return viewName;
184: }
185:
186: /**
187: * Get the provider's UUID
188: *
189: * @return String The provider's UUID
190: */
191: public UUID getObjectID() {
192: return uuid;
193: }
194:
195: /**
196: * Get the provider's type.
197: *
198: * @return String The provider's type.
199: */
200: public String getClassType() {
201: return Dependable.VIEW;
202: }
203:
204: //
205: // Dependent Inteface
206: //
207: /**
208: Check that all of the dependent's dependencies are valid.
209:
210: @return true if the dependent is currently valid
211: */
212: public boolean isValid() {
213: return true;
214: }
215:
216: /**
217: Prepare to mark the dependent as invalid (due to at least one of
218: its dependencies being invalid).
219:
220: @param action The action causing the invalidation
221: @param p the provider
222:
223: @exception StandardException thrown if unable to make it invalid
224: */
225: public void prepareToInvalidate(Provider p, int action,
226: LanguageConnectionContext lcc) throws StandardException {
227: switch (action) {
228: /*
229: * We don't care about creating or dropping indexes or
230: * alter table on an underlying table.
231: */
232: case DependencyManager.CREATE_INDEX:
233: case DependencyManager.DROP_INDEX:
234: case DependencyManager.CREATE_CONSTRAINT:
235: case DependencyManager.ALTER_TABLE:
236: case DependencyManager.CREATE_TRIGGER:
237: case DependencyManager.DROP_TRIGGER:
238:
239: case DependencyManager.BULK_INSERT:
240: case DependencyManager.COMPRESS_TABLE:
241: case DependencyManager.RENAME_INDEX:
242: case DependencyManager.UPDATE_STATISTICS:
243: case DependencyManager.DROP_STATISTICS:
244: case DependencyManager.TRUNCATE_TABLE:
245: /*
246: ** Set constriants is a bit odd in that it
247: ** will send a SET_CONSTRAINTS on the table
248: ** when it enables a constraint, rather than
249: ** on the constraint. So since we depend on
250: ** the table, we have to deal with this action.
251: */
252: case DependencyManager.SET_CONSTRAINTS_ENABLE:
253: case DependencyManager.SET_TRIGGERS_ENABLE:
254: //When REVOKE_PRIVILEGE gets sent (this happens for privilege
255: //types SELECT, UPDATE, DELETE, INSERT, REFERENCES, TRIGGER), we
256: //don't do anything here. Later in makeInvalid method, we make
257: //the ViewDescriptor drop itself.
258: case DependencyManager.REVOKE_PRIVILEGE:
259: break;
260:
261: //Notice that REVOKE_PRIVILEGE_RESTRICT is not caught earlier.
262: //It gets handled in this default: action where an exception
263: //will be thrown. This is because, if such an invalidation
264: //action type is ever received by a dependent, the dependent
265: //show throw an exception.
266: //In Derby, at this point, REVOKE_PRIVILEGE_RESTRICT gets sent
267: //when execute privilege on a routine is getting revoked.
268: default:
269:
270: DependencyManager dm;
271:
272: dm = getDataDictionary().getDependencyManager();
273: throw StandardException.newException(
274: SQLState.LANG_PROVIDER_HAS_DEPENDENT_VIEW, dm
275: .getActionString(action),
276: p.getObjectName(), viewName);
277:
278: } // end switch
279: }
280:
281: /**
282: Mark the dependent as invalid (due to at least one of
283: its dependencies being invalid).
284:
285: @param action The action causing the invalidation
286:
287: @exception StandardException thrown if unable to make it invalid
288: */
289: public void makeInvalid(int action, LanguageConnectionContext lcc)
290: throws StandardException {
291: switch (action) {
292: /* We don't care about creating or dropping indexes or
293: * alter table on an underlying table.
294: */
295: case DependencyManager.CREATE_INDEX:
296: case DependencyManager.DROP_INDEX:
297: case DependencyManager.ALTER_TABLE:
298: case DependencyManager.CREATE_CONSTRAINT:
299: case DependencyManager.BULK_INSERT:
300: case DependencyManager.COMPRESS_TABLE:
301: case DependencyManager.SET_CONSTRAINTS_ENABLE:
302: case DependencyManager.SET_TRIGGERS_ENABLE:
303: case DependencyManager.CREATE_TRIGGER:
304: case DependencyManager.DROP_TRIGGER:
305: case DependencyManager.RENAME_INDEX:
306: case DependencyManager.UPDATE_STATISTICS:
307: case DependencyManager.DROP_STATISTICS:
308: case DependencyManager.TRUNCATE_TABLE:
309: break;
310:
311: //When REVOKE_PRIVILEGE gets sent (this happens for privilege
312: //types SELECT, UPDATE, DELETE, INSERT, REFERENCES, TRIGGER), we
313: //make the ViewDescriptor drop itself.
314: case DependencyManager.REVOKE_PRIVILEGE:
315: dropViewWork(getDataDictionary(), getDataDictionary()
316: .getDependencyManager(), lcc, lcc
317: .getTransactionExecute(), getDataDictionary()
318: .getTableDescriptor(uuid).getSchemaDescriptor(),
319: getDataDictionary().getTableDescriptor(uuid), false);
320: return;
321:
322: default:
323:
324: /* We should never get here, since we can't have dangling references */
325: if (SanityManager.DEBUG) {
326: SanityManager
327: .THROWASSERT("did not expect to get called");
328: }
329: break;
330:
331: } // end switch
332:
333: }
334:
335: /**
336: Attempt to revalidate the dependent. For prepared statements,
337: this could go through its dependencies and check that they
338: are up to date; if not, it would recompile the statement.
339: Any failure during this attempt should throw
340: StandardException.unableToRevalidate().
341:
342: @exception StandardException thrown if unable to make it valid
343: */
344: public void makeValid(LanguageConnectionContext lcc)
345: throws StandardException {
346: }
347:
348: //
349: // class interface
350: //
351:
352: /**
353: * Prints the contents of the ViewDescriptor
354: *
355: * @return The contents as a String
356: */
357: public String toString() {
358: if (SanityManager.DEBUG) {
359: return "uuid: " + uuid + " viewName: " + viewName + "\n"
360: + "viewText: " + viewText + "\n" + "checkOption: "
361: + checkOption + "\n" + "compSchemaId: "
362: + compSchemaId + "\n";
363: } else {
364: return "";
365: }
366: }
367:
368: public void dropViewWork(DataDictionary dd, DependencyManager dm,
369: LanguageConnectionContext lcc, TransactionController tc,
370: SchemaDescriptor sd, TableDescriptor td, boolean cascade)
371: throws StandardException {
372: /* Drop the columns */
373: dd.dropAllColumnDescriptors(td.getUUID(), tc);
374:
375: /* Prepare all dependents to invalidate. (This is there chance
376: * to say that they can't be invalidated. For example, an open
377: * cursor referencing a table/view that the user is attempting to
378: * drop.) If no one objects, then invalidate any dependent objects.
379: */
380: dm.invalidateFor(td, DependencyManager.DROP_VIEW, lcc);
381:
382: /* Clear the dependencies for the view */
383: dm.clearDependencies(lcc, this );
384:
385: /* Drop the view */
386: dd.dropViewDescriptor(this , tc);
387:
388: /* Drop all table and column permission descriptors */
389: dd.dropAllTableAndColPermDescriptors(td.getUUID(), tc);
390:
391: /* Drop the table */
392: dd.dropTableDescriptor(td, sd, tc);
393: }
394:
395: }
|