Quadcap Embeddable Database

com/quadcap/sql/StmtDropColumn.java

Go to the documentation of this file.
00001 package com.quadcap.sql; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.IOException; 00042 00043 import java.util.List; 00044 00045 import java.sql.SQLException; 00046 00047 import com.quadcap.sql.file.BlockFile; 00048 import com.quadcap.sql.file.ByteUtil; 00049 00050 import com.quadcap.sql.index.BCursor; 00051 import com.quadcap.sql.index.Btree; 00052 00053 import com.quadcap.sql.types.Value; 00054 import com.quadcap.sql.types.ValueNull; 00055 00056 import com.quadcap.util.Debug; 00057 00058 /** 00059 * Implementation of SQL <b>ALTER TABLE DROP COLUMN</b> statement. 00060 * 00061 * @author Stan Bailes 00062 */ 00063 public class StmtDropColumn implements Stmt { 00064 String tableName; 00065 String colName; 00066 00067 /** 00068 * Explicit constructor from table name and column name 00069 */ 00070 public StmtDropColumn(String tableName, String colName) { 00071 this.tableName = tableName; 00072 this.colName = colName; 00073 } 00074 00075 /** 00076 * Delete any constraints which reference the specified column. 00077 * Reset all other constraint column maps. 00078 * 00079 * @param col one-based column number 00080 */ 00081 public void deleteColumnConstraints(Session session, Table table, int col) 00082 throws SQLException, IOException 00083 { 00084 int num = table.getNumConstraints(); 00085 00086 // Copy constraints for stable enumeration 00087 Constraint[] tmpC = new Constraint[num]; 00088 for (int i = 0; i < num; i++) { 00089 tmpC[i] = table.getConstraint(i); 00090 } 00091 for (int i = 0; i < num; i++) { 00092 Constraint con = tmpC[i]; 00093 int[] cols = con.getColumns(); 00094 boolean match = false; 00095 for (int j = 0; j < cols.length && !match; j++) { 00096 match = cols[j] == col; 00097 } 00098 if (match) { 00099 session.doStep(new DeleteConstraint(session, table, con)); 00100 } else { 00101 con.resetColumns(); 00102 } 00103 } 00104 } 00105 00106 /** 00107 * Stmt.execute() 00108 * 00109 * For DROP COLUMN, we need to update the table definition, of course. 00110 * But then, we need to update *all* of the rows! 00111 */ 00112 public void execute(Session session) throws IOException, SQLException { 00113 // First, acquire the schema and table locks 00114 Database db = session.getDatabase(); 00115 session.getTableWriteLock("#Schema"); 00116 session.getTableWriteLock(tableName); 00117 00118 Table table = (Table)db.getRelation(tableName); 00119 //#ifdef DEBUG 00120 if (table == null) { 00121 throw new SQLException("No table: " + tableName); 00122 } 00123 //#endif 00124 Column column = table.getColumn(colName); 00125 00126 // Drop all the column's constraints first 00127 List constraints = column.getConstraints(); 00128 if (constraints != null) { 00129 for (int i = 0; i < constraints.size(); i++) { 00130 Constraint constraint = (Constraint)constraints.get(i); 00131 session.doStep(new DeleteConstraint(session, table, 00132 constraint)); 00133 } 00134 } 00135 deleteColumnConstraints(session, table, column.getColumn()); 00136 00137 // Remove the column from the table schema 00138 session.doStep(new DropColumn(session, table, column)); 00139 00140 // Update every row in the table with the new column value 00141 BCursor bc = null; 00142 try { 00143 BlockFile file = db.getFile(); 00144 Expression defaultExpr = column.getDefault(); 00145 Value columnDefault = 00146 defaultExpr == null 00147 ? ValueNull.valueNull 00148 : defaultExpr.getValue(session, null); 00149 00150 IndexConstraint ic = table.getAnyIndex(session); 00151 Btree index = ic.getIndex(db); 00152 bc = index.getCursor(); 00153 LazyRow row1 = new LazyRow(table.getColumnCount() + 1); 00154 Row row2 = new Row(table.getColumnCount()); 00155 final int dc = column.getColumn(); 00156 while (bc.next()) { 00157 long rowId = bc.getValAsLong(); 00158 db.getRow(rowId, row1, false); 00159 int del = 0; 00160 for (int i = 1; i <= row1.size(); i++) { 00161 if (i == dc) del++; 00162 else row2.set(i - del, row1.item(i)); 00163 } 00164 UpdateRow update = null; 00165 if (db.inMemory()) { 00166 update = new UpdateRow(session, rowId, row1, row2); 00167 row1 = new LazyRow(table.getColumnCount() + 1); 00168 row2 = new Row(table.getColumnCount()); 00169 } else { 00170 byte[] oldRowBytes = row1.getBytes(); 00171 byte[] rowBytes = LazyRow.writeRow(session, null, row2); 00172 update = new UpdateRow(session, table, rowId, 00173 oldRowBytes, rowBytes); 00174 } 00175 session.doStep(update); 00176 } 00177 } finally { 00178 if (bc != null) bc.release(); 00179 } 00180 } 00181 }