1 24 25 package com.mckoi.database.interpret; 26 27 import com.mckoi.database.*; 28 import com.mckoi.util.IntegerVector; 29 import java.util.ArrayList ; 30 import java.util.List ; 31 32 37 38 public class AlterTable extends Statement { 39 40 44 StatementTree create_statement; 45 46 49 String table_name; 50 51 54 private ArrayList actions; 55 56 59 private TableName tname; 60 61 64 CreateTable create_stmt; 65 66 67 68 71 public void addAction(AlterTableAction action) { 72 if (actions == null) { 73 actions = new ArrayList (); 74 } 75 actions.add(action); 76 } 77 78 83 public boolean checkColumnNamesMatch(DatabaseConnection db, 84 String col1, String col2) { 85 if (db.isInCaseInsensitiveMode()) { 86 return col1.equalsIgnoreCase(col2); 87 } 88 return col1.equals(col2); 89 } 90 91 private void checkColumnConstraint(String col_name, String [] cols, 92 TableName table, String constraint_name) { 93 for (int i = 0; i < cols.length; ++i) { 94 if (col_name.equals(cols[i])) { 95 throw new DatabaseConstraintViolationException( 96 DatabaseConstraintViolationException.DROP_COLUMN_VIOLATION, 97 "Constraint violation (" + constraint_name + 98 ") dropping column " + col_name + " because of " + 99 "referential constraint in " + table); 100 } 101 } 102 103 } 104 105 106 107 109 public void prepare() throws DatabaseException { 110 111 table_name = (String ) cmd.getObject("table_name"); 113 addAction((AlterTableAction) cmd.getObject("alter_action")); 114 create_statement = (StatementTree) cmd.getObject("create_statement"); 115 116 118 if (create_statement != null) { 119 create_stmt = new CreateTable(); 120 create_stmt.init(database, create_statement, null); 121 create_stmt.prepare(); 122 this.table_name = create_stmt.table_name; 123 } 125 else { 126 } 129 130 tname = resolveTableName(table_name, database); 132 if (tname.getName().indexOf('.') != -1) { 133 throw new DatabaseException("Table name can not contain '.' character."); 134 } 135 136 } 137 138 public Table evaluate() throws DatabaseException { 139 140 DatabaseQueryContext context = new DatabaseQueryContext(database); 141 142 String schema_name = database.getCurrentSchema(); 143 144 if (!database.getDatabase().canUserAlterTableObject(context, user, tname)) { 146 throw new UserAccessException( 147 "User not permitted to alter table: " + table_name); 148 } 149 150 if (create_statement != null) { 151 152 DataTableDef table_def = create_stmt.createDataTableDef(); 154 TableName tname = table_def.getTableName(); 155 if (database.tableExists(tname)) { 157 database.dropAllConstraintsForTable(tname); 159 database.updateTable(table_def); 160 } 161 else { 163 database.createTable(table_def); 164 } 165 166 create_stmt.setupAllConstraints(); 168 169 return FunctionTable.resultTable(context, 0); 171 } 172 else { 173 175 DataTableDef table_def = database.getTable(tname).getDataTableDef(); 177 String table_name = table_def.getName(); 178 DataTableDef new_table = table_def.noColumnCopy(); 179 180 ColumnChecker checker = 182 ColumnChecker.standardColumnChecker(database, tname); 183 184 boolean table_altered = false; 187 188 for (int n = 0; n < table_def.columnCount(); ++n) { 189 DataTableColumnDef column = 190 new DataTableColumnDef(table_def.columnAt(n)); 191 String col_name = column.getName(); 192 boolean mark_dropped = false; 194 for (int i = 0; i < actions.size(); ++i) { 195 AlterTableAction action = (AlterTableAction) actions.get(i); 196 if (action.getAction().equals("ALTERSET") && 197 checkColumnNamesMatch(database, 198 (String ) action.getElement(0), 199 col_name)) { 200 Expression exp = (Expression) action.getElement(1); 201 checker.checkExpression(exp); 202 column.setDefaultExpression(exp); 203 table_altered = true; 204 } 205 else if (action.getAction().equals("DROPDEFAULT") && 206 checkColumnNamesMatch(database, 207 (String ) action.getElement(0), 208 col_name)) { 209 column.setDefaultExpression(null); 210 table_altered = true; 211 } 212 else if (action.getAction().equals("DROP") && 213 checkColumnNamesMatch(database, 214 (String ) action.getElement(0), 215 col_name)) { 216 Transaction.ColumnGroupReference[] refs = 218 database.queryTableImportedForeignKeyReferences(tname); 219 for (int p = 0; p < refs.length; ++p) { 220 checkColumnConstraint(col_name, refs[p].ref_columns, 221 refs[p].ref_table_name, refs[p].name); 222 } 223 refs = database.queryTableForeignKeyReferences(tname); 225 for (int p = 0; p < refs.length; ++p) { 226 checkColumnConstraint(col_name, refs[p].key_columns, 227 refs[p].key_table_name, refs[p].name); 228 } 229 Transaction.ColumnGroup primary_key = 231 database.queryTablePrimaryKeyGroup(tname); 232 if (primary_key != null) { 233 checkColumnConstraint(col_name, primary_key.columns, 234 tname, primary_key.name); 235 } 236 Transaction.ColumnGroup[] uniques = 238 database.queryTableUniqueGroups(tname); 239 for (int p = 0; p < uniques.length; ++p) { 240 checkColumnConstraint(col_name, uniques[p].columns, 241 tname, uniques[p].name); 242 } 243 244 mark_dropped = true; 245 table_altered = true; 246 } 247 } 248 if (!mark_dropped) { 250 new_table.addColumn(column); 251 } 252 } 253 254 for (int i = 0; i < actions.size(); ++i) { 256 AlterTableAction action = (AlterTableAction) actions.get(i); 257 if (action.getAction().equals("ADD")) { 258 ColumnDef cdef = (ColumnDef) action.getElement(0); 259 if (cdef.isUnique() || cdef.isPrimaryKey()) { 260 throw new DatabaseException("Can not use UNIQUE or PRIMARY KEY " + 261 "column constraint when altering a column. Use " + 262 "ADD CONSTRAINT instead."); 263 } 264 DataTableColumnDef col = CreateTable.convertColumnDef(cdef); 266 267 checker.checkExpression( 268 col.getDefaultExpression(database.getSystem())); 269 String col_name = col.getName(); 270 col.setName(checker.stripTableName(table_name, col_name)); 272 new_table.addColumn(col); 273 table_altered = true; 274 } 275 } 276 277 for (int i = 0; i < actions.size(); ++i) { 279 AlterTableAction action = (AlterTableAction) actions.get(i); 280 if (action.getAction().equals("DROP_CONSTRAINT")) { 281 String constraint_name = (String ) action.getElement(0); 282 int drop_count = database.dropNamedConstraint(tname, constraint_name); 283 if (drop_count == 0) { 284 throw new DatabaseException( 285 "Named constraint to drop on table " + tname + 286 " was not found: " + constraint_name); 287 } 288 } 289 else if (action.getAction().equals("DROP_CONSTRAINT_PRIMARY_KEY")) { 290 boolean constraint_dropped = 291 database.dropPrimaryKeyConstraintForTable(tname, null); 292 if (!constraint_dropped) { 293 throw new DatabaseException( 294 "No primary key to delete on table " + tname); 295 } 296 } 297 } 298 299 for (int i = 0; i < actions.size(); ++i) { 301 AlterTableAction action = (AlterTableAction) actions.get(i); 302 if (action.getAction().equals("ADD_CONSTRAINT")) { 303 ConstraintDef constraint = (ConstraintDef) action.getElement(0); 304 boolean foreign_constraint = 305 (constraint.type == ConstraintDef.FOREIGN_KEY); 306 TableName ref_tname = null; 307 if (foreign_constraint) { 308 ref_tname = 309 resolveTableName(constraint.reference_table_name, database); 310 if (database.isInCaseInsensitiveMode()) { 311 ref_tname = database.tryResolveCase(ref_tname); 312 } 313 constraint.reference_table_name = ref_tname.toString(); 314 } 315 316 checker.stripColumnList(table_name, constraint.column_list); 317 checker.stripColumnList(constraint.reference_table_name, 318 constraint.column_list2); 319 checker.checkExpression(constraint.check_expression); 320 checker.checkColumnList(constraint.column_list); 321 if (foreign_constraint && constraint.column_list2 != null) { 322 ColumnChecker referenced_checker = 323 ColumnChecker.standardColumnChecker(database, ref_tname); 324 referenced_checker.checkColumnList(constraint.column_list2); 325 } 326 327 CreateTable.addSchemaConstraint(database, tname, constraint); 328 329 } 330 } 331 332 if (table_altered) { 334 if (new_table.columnCount() == 0) { 335 throw new DatabaseException( 336 "Can not ALTER table to have 0 columns."); 337 } 338 database.updateTable(new_table); 339 } 340 else { 341 database.checkAllConstraints(tname); 345 } 346 347 return FunctionTable.resultTable(context, 0); 349 350 } 351 352 } 353 354 355 } 356 | Popular Tags |