1 30 31 32 package org.hsqldb; 33 34 import org.hsqldb.HsqlNameManager.HsqlName; 35 import org.hsqldb.index.RowIterator; 36 import org.hsqldb.lib.ArrayUtil; 37 import org.hsqldb.lib.HashSet; 38 39 47 class TableWorks { 48 49 private Table table; 50 private Session session; 51 52 TableWorks(Session session, Table table) { 53 this.table = table; 54 this.session = session; 55 } 56 57 Table getTable() { 58 return table; 59 } 60 61 105 void createForeignKey(int[] fkcol, int[] expcol, HsqlName name, 106 Table mainTable, int deleteAction, 107 int updateAction) throws HsqlException { 108 109 table.database.schemaManager.checkConstraintExists(name.name, 110 table.getSchemaName(), false); 111 112 if (table.getConstraint(name.name) != null) { 114 throw Trace.error(Trace.CONSTRAINT_ALREADY_EXISTS); 115 } 116 117 if (table.getConstraintForColumns(mainTable, expcol, fkcol) != null) { 119 throw Trace.error(Trace.CONSTRAINT_ALREADY_EXISTS); 120 } 121 122 if (mainTable.isTemp() != table.isTemp()) { 123 throw Trace.error(Trace.FOREIGN_KEY_NOT_ALLOWED); 124 } 125 126 boolean isSelf = table == mainTable; 127 int offset = table.database.schemaManager.getTableIndex(table); 128 boolean isforward = 129 offset != -1 130 && offset < table.database.schemaManager.getTableIndex(mainTable); 131 Index exportindex = 132 mainTable.getUniqueConstraintIndexForColumns(expcol); 133 134 if (exportindex == null) { 135 throw Trace.error(Trace.SQL_CONSTRAINT_REQUIRED, 136 mainTable.getName().statementName); 137 } 138 139 Constraint.checkReferencedRows(session, table, fkcol, exportindex); 141 142 HsqlName iname = table.database.nameManager.newAutoName("IDX"); 144 Index fkindex = createIndex(fkcol, iname, false, true, isforward); 145 HsqlName pkname = table.database.nameManager.newAutoName("REF", 146 name.name); 147 148 if (isSelf) { 149 150 mainTable = table; 152 } 153 154 Constraint c = new Constraint(pkname, name, mainTable, table, expcol, 155 fkcol, exportindex, fkindex, 156 deleteAction, updateAction); 157 158 table.addConstraint(c); 159 mainTable.addConstraint(new Constraint(pkname, c)); 160 table.database.schemaManager.registerConstraintName(name.name, 161 table.getName()); 162 } 163 164 182 Index createIndex(int[] col, HsqlName name, boolean unique, 183 boolean constraint, 184 boolean forward) throws HsqlException { 185 186 Index newindex; 187 188 if (table.isEmpty(session) || table.isIndexingMutable()) { 189 newindex = table.createIndex(session, col, name, unique, 190 constraint, forward); 191 192 table.database.schemaManager.clearTempTables(session, table); 193 } else { 194 Table tn = table.moveDefinition(null, null, -1, 0); 195 196 newindex = tn.createIndexStructure(col, name, unique, constraint, 197 forward); 198 199 tn.moveData(session, table, -1, 0); 200 tn.updateConstraintsTables(session, table, -1, 0); 201 202 int index = table.database.schemaManager.getTableIndex(table); 203 204 table.database.schemaManager.setTable(index, tn); 205 206 table = tn; 207 } 208 209 table.database.schemaManager.clearTempTables(session, table); 210 table.database.schemaManager.registerIndexName( 211 newindex.getName().name, table.getName()); 212 table.database.schemaManager.recompileViews(table); 213 214 return newindex; 215 } 216 217 void addPrimaryKey(int[] cols, HsqlName name) throws HsqlException { 218 219 if (name == null) { 220 name = table.makeSysPKName(); 221 } 222 223 table.database.schemaManager.checkConstraintExists(name.name, 224 table.getSchemaName(), false); 225 addOrDropPrimaryKey(cols, false); 226 227 Constraint newconstraint = new Constraint(name, table, 228 table.getPrimaryIndex(), Constraint.PRIMARY_KEY); 229 230 table.addPKConstraint(newconstraint); 231 table.database.schemaManager.registerConstraintName(name.name, 232 table.getName()); 233 } 234 235 void addOrDropPrimaryKey(int[] cols, 236 boolean identity) throws HsqlException { 237 238 if (cols == null) { 239 table.checkDropIndex(table.getIndexes()[0].getName().name, null, 240 true); 241 } 242 243 Table tn = table.moveDefinitionPK(cols, identity); 244 245 tn.moveData(session, table, -1, 0); 246 tn.updateConstraintsTables(session, table, -1, 0); 247 248 int index = table.database.schemaManager.getTableIndex(table); 249 250 table.database.schemaManager.setTable(index, tn); 251 252 table = tn; 253 254 table.database.schemaManager.recompileViews(table); 255 } 256 257 270 void createUniqueConstraint(int[] col, 271 HsqlName name) throws HsqlException { 272 273 table.database.schemaManager.checkConstraintExists(name.name, 274 table.getSchemaName(), false); 275 276 Constraint[] constraints = table.getConstraints(); 277 278 for (int i = 0, size = constraints.length; i < size; i++) { 279 Constraint c = constraints[i]; 280 281 if (c.isEquivalent(col, Constraint.UNIQUE) 282 || c.getName().name.equals(name.name)) { 283 throw Trace.error(Trace.CONSTRAINT_ALREADY_EXISTS); 284 } 285 } 286 287 HsqlName indexname = table.database.nameManager.newAutoName("IDX", 289 name.name); 290 Index index = createIndex(col, indexname, true, true, false); 291 Constraint newconstraint = new Constraint(name, table, index, 292 Constraint.UNIQUE); 293 294 table.addConstraint(newconstraint); 295 table.database.schemaManager.registerConstraintName(name.name, 296 table.getName()); 297 } 298 299 void createCheckConstraint(Constraint c, 300 HsqlName name) throws HsqlException { 301 302 table.database.schemaManager.checkConstraintExists(name.name, 303 table.getSchemaName(), false); 304 305 Expression e = c.core.check; 307 308 e.setLikeOptimised(); 310 311 Select s = Expression.getCheckSelect(session, table, e); 312 Result r = s.getResult(session, 1); 313 314 c.core.checkFilter = s.tFilter[0]; 315 c.core.mainTable = table; 316 317 if (r.getSize() != 0) { 318 throw Trace.error(Trace.CHECK_CONSTRAINT_VIOLATION); 319 } 320 321 e.getDDL(); 323 324 c.core.checkFilter.setAsCheckFilter(); 326 table.addConstraint(c); 327 table.database.schemaManager.registerConstraintName(name.name, 328 table.getName()); 329 } 330 331 342 void dropIndex(String indexname) throws HsqlException { 343 344 if (table.isIndexingMutable()) { 345 table.dropIndex(session, indexname); 346 } else { 347 int[] removeIndex = new int[]{ table.getIndexIndex(indexname) }; 348 Table tn = table.moveDefinition(removeIndex, null, -1, 0); 349 350 tn.moveData(session, table, -1, 0); 351 tn.updateConstraintsTables(session, table, -1, 0); 352 353 int i = table.database.schemaManager.getTableIndex(table); 354 355 table.database.schemaManager.setTable(i, tn); 356 357 table = tn; 358 } 359 360 table.database.schemaManager.removeIndexName(indexname, 361 table.getName()); 362 table.database.schemaManager.recompileViews(table); 363 } 364 365 371 void retypeColumn(Column column, int colindex) throws HsqlException { 372 373 if (table.isText() &&!table.isEmpty(session)) { 374 throw Trace.error(Trace.OPERATION_NOT_SUPPORTED); 375 } 376 377 table.database.schemaManager.checkColumnIsInView(table, 378 table.getColumn(colindex).columnName.name); 379 table.checkColumnInCheckConstraint( 380 table.getColumn(colindex).columnName.name); 381 382 int[] dropIndexes = null; 383 Table tn = table.moveDefinition(dropIndexes, column, colindex, 0); 384 385 tn.moveData(session, table, colindex, 0); 386 tn.updateConstraintsTables(session, table, colindex, 0); 387 388 int i = table.database.schemaManager.getTableIndex(table); 389 390 table.database.schemaManager.setTable(i, tn); 391 392 table = tn; 393 394 table.database.schemaManager.recompileViews(table); 395 } 396 397 402 void dropColumn(int colIndex) throws HsqlException { 403 404 HsqlName constNameRemove = null; 405 406 if (table.isText() &&!table.isEmpty(session)) { 407 throw Trace.error(Trace.OPERATION_NOT_SUPPORTED); 408 } 409 410 table.database.schemaManager.checkColumnIsInView(table, 411 table.getColumn(colIndex).columnName.name); 412 table.checkColumnInCheckConstraint( 413 table.getColumn(colIndex).columnName.name); 414 415 Table tn = table; 416 int[] dropIndexes = null; 417 String colName = tn.getColumn(colIndex).columnName.name; 418 419 tn.checkColumnInFKConstraint(colIndex); 420 421 if (table.getPrimaryKey().length == 1 422 && table.getPrimaryKey()[0] == colIndex) { 423 table.checkDropIndex(table.getIndex(0).getName().name, null, 424 true); 425 426 constNameRemove = table.constraintList[0].getName(); 427 tn = table.moveDefinitionPK(null, false); 428 } 429 430 Constraint c = tn.getUniqueConstraintForColumns(new int[]{ 431 colIndex }); 432 433 if (c != null) { 434 Index idx = c.getMainIndex(); 435 436 dropIndexes = new int[]{ tn.getIndexIndex(idx.getName().name) }; 437 constNameRemove = c.getName(); 438 } 439 440 tn = tn.moveDefinition(dropIndexes, null, colIndex, -1); 441 442 tn.moveData(session, table, colIndex, -1); 443 tn.updateConstraintsTables(session, table, colIndex, -1); 444 445 int i = table.database.schemaManager.getTableIndex(table); 446 447 table.database.schemaManager.setTable(i, tn); 448 449 table = tn; 450 451 table.database.schemaManager.recompileViews(table); 452 453 if (constNameRemove != null) { 454 table.removeConstraint(constNameRemove.name); 455 table.database.schemaManager.removeConstraintName( 456 constNameRemove.name, table.getName()); 457 } 458 } 459 460 466 void addColumn(Column column, int colIndex) throws HsqlException { 467 468 if (table.isText() &&!table.isEmpty(session)) { 469 throw Trace.error(Trace.OPERATION_NOT_SUPPORTED); 470 } 471 472 Table tn = table; 473 474 tn = tn.moveDefinition(null, column, colIndex, 1); 475 476 if (column.isPrimaryKey()) { 477 tn = tn.moveDefinitionPK(new int[]{ colIndex }, true); 478 } 479 480 tn.moveData(session, table, colIndex, 1); 481 tn.updateConstraintsTables(session, table, colIndex, 1); 482 483 int i = table.database.schemaManager.getTableIndex(table); 484 485 table.database.schemaManager.setTable(i, tn); 486 487 table = tn; 488 489 table.database.schemaManager.recompileViews(table); 490 491 if (column.isPrimaryKey()) { 492 HsqlName pkNameAdd = tn.makeSysPKName(); 493 Constraint newconstraint = new Constraint(pkNameAdd, table, 494 table.getPrimaryIndex(), Constraint.PRIMARY_KEY); 495 496 table.addConstraint(newconstraint); 497 table.database.schemaManager.registerConstraintName( 498 pkNameAdd.name, table.getName()); 499 } 500 } 501 502 506 void dropConstraint(String name) throws HsqlException { 507 508 Constraint c = table.getConstraint(name); 509 int ctype; 510 511 if (c == null) { 512 throw Trace.error(Trace.CONSTRAINT_NOT_FOUND, 513 Trace.TableWorks_dropConstraint, new Object [] { 514 name, table.getName().name 515 }); 516 } 517 518 ctype = c.getType(); 519 520 if (ctype == Constraint.MAIN) { 521 throw Trace.error(Trace.DROP_SYSTEM_CONSTRAINT); 522 } 523 524 if (ctype == Constraint.PRIMARY_KEY) { 525 addOrDropPrimaryKey(null, false); 526 table.removeConstraint(name); 527 } else if (ctype == Constraint.FOREIGN_KEY) { 528 dropFKConstraint(c); 529 } else if (ctype == Constraint.UNIQUE) { 530 HashSet cset = new HashSet(); 531 532 cset.add(c); 533 534 table.checkDropIndex(c.getMainIndex().getName().name, cset, 536 false); 537 538 dropIndex(c.getMainIndex().getName().name); 540 table.removeConstraint(name); 541 } else if (ctype == Constraint.CHECK) { 542 table.removeConstraint(name); 543 } 544 545 table.database.schemaManager.removeConstraintName(name, 546 table.getName()); 547 } 548 549 void dropFKConstraint(Constraint c) throws HsqlException { 550 551 Index constIndex = c.getRefIndex(); 553 554 dropIndex(constIndex.getName().name); 556 557 Table mainTable = c.getMain(); 558 559 mainTable.removeConstraint(c.getPkName()); 561 table.removeConstraint(c.getFkName()); 562 } 563 564 void reTypeColumn(Column oldCol, Column newCol) throws HsqlException { 565 566 boolean notallowed = false; 567 int oldtype = oldCol.getType(); 568 int newtype = newCol.getType(); 569 570 switch (newtype) { 571 572 case Types.BINARY : 573 case Types.VARBINARY : 574 case Types.LONGVARBINARY : 575 case Types.OTHER : 576 case Types.JAVA_OBJECT : 577 notallowed = !(newtype == oldtype || table.isEmpty(session)); 578 } 579 580 switch (oldtype) { 581 582 case Types.BINARY : 583 case Types.VARBINARY : 584 case Types.LONGVARBINARY : 585 case Types.OTHER : 586 case Types.JAVA_OBJECT : 587 notallowed = !(newtype == oldtype || table.isEmpty(session)); 588 break; 589 590 case Types.TINYINT : 591 case Types.SMALLINT : 592 case Types.INTEGER : 593 case Types.BIGINT : 594 case Types.REAL : 595 case Types.FLOAT : 596 case Types.DOUBLE : 597 case Types.NUMERIC : 598 case Types.DECIMAL : 599 switch (newtype) { 600 601 case Types.DATE : 602 case Types.TIME : 603 case Types.TIMESTAMP : 604 notallowed = !table.isEmpty(session); 605 default : 606 } 607 break; 608 609 case Types.DATE : 610 case Types.TIME : 611 case Types.TIMESTAMP : 612 switch (newtype) { 613 614 case Types.TINYINT : 615 case Types.SMALLINT : 616 case Types.INTEGER : 617 case Types.BIGINT : 618 case Types.REAL : 619 case Types.FLOAT : 620 case Types.DOUBLE : 621 case Types.NUMERIC : 622 case Types.DECIMAL : 623 notallowed = !table.isEmpty(session); 624 default : 625 } 626 break; 627 } 628 629 if (notallowed) { 630 throw Trace.error(Trace.INVALID_CONVERSION); 631 } 632 633 int colIndex = table.getColumnNr(oldCol.columnName.name); 634 635 if (table.getPrimaryKey().length > 1) { 636 637 if (newCol.isIdentity()) { 639 throw Trace.error(Trace.SECOND_PRIMARY_KEY); 640 } 641 642 newCol.setPrimaryKey(oldCol.isPrimaryKey()); 643 644 if (ArrayUtil.find(table.getPrimaryKey(), colIndex) != -1) { 645 newCol.setNullable(false); 646 } 647 } else if (table.hasPrimaryKey()) { 648 if (oldCol.isPrimaryKey()) { 649 newCol.setPrimaryKey(true); 650 newCol.setNullable(false); 651 } else if (newCol.isPrimaryKey()) { 652 throw Trace.error(Trace.SECOND_PRIMARY_KEY); 653 } 654 } else if (newCol.isPrimaryKey()) { 655 throw Trace.error(Trace.PRIMARY_KEY_NOT_ALLOWED); 656 } 657 658 if (newtype == oldtype && oldCol.isNullable() == newCol.isNullable() 660 && oldCol.getScale() == newCol.getScale() 661 && oldCol.isIdentity() == newCol.isIdentity() 662 && oldCol.identityIncrement == newCol.identityIncrement 663 && (oldCol.getSize() == newCol.getSize() 664 || (oldCol.getSize() < newCol.getSize() 665 && (oldtype == Types.VARCHAR 666 || oldtype == Types.DECIMAL 667 || oldtype == Types.NUMERIC)))) { 668 669 oldCol.setType(newCol); 672 oldCol.setDefaultExpression(newCol.getDefaultExpression()); 673 table.setColumnTypeVars(colIndex); 674 table.resetDefaultsFlag(); 675 676 return; 677 } 678 679 table.database.schemaManager.checkColumnIsInView(table, 680 table.getColumn(colIndex).columnName.name); 681 table.checkColumnInCheckConstraint( 682 table.getColumn(colIndex).columnName.name); 683 table.checkColumnInFKConstraint(colIndex); 684 checkConvertColDataType(oldCol, newCol); 685 retypeColumn(newCol, colIndex); 686 } 687 688 void checkConvertColDataType(Column oldCol, 689 Column newCol) throws HsqlException { 690 691 int colIndex = table.getColumnNr(oldCol.columnName.name); 692 RowIterator it = table.getPrimaryIndex().firstRow(session); 693 694 while (it.hasNext()) { 695 Row row = it.next(); 696 Object o = row.getData()[colIndex]; 697 698 Column.convertObject(session, o, newCol.getType(), 699 newCol.getSize(), newCol.getScale()); 700 } 701 } 702 703 706 void setColNullability(Column column, 707 boolean nullable) throws HsqlException { 708 709 int colIndex = table.getColumnNr(column.columnName.name); 710 711 if (nullable) { 712 if (column.isPrimaryKey()) { 713 throw Trace.error(Trace.TRY_TO_INSERT_NULL); 714 } 715 716 table.checkColumnInFKConstraint(colIndex, Constraint.SET_NULL); 717 } else { 718 RowIterator it = table.getPrimaryIndex().firstRow(session); 719 720 while (it.hasNext()) { 721 Row row = it.next(); 722 Object o = row.getData()[colIndex]; 723 724 if (o == null) { 725 throw Trace.error(Trace.TRY_TO_INSERT_NULL); 726 } 727 } 728 } 729 730 column.setNullable(nullable); 731 table.setColumnTypeVars(colIndex); 732 } 733 734 737 void setColDefaultExpression(int colIndex, 738 Expression def) throws HsqlException { 739 740 if (def == null) { 741 table.checkColumnInFKConstraint(colIndex, Constraint.SET_DEFAULT); 742 } 743 744 table.setDefaultExpression(colIndex, def); 745 } 746 } 747 | Popular Tags |