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.Externalizable;
042: import java.io.IOException;
043: import java.io.ObjectInput;
044: import java.io.ObjectOutput;
045:
046: import java.util.ArrayList;
047: import java.util.Enumeration;
048: import java.util.HashMap;
049: import java.util.Iterator;
050: import java.util.Map;
051:
052: import java.sql.SQLException;
053:
054: import com.quadcap.sql.file.BlockFile;
055: import com.quadcap.sql.file.ByteUtil;
056:
057: import com.quadcap.sql.index.Btree;
058: import com.quadcap.sql.index.BCursor;
059:
060: import com.quadcap.sql.io.Extern;
061:
062: import com.quadcap.util.Debug;
063:
064: /**
065: * Implementation of the SQL <b>ALTER TABLE RENAME TO</b> statement.
066: *
067: * @author Stan Bailes
068: */
069:
070: public class StmtRenameTable extends LogStep implements Stmt,
071: Externalizable {
072: String oldName;
073: String newName;
074: Relation r;
075:
076: public StmtRenameTable() {
077: }
078:
079: public StmtRenameTable(String oldName, String newName) {
080: this .oldName = oldName;
081: this .newName = newName;
082: }
083:
084: public void execute(Session session) throws IOException,
085: SQLException {
086: session.getTableWriteLock("#Schema");
087: session.getTableWriteLock(oldName);
088: session.getTableWriteLock(newName);
089: session.doStep(this );
090: }
091:
092: public void redo(Session session) throws IOException, SQLException {
093: rename(session, oldName, newName);
094: }
095:
096: public void undo(Session session) throws IOException, SQLException {
097: rename(session, newName, oldName);
098: }
099:
100: public void rename(Session session, String oldN, String newN)
101: throws IOException, SQLException {
102: Database db = session.getDatabase();
103: Relation oldR = db.getRelation(oldN);
104: if (oldR == null) {
105: throw new SQLException("no such table: " + oldN, "42000");
106: }
107: db.renameRelation(oldR, newN);
108: Relation newR = db.getRelation(newN);
109: if (newR == null) {
110: throw new SQLException("rename failed!: " + newN);
111: }
112:
113: Enumeration views = db.getViews(newN);
114: while (views.hasMoreElements()) {
115: String view1 = views.nextElement().toString();
116: renameView(session, view1, oldN, newN);
117: }
118:
119: if (newR instanceof Table) {
120: Map referencingTables = new HashMap();
121: Table t = (Table) newR;
122: int num = t.getNumConstraints();
123: for (int i = 0; i < num; i++) {
124: Constraint c = t.getConstraint(i);
125: if (c instanceof ForeignKeyConstraint) {
126: ForeignKeyConstraint fc = (ForeignKeyConstraint) c;
127: String fTable = fc.getFTableName();
128: referencingTables.put(fTable, "");
129: }
130: }
131: if (referencingTables.size() > 0) {
132: Iterator iter = referencingTables.keySet().iterator();
133: while (iter.hasNext()) {
134: renameForeignKeys(session, iter.next().toString(),
135: oldN, newN);
136: }
137: db.updateRelation(newR);
138: }
139: }
140: }
141:
142: void renameForeignKeys(Session session, String tableName,
143: String oldN, String newN) throws IOException, SQLException {
144: session.getTableReadLock(tableName);
145: Database db = session.getDatabase();
146: Table t = (Table) db.getRelation(tableName);
147: int num = t.getNumConstraints();
148: for (int i = 0; i < num; i++) {
149: Constraint c = t.getConstraint(i);
150: if (c instanceof ForeignKeyConstraint) {
151: ForeignKeyConstraint fc = (ForeignKeyConstraint) c;
152: String fTable = fc.getFTableName();
153: if (fTable.equals(oldN)) {
154: fc.setFTableName(newN);
155: fc.resetColumns();
156: }
157: }
158: }
159: db.updateRelation(t);
160: }
161:
162: class RenameTableVisitor implements ExpressionVisitor {
163: String oldN;
164: String newN;
165:
166: RenameTableVisitor(String oldN, String newN) {
167: this .oldN = oldN;
168: this .newN = newN;
169: }
170:
171: public void visit(Expression ex) {
172: if (ex instanceof SelectFromTable) {
173: SelectFromTable sf = (SelectFromTable) ex;
174: String tableName = sf.getTableName();
175: if (tableName.equals(oldN)) {
176: sf.setTableName(newN);
177: }
178: } else if (ex instanceof SelectExpression) {
179: Iterator iter = ((SelectExpression) ex).getFrom()
180: .iterator();
181: while (iter.hasNext()) {
182: visit((Expression) iter.next());
183: }
184: }
185: ex.visitSubExpressions(this );
186: }
187: }
188:
189: void renameView(Session session, String viewName, String oldN,
190: String newN) throws IOException, SQLException {
191:
192: session.getTableReadLock(viewName);
193:
194: Database db = session.getDatabase();
195: View v = (View) db.getRelation(viewName);
196: Expression viewEx = v.getViewExpression();
197: RenameTableVisitor visitor = new RenameTableVisitor(oldN, newN);
198: visitor.visit(viewEx);
199: db.updateRelation(v);
200: }
201:
202: public void prepare(Session session) throws IOException,
203: SQLException {
204: }
205:
206: public void readExternal(ObjectInput in) throws IOException,
207: ClassNotFoundException {
208: oldName = (String) in.readObject();
209: newName = (String) in.readObject();
210: }
211:
212: public void writeExternal(ObjectOutput out) throws IOException {
213: out.writeObject(oldName);
214: out.writeObject(newName);
215: }
216:
217: //#ifdef DEBUG
218: /**
219: * Return a displayable representation for debugging
220: */
221: public String toString() {
222: StringBuffer sb = new StringBuffer(super .toString());
223: sb.append(" RenameTable(");
224: sb.append(oldName);
225: sb.append(" to ");
226: sb.append(newName);
227: sb.append(')');
228: return sb.toString();
229: }
230:
231: //#endif
232:
233: static Extern extern;
234:
235: public void setExtern(Extern extern) {
236: StmtRenameTable.extern = extern;
237: }
238:
239: public Extern getExtern() {
240: return extern;
241: }
242: }
|