KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > sql > dictionary > ConstraintDescriptor


1 /*
2
3    Derby - Class org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.iapi.sql.dictionary;
23
24 import org.apache.derby.iapi.error.StandardException;
25
26 import org.apache.derby.iapi.sql.depend.Provider;
27 import org.apache.derby.iapi.sql.depend.Dependent;
28
29 import org.apache.derby.catalog.UUID;
30
31 import org.apache.derby.iapi.reference.SQLState;
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33 import org.apache.derby.catalog.DependableFinder;
34 import org.apache.derby.catalog.Dependable;
35 import org.apache.derby.iapi.services.io.StoredFormatIds;
36 import org.apache.derby.iapi.sql.depend.DependencyManager;
37 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
38
39 import org.apache.derby.impl.sql.execute.DropConstraintConstantAction;
40
41 /**
42  * This class is used to get information from a ConstraintDescriptor.
43  * A ConstraintDescriptor can represent a constraint on a table or on a
44  * column.
45  *
46  * @version 0.1
47  * @author Jeff Lichtman
48  */

49
50 public abstract class ConstraintDescriptor
51     extends TupleDescriptor
52     implements UniqueTupleDescriptor, Provider, Dependent
53 {
54     // used to indicate what type of constraints we
55
// are interested in
56
public static final int ENABLED = 1;
57     public static final int DISABLED = 2;
58     public static final int ALL = 3;
59
60     // field that we want users to be able to know about
61
public static final int SYSCONSTRAINTS_STATE_FIELD = 6;
62
63     TableDescriptor table;
64     final String JavaDoc constraintName;
65     private final boolean deferrable;
66     private final boolean initiallyDeferred;
67     boolean isEnabled;
68     private final int[] referencedColumns;
69     final UUID constraintId;
70     private final SchemaDescriptor schemaDesc;
71     private ColumnDescriptorList colDL;
72
73     /**
74      * Constructor for a ConstraintDescriptor
75      *
76      * @param dataDictionary The data dictionary that this descriptor lives in
77      * @param table The descriptor of the table the constraint is on
78      * @param constraintName The name of the constraint.
79      * @param deferrable If the constraint can be deferred.
80      * @param initiallyDeferred If the constraint starts life deferred.
81      * @param referencedColumns columns that the constraint references
82      * @param constraintId UUID of constraint
83      * @param schemaDesc SchemaDescriptor
84      */

85
86     ConstraintDescriptor(
87             DataDictionary dataDictionary,
88             TableDescriptor table,
89             String JavaDoc constraintName,
90             boolean deferrable,
91             boolean initiallyDeferred,
92             int[] referencedColumns,
93             UUID constraintId,
94             SchemaDescriptor schemaDesc,
95             boolean isEnabled
96             )
97     {
98         super( dataDictionary );
99
100         this.table = table;
101         this.constraintName = constraintName;
102         this.deferrable = deferrable;
103         this.initiallyDeferred = initiallyDeferred;
104         this.referencedColumns = referencedColumns;
105         this.constraintId = constraintId;
106         this.schemaDesc = schemaDesc;
107         this.isEnabled = isEnabled;
108     }
109
110
111     /**
112      * Gets the UUID of the table the constraint is on.
113      *
114      * @return The UUID of the table the constraint is on.
115      */

116     public UUID getTableId()
117     {
118         return table.getUUID();
119     }
120
121     /**
122      * Gets the UUID of the constraint.
123      *
124      * @return The UUID of the constraint.
125      */

126     public UUID getUUID()
127     {
128         return constraintId;
129     }
130
131     /**
132      * Gets the name of the constraint.
133      *
134      * @return A String containing the name of the constraint.
135      */

136     public String JavaDoc getConstraintName()
137     {
138         return constraintName;
139     }
140
141     /**
142      * Gets an identifier telling what type of descriptor it is
143      * (UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK).
144      *
145      * @return An identifier telling what type of descriptor it is
146      * (UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK).
147      */

148     public abstract int getConstraintType();
149
150     public abstract UUID getConglomerateId();
151
152     /**
153      * Get the text of the constraint. (Only non-null/meaningful for check
154      * constraints.)
155      * @return The constraint text.
156      */

157     public String JavaDoc getConstraintText()
158     {
159         return null;
160     }
161
162     /**
163      * Returns TRUE if the constraint is deferrable
164      * (we will probably not do deferrable constraints in the
165      * initial release, but I want this to be part of the interface).
166      *
167      * @return TRUE if the constraint is deferrable, FALSE if not
168      */

169     public boolean deferrable()
170     {
171         return deferrable;
172     }
173
174     /**
175      * Returns TRUE if the constraint is initially deferred
176      * (we will probably not do initially deferred constraints
177      * in the initial release, but I want this to be part of the interface).
178      *
179      * @return TRUE if the constraint is initially deferred,
180      * FALSE if not
181      */

182     public boolean initiallyDeferred()
183     {
184         return initiallyDeferred;
185     }
186
187     /**
188      * Returns an array of column ids (i.e. ordinal positions) for
189      * the columns referenced in this table for a primary key, unique
190      * key, referential, or check constraint.
191      *
192      * @return An array of column ids for those constraints that can
193      * be on columns (primary, unique key, referential
194      * constraints, and check constraints). For check and
195      * unique constraints, it returns an array of columns ids
196      * that are referenced in the constraint. For primary key
197      * and referential constraints, it returns an array of
198      * column ids for the columns in this table (i.e. the
199      * primary key columns for a primary key constraint,
200      * and the foreign key columns for a foreign key
201      * constraint.
202      */

203     public int[] getReferencedColumns()
204     {
205         return referencedColumns;
206     }
207
208     /**
209      * Does this constraint have a backing index?
210      *
211      * @return boolean Whether or not there is a backing index for this constraint.
212      */

213     public abstract boolean hasBackingIndex();
214
215     /**
216      * Get the SchemaDescriptor for the schema that this constraint
217      * belongs to.
218      *
219      * @return SchemaDescriptor The SchemaDescriptor for this constraint.
220      */

221     public SchemaDescriptor getSchemaDescriptor()
222     {
223         return schemaDesc;
224     }
225
226     /**
227       RESOLVE: For now the ConstraintDescriptor code stores the array of key
228       columns in the field 'otherColumns'. Jerry plans to re-organize things.
229       For now to minimize his rototill I've implemented this function on the
230       old structures. All new code should use getKeyColumns to get a constraint's
231       key columns.
232       
233       @see org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor#getKeyColumns
234       */

235     public int[] getKeyColumns()
236     {
237         return getReferencedColumns();
238     }
239
240     /**
241      * Is this constraint active?
242      *
243      * @return true/false
244      */

245     public boolean isEnabled()
246     {
247         return isEnabled;
248     }
249
250     /**
251      * Set the constraint to enabled.
252      * Does not update the data dictionary
253      */

254     public void setEnabled()
255     {
256         isEnabled = true;
257     }
258
259     /**
260      * Set the constraint to disabled.
261      * Does not update the data dictionary
262      */

263     public void setDisabled()
264     {
265         isEnabled = false;
266     }
267
268     /**
269      * Is this constraint referenced? Return
270      * false. Overridden by ReferencedKeyConstraints.
271      *
272      * @return false
273      */

274     public boolean isReferenced()
275     {
276         return false;
277     }
278
279     /**
280      * Get the number of enabled fks that
281      * reference this key. Overriden by
282      * ReferencedKeyConstraints.
283      *
284      * @return the number of fks
285      */

286     public int getReferenceCount()
287     {
288         return 0;
289     }
290
291     /**
292      * Does this constraint need to fire on this type of
293      * DML?
294      *
295      * @param stmtType the type of DML
296      * (StatementType.INSERT|StatementType.UPDATE|StatementType.DELETE)
297      * @param modifiedCols the columns modified, or null for all
298      *
299      * @return true/false
300      */

301     public abstract boolean needsToFire(int stmtType, int[] modifiedCols);
302
303     /**
304      * Get the table descriptor upon which this constraint
305      * is declared.
306      *
307      * @return the table descriptor
308      */

309     public TableDescriptor getTableDescriptor()
310     {
311         return table;
312     }
313
314     /**
315      * Get the column descriptors for all the columns
316      * referenced by this constraint.
317      *
318      * @return the column descriptor list
319      *
320      * @exception StandardException on error
321      */

322     public ColumnDescriptorList getColumnDescriptors()
323         throws StandardException
324     {
325         if (colDL == null)
326         {
327             DataDictionary dd = getDataDictionary();
328             colDL = new ColumnDescriptorList();
329     
330             int[] refCols = getReferencedColumns();
331             for (int i = 0; i < refCols.length; i++)
332             {
333                 colDL.add(table.getColumnDescriptor(refCols[i]));
334             }
335         }
336         return colDL;
337     }
338
339     /**
340      * Indicates whether the column descriptor list is
341      * type comparable with the constraints columns. The
342      * types have to be identical AND in the same order
343      * to succeed.
344      *
345      * @param otherColumns the columns to compare
346      *
347      * @return true/false
348      *
349      * @exception StandardException on error
350      */

351     public boolean areColumnsComparable(ColumnDescriptorList otherColumns)
352         throws StandardException
353     {
354         ColumnDescriptor myColumn;
355         ColumnDescriptor otherColumn;
356
357         ColumnDescriptorList myColDl = getColumnDescriptors();
358
359         /*
360         ** Check the lenghts of the lists
361         */

362         if (otherColumns.size() != myColDl.size())
363         {
364             return false;
365         }
366
367         int mySize = myColDl.size();
368         int otherSize = otherColumns.size();
369         int index;
370         for (index = 0; index < mySize && index < otherSize; index++)
371         {
372             myColumn = (ColumnDescriptor) myColDl.elementAt(index);
373             otherColumn = (ColumnDescriptor) otherColumns.elementAt(index);
374
375             /*
376             ** Just compare the types. Note that this will
377             ** say a decimal(x,y) != numeric(x,y) even though
378             ** it does.
379             */

380             if (!(myColumn.getType()).isExactTypeAndLengthMatch(
381                     (otherColumn.getType())))
382             {
383                 break;
384             }
385         }
386
387         return (index == mySize && index == otherSize);
388     }
389
390     /**
391      * Does a column intersect with our referenced columns
392      * @param columnArray columns to check
393      *
394      * Note-- this is not a static method.
395      */

396     public boolean columnIntersects(int columnArray[])
397     {
398         // call static method.
399
return doColumnsIntersect(getReferencedColumns(), columnArray);
400     }
401
402     /**
403      * Does a column in the input set intersect with
404      * our referenced columns?
405      *
406      * @param otherColumns the columns to compare. If
407      * null, asssumed to mean all columns
408      *
409      * @param referencedColumns the columns referenced by the caller
410      *
411      * @return true/false
412      */

413     static boolean doColumnsIntersect(int[] otherColumns, int[] referencedColumns)
414     {
415         /*
416         ** It is assumed that if otherColumns is null, then
417         ** all other columns are modified. In this case,
418         ** it is assumed that it intersects with some column
419         ** of ours, so just return true.
420         */

421         if ((otherColumns == null) || (referencedColumns == null))
422         {
423             return true;
424         }
425
426         for (int outer = 0; outer < referencedColumns.length; outer++)
427         {
428             for (int inner = 0; inner < otherColumns.length; inner++)
429             {
430                 if (referencedColumns[outer] == otherColumns[inner])
431                 {
432                     return true;
433                 }
434             }
435         }
436         return false;
437     }
438
439     /**
440      * Convert the ColumnDescriptor to a String.
441      *
442      * @return A String representation of this ColumnDescriptor
443      */

444
445     public String JavaDoc toString()
446     {
447         if (SanityManager.DEBUG)
448         {
449             String JavaDoc tableDesc =
450                 "table: " +
451                 table.getQualifiedName() + "(" +
452                 table.getUUID()+","+
453                 table.getTableType()+")";
454
455             return tableDesc + "\n"+
456                 "constraintName: " + constraintName + "\n" +
457                 "constraintId: " + constraintId + "\n" +
458                 "deferrable: " + deferrable + "\n" +
459                 "initiallyDeferred: " + initiallyDeferred + "\n" +
460                 "referencedColumns: " + referencedColumns + "\n" +
461                 "schemaDesc: " + schemaDesc + "\n"
462                 ;
463         }
464         else
465         {
466             return "";
467         }
468     }
469
470     ////////////////////////////////////////////////////////////////////
471
//
472
// PROVIDER INTERFACE
473
//
474
////////////////////////////////////////////////////////////////////
475

476     /**
477         @return the stored form of this provider
478
479             @see Dependable#getDependableFinder
480      */

481     public DependableFinder getDependableFinder()
482     {
483         return getDependableFinder(StoredFormatIds.CONSTRAINT_DESCRIPTOR_FINDER_V01_ID);
484     }
485
486     /**
487      * Return the name of this Provider. (Useful for errors.)
488      *
489      * @return String The name of this provider.
490      */

491     public String JavaDoc getObjectName()
492     {
493         return constraintName;
494     }
495
496     /**
497      * Get the provider's UUID
498      *
499      * @return The provider's UUID
500      */

501     public UUID getObjectID()
502     {
503         return constraintId;
504     }
505
506     /**
507      * Get the provider's type.
508      *
509      * @return char The provider's type.
510      */

511     public String JavaDoc getClassType()
512     {
513         return Dependable.CONSTRAINT;
514     }
515
516     //////////////////////////////////////////////////////
517
//
518
// DEPENDENT INTERFACE
519
//
520
//////////////////////////////////////////////////////
521
/**
522      * Check that all of the dependent's dependencies are valid.
523      *
524      * @return true if the dependent is currently valid
525      */

526     public synchronized boolean isValid()
527     {
528         return true;
529     }
530
531     /**
532      * Prepare to mark the dependent as invalid (due to at least one of
533      * its dependencies being invalid).
534      *
535      * @param action The action causing the invalidation
536      * @param p the provider
537      *
538      * @exception StandardException thrown if unable to make it invalid
539      */

540     public void prepareToInvalidate(Provider p, int action,
541                     LanguageConnectionContext lcc)
542         throws StandardException
543     {
544         DependencyManager dm = getDataDictionary().getDependencyManager();
545
546         switch (action)
547         {
548             /*
549             ** A SET CONSTRAINT stmt will throw an SET_CONSTRAINTS action
550             ** when enabling/disabling constraints. We'll ignore it.
551             ** Same for SET TRIGGERS
552             */

553             case DependencyManager.SET_CONSTRAINTS_ENABLE:
554             case DependencyManager.SET_CONSTRAINTS_DISABLE:
555             case DependencyManager.SET_TRIGGERS_ENABLE:
556             case DependencyManager.SET_TRIGGERS_DISABLE:
557             //When REVOKE_PRIVILEGE gets sent (this happens for privilege
558
//types SELECT, UPDATE, DELETE, INSERT, REFERENCES, TRIGGER), we
559
//don't do anything here. Later in makeInvalid method, we make
560
//the ConstraintDescriptor drop itself.
561
case DependencyManager.REVOKE_PRIVILEGE:
562                 break;
563
564             /*
565             ** Currently, the only thing we are depenedent
566             ** on is another constraint or an alias..
567             */

568             //Notice that REVOKE_PRIVILEGE_RESTRICT is not caught earlier.
569
//It gets handled in this default: action where an exception
570
//will be thrown. This is because, if such an invalidation
571
//action type is ever received by a dependent, the dependent
572
//should throw an exception.
573
//In Derby, at this point, REVOKE_PRIVILEGE_RESTRICT gets sent
574
//when execute privilege on a routine is getting revoked.
575
//Currently, in Derby, a constraint can't depend on a routine
576
//and hence a REVOKE_PRIVILEGE_RESTRICT invalidation action
577
//should never be received by a ConstraintDescriptor. But this
578
//may change in future and when it does, the code to do the right
579
//thing is already here.
580
default:
581                 throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
582                                     dm.getActionString(action),
583                                     p.getObjectName(), "CONSTRAINT", constraintName);
584         }
585     }
586
587     /**
588      * Mark the dependent as invalid (due to at least one of
589      * its dependencies being invalid). Always an error
590      * for a constraint -- should never have gotten here.
591      *
592      * @param action The action causing the invalidation
593      *
594      * @exception StandardException thrown if called in sanity mode
595      */

