001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.ConstraintDefinitionNode
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.compile;
023:
024: import org.apache.derby.iapi.sql.StatementType;
025:
026: import org.apache.derby.iapi.types.TypeId;
027: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
028: import org.apache.derby.iapi.error.StandardException;
029: import org.apache.derby.iapi.services.sanity.SanityManager;
030: import org.apache.derby.iapi.sql.depend.ProviderList;
031:
032: import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
033:
034: import org.apache.derby.iapi.services.monitor.Monitor;
035:
036: import org.apache.derby.iapi.util.JBitSet;
037: import org.apache.derby.iapi.util.ReuseFactory;
038:
039: import org.apache.derby.catalog.UUID;
040: import org.apache.derby.iapi.services.uuid.UUIDFactory;
041: import org.apache.derby.iapi.reference.SQLState;
042: import java.util.Properties;
043:
044: /**
045: * A ConstraintDefintionNode is a class for all nodes that can represent
046: * constraint definitions.
047: *
048: * @author Jerry Brenner
049: */
050:
051: public class ConstraintDefinitionNode extends TableElementNode {
052:
053: private TableName constraintName;
054: protected int constraintType;
055: protected Properties properties;
056: ProviderList apl;
057:
058: UUIDFactory uuidFactory;
059:
060: String backingIndexName;
061: UUID backingIndexUUID;
062: int[] checkColumnReferences;
063: ResultColumnList columnList;
064: String constraintText;
065: ValueNode checkCondition;
066: private int behavior;
067: private int verifyType = DataDictionary.DROP_CONSTRAINT; // By default do not check the constraint type
068:
069: public void init(Object constraintName, Object constraintType,
070: Object rcl, Object properties, Object checkCondition,
071: Object constraintText, Object behavior) {
072: this .constraintName = (TableName) constraintName;
073:
074: /* We need to pass null as name to TableElementNode's constructor
075: * since constraintName may be null.
076: */
077: super .init(null);
078: if (this .constraintName != null) {
079: this .name = this .constraintName.getTableName();
080: }
081: this .constraintType = ((Integer) constraintType).intValue();
082: this .properties = (Properties) properties;
083: this .columnList = (ResultColumnList) rcl;
084: this .checkCondition = (ValueNode) checkCondition;
085: this .constraintText = (String) constraintText;
086: this .behavior = ((Integer) behavior).intValue();
087: }
088:
089: public void init(Object constraintName, Object constraintType,
090: Object rcl, Object properties, Object checkCondition,
091: Object constraintText) {
092: init(constraintName, constraintType, rcl, properties,
093: checkCondition, constraintText, ReuseFactory
094: .getInteger(StatementType.DROP_DEFAULT));
095: }
096:
097: public void init(Object constraintName, Object constraintType,
098: Object rcl, Object properties, Object checkCondition,
099: Object constraintText, Object behavior, Object verifyType) {
100: init(constraintName, constraintType, rcl, properties,
101: checkCondition, constraintText, behavior);
102: this .verifyType = ((Integer) verifyType).intValue();
103: }
104:
105: /**
106: * Convert this object to a String. See comments in QueryTreeNode.java
107: * for how this should be done for tree printing.
108: *
109: * @return This object as a String
110: */
111:
112: public String toString() {
113: if (SanityManager.DEBUG) {
114: return "constraintName: "
115: + ((constraintName != null) ? constraintName
116: .toString() : "null")
117: + "\n"
118: + "constraintType: "
119: + constraintType
120: + "\n"
121: + "properties: "
122: + ((properties != null) ? properties.toString()
123: : "null") + "\n" + super .toString();
124: } else {
125: return "";
126: }
127: }
128:
129: /**
130: * Bind this constraint definition.
131: *
132: @param ddlNode the create or alter table node
133: * @param dd the dd
134: *
135: * @exception StandardException on error
136: */
137: protected void bind(DDLStatementNode ddlNode, DataDictionary dd)
138: throws StandardException {
139: // we need to allow drops on constraints with different schemas
140: // to support removing constraints created pre 5.2.
141: if (constraintType == DataDictionary.DROP_CONSTRAINT)
142: return;
143:
144: // ensure the schema of the constraint matches the schema of the table
145: if (constraintName != null) {
146:
147: String constraintSchema = constraintName.getSchemaName();
148:
149: if (constraintSchema != null) {
150:
151: TableName tableName = ddlNode.getObjectName();
152: String tableSchema = tableName.getSchemaName();
153: if (tableSchema == null) {
154: tableSchema = getSchemaDescriptor((String) null)
155: .getSchemaName();
156: tableName.setSchemaName(tableSchema);
157: }
158: if (!constraintSchema.equals(tableSchema)) {
159: throw StandardException.newException(
160: SQLState.LANG_CONSTRAINT_SCHEMA_MISMATCH,
161: constraintName, tableName);
162:
163: }
164: }
165: } else {
166: name = getBackingIndexName(dd);
167: }
168: }
169:
170: /**
171: * Get the name of the constraint. If the user didn't provide one, we make one up. This allows Replication
172: * to agree with the core compiler on the names of constraints.
173: *
174: * @return constraint name
175: */
176: String getConstraintMoniker() {
177: return name;
178: }
179:
180: /**
181: To support dropping exisiting constraints that may have mismatched schema names
182: we need to support ALTER TABLE S1.T DROP CONSTRAINT S2.C.
183: If a constraint name was specified this returns it, otherwise it returns null.
184: */
185: String getDropSchemaName() {
186: if (constraintName != null)
187: return constraintName.getSchemaName();
188: return null;
189: }
190:
191: /**
192: * Allocates a UUID if one doesn't already exist for the index backing this constraint. This allows Replication
193: * logic to agree with the core compiler on what the UUIDs of indices are.
194: *
195: * @return a UUID for the constraint. allocates one if this is the first time this method is called.
196: */
197: UUID getBackingIndexUUID() {
198: if (backingIndexUUID == null) {
199: backingIndexUUID = getUUIDFactory().createUUID();
200: }
201:
202: return backingIndexUUID;
203: }
204:
205: /**
206: * Gets a unique name for the backing index for this constraint of the form SQLyymmddhhmmssxxn
207: * yy - year, mm - month, dd - day of month, hh - hour, mm - minute, ss - second,
208: * xx - the first 2 digits of millisec because we don't have enough space to keep the exact millisec value,
209: * n - number between 0-9
210: *
211: * @return name of backing index
212: */
213: String getBackingIndexName(DataDictionary dd) {
214: if (backingIndexName == null)
215: backingIndexName = dd.getSystemSQLName();
216:
217: return backingIndexName;
218: }
219:
220: /**
221: * Set the auxiliary provider list.
222: *
223: * @param apl The new auxiliary provider list.
224: */
225: void setAuxiliaryProviderList(ProviderList apl) {
226: this .apl = apl;
227: }
228:
229: /**
230: * Return the auxiliary provider list.
231: *
232: * @return The auxiliary provider list.
233: */
234: public ProviderList getAuxiliaryProviderList() {
235: return apl;
236: }
237:
238: /**
239: * Is this a primary key constraint.
240: *
241: * @return boolean Whether or not this is a primary key constraint
242: */
243: boolean hasPrimaryKeyConstraint() {
244: return constraintType == DataDictionary.PRIMARYKEY_CONSTRAINT;
245: }
246:
247: /**
248: * Is this a unique key constraint.
249: *
250: * @return boolean Whether or not this is a unique key constraint
251: */
252: boolean hasUniqueKeyConstraint() {
253: return constraintType == DataDictionary.UNIQUE_CONSTRAINT;
254: }
255:
256: /**
257: * Is this a foreign key constraint.
258: *
259: * @return boolean Whether or not this is a unique key constraint
260: */
261: boolean hasForeignKeyConstraint() {
262: return constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT;
263: }
264:
265: /**
266: * Does this element have a check constraint.
267: *
268: * @return boolean Whether or not this element has a check constraint
269: */
270: boolean hasCheckConstraint() {
271: return constraintType == DataDictionary.CHECK_CONSTRAINT;
272: }
273:
274: /**
275: * Does this element have a constraint on it.
276: *
277: * @return boolean Whether or not this element has a constraint on it
278: */
279: boolean hasConstraint() {
280: return true;
281: }
282:
283: /**
284: * Is this a foreign key constraint.
285: *
286: * @return boolean Whether or not this is a unique key constraint
287: */
288: boolean requiresBackingIndex() {
289: switch (constraintType) {
290: case DataDictionary.FOREIGNKEY_CONSTRAINT:
291: case DataDictionary.PRIMARYKEY_CONSTRAINT:
292: case DataDictionary.UNIQUE_CONSTRAINT:
293: return true;
294: default:
295: return false;
296: }
297: }
298:
299: /**
300: * Is this a foreign key constraint.
301: *
302: * @return boolean Whether or not this is a unique key constraint
303: */
304: boolean requiresUniqueIndex() {
305: switch (constraintType) {
306: case DataDictionary.PRIMARYKEY_CONSTRAINT:
307: case DataDictionary.UNIQUE_CONSTRAINT:
308: return true;
309: default:
310: return false;
311: }
312: }
313:
314: /**
315: * Get the constraint type
316: *
317: * @return constraintType The constraint type.
318: */
319: int getConstraintType() {
320: return constraintType;
321: }
322:
323: /**
324: * Set the optional properties for the backing index to this constraint.
325: *
326: * @param properties The optional Properties for this constraint.
327: */
328: public void setProperties(Properties properties) {
329: this .properties = properties;
330: }
331:
332: /**
333: * Get the optional properties for the backing index to this constraint.
334: *
335: *
336: * @return The optional properties for the backing index to this constraint
337: */
338: public Properties getProperties() {
339: return properties;
340: }
341:
342: /**
343: * Is this constraint referenced.
344: *
345: * @return true/false
346: */
347: public boolean isReferenced() {
348: return false;
349: }
350:
351: /**
352: * Get the count of enabled fks
353: * that reference this constraint
354: *
355: * @return the number
356: */
357: public int getReferenceCount() {
358: return 0;
359: }
360:
361: /**
362: * Is this constraint enabled.
363: *
364: * @return true/false
365: */
366: public boolean isEnabled() {
367: return true;
368: }
369:
370: /**
371: * Get the column list from this node.
372: *
373: * @return ResultColumnList The column list from this table constraint.
374: */
375: public ResultColumnList getColumnList() {
376: return columnList;
377: }
378:
379: /**
380: * Set the column list for this node. This is useful for check constraints
381: * where the list of referenced columns is built at bind time.
382: *
383: * @param columnList The new columnList.
384: */
385: public void setColumnList(ResultColumnList columnList) {
386: this .columnList = columnList;
387: }
388:
389: /**
390: * Get the check condition from this table constraint.
391: *
392: * @return The check condition from this node.
393: */
394: public ValueNode getCheckCondition() {
395: return checkCondition;
396: }
397:
398: /**
399: * Set the check condition for this table constraint.
400: *
401: * @param checkCondition The check condition
402: */
403: public void setCheckCondition(ValueNode checkCondition) {
404: this .checkCondition = checkCondition;
405: }
406:
407: /**
408: * Get the text of the constraint. (Only meaningful for check constraints.)
409: *
410: * @return The constraint text.
411: */
412: public String getConstraintText() {
413: return constraintText;
414: }
415:
416: /**
417: * Get the array of 1-based column references for a check constraint.
418: *
419: * @return The array of 1-based column references for a check constraint.
420: */
421: public int[] getCheckColumnReferences() {
422: return checkColumnReferences;
423: }
424:
425: /**
426: * Set the array of 1-based column references for a check constraint.
427: *
428: * @param checkColumnReferences The array of 1-based column references
429: * for the check constraint.
430: */
431: public void setCheckColumnReferences(int[] checkColumnReferences) {
432: this .checkColumnReferences = checkColumnReferences;
433: }
434:
435: /**
436: * Return the behavior of this constriant (DropStatementNode.xxx)
437: *
438: * @return the behavior
439: */
440: int getDropBehavior() {
441: return behavior;
442: }
443:
444: /**
445: * @return the expected type of the constraint, DataDictionary.DROP_CONSTRAINT if the constraint is
446: * to be dropped without checking its type.
447: */
448: int getVerifyType() {
449: return verifyType;
450: }
451:
452: ///////////////////////////////////////////////////////////////////////////
453: //
454: // MINIONS
455: //
456: ///////////////////////////////////////////////////////////////////////////
457: /**
458: * Get the UUID factory
459: *
460: * @return the UUID factory
461: *
462: */
463: private UUIDFactory getUUIDFactory() {
464: if (uuidFactory == null) {
465: uuidFactory = Monitor.getMonitor().getUUIDFactory();
466: }
467: return uuidFactory;
468: }
469: }
|