1 | /* |
2 | |
3 | Derby - Class org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor |
4 | |
5 | Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.iapi.sql.dictionary; |
22 | |
23 | import org.apache.derby.iapi.error.StandardException; |
24 | import org.apache.derby.catalog.UUID; |
25 | |
26 | import org.apache.derby.iapi.reference.SQLState; |
27 | import org.apache.derby.iapi.services.sanity.SanityManager; |
28 | import org.apache.derby.iapi.sql.StatementType; |
29 | import org.apache.derby.iapi.services.io.StoredFormatIds; |
30 | import org.apache.derby.iapi.error.StandardException; |
31 | import org.apache.derby.iapi.sql.depend.DependencyManager; |
32 | import org.apache.derby.iapi.sql.depend.Dependent; |
33 | import org.apache.derby.iapi.sql.depend.Dependency; |
34 | import org.apache.derby.iapi.sql.depend.Provider; |
35 | import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; |
36 | import org.apache.derby.iapi.services.sanity.SanityManager; |
37 | |
38 | /** |
39 | * A foreign key. |
40 | * |
41 | * @author Jamie |
42 | */ |
43 | public class ForeignKeyConstraintDescriptor extends KeyConstraintDescriptor |
44 | { |
45 | /** |
46 | interface to this descriptor |
47 | <ol> |
48 | <li>public ReferencedKeyConstraintDescriptor getReferencedConstraint() |
49 | throws StandardException; |
50 | <li>public UUID getReferencedConstraintId() |
51 | throws StandardException; |
52 | <li>public boolean isSelfReferencingFK() |
53 | throws StandardException; |
54 | <ol> |
55 | */ |
56 | |
57 | // Implementation |
58 | ReferencedKeyConstraintDescriptor referencedConstraintDescriptor; |
59 | UUID referencedConstraintId; |
60 | int raDeleteRule; |
61 | int raUpdateRule; |
62 | /** |
63 | * Constructor for a ForeignKeyConstraintDescriptor |
64 | * |
65 | * @param dataDictionary The data dictionary that this descriptor lives in |
66 | * @param table The descriptor of the table the constraint is on |
67 | * @param constraintName The name of the constraint. |
68 | * @param deferrable If the constraint can be deferred. |
69 | * @param initiallyDeferred If the constraint starts life deferred. |
70 | * @param fkColumns columns in the foreign key |
71 | * @param constraintId UUID of constraint |
72 | * @param indexId The UUID for the backing index |
73 | * @param schemaDesc The SchemaDescriptor for the constraint |
74 | * @param referencedConstraintDescriptor is referenced constraint descriptor |
75 | * @param isEnabled is the constraint enabled? |
76 | */ |
77 | protected ForeignKeyConstraintDescriptor( |
78 | DataDictionary dataDictionary, |
79 | TableDescriptor table, |
80 | String constraintName, |
81 | boolean deferrable, |
82 | boolean initiallyDeferred, |
83 | int[] fkColumns, |
84 | UUID constraintId, |
85 | UUID indexId, |
86 | SchemaDescriptor schemaDesc, |
87 | ReferencedKeyConstraintDescriptor referencedConstraintDescriptor, |
88 | boolean isEnabled, |
89 | int raDeleteRule, |
90 | int raUpdateRule |
91 | ) |
92 | { |
93 | super(dataDictionary, table, constraintName, deferrable, |
94 | initiallyDeferred, fkColumns, |
95 | constraintId, indexId, schemaDesc, isEnabled); |
96 | |
97 | this.referencedConstraintDescriptor = referencedConstraintDescriptor; |
98 | this.raDeleteRule = raDeleteRule; |
99 | this.raUpdateRule = raUpdateRule; |
100 | } |
101 | |
102 | /** |
103 | * Constructor for a ForeignKeyConstraintDescriptor |
104 | * |
105 | * @param dataDictionary The data dictionary that this descriptor lives in |
106 | * @param table The descriptor of the table the constraint is on |
107 | * @param constraintName The name of the constraint. |
108 | * @param deferrable If the constraint can be deferred. |
109 | * @param initiallyDeferred If the constraint starts life deferred. |
110 | * @param fkColumns columns in the foreign key |
111 | * @param constraintId UUID of constraint |
112 | * @param indexId The UUID for the backing index |
113 | * @param schemaDesc The SchemaDescriptor for the constraint |
114 | * @param referencedConstraintId is referenced constraint id |
115 | * @param isEnabled is the constraint enabled? |
116 | */ |
117 | ForeignKeyConstraintDescriptor( |
118 | DataDictionary dataDictionary, |
119 | TableDescriptor table, |
120 | String constraintName, |
121 | boolean deferrable, |
122 | boolean initiallyDeferred, |
123 | int[] fkColumns, |
124 | UUID constraintId, |
125 | UUID indexId, |
126 | SchemaDescriptor schemaDesc, |
127 | UUID referencedConstraintId, |
128 | boolean isEnabled, |
129 | int raDeleteRule, |
130 | int raUpdateRule |
131 | ) |
132 | { |
133 | super(dataDictionary, table, constraintName, deferrable, |
134 | initiallyDeferred, fkColumns, |
135 | constraintId, indexId, schemaDesc, isEnabled); |
136 | this.referencedConstraintId = referencedConstraintId; |
137 | this.raDeleteRule = raDeleteRule; |
138 | this.raUpdateRule = raUpdateRule; |
139 | |
140 | } |
141 | |
142 | /** |
143 | * Get the constraint that this FK references. Will |
144 | * return either a primary key or a unique key constriant. |
145 | * |
146 | * @return the constraint |
147 | * |
148 | * @exception StandardException on error |
149 | */ |
150 | public ReferencedKeyConstraintDescriptor getReferencedConstraint() |
151 | throws StandardException |
152 | { |
153 | if (referencedConstraintDescriptor != null) |
154 | { |
155 | return referencedConstraintDescriptor; |
156 | } |
157 | |
158 | if (referencedConstraintId == null) |
159 | { |
160 | getReferencedConstraintId(); |
161 | } |
162 | |
163 | TableDescriptor refTd = getDataDictionary().getConstraintTableDescriptor(referencedConstraintId); |
164 | |
165 | if (SanityManager.DEBUG) |
166 | { |
167 | if (refTd == null) |
168 | { |
169 | SanityManager.THROWASSERT("not able to find "+referencedConstraintId+ |
170 | " in SYS.SYSCONSTRAINTS"); |
171 | } |
172 | } |
173 | |
174 | ConstraintDescriptorList cdl = getDataDictionary().getConstraintDescriptors(refTd); |
175 | referencedConstraintDescriptor = (ReferencedKeyConstraintDescriptor) |
176 | cdl.getConstraintDescriptorById(referencedConstraintId); |
177 | |
178 | if (SanityManager.DEBUG) |
179 | { |
180 | if (referencedConstraintDescriptor == null) |
181 | { |
182 | SanityManager.THROWASSERT("not able to find " |
183 | +referencedConstraintDescriptor+ " off of table descriptor " |
184 | +refTd.getName()); |
185 | } |
186 | } |
187 | |
188 | return referencedConstraintDescriptor; |
189 | } |
190 | |
191 | |
192 | /** |
193 | * Get the constraint id for the constraint that this FK references. |
194 | * Will return either a primary key or a unique key constriant. |
195 | * |
196 | * @return the constraint id |
197 | * |
198 | * @exception StandardException on error |
199 | */ |
200 | public UUID getReferencedConstraintId() throws StandardException |
201 | { |
202 | if (referencedConstraintDescriptor != null) |
203 | { |
204 | return referencedConstraintDescriptor.getUUID(); |
205 | } |
206 | |
207 | SubKeyConstraintDescriptor subKey; |
208 | subKey = getDataDictionary().getSubKeyConstraint(constraintId, |
209 | DataDictionary.FOREIGNKEY_CONSTRAINT); |
210 | if (SanityManager.DEBUG) |
211 | { |
212 | if (subKey == null) |
213 | { |
214 | SanityManager.THROWASSERT("not able to find "+constraintName+ |
215 | " in SYS.SYSFOREIGNKEYS"); |
216 | } |
217 | } |
218 | referencedConstraintId = subKey.getKeyConstraintId(); |
219 | return referencedConstraintId; |
220 | } |
221 | |
222 | /** |
223 | * Gets an identifier telling what type of descriptor it is |
224 | * (UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK). |
225 | * |
226 | * @return An identifier telling what type of descriptor it is |
227 | * (UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK). |
228 | */ |
229 | public int getConstraintType() |
230 | { |
231 | return DataDictionary.FOREIGNKEY_CONSTRAINT; |
232 | } |
233 | |
234 | /** |
235 | * Does this constraint need to fire on this type of |
236 | * DML? True if insert or update and columns intersect |
237 | * |
238 | * @param stmtType the type of DML |
239 | * (StatementType.INSERT|StatementType.UPDATE|StatementType.DELETE) |
240 | * @param modifiedCols the columns modified, or null for all |
241 | * |
242 | * @return true/false |
243 | */ |
244 | public boolean needsToFire(int stmtType, int[] modifiedCols) |
245 | { |
246 | /* |
247 | ** If we are disabled, we never fire |
248 | */ |
249 | if (!isEnabled) |
250 | { |
251 | return false; |
252 | } |
253 | |
254 | if (stmtType == StatementType.DELETE) |
255 | { |
256 | return false; |
257 | } |
258 | if (stmtType == StatementType.INSERT) |
259 | { |
260 | return true; |
261 | } |
262 | |
263 | // if update, only relevant if columns intersect |
264 | return doColumnsIntersect(modifiedCols, getReferencedColumns()); |
265 | } |
266 | |
267 | /** |
268 | * Am I a self-referencing FK? True if my referenced |
269 | * constraint is on the same table as me. |
270 | * |
271 | * @return true/false |
272 | * |
273 | * @exception StandardException on error |
274 | */ |
275 | public boolean isSelfReferencingFK() |
276 | throws StandardException |
277 | { |
278 | ReferencedKeyConstraintDescriptor refcd = getReferencedConstraint(); |
279 | return (refcd.getTableId().equals(getTableId())); |
280 | } |
281 | |
282 | /** |
283 | * Gets a referential action rule on a DELETE |
284 | * @return referential rule defined by the user during foreign key creattion |
285 | * for a delete (like CASCDE , RESTRICT ..etc) |
286 | */ |
287 | public int getRaDeleteRule() |
288 | { |
289 | return raDeleteRule; |
290 | } |
291 | |
292 | |
293 | /** |
294 | * Gets a referential action rule on a UPDATE |
295 | * @return referential rule defined by the user during foreign key creattion |
296 | * for an UPDATE (like CASCDE , RESTRICT ..etc) |
297 | */ |
298 | public int getRaUpdateRule() |
299 | { |
300 | return raUpdateRule; |
301 | } |
302 | |
303 | } |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | |