001: /*
002: * $Id: AddConstraintCommand.java,v 1.20 2005/12/20 18:32:28 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2004 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.engine.commands;
042:
043: import java.util.List;
044:
045: import org.axiondb.AxionException;
046: import org.axiondb.Column;
047: import org.axiondb.ColumnIdentifier;
048: import org.axiondb.Constraint;
049: import org.axiondb.Database;
050: import org.axiondb.Index;
051: import org.axiondb.Table;
052: import org.axiondb.TableIdentifier;
053: import org.axiondb.constraints.ForeignKeyConstraint;
054: import org.axiondb.constraints.UniqueConstraint;
055: import org.axiondb.util.StringIdentifierGenerator;
056:
057: /**
058: * An <code>ADD CONSTRAINT</code> command, as generated by <code>ALTER TABLE</code>
059: * and <code>CREATE TABLE</code> statements.
060: *
061: * @version $Revision: 1.20 $ $Date: 2005/12/20 18:32:28 $
062: * @author James Strachan
063: * @author Rodney Waldhoff
064: * @author Jonathan Giron
065: * @author Ahimanikya Satapathy
066: */
067: public class AddConstraintCommand extends ConstraintCommand {
068: public AddConstraintCommand(String tableName, Constraint constraint) {
069: super (tableName);
070: setConstraint(constraint);
071: }
072:
073: public Constraint getConstraint() {
074: return _constraint;
075: }
076:
077: private void setConstraint(Constraint c) {
078: _constraint = c;
079: }
080:
081: protected void execute(Database db, Table table)
082: throws AxionException {
083: assertNotReadOnly(db);
084: if (null == getConstraint()) {
085: throw new AxionException("Constraint must not be null.");
086: }
087:
088: getConstraint()
089: .resolve(db, new TableIdentifier(getTableName()));
090: table.addConstraint(getConstraint()); // first add the constraint
091:
092: // Automagically add btree index before adding the constraint if it is a PK or
093: // unique or FK, and an index doesn't already exist for its column. This should
094: // speed up evaluation of constraints on tables with existing data, as the
095: // matching algorithm takes advantage of indexes.
096: if (getConstraint() instanceof UniqueConstraint) {
097: UniqueConstraint pk = (UniqueConstraint) getConstraint();
098: boolean isUnique = pk.getSelectableCount() == 1;
099: buildIndexIfRequired(db, pk.getSelectableList(), table,
100: isUnique);
101: } else if (getConstraint() instanceof ForeignKeyConstraint) {
102: ForeignKeyConstraint fk = (ForeignKeyConstraint) getConstraint();
103: if (!fk.getParentTableName().equals(fk.getChildTableName())) {
104: Table parentTable = db
105: .getTable(fk.getParentTableName());
106: parentTable.addConstraint(fk);
107: }
108:
109: List childColumns = fk.getChildTableColumns();
110: Table childTable = db.getTable(fk.getChildTableName());
111: buildIndexIfRequired(db, childColumns, childTable, false);
112: }
113: }
114:
115: private void buildIndexIfRequired(Database db, List columns,
116: Table table, boolean isUnique) throws AxionException {
117: boolean foundIndex = false;
118: for (int i = 0, I = columns.size(); i < I; i++) {
119: Object sel = columns.get(i);
120: if (sel instanceof ColumnIdentifier) {
121: ColumnIdentifier columnId = (ColumnIdentifier) sel;
122: Column column = table.getColumn(columnId.getName());
123: if (table.isColumnIndexed(column)) {
124: foundIndex = true;
125: break;
126: }
127: }
128: }
129:
130: if (!foundIndex && columns.size() >= 1) {
131: Object sel = columns.get(0);
132: if (sel instanceof ColumnIdentifier) {
133: ColumnIdentifier columnId = (ColumnIdentifier) sel;
134: Column column = table.getColumn(columnId.getName());
135: if (!table.isColumnIndexed(column)) {
136: boolean isMemorydb = db.getDBDirectory() == null;
137: String name = StringIdentifierGenerator.INSTANCE
138: .next16DigitIdentifier("SYS");
139: Index index = db.getIndexFactory("default")
140: .makeNewInstance(name, column, isUnique,
141: isMemorydb);
142: if (index != null) {
143: db.addIndex(index, table, true);
144: }
145: }
146: }
147: }
148: }
149:
150: private Constraint _constraint;
151: }
|