001: package com.quadcap.sql;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.IOException;
042:
043: import java.util.List;
044:
045: import java.sql.SQLException;
046:
047: import com.quadcap.sql.file.BlockFile;
048: import com.quadcap.sql.file.ByteUtil;
049:
050: import com.quadcap.sql.index.BCursor;
051: import com.quadcap.sql.index.Btree;
052:
053: import com.quadcap.sql.types.Value;
054: import com.quadcap.sql.types.ValueNull;
055:
056: import com.quadcap.util.Debug;
057:
058: /**
059: * Implementation of SQL <b>ALTER TABLE DROP COLUMN</b> statement.
060: *
061: * @author Stan Bailes
062: */
063: public class StmtDropColumn implements Stmt {
064: String tableName;
065: String colName;
066:
067: /**
068: * Explicit constructor from table name and column name
069: */
070: public StmtDropColumn(String tableName, String colName) {
071: this .tableName = tableName;
072: this .colName = colName;
073: }
074:
075: /**
076: * Delete any constraints which reference the specified column.
077: * Reset all other constraint column maps.
078: *
079: * @param col one-based column number
080: */
081: public void deleteColumnConstraints(Session session, Table table,
082: int col) throws SQLException, IOException {
083: int num = table.getNumConstraints();
084:
085: // Copy constraints for stable enumeration
086: Constraint[] tmpC = new Constraint[num];
087: for (int i = 0; i < num; i++) {
088: tmpC[i] = table.getConstraint(i);
089: }
090: for (int i = 0; i < num; i++) {
091: Constraint con = tmpC[i];
092: int[] cols = con.getColumns();
093: boolean match = false;
094: for (int j = 0; j < cols.length && !match; j++) {
095: match = cols[j] == col;
096: }
097: if (match) {
098: session
099: .doStep(new DeleteConstraint(session, table,
100: con));
101: } else {
102: con.resetColumns();
103: }
104: }
105: }
106:
107: /**
108: * Stmt.execute()
109: *
110: * For DROP COLUMN, we need to update the table definition, of course.
111: * But then, we need to update *all* of the rows!
112: */
113: public void execute(Session session) throws IOException,
114: SQLException {
115: // First, acquire the schema and table locks
116: Database db = session.getDatabase();
117: session.getTableWriteLock("#Schema");
118: session.getTableWriteLock(tableName);
119:
120: Table table = (Table) db.getRelation(tableName);
121: //#ifdef DEBUG
122: if (table == null) {
123: throw new SQLException("No table: " + tableName);
124: }
125: //#endif
126: Column column = table.getColumn(colName);
127:
128: // Drop all the column's constraints first
129: List constraints = column.getConstraints();
130: if (constraints != null) {
131: for (int i = 0; i < constraints.size(); i++) {
132: Constraint constraint = (Constraint) constraints.get(i);
133: session.doStep(new DeleteConstraint(session, table,
134: constraint));
135: }
136: }
137: deleteColumnConstraints(session, table, column.getColumn());
138:
139: // Remove the column from the table schema
140: session.doStep(new DropColumn(session, table, column));
141:
142: // Update every row in the table with the new column value
143: BCursor bc = null;
144: try {
145: BlockFile file = db.getFile();
146: Expression defaultExpr = column.getDefault();
147: Value columnDefault = defaultExpr == null ? ValueNull.valueNull
148: : defaultExpr.getValue(session, null);
149:
150: IndexConstraint ic = table.getAnyIndex(session);
151: Btree index = ic.getIndex(db);
152: bc = index.getCursor();
153: LazyRow row1 = new LazyRow(table.getColumnCount() + 1);
154: Row row2 = new Row(table.getColumnCount());
155: final int dc = column.getColumn();
156: while (bc.next()) {
157: long rowId = bc.getValAsLong();
158: db.getRow(rowId, row1, false);
159: int del = 0;
160: for (int i = 1; i <= row1.size(); i++) {
161: if (i == dc)
162: del++;
163: else
164: row2.set(i - del, row1.item(i));
165: }
166: UpdateRow update = null;
167: if (db.inMemory()) {
168: update = new UpdateRow(session, rowId, row1, row2);
169: row1 = new LazyRow(table.getColumnCount() + 1);
170: row2 = new Row(table.getColumnCount());
171: } else {
172: byte[] oldRowBytes = row1.getBytes();
173: byte[] rowBytes = LazyRow.writeRow(session, null,
174: row2);
175: update = new UpdateRow(session, table, rowId,
176: oldRowBytes, rowBytes);
177: }
178: session.doStep(update);
179: }
180: } finally {
181: if (bc != null)
182: bc.release();
183: }
184: }
185: }
|