001: /*
002:
003: Derby - Class org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor
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.iapi.error.StandardException;
025: import org.apache.derby.catalog.UUID;
026:
027: import org.apache.derby.iapi.reference.SQLState;
028: import org.apache.derby.iapi.services.sanity.SanityManager;
029: import org.apache.derby.iapi.sql.StatementType;
030: import org.apache.derby.iapi.services.io.StoredFormatIds;
031: import org.apache.derby.iapi.error.StandardException;
032: import org.apache.derby.iapi.sql.depend.DependencyManager;
033: import org.apache.derby.iapi.sql.depend.Dependent;
034: import org.apache.derby.iapi.sql.depend.Dependency;
035: import org.apache.derby.iapi.sql.depend.Provider;
036: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
037: import org.apache.derby.iapi.services.sanity.SanityManager;
038:
039: /**
040: * A foreign key.
041: *
042: * @author Jamie
043: */
044: public class ForeignKeyConstraintDescriptor extends
045: KeyConstraintDescriptor {
046: /**
047: interface to this descriptor
048: <ol>
049: <li>public ReferencedKeyConstraintDescriptor getReferencedConstraint()
050: throws StandardException;
051: <li>public UUID getReferencedConstraintId()
052: throws StandardException;
053: <li>public boolean isSelfReferencingFK()
054: throws StandardException;
055: <ol>
056: */
057:
058: // Implementation
059: ReferencedKeyConstraintDescriptor referencedConstraintDescriptor;
060: UUID referencedConstraintId;
061: int raDeleteRule;
062: int raUpdateRule;
063:
064: /**
065: * Constructor for a ForeignKeyConstraintDescriptor
066: *
067: * @param dataDictionary The data dictionary that this descriptor lives in
068: * @param table The descriptor of the table the constraint is on
069: * @param constraintName The name of the constraint.
070: * @param deferrable If the constraint can be deferred.
071: * @param initiallyDeferred If the constraint starts life deferred.
072: * @param fkColumns columns in the foreign key
073: * @param constraintId UUID of constraint
074: * @param indexId The UUID for the backing index
075: * @param schemaDesc The SchemaDescriptor for the constraint
076: * @param referencedConstraintDescriptor is referenced constraint descriptor
077: * @param isEnabled is the constraint enabled?
078: */
079: protected ForeignKeyConstraintDescriptor(
080: DataDictionary dataDictionary,
081: TableDescriptor table,
082: String constraintName,
083: boolean deferrable,
084: boolean initiallyDeferred,
085: int[] fkColumns,
086: UUID constraintId,
087: UUID indexId,
088: SchemaDescriptor schemaDesc,
089: ReferencedKeyConstraintDescriptor referencedConstraintDescriptor,
090: boolean isEnabled, int raDeleteRule, int raUpdateRule) {
091: super (dataDictionary, table, constraintName, deferrable,
092: initiallyDeferred, fkColumns, constraintId, indexId,
093: schemaDesc, isEnabled);
094:
095: this .referencedConstraintDescriptor = referencedConstraintDescriptor;
096: this .raDeleteRule = raDeleteRule;
097: this .raUpdateRule = raUpdateRule;
098: }
099:
100: /**
101: * Constructor for a ForeignKeyConstraintDescriptor
102: *
103: * @param dataDictionary The data dictionary that this descriptor lives in
104: * @param table The descriptor of the table the constraint is on
105: * @param constraintName The name of the constraint.
106: * @param deferrable If the constraint can be deferred.
107: * @param initiallyDeferred If the constraint starts life deferred.
108: * @param fkColumns columns in the foreign key
109: * @param constraintId UUID of constraint
110: * @param indexId The UUID for the backing index
111: * @param schemaDesc The SchemaDescriptor for the constraint
112: * @param referencedConstraintId is referenced constraint id
113: * @param isEnabled is the constraint enabled?
114: */
115: ForeignKeyConstraintDescriptor(DataDictionary dataDictionary,
116: TableDescriptor table, String constraintName,
117: boolean deferrable, boolean initiallyDeferred,
118: int[] fkColumns, UUID constraintId, UUID indexId,
119: SchemaDescriptor schemaDesc, UUID referencedConstraintId,
120: boolean isEnabled, int raDeleteRule, int raUpdateRule) {
121: super (dataDictionary, table, constraintName, deferrable,
122: initiallyDeferred, fkColumns, constraintId, indexId,
123: schemaDesc, isEnabled);
124: this .referencedConstraintId = referencedConstraintId;
125: this .raDeleteRule = raDeleteRule;
126: this .raUpdateRule = raUpdateRule;
127:
128: }
129:
130: /**
131: * Get the constraint that this FK references. Will
132: * return either a primary key or a unique key constriant.
133: *
134: * @return the constraint
135: *
136: * @exception StandardException on error
137: */
138: public ReferencedKeyConstraintDescriptor getReferencedConstraint()
139: throws StandardException {
140: if (referencedConstraintDescriptor != null) {
141: return referencedConstraintDescriptor;
142: }
143:
144: if (referencedConstraintId == null) {
145: getReferencedConstraintId();
146: }
147:
148: TableDescriptor refTd = getDataDictionary()
149: .getConstraintTableDescriptor(referencedConstraintId);
150:
151: if (SanityManager.DEBUG) {
152: if (refTd == null) {
153: SanityManager.THROWASSERT("not able to find "
154: + referencedConstraintId
155: + " in SYS.SYSCONSTRAINTS");
156: }
157: }
158:
159: ConstraintDescriptorList cdl = getDataDictionary()
160: .getConstraintDescriptors(refTd);
161: referencedConstraintDescriptor = (ReferencedKeyConstraintDescriptor) cdl
162: .getConstraintDescriptorById(referencedConstraintId);
163:
164: if (SanityManager.DEBUG) {
165: if (referencedConstraintDescriptor == null) {
166: SanityManager
167: .THROWASSERT("not able to find "
168: + referencedConstraintDescriptor
169: + " off of table descriptor "
170: + refTd.getName());
171: }
172: }
173:
174: return referencedConstraintDescriptor;
175: }
176:
177: /**
178: * Get the constraint id for the constraint that this FK references.
179: * Will return either a primary key or a unique key constriant.
180: *
181: * @return the constraint id
182: *
183: * @exception StandardException on error
184: */
185: public UUID getReferencedConstraintId() throws StandardException {
186: if (referencedConstraintDescriptor != null) {
187: return referencedConstraintDescriptor.getUUID();
188: }
189:
190: SubKeyConstraintDescriptor subKey;
191: subKey = getDataDictionary().getSubKeyConstraint(constraintId,
192: DataDictionary.FOREIGNKEY_CONSTRAINT);
193: if (SanityManager.DEBUG) {
194: if (subKey == null) {
195: SanityManager.THROWASSERT("not able to find "
196: + constraintName + " in SYS.SYSFOREIGNKEYS");
197: }
198: }
199: referencedConstraintId = subKey.getKeyConstraintId();
200: return referencedConstraintId;
201: }
202:
203: /**
204: * Gets an identifier telling what type of descriptor it is
205: * (UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK).
206: *
207: * @return An identifier telling what type of descriptor it is
208: * (UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK).
209: */
210: public int getConstraintType() {
211: return DataDictionary.FOREIGNKEY_CONSTRAINT;
212: }
213:
214: /**
215: * Does this constraint need to fire on this type of
216: * DML? True if insert or update and columns intersect
217: *
218: * @param stmtType the type of DML
219: * (StatementType.INSERT|StatementType.UPDATE|StatementType.DELETE)
220: * @param modifiedCols the columns modified, or null for all
221: *
222: * @return true/false
223: */
224: public boolean needsToFire(int stmtType, int[] modifiedCols) {
225: /*
226: ** If we are disabled, we never fire
227: */
228: if (!isEnabled) {
229: return false;
230: }
231:
232: if (stmtType == StatementType.DELETE) {
233: return false;
234: }
235: if (stmtType == StatementType.INSERT) {
236: return true;
237: }
238:
239: // if update, only relevant if columns intersect
240: return doColumnsIntersect(modifiedCols, getReferencedColumns());
241: }
242:
243: /**
244: * Am I a self-referencing FK? True if my referenced
245: * constraint is on the same table as me.
246: *
247: * @return true/false
248: *
249: * @exception StandardException on error
250: */
251: public boolean isSelfReferencingFK() throws StandardException {
252: ReferencedKeyConstraintDescriptor refcd = getReferencedConstraint();
253: return (refcd.getTableId().equals(getTableId()));
254: }
255:
256: /**
257: * Gets a referential action rule on a DELETE
258: * @return referential rule defined by the user during foreign key creattion
259: * for a delete (like CASCDE , RESTRICT ..etc)
260: */
261: public int getRaDeleteRule() {
262: return raDeleteRule;
263: }
264:
265: /**
266: * Gets a referential action rule on a UPDATE
267: * @return referential rule defined by the user during foreign key creattion
268: * for an UPDATE (like CASCDE , RESTRICT ..etc)
269: */
270: public int getRaUpdateRule() {
271: return raUpdateRule;
272: }
273:
274: }
|