1 5 package org.h2.table; 6 7 import java.sql.SQLException ; 8 import java.util.HashMap ; 9 10 import org.h2.constraint.Constraint; 11 import org.h2.engine.Constants; 12 import org.h2.engine.DbObject; 13 import org.h2.engine.Right; 14 import org.h2.engine.Session; 15 import org.h2.index.Index; 16 import org.h2.index.IndexType; 17 import org.h2.message.Message; 18 import org.h2.message.Trace; 19 import org.h2.result.Row; 20 import org.h2.result.SearchRow; 21 import org.h2.result.SimpleRow; 22 import org.h2.result.SimpleRowValue; 23 import org.h2.schema.Schema; 24 import org.h2.schema.SchemaObject; 25 import org.h2.schema.Sequence; 26 import org.h2.schema.TriggerObject; 27 import org.h2.util.ObjectArray; 28 import org.h2.value.Value; 29 import org.h2.value.ValueNull; 30 31 34 35 public abstract class Table extends SchemaObject { 36 37 public static final int TYPE_CACHED = 0, TYPE_MEMORY = 1; 38 39 public static final String TABLE_LINK = "TABLE LINK"; 40 public static final String SYSTEM_TABLE = "SYSTEM TABLE"; 41 public static final String TABLE = "TABLE"; 42 public static final String VIEW = "VIEW"; 43 44 protected Column[] columns; 45 private HashMap columnMap = new HashMap (); 46 private boolean persistent; 47 private ObjectArray triggers; 48 private ObjectArray constraints; 49 private ObjectArray sequences; 50 private ObjectArray views; 51 private boolean checkForeignKeyConstraints = true; 52 53 public Table(Schema schema, int id, String name, boolean persistent) { 54 super(schema, id, name, Trace.TABLE); 55 this.persistent = persistent; 56 } 57 58 public String getCreateSQLForCopy(Table table, String quotedName) { 59 throw Message.getInternalError(); 60 } 61 62 public ObjectArray getChildren() { 63 ObjectArray children = new ObjectArray(); 64 ObjectArray indexes = getIndexes(); 65 if(indexes != null) { 66 children.addAll(indexes); 67 } 68 if(constraints != null) { 69 children.addAll(constraints); 70 } 71 if(triggers != null) { 72 children.addAll(triggers); 73 } 74 if(sequences != null) { 75 children.addAll(sequences); 76 } 77 if(views != null) { 78 children.addAll(views); 79 } 80 ObjectArray rights = database.getAllRights(); 81 for(int i=0; i<rights.size(); i++) { 82 Right right = (Right) rights.get(i); 83 if(right.getGrantedTable() == this) { 84 children.add(right); 85 } 86 } 87 return children; 88 } 89 90 protected void setColumns(Column[] columns) throws SQLException { 91 this.columns = columns; 92 if(columnMap.size() > 0) { 93 columnMap.clear(); 94 } 95 for (int i = 0; i < columns.length; i++) { 96 Column col = columns[i]; 97 col.setTable(this, i); 98 String columnName = col.getName(); 99 if (columnMap.get(columnName) != null) { 100 throw Message.getSQLException(Message.DUPLICATE_COLUMN_NAME_1, 101 columnName); 102 } 103 columnMap.put(columnName, col); 104 } 105 } 106 107 public void renameColumn(Column column, String newName) { 108 columnMap.remove(column.getName()); 109 column.rename(newName); 110 columnMap.put(newName, column); 111 } 112 113 public abstract void lock(Session session, boolean exclusive) throws SQLException ; 114 public abstract void close(Session session) throws SQLException ; 115 public abstract void unlock(Session s); 116 public abstract Index addIndex(Session session, String indexName, int indexId, Column[] cols, IndexType indexType, int headPos, String comment) throws SQLException ; 117 public abstract void removeRow(Session session, Row row) throws SQLException ; 118 public abstract void truncate(Session session) throws SQLException ; 119 public abstract void addRow(Session session, Row row) throws SQLException ; 120 public abstract void checkSupportAlter() throws SQLException ; 121 public abstract String getTableType(); 122 public abstract Index getScanIndex(Session session) throws SQLException ; 123 public abstract Index getUniqueIndex(); 124 public abstract ObjectArray getIndexes(); 125 public abstract boolean isLockedExclusively(); 126 public abstract long getMaxDataModificationId(); 127 128 public void removeChildrenAndResources(Session session) throws SQLException { 129 while(views != null && views.size() > 0) { 130 TableView view = (TableView)views.get(0); 131 views.remove(0); 132 database.removeSchemaObject(session, view); 133 } 134 while(triggers != null && triggers.size() > 0) { 135 TriggerObject trigger = (TriggerObject)triggers.get(0); 136 triggers.remove(0); 137 database.removeSchemaObject(session, trigger); 138 } 139 while(constraints != null && constraints.size() > 0) { 140 Constraint constraint = (Constraint)constraints.get(0); 141 constraints.remove(0); 142 database.removeSchemaObject(session, constraint); 143 } 144 while(sequences != null && sequences.size() > 0) { 145 Sequence sequence = (Sequence)sequences.get(0); 146 sequences.remove(0); 147 if(!getTemporary()) { 148 database.removeSchemaObject(session, sequence); 149 } 150 } 151 ObjectArray rights = database.getAllRights(); 152 for(int i=0; i<rights.size(); i++) { 153 Right right = (Right) rights.get(i); 154 if(right.getGrantedTable() == this) { 155 database.removeDatabaseObject(session, right); 156 } 157 } 158 } 159 160 public void checkColumnIsNotReferenced(Column col) throws SQLException { 161 for(int i=0; constraints != null && i<constraints.size(); i++) { 162 Constraint constraint = (Constraint) constraints.get(i); 163 if(constraint.containsColumn(col)) { 164 throw Message.getSQLException(Message.COLUMN_MAY_BE_REFERENCED_1, constraint.getSQL()); 165 } 166 } 167 ObjectArray indexes = getIndexes(); 168 for(int i=0; indexes != null && i < indexes.size(); i++) { 169 Index index = (Index) indexes.get(i); 170 if(index.getColumns().length == 1) { 171 continue; 172 } 173 if(index.getCreateSQL() == null) { 174 continue; 175 } 176 if(index.getColumnIndex(col) >= 0) { 177 throw Message.getSQLException(Message.COLUMN_MAY_BE_REFERENCED_1, index.getSQL()); 178 } 179 } 180 } 181 182 public Row getTemplateRow() { 183 return new Row(new Value[columns.length]); 184 } 185 186 public SearchRow getTemplateSimpleRow(boolean singleColumn) { 187 if(singleColumn) { 188 return new SimpleRowValue(columns.length); 189 } else { 190 return new SimpleRow(new Value[columns.length]); 191 } 192 } 193 194 public Row getNullRow() { 195 Row row = new Row(new Value[columns.length]); 197 for (int i = 0; i < columns.length; i++) { 198 row.setValue(i, ValueNull.INSTANCE); 199 } 200 return row; 201 } 202 203 public Column[] getColumns() { 204 return columns; 205 } 206 207 public int getType() { 208 return DbObject.TABLE_OR_VIEW; 209 } 210 211 public Column getColumn(int index) { 212 return columns[index]; 213 } 214 215 public Column getColumn(String columnName) throws SQLException { 216 Column column = (Column) columnMap.get(columnName); 217 if (column == null) { 218 throw Message.getSQLException(Message.COLUMN_NOT_FOUND_1, columnName); 219 } 220 return column; 221 } 222 223 226 public PlanItem getBestPlanItem(Session session, int[] masks) throws SQLException { 227 PlanItem item = new PlanItem(); 228 item.index = getScanIndex(session); 229 item.cost = item.index.getCost(null); 230 ObjectArray indexes = getIndexes(); 231 for (int i = 1; indexes != null && masks != null && i < indexes.size(); i++) { 232 Index index = (Index) indexes.get(i); 233 int cost = index.getCost(masks); 234 if (cost < item.cost) { 235 item.cost = cost; 236 item.index = index; 237 } 238 } 239 return item; 240 } 241 242 public Index findPrimaryKey() throws SQLException { 243 ObjectArray indexes = getIndexes(); 244 for(int i=0; indexes != null && i<indexes.size(); i++) { 245 Index idx = (Index) indexes.get(i); 246 if(idx.getIndexType().isPrimaryKey()) { 247 return idx; 248 } 249 } 250 return null; 251 } 252 253 public Index getPrimaryKey() throws SQLException { 254 Index index = findPrimaryKey(); 255 if(index != null) { 256 return index; 257 } 258 throw Message.getSQLException(Message.INDEX_NOT_FOUND_1, Constants.PRIMARY_KEY_PREFIX); 259 } 260 261 public void validateConvertUpdateSequence(Session session, Row row) throws SQLException { 262 for (int i = 0; i < columns.length; i++) { 263 Value value = row.getValue(i); 264 Column column = columns[i]; 265 Value v2; 266 if(column.getComputed()) { 267 v2 = column.computeValue(session, row); 268 } else { 269 v2 = column.validateConvertUpdateSequence(session, value); 270 } 271 if(v2 != value) { 272 row.setValue(i, v2); 273 } 274 } 275 } 276 277 public boolean isPersistent() { 278 return persistent; 279 } 280 281 private void remove(ObjectArray list, DbObject obj) { 282 int i = list.indexOf(obj); 283 if(i>=0) { 284 list.remove(i); 285 } 286 } 287 288 public void removeIndex(Index index) { 289 ObjectArray indexes = getIndexes(); 290 if(indexes != null) { 291 remove(indexes, index); 292 } 293 } 294 295 public void removeView(TableView view) { 296 remove(views, view); 297 } 298 299 public void removeConstraint(Constraint constraint) { 300 remove(constraints, constraint); 301 } 302 303 public void removeSequence(Session session, Sequence sequence) { 304 remove(sequences, sequence); 305 } 306 307 public void removeTrigger(Session session, TriggerObject trigger) { 308 remove(triggers, trigger); 309 } 310 311 public void addView(TableView view) { 312 views = add(views, view); 313 } 314 315 public void addConstraint(Constraint constraint) { 316 if(constraints == null || constraints.indexOf(constraint) < 0) { 317 constraints = add(constraints, constraint); 318 } 319 } 320 321 public ObjectArray getConstraints() { 322 return constraints; 323 } 324 325 public void addSequence(Sequence sequence) { 326 sequences = add(sequences, sequence); 327 } 328 329 public void addTrigger(TriggerObject trigger) { 330 triggers = add(triggers, trigger); 331 } 332 333 private ObjectArray add(ObjectArray list, DbObject obj) { 334 if(list == null) { 335 list = new ObjectArray(); 336 } 337 list.add(obj); 344 return list; 345 } 346 347 public void fireBefore(Session session) throws SQLException { 348 fire(session, true); 350 } 351 352 public void fireAfter(Session session) throws SQLException { 353 fire(session, false); 354 } 355 356 private void fire(Session session, boolean beforeAction) throws SQLException { 357 if(triggers != null) { 358 for (int i = 0; i < triggers.size(); i++) { 359 TriggerObject trigger = (TriggerObject) triggers.get(i); 360 trigger.fire(session, beforeAction); 361 } 362 } 363 } 364 365 public boolean fireRow() { 366 return (constraints != null && constraints.size()>0) || (triggers != null && triggers.size()>0); 367 } 368 369 public void fireBeforeRow(Session session, Row oldRow, Row newRow) throws SQLException { 370 fireRow(session, oldRow, newRow, true); 371 fireConstraints(session, oldRow, newRow, true); 372 } 373 374 private void fireConstraints(Session session, Row oldRow, Row newRow, boolean before) throws SQLException { 375 if(constraints != null) { 376 for (int i = 0; i < constraints.size(); i++) { 377 Constraint constraint = (Constraint) constraints.get(i); 378 if(constraint.isBefore() == before) { 379 constraint.checkRow(session, this, oldRow, newRow); 380 } 381 } 382 } 383 } 384 385 public void fireAfterRow(Session session, Row oldRow, Row newRow) throws SQLException { 386 fireRow(session, oldRow, newRow, false); 387 fireConstraints(session, oldRow, newRow, false); 388 } 389 390 private void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction) throws SQLException { 391 if(triggers != null) { 392 for (int i = 0; i < triggers.size(); i++) { 393 TriggerObject trigger = (TriggerObject) triggers.get(i); 394 trigger.fireRow(session, oldRow, newRow, beforeAction); 395 } 396 } 397 } 398 399 public Column[] getColumns(String [] columnNames) throws SQLException { 400 Column[] cols = new Column[columnNames.length]; 401 for(int i=0; i<cols.length; i++) { 402 cols[i] = getColumn(columnNames[i]); 403 } 404 return cols; 405 } 406 407 public abstract boolean canGetRowCount(); 408 public abstract boolean canDrop(); 409 public abstract int getRowCount() throws SQLException ; 410 411 public boolean getGlobalTemporary() { 412 return false; 413 } 414 415 public boolean canTruncate() { 416 return false; 417 } 418 419 public void setCheckForeignKeyConstraints(boolean b) { 420 checkForeignKeyConstraints = b; 421 } 422 423 public boolean getCheckForeignKeyConstraints() { 424 return checkForeignKeyConstraints; 425 } 426 427 public Index getIndexForColumn(Column column, boolean first) { 428 ObjectArray indexes = getIndexes(); 429 for (int i = 1; indexes != null && i < indexes.size(); i++) { 430 Index index = (Index) indexes.get(i); 431 if(index.canGetFirstOrLast(first)) { 432 int idx = index.getColumnIndex(column); 433 if(idx== 0) { 434 return index; 435 } 436 } 437 } 438 return null; 439 } 440 441 } 442 | Popular Tags |