596     public void makeInvalid(int action, LanguageConnectionContext lcc)
597         throws StandardException
598     {
599         /*
600         ** For ConstraintDescriptor, SET_CONSTRAINTS/TRIGGERS and
601         * REVOKE_PRIVILEGE are the only valid actions
602         */

603
604         //Let's handle REVOKE_PRIVILEGE first
605
if (action == DependencyManager.REVOKE_PRIVILEGE)
606         {
607             //At this point (Derby 10.2), only a FOREIGN KEY key constraint can
608
//depend on a privilege. None of the other constraint types
609
//can be dependent on a privilege becuse those constraint types
610
//can not reference a table/routine.
611
DropConstraintConstantAction.dropConstraintAndIndex(
612                     getDataDictionary().getDependencyManager(),
613                     table,
614                     getDataDictionary(),
615                     this,
616                     lcc.getTransactionExecute(),
617                     lcc, true);
618             return;
619         }
620
621         /*
622         ** Now, handle SET_CONSTRAINTS/TRIGGERS
623         */

624         if ((action != DependencyManager.SET_CONSTRAINTS_DISABLE) &&
625             (action != DependencyManager.SET_CONSTRAINTS_ENABLE) &&
626             (action != DependencyManager.SET_TRIGGERS_ENABLE) &&
627             (action != DependencyManager.SET_TRIGGERS_DISABLE)
628            )
629         {
630             /*
631             ** We should never get here, we should have barfed on
632             ** prepareToInvalidate().
633             */

634             if (SanityManager.DEBUG)
635             {
636                 DependencyManager dm;
637         
638                 dm = getDataDictionary().getDependencyManager();
639     
640                 SanityManager.THROWASSERT("makeInvalid("+
641                     dm.getActionString(action)+
642                     ") not expected to get called");
643             }
644         }
645     }
646
647     /**
648      * Attempt to revalidate the dependent. Meaningless
649      * for constraints.
650      */

651     public void makeValid(LanguageConnectionContext lcc)
652     {
653     }
654     
655     /** @see TupleDescriptor#getDescriptorName */
656     public String JavaDoc getDescriptorName() { return constraintName; }
657     
658     public String JavaDoc getDescriptorType() { return "Constraint"; }
659 }
660
Popular Tags