001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.FKConstraintDefinitionNode
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.types.TypeId;
025: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
026: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
027: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
028: import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
029: import org.apache.derby.iapi.sql.conn.Authorizer;
030: import org.apache.derby.iapi.error.StandardException;
031: import org.apache.derby.iapi.services.sanity.SanityManager;
032:
033: import org.apache.derby.iapi.error.StandardException;
034: import org.apache.derby.iapi.reference.SQLState;
035:
036: import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
037: import org.apache.derby.impl.sql.execute.ConstraintInfo;
038:
039: import org.apache.derby.iapi.util.JBitSet;
040: import org.apache.derby.iapi.util.ReuseFactory;
041: import org.apache.derby.iapi.sql.dictionary.DDUtils;
042:
043: /**
044: * A FKConstraintDefintionNode represents table constraint definitions.
045: *
046: * @author jamie
047: */
048:
049: public final class FKConstraintDefinitionNode extends
050: ConstraintDefinitionNode {
051: TableName refTableName;
052: ResultColumnList refRcl;
053: SchemaDescriptor refTableSd;
054: int refActionDeleteRule; // referential action on delete
055: int refActionUpdateRule; // referential action on update
056:
057: public void init(Object constraintName, Object refTableName,
058: Object fkRcl, Object refRcl, Object refActions) {
059: super .init(constraintName, ReuseFactory
060: .getInteger(DataDictionary.FOREIGNKEY_CONSTRAINT),
061: fkRcl, null, null, null);
062: this .refRcl = (ResultColumnList) refRcl;
063: this .refTableName = (TableName) refTableName;
064:
065: this .refActionDeleteRule = ((int[]) refActions)[0];
066: this .refActionUpdateRule = ((int[]) refActions)[1];
067: }
068:
069: /**
070: * Bind this constraint definition. Figure out some
071: * information about the table we are binding against.
072: *
073: * @param dd DataDictionary
074: *
075: * @exception StandardException on error
076: */
077: protected void bind(DDLStatementNode ddlNode, DataDictionary dd)
078: throws StandardException {
079: super .bind(ddlNode, dd);
080:
081: refTableSd = getSchemaDescriptor(refTableName.getSchemaName());
082:
083: if (refTableSd.isSystemSchema()) {
084: throw StandardException
085: .newException(SQLState.LANG_NO_FK_ON_SYSTEM_SCHEMA);
086: }
087:
088: // check the referenced table, unless this is a self-referencing constraint
089: if (refTableName.equals(ddlNode.getObjectName()))
090: return;
091:
092: // error when the referenced table does not exist
093: TableDescriptor td = getTableDescriptor(refTableName
094: .getTableName(), refTableSd);
095: if (td == null)
096: throw StandardException
097: .newException(SQLState.LANG_INVALID_FK_NO_REF_TAB,
098: getConstraintMoniker(), refTableName
099: .getTableName());
100:
101: // Verify if REFERENCES_PRIV is granted to columns referenced
102: getCompilerContext().pushCurrentPrivType(getPrivType());
103:
104: // Indicate that this statement has a dependency on the
105: // table which is referenced by this foreign key:
106: getCompilerContext().createDependency(td);
107:
108: // If references clause doesn't have columnlist, get primary key info
109: if (refRcl.size() == 0 && (td.getPrimaryKey() != null)) {
110: // Get the primary key columns
111: int[] refCols = td.getPrimaryKey().getReferencedColumns();
112: for (int i = 0; i < refCols.length; i++) {
113: ColumnDescriptor cd = td
114: .getColumnDescriptor(refCols[i]);
115: // Set tableDescriptor for this column descriptor. Needed for adding required table
116: // access permission. Column descriptors may not have this set already.
117: cd.setTableDescriptor(td);
118: if (isPrivilegeCollectionRequired())
119: getCompilerContext().addRequiredColumnPriv(cd);
120: }
121:
122: } else {
123: for (int i = 0; i < refRcl.size(); i++) {
124: ResultColumn rc = (ResultColumn) refRcl.elementAt(i);
125: ColumnDescriptor cd = td.getColumnDescriptor(rc
126: .getName());
127: if (cd != null) {
128: // Set tableDescriptor for this column descriptor. Needed for adding required table
129: // access permission. Column descriptors may not have this set already.
130: cd.setTableDescriptor(td);
131: if (isPrivilegeCollectionRequired())
132: getCompilerContext().addRequiredColumnPriv(cd);
133: }
134: }
135: }
136: getCompilerContext().popCurrentPrivType();
137: }
138:
139: public ConstraintInfo getReferencedConstraintInfo() {
140: if (SanityManager.DEBUG) {
141: SanityManager
142: .ASSERT(refTableSd != null,
143: "You must call bind() before calling getConstraintInfo");
144: }
145: return new ConstraintInfo(refTableName.getTableName(),
146: refTableSd, refRcl.getColumnNames(),
147: refActionDeleteRule, refActionUpdateRule);
148: }
149:
150: public TableName getRefTableName() {
151: return refTableName;
152: }
153:
154: int getPrivType() {
155: return Authorizer.REFERENCES_PRIV;
156: }
157: }
|